@sanity/ui 1.7.2 → 1.7.4

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 (137) hide show
  1. package/README.md +1 -1
  2. package/dist/index.d.ts +19 -19
  3. package/dist/index.esm.js +340 -103
  4. package/dist/index.esm.js.map +1 -1
  5. package/dist/index.js +340 -103
  6. package/dist/index.js.map +1 -1
  7. package/package.json +33 -33
  8. package/src/__workshop__/constants.ts +2 -2
  9. package/src/components/autocomplete/__mocks__/apiStore.ts +2 -2
  10. package/src/components/autocomplete/__workshop__/async.tsx +2 -2
  11. package/src/components/autocomplete/__workshop__/constrainedHeight.tsx +2 -2
  12. package/src/components/autocomplete/__workshop__/custom.tsx +1 -1
  13. package/src/components/autocomplete/__workshop__/fullscreen.tsx +6 -6
  14. package/src/components/autocomplete/autocomplete.tsx +20 -20
  15. package/src/components/autocomplete/autocompleteOption.tsx +1 -1
  16. package/src/components/autocomplete/autocompleteReducer.ts +1 -1
  17. package/src/components/breadcrumbs/breadcrumbs.tsx +2 -2
  18. package/src/components/dialog/dialog.tsx +11 -11
  19. package/src/components/dialog/dialogProvider.tsx +1 -1
  20. package/src/components/dialog/styles.ts +1 -1
  21. package/src/components/hotkeys/hotkeys.tsx +1 -1
  22. package/src/components/menu/__workshop__/asComponent.tsx +1 -1
  23. package/src/components/menu/__workshop__/index.ts +5 -0
  24. package/src/components/menu/__workshop__/menuButton.tsx +1 -1
  25. package/src/components/menu/__workshop__/shouldFocus.tsx +46 -0
  26. package/src/components/menu/menu.test.tsx +3 -3
  27. package/src/components/menu/menu.tsx +7 -7
  28. package/src/components/menu/menuButton.tsx +7 -7
  29. package/src/components/menu/menuGroup.tsx +4 -4
  30. package/src/components/menu/menuItem.tsx +4 -4
  31. package/src/components/menu/useMenuController.ts +10 -5
  32. package/src/components/skeleton/skeleton.tsx +2 -2
  33. package/src/components/skeleton/textSkeleton.tsx +25 -19
  34. package/src/components/tab/tab.tsx +2 -2
  35. package/src/components/tab/tabList.tsx +3 -3
  36. package/src/components/tab/tabPanel.tsx +1 -1
  37. package/src/components/toast/toast.test.tsx +2 -1
  38. package/src/components/toast/toast.tsx +1 -1
  39. package/src/components/toast/toastProvider.tsx +1 -1
  40. package/src/components/tree/__workshop__/basic.perf.ts +1 -1
  41. package/src/components/tree/helpers.ts +2 -2
  42. package/src/components/tree/style.ts +1 -1
  43. package/src/components/tree/tree.tsx +9 -9
  44. package/src/components/tree/treeGroup.tsx +1 -1
  45. package/src/components/tree/treeItem.tsx +4 -4
  46. package/src/hooks/useArrayProp.ts +2 -2
  47. package/src/hooks/useClickOutside.ts +2 -2
  48. package/src/hooks/useCustomValidity.ts +1 -1
  49. package/src/hooks/useMediaIndex/useMediaIndex.test.tsx +4 -4
  50. package/src/hooks/usePrefersDark.hydration.test.tsx +2 -1
  51. package/src/hooks/usePrefersReducedMotion.hydration.test.tsx +2 -1
  52. package/src/lib/globalScope.ts +1 -0
  53. package/src/primitives/_selectable/selectable.tsx +1 -1
  54. package/src/primitives/_selectable/style.ts +1 -1
  55. package/src/primitives/avatar/avatar.tsx +3 -3
  56. package/src/primitives/avatar/avatarCounter.tsx +5 -3
  57. package/src/primitives/avatar/avatarStack.tsx +2 -2
  58. package/src/primitives/avatar/styles.ts +1 -1
  59. package/src/primitives/badge/badge.tsx +2 -2
  60. package/src/primitives/box/box.tsx +2 -2
  61. package/src/primitives/button/button.tsx +2 -2
  62. package/src/primitives/button/styles.ts +1 -1
  63. package/src/primitives/card/__workshop__/asComponent.tsx +1 -1
  64. package/src/primitives/card/__workshop__/selected.tsx +19 -15
  65. package/src/primitives/card/card.tsx +1 -1
  66. package/src/primitives/card/styles.ts +1 -1
  67. package/src/primitives/checkbox/checkbox.tsx +1 -1
  68. package/src/primitives/code/code.tsx +2 -1
  69. package/src/primitives/container/container.tsx +2 -2
  70. package/src/primitives/container/styles.ts +1 -1
  71. package/src/primitives/flex/flex.tsx +2 -2
  72. package/src/primitives/grid/grid.tsx +1 -1
  73. package/src/primitives/heading/heading.tsx +1 -1
  74. package/src/primitives/heading/styles.ts +4 -2
  75. package/src/primitives/helpers.ts +2 -2
  76. package/src/primitives/inline/inline.tsx +2 -2
  77. package/src/primitives/kbd/kbd.tsx +1 -1
  78. package/src/primitives/label/label.tsx +1 -1
  79. package/src/primitives/label/styles.ts +1 -1
  80. package/src/primitives/popover/__workshop__/RecursiveStory.tsx +1 -1
  81. package/src/primitives/popover/__workshop__/TestStory.tsx +1 -1
  82. package/src/primitives/popover/helpers.ts +1 -1
  83. package/src/primitives/popover/popover.tsx +11 -11
  84. package/src/primitives/popover/popoverArrow.tsx +1 -1
  85. package/src/primitives/popover/popoverCard.tsx +4 -4
  86. package/src/primitives/radio/radio.tsx +1 -1
  87. package/src/primitives/select/select.tsx +1 -1
  88. package/src/primitives/select/styles.ts +2 -2
  89. package/src/primitives/spinner/spinner.tsx +1 -1
  90. package/src/primitives/stack/stack.tsx +1 -1
  91. package/src/primitives/stack/styles.ts +1 -1
  92. package/src/primitives/switch/__workshop__/props.tsx +1 -1
  93. package/src/primitives/switch/styles.ts +1 -1
  94. package/src/primitives/switch/switch.tsx +1 -1
  95. package/src/primitives/text/__workshop__/colored.tsx +9 -8
  96. package/src/primitives/text/styles.ts +4 -2
  97. package/src/primitives/text/text.tsx +2 -2
  98. package/src/primitives/textArea/textArea.tsx +3 -3
  99. package/src/primitives/textInput/__workshop__/plain.tsx +2 -2
  100. package/src/primitives/textInput/textInput.tsx +11 -11
  101. package/src/primitives/tooltip/tooltip.tsx +8 -7
  102. package/src/primitives/tooltip/tooltipArrow.tsx +1 -1
  103. package/src/styles/border/borderStyle.ts +5 -5
  104. package/src/styles/colorVars/colorVarsStyle.ts +1 -1
  105. package/src/styles/flex/flexItemStyle.ts +1 -1
  106. package/src/styles/flex/flexStyle.ts +3 -3
  107. package/src/styles/font/responsiveFont.ts +1 -1
  108. package/src/styles/font/textAlignStyle.ts +1 -1
  109. package/src/styles/helpers.ts +3 -3
  110. package/src/styles/input/responsiveInputPaddingStyle.ts +4 -4
  111. package/src/styles/input/textInputStyle.ts +2 -2
  112. package/src/styles/margin/marginStyle.ts +1 -1
  113. package/src/styles/padding/paddingStyle.ts +1 -1
  114. package/src/theme/__workshop__/color.tsx +1 -0
  115. package/src/theme/lib/theme/color/button/createButtonModes.ts +1 -1
  116. package/src/theme/lib/theme/color/button/createButtonTones.ts +1 -1
  117. package/src/theme/lib/theme/color/card/createCardStates.ts +1 -1
  118. package/src/theme/lib/theme/color/factory.ts +2 -2
  119. package/src/theme/lib/theme/color/input/createInputModes.ts +1 -1
  120. package/src/theme/lib/theme/color/muted/createMuted.ts +1 -1
  121. package/src/theme/lib/theme/color/selectable/createSelectableTones.ts +2 -2
  122. package/src/theme/lib/theme/color/solid/createSolidTones.ts +1 -1
  123. package/src/theme/lib/theme/color/spot/createSpot.ts +1 -1
  124. package/src/theme/lib/theme/shadow.ts +1 -1
  125. package/src/theme/lib/theme/theme.ts +1 -1
  126. package/src/theme/theme.test.tsx +2 -1
  127. package/src/theme/themeProvider.tsx +1 -1
  128. package/src/theme/useRootTheme.ts +1 -0
  129. package/src/utils/boundaryElement/boundaryElement.test.tsx +2 -1
  130. package/src/utils/elementQuery/elementQuery.tsx +2 -2
  131. package/src/utils/layer/layer.test.tsx +2 -1
  132. package/src/utils/layer/layer.tsx +3 -3
  133. package/src/utils/layer/layerProvider.tsx +2 -2
  134. package/src/utils/portal/portal.test.tsx +2 -1
  135. package/src/utils/srOnly/srOnly.tsx +1 -1
  136. package/src/utils/virtualList/__workshop__/changingProps.tsx +1 -1
  137. package/src/utils/virtualList/virtualList.tsx +2 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sanity/ui",
