@react-spectrum/s2 0.10.0 → 0.11.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 (296) hide show
  1. package/dist/Accordion.cjs +2 -2
  2. package/dist/Accordion.css +2 -2
  3. package/dist/Accordion.mjs +2 -2
  4. package/dist/ActionBar.cjs +62 -62
  5. package/dist/ActionBar.css +61 -61
  6. package/dist/ActionBar.mjs +62 -62
  7. package/dist/ActionButton.cjs +202 -202
  8. package/dist/ActionButton.css +138 -138
  9. package/dist/ActionButton.mjs +202 -202
  10. package/dist/ActionButtonGroup.cjs +15 -15
  11. package/dist/ActionButtonGroup.css +9 -9
  12. package/dist/ActionButtonGroup.mjs +15 -15
  13. package/dist/Add.cjs +10 -10
  14. package/dist/Add.css +6 -6
  15. package/dist/Add.mjs +10 -10
  16. package/dist/AlertDialog.cjs +3 -3
  17. package/dist/AlertDialog.css +3 -3
  18. package/dist/AlertDialog.mjs +3 -3
  19. package/dist/Asterisk.cjs +6 -6
  20. package/dist/Asterisk.css +4 -4
  21. package/dist/Asterisk.mjs +6 -6
  22. package/dist/Avatar.cjs +14 -14
  23. package/dist/Avatar.css +14 -14
  24. package/dist/Avatar.mjs +14 -14
  25. package/dist/AvatarGroup.cjs +134 -134
  26. package/dist/AvatarGroup.css +33 -33
  27. package/dist/AvatarGroup.mjs +134 -134
  28. package/dist/Badge.cjs +206 -206
  29. package/dist/Badge.css +127 -127
  30. package/dist/Badge.mjs +206 -206
  31. package/dist/Breadcrumbs.cjs +254 -254
  32. package/dist/Breadcrumbs.css +109 -109
  33. package/dist/Breadcrumbs.mjs +254 -254
  34. package/dist/Button.cjs +341 -341
  35. package/dist/Button.css +177 -177
  36. package/dist/Button.mjs +341 -341
  37. package/dist/ButtonGroup.cjs +20 -20
  38. package/dist/ButtonGroup.css +15 -15
  39. package/dist/ButtonGroup.mjs +20 -20
  40. package/dist/Calendar.cjs +151 -139
  41. package/dist/Calendar.cjs.map +1 -1
  42. package/dist/Calendar.css +134 -134
  43. package/dist/Calendar.css.map +1 -1
  44. package/dist/Calendar.mjs +153 -141
  45. package/dist/Calendar.mjs.map +1 -1
  46. package/dist/Card.cjs +304 -304
  47. package/dist/Card.css +209 -209
  48. package/dist/Card.mjs +304 -304
  49. package/dist/CardView.cjs +16 -16
  50. package/dist/CardView.css +16 -16
  51. package/dist/CardView.mjs +16 -16
  52. package/dist/CenterBaseline.cjs +1 -1
  53. package/dist/CenterBaseline.css +2 -2
  54. package/dist/CenterBaseline.mjs +1 -1
  55. package/dist/Checkbox.cjs +170 -170
  56. package/dist/Checkbox.css +92 -92
  57. package/dist/Checkbox.mjs +170 -170
  58. package/dist/CheckboxGroup.cjs +45 -45
  59. package/dist/CheckboxGroup.css +38 -38
  60. package/dist/CheckboxGroup.mjs +45 -45
  61. package/dist/Checkmark.cjs +12 -12
  62. package/dist/Checkmark.css +8 -8
  63. package/dist/Checkmark.mjs +12 -12
  64. package/dist/Chevron.cjs +12 -12
  65. package/dist/Chevron.css +10 -10
  66. package/dist/Chevron.mjs +12 -12
  67. package/dist/ClearButton.cjs +29 -29
  68. package/dist/ClearButton.css +29 -29
  69. package/dist/ClearButton.mjs +29 -29
  70. package/dist/CloseButton.cjs +54 -54
  71. package/dist/CloseButton.css +46 -46
  72. package/dist/CloseButton.mjs +54 -54
  73. package/dist/ColorArea.cjs +16 -16
  74. package/dist/ColorArea.css +16 -16
  75. package/dist/ColorArea.mjs +16 -16
  76. package/dist/ColorField.cjs +32 -32
  77. package/dist/ColorField.css +28 -28
  78. package/dist/ColorField.mjs +32 -32
  79. package/dist/ColorHandle.cjs +27 -27
  80. package/dist/ColorHandle.css +42 -42
  81. package/dist/ColorHandle.mjs +27 -27
  82. package/dist/ColorSlider.cjs +118 -118
  83. package/dist/ColorSlider.css +54 -54
  84. package/dist/ColorSlider.mjs +118 -118
  85. package/dist/ColorSwatch.cjs +29 -29
  86. package/dist/ColorSwatch.css +29 -29
  87. package/dist/ColorSwatch.mjs +29 -29
  88. package/dist/ColorSwatchPicker.cjs +27 -27
  89. package/dist/ColorSwatchPicker.css +46 -46
  90. package/dist/ColorSwatchPicker.mjs +27 -27
  91. package/dist/ColorWheel.cjs +26 -26
  92. package/dist/ColorWheel.css +17 -17
  93. package/dist/ColorWheel.mjs +26 -26
  94. package/dist/ComboBox.cjs +415 -400
  95. package/dist/ComboBox.cjs.map +1 -1
  96. package/dist/ComboBox.css +181 -181
  97. package/dist/ComboBox.css.map +1 -1
  98. package/dist/ComboBox.mjs +415 -400
  99. package/dist/ComboBox.mjs.map +1 -1
  100. package/dist/ContextualHelp.cjs +5 -5
  101. package/dist/ContextualHelp.css +60 -60
  102. package/dist/ContextualHelp.mjs +5 -5
  103. package/dist/Cross.cjs +14 -14
  104. package/dist/Cross.css +10 -10
  105. package/dist/Cross.mjs +14 -14
  106. package/dist/CustomDialog.cjs +25 -25
  107. package/dist/CustomDialog.css +25 -25
  108. package/dist/CustomDialog.mjs +25 -25
  109. package/dist/Dash.cjs +10 -10
  110. package/dist/Dash.css +6 -6
  111. package/dist/Dash.mjs +10 -10
  112. package/dist/DateField.cjs +73 -73
  113. package/dist/DateField.css +77 -77
  114. package/dist/DateField.mjs +73 -73
  115. package/dist/DatePicker.cjs +182 -185
  116. package/dist/DatePicker.cjs.map +1 -1
  117. package/dist/DatePicker.css +126 -126
  118. package/dist/DatePicker.css.map +1 -1
  119. package/dist/DatePicker.mjs +182 -185
  120. package/dist/DatePicker.mjs.map +1 -1
  121. package/dist/DateRangePicker.cjs +58 -61
  122. package/dist/DateRangePicker.cjs.map +1 -1
  123. package/dist/DateRangePicker.css +60 -60
  124. package/dist/DateRangePicker.css.map +1 -1
  125. package/dist/DateRangePicker.mjs +58 -61
  126. package/dist/DateRangePicker.mjs.map +1 -1
  127. package/dist/Dialog.cjs +17 -17
  128. package/dist/Dialog.css +82 -82
  129. package/dist/Dialog.mjs +17 -17
  130. package/dist/Disclosure.cjs +135 -135
  131. package/dist/Disclosure.css +106 -106
  132. package/dist/Disclosure.mjs +135 -135
  133. package/dist/Divider.cjs +25 -25
  134. package/dist/Divider.css +25 -25
  135. package/dist/Divider.mjs +25 -25
  136. package/dist/DropZone.cjs +62 -62
  137. package/dist/DropZone.css +58 -58
  138. package/dist/DropZone.mjs +62 -62
  139. package/dist/Field.cjs +370 -370
  140. package/dist/Field.cjs.map +1 -1
  141. package/dist/Field.css +142 -142
  142. package/dist/Field.mjs +370 -370
  143. package/dist/Field.mjs.map +1 -1
  144. package/dist/Form.cjs +9 -9
  145. package/dist/Form.css +9 -9
  146. package/dist/Form.mjs +9 -9
  147. package/dist/FullscreenDialog.cjs +5 -5
  148. package/dist/FullscreenDialog.css +91 -91
  149. package/dist/FullscreenDialog.mjs +5 -5
  150. package/dist/IllustratedMessage.cjs +256 -256
  151. package/dist/IllustratedMessage.css +78 -78
  152. package/dist/IllustratedMessage.mjs +256 -256
  153. package/dist/Image.cjs +13 -13
  154. package/dist/Image.css +14 -14
  155. package/dist/Image.mjs +13 -13
  156. package/dist/InlineAlert.cjs +117 -117
  157. package/dist/InlineAlert.css +98 -98
  158. package/dist/InlineAlert.mjs +117 -117
  159. package/dist/Link.cjs +54 -54
  160. package/dist/Link.css +46 -46
  161. package/dist/Link.mjs +54 -54
  162. package/dist/LinkOut.cjs +8 -8
  163. package/dist/LinkOut.css +8 -8
  164. package/dist/LinkOut.mjs +8 -8
  165. package/dist/Menu.cjs +459 -459
  166. package/dist/Menu.css +185 -185
  167. package/dist/Menu.mjs +459 -459
  168. package/dist/Meter.cjs +163 -163
  169. package/dist/Meter.css +93 -93
  170. package/dist/Meter.mjs +163 -163
  171. package/dist/Modal.cjs +58 -58
  172. package/dist/Modal.css +50 -50
  173. package/dist/Modal.mjs +58 -58
  174. package/dist/NotificationBadge.cjs +58 -58
  175. package/dist/NotificationBadge.css +51 -51
  176. package/dist/NotificationBadge.mjs +58 -58
  177. package/dist/NumberField.cjs +115 -115
  178. package/dist/NumberField.css +100 -100
  179. package/dist/NumberField.mjs +115 -115
  180. package/dist/Picker.cjs +283 -283
  181. package/dist/Picker.css +169 -169
  182. package/dist/Picker.mjs +283 -283
  183. package/dist/Popover.cjs +86 -86
  184. package/dist/Popover.css +66 -66
  185. package/dist/Popover.mjs +86 -86
  186. package/dist/ProgressBar.cjs +173 -173
  187. package/dist/ProgressBar.css +101 -101
  188. package/dist/ProgressBar.mjs +173 -173
  189. package/dist/ProgressCircle.cjs +31 -31
  190. package/dist/ProgressCircle.css +24 -24
  191. package/dist/ProgressCircle.mjs +31 -31
  192. package/dist/Provider.cjs +11 -11
  193. package/dist/Provider.css +10 -10
  194. package/dist/Provider.mjs +11 -11
  195. package/dist/Radio.cjs +154 -154
  196. package/dist/Radio.css +79 -79
  197. package/dist/Radio.mjs +154 -154
  198. package/dist/RadioGroup.cjs +42 -42
  199. package/dist/RadioGroup.css +38 -38
  200. package/dist/RadioGroup.mjs +42 -42
  201. package/dist/RangeCalendar.cjs +32 -20
  202. package/dist/RangeCalendar.cjs.map +1 -1
  203. package/dist/RangeCalendar.css +10 -10
  204. package/dist/RangeCalendar.css.map +1 -1
  205. package/dist/RangeCalendar.mjs +34 -22
  206. package/dist/RangeCalendar.mjs.map +1 -1
  207. package/dist/SearchField.cjs +42 -42
  208. package/dist/SearchField.css +46 -46
  209. package/dist/SearchField.mjs +42 -42
  210. package/dist/SegmentedControl.cjs +181 -181
  211. package/dist/SegmentedControl.css +118 -118
  212. package/dist/SegmentedControl.mjs +181 -181
  213. package/dist/SelectBoxGroup.cjs +342 -0
  214. package/dist/SelectBoxGroup.cjs.map +1 -0
  215. package/dist/SelectBoxGroup.css +503 -0
  216. package/dist/SelectBoxGroup.css.map +1 -0
  217. package/dist/SelectBoxGroup.mjs +335 -0
  218. package/dist/SelectBoxGroup.mjs.map +1 -0
  219. package/dist/SkeletonCollection.cjs +6 -1
  220. package/dist/SkeletonCollection.cjs.map +1 -1
  221. package/dist/SkeletonCollection.mjs +7 -2
  222. package/dist/SkeletonCollection.mjs.map +1 -1
  223. package/dist/Slider.cjs +299 -299
  224. package/dist/Slider.css +151 -151
  225. package/dist/Slider.mjs +299 -299
  226. package/dist/StatusLight.cjs +125 -125
  227. package/dist/StatusLight.css +61 -61
  228. package/dist/StatusLight.mjs +125 -125
  229. package/dist/Switch.cjs +162 -162
  230. package/dist/Switch.css +74 -74
  231. package/dist/Switch.mjs +162 -162
  232. package/dist/TableView.cjs +319 -319
  233. package/dist/TableView.css +172 -172
  234. package/dist/TableView.mjs +319 -319
  235. package/dist/Tabs.cjs +213 -188
  236. package/dist/Tabs.cjs.map +1 -1
  237. package/dist/Tabs.css +105 -101
  238. package/dist/Tabs.css.map +1 -1
  239. package/dist/Tabs.mjs +213 -188
  240. package/dist/Tabs.mjs.map +1 -1
  241. package/dist/TabsPicker.cjs +127 -127
  242. package/dist/TabsPicker.css +111 -111
  243. package/dist/TabsPicker.mjs +127 -127
  244. package/dist/TagGroup.cjs +213 -213
  245. package/dist/TagGroup.css +147 -147
  246. package/dist/TagGroup.mjs +213 -213
  247. package/dist/TextField.cjs +59 -59
  248. package/dist/TextField.css +54 -54
  249. package/dist/TextField.mjs +59 -59
  250. package/dist/TimeField.cjs +52 -52
  251. package/dist/TimeField.css +48 -48
  252. package/dist/TimeField.mjs +52 -52
  253. package/dist/Toast.cjs +120 -120
  254. package/dist/Toast.css +107 -107
  255. package/dist/Toast.mjs +120 -120
  256. package/dist/ToggleButton.cjs +3 -3
  257. package/dist/ToggleButton.css +12 -12
  258. package/dist/ToggleButton.mjs +3 -3
  259. package/dist/Tooltip.cjs +83 -83
  260. package/dist/Tooltip.css +70 -70
  261. package/dist/Tooltip.mjs +83 -83
  262. package/dist/TreeView.cjs +146 -146
  263. package/dist/TreeView.css +147 -147
  264. package/dist/TreeView.mjs +146 -146
  265. package/dist/main.cjs +5 -0
  266. package/dist/main.cjs.map +1 -1
  267. package/dist/module.mjs +3 -1
  268. package/dist/module.mjs.map +1 -1
  269. package/dist/types.d.ts +43 -1
  270. package/dist/types.d.ts.map +1 -1
  271. package/icons/Icon.cjs +10 -10
  272. package/icons/Icon.css +9 -9
  273. package/icons/Icon.mjs +10 -10
  274. package/icons/Skeleton.cjs +2 -2
  275. package/icons/Skeleton.cjs.map +1 -1
  276. package/icons/Skeleton.css +6 -6
  277. package/icons/Skeleton.mjs +2 -2
  278. package/icons/Skeleton.mjs.map +1 -1
  279. package/package.json +21 -21
  280. package/src/Calendar.tsx +13 -6
  281. package/src/ComboBox.tsx +20 -5
  282. package/src/DatePicker.tsx +1 -7
  283. package/src/DateRangePicker.tsx +1 -7
  284. package/src/RangeCalendar.tsx +13 -6
  285. package/src/SelectBoxGroup.tsx +408 -0
  286. package/src/SkeletonCollection.tsx +6 -2
  287. package/src/Tabs.tsx +49 -24
  288. package/src/index.ts +2 -0
  289. package/style/__tests__/style-macro.test.js +162 -166
  290. package/style/dist/main.cjs +24 -24
  291. package/style/dist/module.mjs +13 -13
  292. package/style/dist/properties.mjs +3 -3
  293. package/style/dist/spectrum-theme.cjs +219 -219
  294. package/style/dist/spectrum-theme.mjs +210 -210
  295. package/style/dist/style-macro.cjs +80 -80
  296. package/style/dist/style-macro.mjs +75 -75
@@ -0,0 +1,408 @@
1
+ /*
2
+ * Copyright 2025 Adobe. All rights reserved.
3
+ * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4
+ * you may not use this file except in compliance with the License. You may obtain a copy
5
+ * of the License at http://www.apache.org/licenses/LICENSE-2.0
6
+ *
7
+ * Unless required by applicable law or agreed to in writing, software distributed under
8
+ * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language
9
+ * governing permissions and limitations under the License.
10
+ */
11
+
12
+ import {baseColor, focusRing, style} from '../style' with {type: 'macro'};
13
+ import {box, iconStyles} from './Checkbox';
14
+ import Checkmark from '../ui-icons/Checkmark';
15
+ import {
16
+ ContextValue,
17
+ DEFAULT_SLOT,
18
+ ListBox,
19
+ ListBoxItem,
20
+ ListBoxProps,
21
+ Provider
22
+ } from 'react-aria-components';
23
+ import {DOMRef, DOMRefValue, GlobalDOMAttributes, Key, Orientation} from '@react-types/shared';
24
+ import {getAllowedOverrides, StyleProps} from './style-utils' with {type: 'macro'};
25
+ import {IllustrationContext} from '../src/Icon';
26
+ import {pressScale} from './pressScale';
27
+ import React, {createContext, forwardRef, ReactNode, useContext, useMemo, useRef} from 'react';
28
+ import {TextContext} from './Content';
29
+ import {useSpectrumContextProps} from './useSpectrumContextProps';
30
+
31
+ export interface SelectBoxGroupProps<T> extends StyleProps, Omit<ListBoxProps<T>, keyof GlobalDOMAttributes | 'layout' | 'dragAndDropHooks' | 'dependencies' | 'renderEmptyState' | 'children' | 'onAction' | 'shouldFocusOnHover' | 'selectionBehavior' | 'shouldSelectOnPressUp' | 'shouldFocusWrap' | 'style' | 'className'> {
32
+ /**
33
+ * The SelectBox elements contained within the SelectBoxGroup.
34
+ */
35
+ children: ReactNode,
36
+ /**
37
+ * The layout direction of the content in each SelectBox.
38
+ * @default 'vertical'
39
+ */
40
+ orientation?: Orientation,
41
+ /**
42
+ * The selection mode for the SelectBoxGroup.
43
+ * @default 'single'
44
+ */
45
+ selectionMode?: 'single' | 'multiple',
46
+ /**
47
+ * Whether the SelectBoxGroup is disabled.
48
+ */
49
+ isDisabled?: boolean
50
+ }
51
+
52
+ export interface SelectBoxProps extends StyleProps {
53
+ /** The unique id of the SelectBox. */
54
+ id?: Key,
55
+ /** A string representation of the SelectBox's contents, used for features like typeahead. */
56
+ textValue?: string,
57
+ /** An accessibility label for this item. */
58
+ 'aria-label'?: string,
59
+ /**
60
+ * The contents of the SelectBox.
61
+ */
62
+ children: ReactNode,
63
+ /**
64
+ * Whether the SelectBox is disabled.
65
+ */
66
+ isDisabled?: boolean
67
+ }
68
+
69
+ interface SelectBoxContextValue {
70
+ allowMultiSelect?: boolean,
71
+ orientation?: Orientation,
72
+ isDisabled?: boolean
73
+ }
74
+
75
+ const SelectBoxContext = createContext<SelectBoxContextValue>({orientation: 'vertical'});
76
+ export const SelectBoxGroupContext = createContext<ContextValue<Partial<SelectBoxGroupProps<any>>, DOMRefValue<HTMLDivElement>>>(null);
77
+
78
+ const labelOnly = ':has([slot=label]):not(:has([slot=description]))';
79
+ const noIllustration = ':not(:has([slot=illustration]))';
80
+ const selectBoxStyles = style({
81
+ ...focusRing(),
82
+ display: 'grid',
83
+ gridAutoRows: '1fr',
84
+ position: 'relative',
85
+ font: 'ui',
86
+ cursor: 'default',
87
+ boxSizing: 'border-box',
88
+ overflow: 'hidden',
89
+ width: {
90
+ default: 170,
91
+ orientation: {
92
+ horizontal: 368
93
+ }
94
+ },
95
+ height: {
96
+ default: 170,
97
+ orientation: {
98
+ horizontal: 'auto'
99
+ }
100
+ },
101
+ minWidth: {
102
+ default: 144,
103
+ orientation: {
104
+ horizontal: 188
105
+ }
106
+ },
107
+ maxWidth: {
108
+ default: 170,
109
+ orientation: {
110
+ horizontal: 480
111
+ }
112
+ },
113
+ minHeight: {
114
+ default: 144,
115
+ orientation: {
116
+ horizontal: 80
117
+ }
118
+ },
119
+ maxHeight: {
120
+ default: 170,
121
+ orientation: {
122
+ horizontal: 240
123
+ }
124
+ },
125
+ padding: {
126
+ default: 24,
127
+ orientation: {
128
+ horizontal: 16
129
+ }
130
+ },
131
+ paddingStart: {
132
+ orientation: {
133
+ horizontal: 32
134
+ }
135
+ },
136
+ paddingEnd: {
137
+ orientation: {
138
+ horizontal: 24
139
+ }
140
+ },
141
+ gridTemplateAreas: {
142
+ orientation: {
143
+ vertical: [
144
+ 'illustration',
145
+ '.',
146
+ 'label'
147
+ ],
148
+ horizontal: {
149
+ default: [
150
+ 'illustration . label',
151
+ 'illustration . description'
152
+ ],
153
+ [labelOnly]: [
154
+ 'illustration . label'
155
+ ]
156
+ }
157
+ }
158
+ },
159
+ gridTemplateRows: {
160
+ orientation: {
161
+ vertical: ['min-content', 8, 'min-content'],
162
+ horizontal: {
163
+ default: ['min-content', 2, 'min-content'],
164
+ [noIllustration]: ['min-content']
165
+ }
166
+ }
167
+ },
168
+ gridTemplateColumns: {
169
+ orientation: {
170
+ horizontal: 'min-content 10px 1fr'
171
+ }
172
+ },
173
+ alignContent: {
174
+ orientation: {
175
+ vertical: 'center'
176
+ }
177
+ },
178
+ borderRadius: 'lg',
179
+ borderStyle: 'solid',
180
+ borderColor: {
181
+ default: 'transparent',
182
+ isSelected: 'gray-900',
183
+ isDisabled: 'transparent'
184
+ },
185
+ backgroundColor: {
186
+ default: 'layer-2',
187
+ isDisabled: 'disabled'
188
+ },
189
+ color: {
190
+ isDisabled: 'disabled'
191
+ },
192
+ boxShadow: {
193
+ default: 'emphasized',
194
+ isHovered: 'elevated',
195
+ isSelected: 'elevated',
196
+ isDisabled: 'none'
197
+ },
198
+ borderWidth: 2,
199
+ transition: 'default'
200
+ }, getAllowedOverrides());
201
+
202
+ const illustrationContainer = style({
203
+ gridArea: 'illustration',
204
+ alignSelf: 'center',
205
+ justifySelf: 'center',
206
+ minSize: 48,
207
+ '--iconPrimary': {
208
+ type: 'color',
209
+ value: {
210
+ default: baseColor('neutral'),
211
+ isDisabled: 'disabled'
212
+ }
213
+ }
214
+ });
215
+
216
+ const descriptionText = style({
217
+ gridArea: 'description',
218
+ alignSelf: 'center',
219
+ display: {
220
+ default: 'block',
221
+ orientation: {
222
+ vertical: 'none'
223
+ }
224
+ },
225
+ overflow: 'hidden',
226
+ textAlign: {
227
+ default: 'center',
228
+ orientation: {
229
+ horizontal: 'start'
230
+ }
231
+ },
232
+ color: {
233
+ default: baseColor('neutral'),
234
+ isDisabled: 'disabled'
235
+ }
236
+ });
237
+
238
+ const labelText = style({
239
+ gridArea: 'label',
240
+ alignSelf: 'center',
241
+ justifySelf: {
242
+ default: 'center',
243
+ orientation: {
244
+ horizontal: 'start'
245
+ }
246
+ },
247
+ width: '100%',
248
+ overflow: 'hidden',
249
+ minWidth: 0,
250
+ textAlign: {
251
+ default: 'center',
252
+ orientation: {
253
+ horizontal: 'start'
254
+ }
255
+ },
256
+ whiteSpace: 'nowrap',
257
+ textOverflow: 'ellipsis',
258
+ fontWeight: {
259
+ orientation: {
260
+ horizontal: 'bold'
261
+ }
262
+ },
263
+ color: {
264
+ default: baseColor('neutral'),
265
+ isDisabled: 'disabled'
266
+ }
267
+ });
268
+
269
+ const gridStyles = style<{orientation?: Orientation}>({
270
+ display: 'grid',
271
+ gridAutoRows: '1fr',
272
+ gap: 24,
273
+ justifyContent: 'center',
274
+ '--size': {
275
+ type: 'width',
276
+ value: {
277
+ orientation: {
278
+ horizontal: 368,
279
+ vertical: 170
280
+ }
281
+ }
282
+ },
283
+ gridTemplateColumns: {
284
+ orientation: {
285
+ horizontal: 'repeat(auto-fit, var(--size))',
286
+ vertical: 'repeat(auto-fit, var(--size))'
287
+ }
288
+ }
289
+ }, getAllowedOverrides());
290
+
291
+ /**
292
+ * SelectBox is a single selectable item in a SelectBoxGroup.
293
+ */
294
+ export function SelectBox(props: SelectBoxProps): ReactNode {
295
+ let {children, isDisabled: individualDisabled = false, UNSAFE_style, UNSAFE_className, styles, ...otherProps} = props;
296
+
297
+ let {
298
+ orientation = 'vertical',
299
+ isDisabled: groupDisabled = false
300
+ } = useContext(SelectBoxContext);
301
+
302
+ const isDisabled = individualDisabled || groupDisabled;
303
+ const ref = useRef<HTMLDivElement>(null);
304
+
305
+ return (
306
+ <ListBoxItem
307
+ isDisabled={isDisabled}
308
+ ref={ref}
309
+ className={renderProps => (UNSAFE_className || '') + selectBoxStyles({
310
+ ...renderProps,
311
+ orientation
312
+ }, styles)}
313
+ style={pressScale(ref, UNSAFE_style)}
314
+ {...otherProps}>
315
+ {({isSelected, isDisabled, isHovered}) => {
316
+ return (
317
+ <>
318
+ <div
319
+ className={style({
320
+ position: 'absolute',
321
+ top: 8,
322
+ insetStart: 8,
323
+ pointerEvents: 'none'
324
+ })}
325
+ aria-hidden="true">
326
+ {!isDisabled && (
327
+ <div
328
+ className={box({
329
+ isSelected,
330
+ isDisabled,
331
+ size: 'M'
332
+ } as any)}>
333
+ <Checkmark
334
+ size="S"
335
+ className={iconStyles} />
336
+ </div>
337
+ )}
338
+ </div>
339
+ <Provider
340
+ values={[
341
+ [IllustrationContext, {
342
+ size: 'S',
343
+ styles: illustrationContainer({size: 'S', orientation, isDisabled, isHovered})
344
+ }],
345
+ [TextContext, {
346
+ slots: {
347
+ [DEFAULT_SLOT]: {
348
+ styles: labelText({orientation, isDisabled, isHovered})
349
+ },
350
+ label: {
351
+ styles: labelText({orientation, isDisabled, isHovered})
352
+ },
353
+ description: {
354
+ styles: descriptionText({orientation, isDisabled, isHovered})
355
+ }
356
+ }
357
+ }]
358
+ ]}>
359
+ {children}
360
+ </Provider>
361
+ </>
362
+ );
363
+ }}
364
+ </ListBoxItem>
365
+ );
366
+ }
367
+
368
+ /*
369
+ * SelectBoxGroup allows users to select one or more options from a list.
370
+ */
371
+ export const SelectBoxGroup = /*#__PURE__*/ forwardRef(function SelectBoxGroup<T extends object>(props: SelectBoxGroupProps<T>, ref: DOMRef<HTMLDivElement>) {
372
+ [props, ref] = useSpectrumContextProps(props, ref, SelectBoxGroupContext);
373
+
374
+ let {
375
+ children,
376
+ selectionMode = 'single',
377
+ orientation = 'vertical',
378
+ isDisabled = false,
379
+ UNSAFE_className,
380
+ UNSAFE_style,
381
+ styles,
382
+ ...otherProps
383
+ } = props;
384
+
385
+ const selectBoxContextValue = useMemo(
386
+ () => {
387
+ const contextValue = {
388
+ orientation,
389
+ isDisabled
390
+ };
391
+ return contextValue;
392
+ },
393
+ [orientation, isDisabled]
394
+ );
395
+
396
+ return (
397
+ <ListBox
398
+ selectionMode={selectionMode}
399
+ layout="grid"
400
+ className={(UNSAFE_className || '') + gridStyles({orientation}, styles)}
401
+ style={UNSAFE_style}
402
+ {...otherProps}>
403
+ <SelectBoxContext.Provider value={selectBoxContextValue}>
404
+ {children}
405
+ </SelectBoxContext.Provider>
406
+ </ListBox>
407
+ );
408
+ });
@@ -10,7 +10,7 @@
10
10
  * governing permissions and limitations under the License.