3
- "version": "1.7.2",
3
+ "version": "1.7.4",
4
4
  "sideEffects": false,
5
5
  "types": "./dist/index.d.ts",
6
6
  "source": "./src/index.ts",
@@ -51,67 +51,67 @@
51
51
  "dependencies": {
52
52
  "@floating-ui/react-dom": "2.0.0",
53
53
  "@sanity/color": "^2.2.5",
54
- "@sanity/icons": "^2.3.1",
54
+ "@sanity/icons": "^2.4.1",
55
55
  "csstype": "^3.1.2",
56
- "framer-motion": "^10.12.16",
56
+ "framer-motion": "^10.13.1",
57
57
  "react-refractor": "^2.1.7"
58
58
  },
59
59
  "devDependencies": {
60
- "@babel/core": "^7.22.5",
61
- "@babel/preset-env": "^7.22.5",
60
+ "@babel/core": "^7.22.9",
61
+ "@babel/preset-env": "^7.22.9",
62
62
  "@babel/preset-react": "^7.22.5",
63
63
  "@babel/preset-typescript": "^7.22.5",
64
- "@commitlint/cli": "^17.6.5",
65
- "@commitlint/config-conventional": "^17.6.5",
64
+ "@commitlint/cli": "^17.6.7",
65
+ "@commitlint/config-conventional": "^17.6.7",
66
66
  "@juggle/resize-observer": "^3.4.0",
67
- "@sanity/pkg-utils": "^2.3.2",
68
- "@sanity/semantic-release-preset": "^4.1.1",
69
- "@sanity/ui-workshop": "^1.2.1",
70
- "@testing-library/dom": "^9.3.0",
71
- "@testing-library/jest-dom": "^5.16.5",
67
+ "@sanity/pkg-utils": "^2.3.6",
68
+ "@sanity/semantic-release-preset": "^4.1.2",
69
+ "@sanity/ui-workshop": "^1.2.7",
70
+ "@testing-library/dom": "^9.3.1",
71
+ "@testing-library/jest-dom": "^5.17.0",
72
72
  "@testing-library/react": "^14.0.0",
73
- "@types/jest": "^29.5.2",
73
+ "@types/jest": "^29.5.3",
74
74
  "@types/jest-axe": "^3.5.5",
75
- "@types/node": "^20.2.5",
76
- "@types/react": "^18.2.9",
77
- "@types/react-dom": "^18.2.4",
78
- "@types/react-is": "^18.2.0",
75
+ "@types/node": "^20.4.4",
76
+ "@types/react": "^18.2.16",
77
+ "@types/react-dom": "^18.2.7",
78
+ "@types/react-is": "^18.2.1",
79
79
  "@types/refractor": "^3.0.2",
80
80
  "@types/styled-components": "^5.1.26",
81
- "@types/testing-library__jest-dom": "^5.14.6",
82
- "@typescript-eslint/eslint-plugin": "^5.59.9",
83
- "@typescript-eslint/parser": "^5.59.9",
81
+ "@types/testing-library__jest-dom": "^5.14.9",
82
+ "@typescript-eslint/eslint-plugin": "^5.62.0",
83
+ "@typescript-eslint/parser": "^5.62.0",
84
84
  "commitizen": "^4.3.0",
85
- "cypress": "^12.14.0",
86
- "cypress-real-events": "^1.8.1",
85
+ "cypress": "^12.17.2",
86
+ "cypress-real-events": "^1.9.1",
87
87
  "cz-conventional-changelog": "^3.3.0",
88
- "esbuild": "^0.17.19",
88
+ "esbuild": "^0.18.16",
89
89
  "esbuild-register": "^3.4.2",
90
- "eslint": "^8.42.0",
90
+ "eslint": "^8.45.0",
91
91
  "eslint-config-prettier": "^8.8.0",
92
92
  "eslint-plugin-import": "^2.27.5",
93
93
  "eslint-plugin-jsx-a11y": "^6.7.1",
94
- "eslint-plugin-prettier": "^4.2.1",
95
- "eslint-plugin-react": "^7.32.2",
94
+ "eslint-plugin-prettier": "^5.0.0",
95
+ "eslint-plugin-react": "^7.33.0",
96
96
  "eslint-plugin-react-hooks": "^4.6.0",
97
97
  "http-server": "^14.1.1",
98
98
  "husky": "^8.0.3",
99
- "jest": "^29.5.0",
99
+ "jest": "^29.6.1",
100
100
  "jest-axe": "^7.0.1",
101
- "jest-environment-jsdom": "^29.5.0",
102
- "lint-staged": "^13.2.2",
101
+ "jest-environment-jsdom": "^29.6.1",
102
+ "lint-staged": "^13.2.3",
103
103
  "module-alias": "^2.2.3",
104
104
  "npm-run-all": "^4.1.5",
105
- "prettier": "^2.8.8",
105
+ "prettier": "^3.0.0",
106
106
  "react": "^18.2.0",
107
107
  "react-dom": "^18.2.0",
108
108
  "react-is": "^18.2.0",
109
109
  "rimraf": "^5.0.1",
110
- "semantic-release": "^21.0.3",
110
+ "semantic-release": "^21.0.7",
111
111
  "start-server-and-test": "^2.0.0",
112
112
  "styled-components": "^5.3.11",
113
113
  "tsconfig-paths": "^4.2.0",
114
- "typescript": "^5.1.3"
114
+ "typescript": "^5.1.6"
115
115
  },