11
11
  */
12
12
 
13
- import {createLeafComponent} from '@react-aria/collections';
13
+ import {CollectionNode, createLeafComponent} from '@react-aria/collections';
14
14
  import {ReactNode} from 'react';
15
15
  import {Skeleton} from './Skeleton';
16
16
 
@@ -20,10 +20,14 @@ export interface SkeletonCollectionProps {
20
20
 
21
21
  let cache = new WeakMap();
22
22
 
23
+ class SkeletonNode extends CollectionNode<unknown> {
24
+ static readonly type = 'skeleton';
25
+ }
26
+
23
27
  /**
24
28
  * A SkeletonCollection generates placeholder content within a collection component such as CardView.
25
29
  */
26
- export const SkeletonCollection = createLeafComponent('skeleton', (props: SkeletonCollectionProps, ref, node) => {
30
+ export const SkeletonCollection = createLeafComponent(SkeletonNode, (props: SkeletonCollectionProps, ref, node) => {
27
31
  // Cache rendering based on node object identity. This allows the children function to randomize
28
32
  // its content (e.g. heights) and preserve on re-renders.
29
33
  // TODO: do we need a `dependencies` prop here?
package/src/Tabs.tsx CHANGED
@@ -82,10 +82,23 @@ const InternalTabsContext = createContext<Partial<TabsProps> & {
82
82
  prevRef?: RefObject<DOMRect | null>,
83
83
  selectedKey?: Key | null
84
84
  }>({});
85
- const CollapseContext = createContext({
85
+
86
+ interface CollapseContextType {
87
+ showTabs: boolean,
88
+ menuId: string,
89
+ valueId: string,
90
+ ariaLabel?: string | undefined,
91
+ ariaDescribedBy?: string | undefined,
92
+ tabs: Array<Node<any>>,
93
+ listRef?: RefObject<HTMLDivElement | null>,
94
+ onSelectionChange?: (key: Key) => void
95
+ }
96
+
97
+ const CollapseContext = createContext<CollapseContextType>({
86
98
  showTabs: true,
87
99
  menuId: '',
88
- valueId: ''
100
+ valueId: '',
101
+ tabs: []
89
102
  });
90
103
 
91
104
  const tabs = style({
@@ -198,35 +211,57 @@ const tablist = style({
198
211
  minWidth: 'min'
199
212
  });
200
213
 
214
+ const tablistWrapper = style({
215
+ position: 'relative',
216
+ minWidth: 0,
217
+ flexShrink: 0,
218
+ flexGrow: 0
219
+ }, getAllowedOverrides());
220
+
201
221
  export function TabList<T extends object>(props: TabListProps<T>): ReactNode | null {
202
- let {showTabs} = useContext(CollapseContext) ?? {};
222
+ let {showTabs, menuId, valueId, tabs, listRef, onSelectionChange, ariaLabel, ariaDescribedBy} = useContext(CollapseContext) ?? {};
223
+ let {density, orientation, labelBehavior} = useContext(InternalTabsContext);
203
224
 
204
225
  if (showTabs) {
205
226
  return <TabListInner {...props} />;
206
227
  }
207
- return null;
228
+
229
+ return (
230
+ <div className={tablistWrapper(null, props.styles)}>
231
+ {listRef && <div className={tablist({orientation, labelBehavior, density})}>
232
+ <HiddenTabs items={tabs} density={density} listRef={listRef} />
233
+ </div>}
234
+ <TabsMenu
235
+ id={menuId}
236
+ valueId={valueId}
237
+ items={tabs}
238
+ onSelectionChange={onSelectionChange}
239
+ aria-label={ariaLabel}
240
+ aria-describedby={ariaDescribedBy} />
241
+ </div>
242
+ );
208
243
  }
209
244
 
210
245
  function TabListInner<T extends object>(props: TabListProps<T>) {
211
246
  let {
212
247
  tablistRef,
248
+ orientation,
213
249
  density,
214
250
  labelBehavior,
215
251
  'aria-label': ariaLabel,
216
252
  'aria-labelledby': ariaLabelledBy
217
253
  } = useContext(InternalTabsContext) ?? {};
254
+ let {tabs, listRef} = useContext(CollapseContext) ?? {};
218
255
 
219
256
  return (
220
257
  <div
221
258
  style={props.UNSAFE_style}
222
259
  className={
223
260
  (props.UNSAFE_className || '') +
224
- style({
225
- position: 'relative',
226
- flexGrow: 0,
227
- flexShrink: 0,
228
- minWidth: 'min'
229
- }, getAllowedOverrides())(null, props.styles)}>
261
+ tablistWrapper(null, props.styles)}>
262
+ {listRef && <div className={tablist({orientation, labelBehavior, density})}>
263
+ <HiddenTabs items={tabs} density={density} listRef={listRef} />
264
+ </div>}
230
265
  <RACTabList
231
266
  {...props}
232
267
  aria-label={ariaLabel}
@@ -519,7 +554,7 @@ let HiddenTabs = function (props: {
519
554
  size?: string,
520
555
  density?: 'compact' | 'regular'
521
556
  }) {
522
- let {listRef, items, size, density} = props;
557
+ let {listRef, items = [], size, density} = props;
523
558
 
524
559
  return (
525
560
  <div
@@ -612,7 +647,7 @@ let TabsMenu = (props: {valueId: string, items: Array<Node<any>>, onSelectionCha
612
647
  };
613
648
 
614
649
  let CollapsingTabs = ({collection, containerRef, ...props}: {collection: Collection<Node<unknown>>, containerRef: any} & TabsProps) => {
615
- let {density = 'regular', orientation = 'horizontal', labelBehavior = 'show', onSelectionChange} = props;
650
+ let {orientation = 'horizontal', onSelectionChange} = props;
616
651
  let [showItems, _setShowItems] = useState(true);
617
652
  showItems = orientation === 'vertical' ? true : showItems;
618
653
  let setShowItems = useCallback((value: boolean) => {
@@ -683,14 +718,7 @@ let CollapsingTabs = ({collection, containerRef, ...props}: {collection: Collect
683
718
  } else {
684
719
  contents = (
685
720
  <>
686
- <TabsMenu
687
- id={menuId}
688
- valueId={valueId}
689
- items={children}
690
- onSelectionChange={onSelectionChange}
691
- aria-label={props['aria-label']}
692
- aria-describedby={props['aria-labelledby']} />
693
- <CollapseContext.Provider value={{showTabs: false, menuId, valueId}}>
721
+ <CollapseContext.Provider value={{showTabs: false, tabs: children, menuId, valueId, listRef: listRef, onSelectionChange, ariaLabel: props['aria-label'], ariaDescribedBy: props['aria-labelledby']}}>
694
722
  {props.children}
695
723
  </CollapseContext.Provider>
696
724
  </>
@@ -699,10 +727,7 @@ let CollapsingTabs = ({collection, containerRef, ...props}: {collection: Collect
699
727
 
700
728
  return (
701
729
  <div style={props.UNSAFE_style} className={(props.UNSAFE_className || '') + tabs({orientation}, props.styles)} ref={containerRef}>
702
- <div className={tablist({orientation, labelBehavior, density})}>
703
- <HiddenTabs items={children} density={density} listRef={listRef} />
704
- </div>
705
- <CollapseContext.Provider value={{showTabs: true, menuId, valueId}}>
730
+ <CollapseContext.Provider value={{showTabs: true, menuId, valueId, tabs: children, listRef: listRef}}>
706
731
  {contents}
707
732
  </CollapseContext.Provider>
708
733
  </div>
package/src/index.ts CHANGED
@@ -72,6 +72,7 @@ export {RangeCalendar, RangeCalendarContext} from './RangeCalendar';
72
72
  export {RangeSlider, RangeSliderContext} from './RangeSlider';
73
73
  export {SearchField, SearchFieldContext} from './SearchField';
74
74
  export {SegmentedControl, SegmentedControlItem, SegmentedControlContext} from './SegmentedControl';
75
+ export {SelectBox, SelectBoxGroup, SelectBoxGroupContext} from './SelectBoxGroup';
75
76
  export {Slider, SliderContext} from './Slider';
76
77
  export {Skeleton, useIsSkeleton} from './Skeleton';
77
78
  export {SkeletonCollection} from './SkeletonCollection';
@@ -148,6 +149,7 @@ export type {RadioProps} from './Radio';
148
149
  export type {RadioGroupProps} from './RadioGroup';
149
150
  export type {SearchFieldProps} from './SearchField';
150
151
  export type {SegmentedControlProps, SegmentedControlItemProps} from './SegmentedControl';
152
+ export type {SelectBoxProps, SelectBoxGroupProps} from './SelectBoxGroup';
151
153
  export type {SliderProps} from './Slider';
152
154
  export type {RangeCalendarProps} from './RangeCalendar';
153
155
  export type {RangeSliderProps} from './RangeSlider';