116
116
  "peerDependencies": {
117
117
  "react": "^18",
@@ -146,7 +146,7 @@
146
146
  "prettier --write --cache --ignore-unknown"
147
147
  ]
148
148
  },
149
- "packageManager": "pnpm@8.2.0",
149
+ "packageManager": "pnpm@8.6.10",
150
150
  "publishConfig": {
151
151
  "access": "public"
152
152
  },
@@ -139,14 +139,14 @@ export const WORKSHOP_HEADING_FONT_SIZE_OPTIONS = {
139
139
  }
140
140
 
141
141
  export const WORKSHOP_ICON_SYMBOL_OPTIONS: {[key: string]: IconSymbol | ''} = Object.keys(
142
- icons
142
+ icons,
143
143
  ).reduce(
144
144
  (acc: {[key: string]: IconSymbol | ''}, key) => {
145
145
  acc[key] = key as IconSymbol
146
146
 
147
147
  return acc
148
148
  },
149
- {'(none)': ''}
149
+ {'(none)': ''},
150
150
  )
151
151
 
152
152
  export const WORKSHOP_LABEL_FONT_SIZE_OPTIONS = {
@@ -4,7 +4,7 @@ export const countriesStore = {
4
4
  search(
5
5
  query: string,
6
6
  onResults: (results: {value: string}[]) => void,
7
- onLoading: (flag: boolean) => void
7
+ onLoading: (flag: boolean) => void,
8
8
  ): {cancel: () => void} {
9
9
  const fakeDelay = 350 + Math.random() * 800
10
10
 
@@ -27,7 +27,7 @@ export const countriesStore = {
27
27
  fetchDocument(
28
28
  id: string,
29
29
  onResult: (value: {code: string; title: string} | null) => void,
30
- onLoading: (flag: boolean) => void
30
+ onLoading: (flag: boolean) => void,
31
31
  ): {cancel: () => void} {
32
32
  const fakeDelay = 50 + Math.random() * 400
33
33
 
@@ -38,7 +38,7 @@ export default function AsyncStory() {
38
38
  doSearch(query)
39
39
  }
40
40
  },
41
- [doSearch]
41
+ [doSearch],
42
42
  )
43
43
 
44
44
  const handleOpenButtonClick = useCallback(() => {
@@ -66,7 +66,7 @@ export default function AsyncStory() {
66
66
  fetchRef.current = countriesStore.fetchDocument(
67
67
  value,
68
68
  (data) => setOptionTitle(data?.title || null),
69
- setLoadingCurrentRef
69
+ setLoadingCurrentRef,
70
70
  )
71
71
  } else {
72
72
  setOptionTitle(null)
@@ -82,7 +82,7 @@ function ConstrainedHeightExampleField({id, label}: {id: string; label: string})
82
82
  onMouseEnter: () => void
83
83
  onMouseLeave: () => void
84
84
  },
85
- popoverRef: React.Ref<HTMLDivElement>
85
+ popoverRef: React.Ref<HTMLDivElement>,
86
86
  ) => {
87
87
  const {hidden, inputElement, ...restProps} = popoverProps
88
88
 
@@ -103,7 +103,7 @@ function ConstrainedHeightExampleField({id, label}: {id: string; label: string})
103
103
  />
104
104
  )
105
105
  },
106
- []
106
+ [],
107
107
  )
108
108
 
109
109
  return (
@@ -34,7 +34,7 @@ export default function CustomStory() {
34
34
  <Text size={fontSize}>{option.title}</Text>
35
35
  </Card>
36
36
  ),
37
- [fontSize, padding, radius]
37
+ [fontSize, padding, radius],
38
38
  )
39
39
 
40
40
  const renderValue = useCallback((currentValue: string, option?: ExampleOption) => {
@@ -42,7 +42,7 @@ export default function Fullscreen() {
42
42
 
43
43
  const relatedElements = useMemo(
44
44
  () => [closeSearchButtonElement].filter(Boolean) as HTMLElement[],
45
- [closeSearchButtonElement]
45
+ [closeSearchButtonElement],
46
46
  )
47
47
 
48
48
  const search = useCallback((query: string | null) => {
@@ -59,7 +59,7 @@ export default function Fullscreen() {
59
59
  if (query !== null) search(query)
60
60
  setQuery(query)
61
61
  },
62
- [search]
62
+ [search],
63
63
  )
64
64
 
65
65
  const handleOpen = useCallback(() => {
@@ -73,7 +73,7 @@ export default function Fullscreen() {
73
73
  setValue(v)
74
74
  pushToast({status: 'info', title: `Selected “${v}”`})
75
75
  },
76
- [pushToast]
76
+ [pushToast],
77
77
  )
78
78
 
79
79
  const renderOption = useCallback((option: BaseAutocompleteOption) => {
@@ -88,7 +88,7 @@ export default function Fullscreen() {
88
88
  onMouseEnter: () => void
89
89
  onMouseLeave: () => void
90
90
  },
91
- ref: React.Ref<HTMLDivElement>
91
+ ref: React.Ref<HTMLDivElement>,
92
92
  ) => {
93
93
  if (!props.hidden && error) {
94
94
  return (
@@ -142,7 +142,7 @@ export default function Fullscreen() {
142
142
  </Portal>
143
143
  )
144
144
  },
145
- [error, loading, options, query]
145
+ [error, loading, options, query],
146
146
  )
147
147
 
148
148
  const renderValue = useCallback(() => {
@@ -165,7 +165,7 @@ export default function Fullscreen() {
165
165
  fetchRef.current = countriesStore.fetchDocument(
166
166
  value,
167
167
  (data) => setOptionTitle(data?.title || null),
168
- setLoadingCurrentRef
168
+ setLoadingCurrentRef,
169
169
  )
170
170
  } else {
171
171
  setOptionTitle(null)
@@ -77,7 +77,7 @@ export interface AutocompleteProps<Option extends BaseAutocompleteOption = BaseA
77
77
  onMouseEnter: () => void
78
78
  onMouseLeave: () => void
79
79
  },
80
- ref: Ref<HTMLDivElement>
80
+ ref: Ref<HTMLDivElement>,
81
81
  ) => ReactNode
82
82
  renderValue?: (value: string, option?: Option) => string
83
83
  suffix?: ReactNode
@@ -91,7 +91,7 @@ const DEFAULT_FILTER_OPTION = (query: string, option: BaseAutocompleteOption) =>
91
91
  option.value.toLowerCase().indexOf(query.toLowerCase()) > -1
92
92
 
93
93
  const InnerAutocomplete = forwardRef(function InnerAutocomplete<
94
- Option extends BaseAutocompleteOption
94
+ Option extends BaseAutocompleteOption,
95
95
  >(
96
96
  props: AutocompleteProps<Option> &
97
97
  Omit<
@@ -115,7 +115,7 @@ const InnerAutocomplete = forwardRef(function InnerAutocomplete<
115
115
  | 'type'
116
116
  | 'value'
117
117
  >,
118
- ref: Ref<HTMLInputElement>
118
+ ref: Ref<HTMLInputElement>,
119
119
  ) {
120
120
  const {
121
121
  border = true,
@@ -166,7 +166,7 @@ const InnerAutocomplete = forwardRef(function InnerAutocomplete<
166
166
  </Text>
167
167
  </Card>
168
168
  ),
169
- [fontSize, paddingProp]
169
+ [fontSize, paddingProp],
170
170
  )
171
171
 
172
172
  const renderOption =
@@ -194,11 +194,11 @@ const InnerAutocomplete = forwardRef(function InnerAutocomplete<
194
194
  const padding = useArrayProp(paddingProp)
195
195
  const currentOption = useMemo(
196
196
  () => (value !== null ? options.find((o) => o.value === value) : undefined),
197
- [options, value]
197
+ [options, value],
198
198
  )
199
199
  const filteredOptions = useMemo(
200
200
  () => options.filter((option) => (query ? filterOption(query, option) : true)),
201
- [filterOption, options, query]
201
+ [filterOption, options, query],
202
202
  )
203
203
  const filteredOptionsLen = filteredOptions.length
204
204
  const activeItemId = activeValue ? `${id}-option-${activeValue}` : undefined
@@ -216,7 +216,7 @@ const InnerAutocomplete = forwardRef(function InnerAutocomplete<
216
216
 
217
217
  const elements: HTMLElement[] = (relatedElements || []).concat(
218
218
  rootElementRef.current ? [rootElementRef.current] : [],
219
- resultsPopoverElementRef.current ? [resultsPopoverElementRef.current] : []
219
+ resultsPopoverElementRef.current ? [resultsPopoverElementRef.current] : [],
220
220
  )
221
221
 
222
222
  let focusInside = false
@@ -238,7 +238,7 @@ const InnerAutocomplete = forwardRef(function InnerAutocomplete<
238
238
  }
239
239
  }, 0)
240
240
  },
241
- [onBlur, onQueryChange, relatedElements]
241
+ [onBlur, onQueryChange, relatedElements],
242
242
  )
243
243
 
244
244
  const handleRootFocus = useCallback((event: FocusEvent<HTMLDivElement>) => {
@@ -268,7 +268,7 @@ const InnerAutocomplete = forwardRef(function InnerAutocomplete<
268
268
 
269
269
  inputElementRef.current?.focus()
270
270
  },
271
- [onChange, onSelect, onQueryChange]
271
+ [onChange, onSelect, onQueryChange],
272
272
  )
273
273
 
274
274
  const handleRootKeyDown = useCallback(
@@ -331,7 +331,7 @@ const InnerAutocomplete = forwardRef(function InnerAutocomplete<
331
331
  return
332
332
  }
333
333
  },
334
- [activeValue, filteredOptions, filteredOptionsLen, onQueryChange]
334
+ [activeValue, filteredOptions, filteredOptionsLen, onQueryChange],
335
335
  )
336
336
 
337
337
  const handleInputChange = useCallback(
@@ -342,7 +342,7 @@ const InnerAutocomplete = forwardRef(function InnerAutocomplete<
342
342
 
343
343
  if (onQueryChange) onQueryChange(nextQuery)
344
344
  },
345
- [onQueryChange]
345
+ [onQueryChange],
346
346
  )
347
347
 
348
348
  const handleInputFocus = useCallback(
@@ -353,7 +353,7 @@ const InnerAutocomplete = forwardRef(function InnerAutocomplete<
353
353
  if (onFocus) onFocus(event)
354
354
  }
355
355
  },
356
- [focused, onFocus]
356
+ [focused, onFocus],
357
357
  )
358
358
 
359
359
  const handlePopoverMouseEnter = useCallback(() => {
@@ -433,7 +433,7 @@ const InnerAutocomplete = forwardRef(function InnerAutocomplete<
433
433
  inputElementRef.current = el
434
434
  forwardedRef.current = el
435
435
  },
436
- [forwardedRef]
436
+ [forwardedRef],
437
437
  )
438
438
 
439
439
  const clearButton = useMemo(() => {
@@ -456,12 +456,12 @@ const InnerAutocomplete = forwardRef(function InnerAutocomplete<
456
456
 
457
457
  return v - 2
458
458
  }),
459
- [padding]
459
+ [padding],
460
460
  )
461
461
  const openButtonPadding = useMemo(() => padding.map((v) => Math.max(v - 1, 0)), [padding])
462
462
  const openButtonProps: AutocompleteOpenButtonProps = useMemo(
463
463
  () => (typeof openButton === 'object' ? openButton : EMPTY_RECORD),
464
- [openButton]
464
+ [openButton],
465
465
  )
466
466
 
467
467
  const handleOpenClick = useCallback(
@@ -475,7 +475,7 @@ const InnerAutocomplete = forwardRef(function InnerAutocomplete<
475
475
 
476
476
  _raf(() => inputElementRef.current?.focus())
477
477
  },
478
- [currentOption, openButtonProps, renderValue, value]
478
+ [currentOption, openButtonProps, renderValue, value],
479
479
  )
480
480
 
481
481
  const openButtonNode = useMemo(
@@ -504,7 +504,7 @@ const InnerAutocomplete = forwardRef(function InnerAutocomplete<
504
504
  openButtonPadding,
505
505
  openButtonProps,
506
506
  readOnly,
507
- ]
507
+ ],
508
508
  )
509
509
 
510
510
  const inputValue = useMemo(() => {
@@ -560,7 +560,7 @@ const InnerAutocomplete = forwardRef(function InnerAutocomplete<
560
560
  if (listFocused) inputElementRef.current?.focus()
561
561
  }
562
562
  },
563
- [listFocused]
563
+ [listFocused],
564
564
  )
565
565
 
566
566
  const content = useMemo(() => {
@@ -630,7 +630,7 @@ const InnerAutocomplete = forwardRef(function InnerAutocomplete<
630
630
  onMouseEnter: handlePopoverMouseEnter,
631
631
  onMouseLeave: handlePopoverMouseLeave,
632
632
  },
633
- resultsPopoverElementRef
633
+ resultsPopoverElementRef,
634
634
  )
635
635
  }
636
636
 
@@ -709,5 +709,5 @@ export const Autocomplete = InnerAutocomplete as <Option extends BaseAutocomplet
709
709
  | 'value'
710
710
  > & {
711
711
  ref?: Ref<HTMLInputElement>
712
- }
712
+ },
713
713
  ) => ReactElement
@@ -26,7 +26,7 @@ export function AutocompleteOption(props: AutocompleteOptionProps): React.ReactE
26
26
  handleClick()
27
27
  }
28
28
  },
29
- [handleClick]
29
+ [handleClick],
30
30
  )
31
31
 
32
32
  return (
@@ -5,7 +5,7 @@ import {AutocompleteMsg, AutocompleteState} from './types'
5
5
  */
6
6
  export function autocompleteReducer(
7
7
  state: AutocompleteState,
8
- msg: AutocompleteMsg
8
+ msg: AutocompleteMsg,
9
9
  ): AutocompleteState {
10
10
  if (msg.type === 'input/change') {
11
11
  return {...state, activeValue: null, focused: true, query: msg.query}
@@ -17,7 +17,7 @@ export interface BreadcrumbsProps {
17
17
  */
18
18
  export const Breadcrumbs = forwardRef(function Breadcrumbs(
19
19
  props: BreadcrumbsProps & Omit<React.HTMLProps<HTMLOListElement>, 'as' | 'ref' | 'type'>,
20
- ref: React.ForwardedRef<HTMLOListElement>
20
+ ref: React.ForwardedRef<HTMLOListElement>,
21
21
  ) {
22
22
  const {children, maxLength, separator, space: spaceRaw = 2, ...restProps} = props
23
23
  const space = useArrayProp(spaceRaw)
@@ -35,7 +35,7 @@ export const Breadcrumbs = forwardRef(function Breadcrumbs(
35
35
  Children.toArray(children).filter((child) => {
36
36
  return isValidElement(child)
37
37
  }),
38
- [children]
38
+ [children],
39
39
  )
40
40
 
41
41
  const items = useMemo(() => {
@@ -74,7 +74,7 @@ interface DialogCardProps extends ResponsiveWidthProps {
74
74
  function isTargetWithinScope(
75
75
  boundaryElement: HTMLElement | null,
76
76
  portalElement: HTMLElement | null,
77
- target: Node
77
+ target: Node,
78
78
  ): boolean {
79
79
  if (!boundaryElement || !portalElement) return true
80
80
 
@@ -87,7 +87,7 @@ function isTargetWithinScope(
87
87
  const Root = styled(Layer)<ResponsiveDialogPositionStyleProps & ResponsivePaddingStyleProps>(
88
88
  responsivePaddingStyle,
89
89
  dialogStyle,
90
- responsiveDialogPositionStyle
90
+ responsiveDialogPositionStyle,
91
91
  )
92
92
 
93
93
  const DialogContainer = styled(Container)`
@@ -148,7 +148,7 @@ const DialogFooter = styled(Box)`
148
148
 
149
149
  const DialogCard = forwardRef(function DialogCard(
150
150
  props: DialogCardProps,
151
- ref: React.ForwardedRef<HTMLDivElement>
151
+ ref: React.ForwardedRef<HTMLDivElement>,
152
152
  ) {
153
153
  const {
154
154
  __unstable_autoFocus: autoFocus,
@@ -208,8 +208,8 @@ const DialogCard = forwardRef(function DialogCard(
208
208
  onClose()
209
209
  }
210
210
  },
211
- [boundaryElement, isTopLayer, onClose, portalElement]
212
- )
211
+ [boundaryElement, isTopLayer, onClose, portalElement],
212
+ ),
213
213
  )
214
214
 
215
215
  useClickOutside(
@@ -226,9 +226,9 @@ const DialogCard = forwardRef(function DialogCard(
226
226
 
227
227
  onClickOutside()
228
228
  },
229
- [boundaryElement, isTopLayer, onClickOutside, portalElement]
229
+ [boundaryElement, isTopLayer, onClickOutside, portalElement],
230
230
  ),
231
- [rootElement]
231
+ [rootElement],
232
232
  )
233
233
 
234
234
  const setRef = useCallback(
@@ -236,7 +236,7 @@ const DialogCard = forwardRef(function DialogCard(
236
236
  setRootElement(el)
237
237
  forwardedRef.current = el
238
238
  },
239
- [forwardedRef]
239
+ [forwardedRef],
240
240
  )
241
241
 
242
242
  const setContentRef = useCallback(
@@ -245,7 +245,7 @@ const DialogCard = forwardRef(function DialogCard(
245
245
  if (typeof contentRef === 'function') contentRef(el)
246
246
  else if (contentRef) contentRef.current = el
247
247
  },
248
- [contentRef]
248
+ [contentRef],
249
249
  )
250
250
 
251
251
  return (
@@ -294,7 +294,7 @@ const DialogCard = forwardRef(function DialogCard(
294
294
  */
295
295
  export const Dialog = forwardRef(function Dialog(
296
296
  props: DialogProps & Omit<React.HTMLProps<HTMLDivElement>, 'as' | 'id' | 'width'>,
297
- ref: React.Ref<HTMLDivElement>
297
+ ref: React.Ref<HTMLDivElement>,
298
298
  ) {
299
299
  const dialog = useDialog()
300
300
  const theme = useTheme()
@@ -356,7 +356,7 @@ export const Dialog = forwardRef(function Dialog(
356
356
  focusedElementRef.current = event.target
357
357
  }
358
358
  },
359
- [onFocus]
359
+ [onFocus],
360
360
  )
361
361
 
362
362
  const labelId = `${id}_label`
@@ -25,7 +25,7 @@ export function DialogProvider(props: DialogProviderProps): React.ReactElement {
25
25
  position,
26
26
  zOffset,
27
27
  }),
28
- [position, zOffset]
28
+ [position, zOffset],
29
29
  )
30
30
 
31
31
  return <DialogContext.Provider value={contextValue}>{children}</DialogContext.Provider>
@@ -29,7 +29,7 @@ export function dialogStyle({theme}: ThemeProps): CSSObject {
29
29
  }
30
30
 
31
31
  export function responsiveDialogPositionStyle(
32
- props: ResponsiveDialogPositionStyleProps & ThemeProps
32
+ props: ResponsiveDialogPositionStyleProps & ThemeProps,
33
33
  ): CSSObject[] {
34
34
  const {theme} = props
35
35
  const {media} = theme.sanity
@@ -32,7 +32,7 @@ const Key = styled(KBD)`
32
32
  */
33
33
  export const Hotkeys = forwardRef(function Hotkeys(
34
34
  props: HotkeysProps & Omit<React.HTMLProps<HTMLElement>, 'as' | 'ref' | 'size'>,
35
- ref: React.Ref<HTMLElement>
35
+ ref: React.Ref<HTMLElement>,
36
36
  ) {
37
37
  const {fontSize, keys, padding, radius, space: spaceProp = 1, ...restProps} = props
38
38
  const space = useArrayProp(spaceProp)
@@ -3,7 +3,7 @@ import {forwardRef} from 'react'
3
3
 
4
4
  const CustomLink = forwardRef(function CustomLink(
5
5
  props: {req: string} & Omit<React.HTMLProps<HTMLAnchorElement>, 'as' | 'href'>,
6
- ref: React.ForwardedRef<HTMLAnchorElement>
6
+ ref: React.ForwardedRef<HTMLAnchorElement>,
7
7
  ): React.ReactElement {
8
8
  const {children, req, ...restProps} = props
9
9
 
@@ -70,5 +70,10 @@ export default defineScope({
70
70
  title: 'MenuButton with on close',
71
71
  component: lazy(() => import('./onCloseMenuButton')),
72
72
  },
73
+ {
74
+ name: 'shouldFocus',
75
+ title: 'Menu with shouldFocus',
76
+ component: lazy(() => import('./shouldFocus')),
77
+ },
73
78
  ],
74
79
  })
@@ -24,7 +24,7 @@ export default function MenuButtonStory() {
24
24
  constrainSize: true,
25
25
  portal,
26
26
  }),
27
- [portal]
27
+ [portal],
28
28
  )
29
29
 
30
30
  return (
@@ -0,0 +1,46 @@
1
+ import {useSelect} from '@sanity/ui-workshop'
2
+ import {Fragment, useCallback, useState} from 'react'
3
+ import {Button, Flex, Popover} from '../../../primitives'
4
+ import {LayerProvider} from '../../../utils'
5
+ import {Menu} from '../menu'
6
+ import {MenuDivider} from '../menuDivider'
7
+ import {MenuItem} from '../menuItem'
8
+
9
+ const ITEMS = [...Array(8).keys()].map((num) => ({
10
+ title: `Item ${num + 1}`,
11
+ divider: num === 3,
12
+ }))
13
+
14
+ const OPTIONS = {first: 'first', last: 'last'}
15
+
16
+ export default function ShouldFocusStory() {
17
+ const shouldFocus = useSelect('Should focus', OPTIONS, 'first')
18
+
19
+ const [popoverOpen, setPopoverOpen] = useState<boolean>(false)
20
+ const handleToggleOpen = useCallback(() => setPopoverOpen((v) => !v), [])
21
+
22
+ return (
23
+ <LayerProvider>
24
+ <Flex align="center" justify="center" padding={4}>
25
+ <Popover
26
+ content={
27
+ <Menu shouldFocus={shouldFocus}>
28
+ {ITEMS.map((item) => {
29
+ return (
30
+ <Fragment key={item.title}>
31
+ <MenuItem text={item.title} />
32
+ {item.divider && <MenuDivider />}
33
+ </Fragment>
34
+ )
35
+ })}
36
+ </Menu>
37
+ }
38
+ open={popoverOpen}
39
+ portal
40
+ >
41
+ <Button text="Open menu" onClick={handleToggleOpen} />
42
+ </Popover>
43
+ </Flex>
44
+ </LayerProvider>
45
+ )
46
+ }
@@ -23,12 +23,12 @@ describe('components/menu', () => {
23
23
  function Root() {
24
24
  const handleItemMouseEnter = useCallback(
25
25
  (event: React.MouseEvent<HTMLElement>) => console.log(event),
26
- []
26
+ [],
27
27
  )
28
28
 
29
29
  const handleItemMouseLeave = useCallback(
30
30
  (event: React.MouseEvent<HTMLElement>) => console.log(event),
31
- []
31
+ [],
32
32
  )
33
33
 
34
34
  const value: MenuContextValue = useMemo(
@@ -43,7 +43,7 @@ describe('components/menu', () => {
43
43
  onMouseEnter: handleItemMouseEnter,
44
44
  onMouseLeave: handleItemMouseLeave,
45
45
  }),
46
- [handleItemMouseEnter, handleItemMouseLeave]
46
+ [handleItemMouseEnter, handleItemMouseLeave],
47
47
  )
48
48
 
49
49
  return (