@react-spectrum/s2 1.1.0 → 1.2.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.
- package/dist/Accordion.cjs +2 -2
- package/dist/Accordion.css +2 -2
- package/dist/Accordion.mjs +2 -2
- package/dist/ActionBar.cjs +59 -59
- package/dist/ActionBar.css +58 -58
- package/dist/ActionBar.mjs +59 -59
- package/dist/ActionButton.cjs +233 -233
- package/dist/ActionButton.css +160 -160
- package/dist/ActionButton.mjs +233 -233
- package/dist/ActionButtonGroup.cjs +15 -15
- package/dist/ActionButtonGroup.css +9 -9
- package/dist/ActionButtonGroup.mjs +15 -15
- package/dist/Add.cjs +10 -10
- package/dist/Add.css +6 -6
- package/dist/Add.mjs +10 -10
- package/dist/AlertDialog.cjs +3 -3
- package/dist/AlertDialog.css +3 -3
- package/dist/AlertDialog.mjs +3 -3
- package/dist/Asterisk.cjs +6 -6
- package/dist/Asterisk.css +4 -4
- package/dist/Asterisk.mjs +6 -6
- package/dist/Avatar.cjs +16 -16
- package/dist/Avatar.css +16 -16
- package/dist/Avatar.mjs +16 -16
- package/dist/AvatarGroup.cjs +120 -120
- package/dist/AvatarGroup.css +31 -31
- package/dist/AvatarGroup.mjs +120 -120
- package/dist/Badge.cjs +196 -196
- package/dist/Badge.css +125 -125
- package/dist/Badge.mjs +196 -196
- package/dist/Breadcrumbs.cjs +234 -234
- package/dist/Breadcrumbs.css +100 -100
- package/dist/Breadcrumbs.mjs +234 -234
- package/dist/Button.cjs +332 -332
- package/dist/Button.css +174 -174
- package/dist/Button.mjs +332 -332
- package/dist/ButtonGroup.cjs +20 -20
- package/dist/ButtonGroup.css +15 -15
- package/dist/ButtonGroup.mjs +20 -20
- package/dist/Calendar.cjs +168 -168
- package/dist/Calendar.css +134 -134
- package/dist/Calendar.mjs +168 -168
- package/dist/Card.cjs +309 -309
- package/dist/Card.css +206 -206
- package/dist/Card.mjs +309 -309
- package/dist/CardView.cjs +17 -17
- package/dist/CardView.css +17 -17
- package/dist/CardView.mjs +17 -17
- package/dist/CenterBaseline.cjs +1 -1
- package/dist/CenterBaseline.css +2 -2
- package/dist/CenterBaseline.mjs +1 -1
- package/dist/Checkbox.cjs +161 -161
- package/dist/Checkbox.css +92 -92
- package/dist/Checkbox.mjs +161 -161
- package/dist/CheckboxGroup.cjs +43 -43
- package/dist/CheckboxGroup.css +37 -37
- package/dist/CheckboxGroup.mjs +43 -43
- package/dist/Checkmark.cjs +12 -12
- package/dist/Checkmark.css +8 -8
- package/dist/Checkmark.mjs +12 -12
- package/dist/Chevron.cjs +12 -12
- package/dist/Chevron.css +10 -10
- package/dist/Chevron.mjs +12 -12
- package/dist/ClearButton.cjs +30 -30
- package/dist/ClearButton.css +30 -30
- package/dist/ClearButton.mjs +30 -30
- package/dist/CloseButton.cjs +55 -55
- package/dist/CloseButton.css +47 -47
- package/dist/CloseButton.mjs +55 -55
- package/dist/ColorArea.cjs +16 -16
- package/dist/ColorArea.css +16 -16
- package/dist/ColorArea.mjs +16 -16
- package/dist/ColorField.cjs +31 -31
- package/dist/ColorField.css +27 -27
- package/dist/ColorField.mjs +31 -31
- package/dist/ColorHandle.cjs +27 -27
- package/dist/ColorHandle.css +42 -42
- package/dist/ColorHandle.mjs +27 -27
- package/dist/ColorSlider.cjs +108 -108
- package/dist/ColorSlider.css +52 -52
- package/dist/ColorSlider.mjs +108 -108
- package/dist/ColorSwatch.cjs +29 -29
- package/dist/ColorSwatch.css +29 -29
- package/dist/ColorSwatch.mjs +29 -29
- package/dist/ColorSwatchPicker.cjs +29 -29
- package/dist/ColorSwatchPicker.css +48 -48
- package/dist/ColorSwatchPicker.mjs +29 -29
- package/dist/ColorWheel.cjs +26 -26
- package/dist/ColorWheel.css +17 -17
- package/dist/ColorWheel.mjs +26 -26
- package/dist/ComboBox.cjs +381 -381
- package/dist/ComboBox.cjs.map +1 -1
- package/dist/ComboBox.css +187 -187
- package/dist/ComboBox.css.map +1 -1
- package/dist/ComboBox.mjs +381 -381
- package/dist/ComboBox.mjs.map +1 -1
- package/dist/ContextualHelp.cjs +70 -41
- package/dist/ContextualHelp.cjs.map +1 -1
- package/dist/ContextualHelp.css +71 -71
- package/dist/ContextualHelp.css.map +1 -1
- package/dist/ContextualHelp.mjs +74 -46
- package/dist/ContextualHelp.mjs.map +1 -1
- package/dist/Cross.cjs +14 -14
- package/dist/Cross.css +10 -10
- package/dist/Cross.mjs +14 -14
- package/dist/CustomDialog.cjs +25 -25
- package/dist/CustomDialog.css +25 -25
- package/dist/CustomDialog.mjs +25 -25
- package/dist/Dash.cjs +10 -10
- package/dist/Dash.css +6 -6
- package/dist/Dash.mjs +10 -10
- package/dist/DateField.cjs +73 -73
- package/dist/DateField.css +77 -77
- package/dist/DateField.mjs +73 -73
- package/dist/DatePicker.cjs +172 -172
- package/dist/DatePicker.css +128 -128
- package/dist/DatePicker.mjs +172 -172
- package/dist/DateRangePicker.cjs +55 -55
- package/dist/DateRangePicker.css +59 -59
- package/dist/DateRangePicker.mjs +55 -55
- package/dist/Dialog.cjs +17 -17
- package/dist/Dialog.css +70 -70
- package/dist/Dialog.mjs +17 -17
- package/dist/Disclosure.cjs +119 -119
- package/dist/Disclosure.css +112 -112
- package/dist/Disclosure.mjs +119 -119
- package/dist/Divider.cjs +25 -25
- package/dist/Divider.css +25 -25
- package/dist/Divider.mjs +25 -25
- package/dist/DropZone.cjs +61 -61
- package/dist/DropZone.css +57 -57
- package/dist/DropZone.mjs +61 -61
- package/dist/Field.cjs +351 -351
- package/dist/Field.cjs.map +1 -1
- package/dist/Field.css +147 -147
- package/dist/Field.css.map +1 -1
- package/dist/Field.mjs +351 -351
- package/dist/Field.mjs.map +1 -1
- package/dist/Form.cjs +9 -9
- package/dist/Form.css +9 -9
- package/dist/Form.mjs +9 -9
- package/dist/FullscreenDialog.cjs +5 -5
- package/dist/FullscreenDialog.css +78 -78
- package/dist/FullscreenDialog.mjs +5 -5
- package/dist/IllustratedMessage.cjs +228 -228
- package/dist/IllustratedMessage.css +72 -72
- package/dist/IllustratedMessage.mjs +228 -228
- package/dist/Image.cjs +14 -14
- package/dist/Image.css +14 -14
- package/dist/Image.mjs +14 -14
- package/dist/InlineAlert.cjs +100 -100
- package/dist/InlineAlert.css +76 -76
- package/dist/InlineAlert.mjs +100 -100
- package/dist/Link.cjs +49 -49
- package/dist/Link.css +41 -41
- package/dist/Link.mjs +49 -49
- package/dist/LinkOut.cjs +8 -8
- package/dist/LinkOut.css +8 -8
- package/dist/LinkOut.mjs +8 -8
- package/dist/ListView.cjs +777 -0
- package/dist/ListView.cjs.map +1 -0
- package/dist/ListView.css +740 -0
- package/dist/ListView.css.map +1 -0
- package/dist/ListView.mjs +770 -0
- package/dist/ListView.mjs.map +1 -0
- package/dist/Menu.cjs +529 -437
- package/dist/Menu.cjs.map +1 -1
- package/dist/Menu.css +234 -190
- package/dist/Menu.css.map +1 -1
- package/dist/Menu.mjs +530 -439
- package/dist/Menu.mjs.map +1 -1
- package/dist/Meter.cjs +153 -153
- package/dist/Meter.css +91 -91
- package/dist/Meter.mjs +153 -153
- package/dist/Modal.cjs +66 -66
- package/dist/Modal.css +54 -54
- package/dist/Modal.mjs +66 -66
- package/dist/NotificationBadge.cjs +56 -56
- package/dist/NotificationBadge.css +49 -49
- package/dist/NotificationBadge.mjs +56 -56
- package/dist/NumberField.cjs +114 -114
- package/dist/NumberField.css +99 -99
- package/dist/NumberField.mjs +114 -114
- package/dist/Picker.cjs +336 -284
- package/dist/Picker.cjs.map +1 -1
- package/dist/Picker.css +173 -173
- package/dist/Picker.css.map +1 -1
- package/dist/Picker.mjs +338 -286
- package/dist/Picker.mjs.map +1 -1
- package/dist/Popover.cjs +87 -87
- package/dist/Popover.css +70 -70
- package/dist/Popover.mjs +87 -87
- package/dist/ProgressBar.cjs +163 -163
- package/dist/ProgressBar.css +99 -99
- package/dist/ProgressBar.mjs +163 -163
- package/dist/ProgressCircle.cjs +31 -31
- package/dist/ProgressCircle.css +24 -24
- package/dist/ProgressCircle.mjs +31 -31
- package/dist/Provider.cjs +11 -11
- package/dist/Provider.css +10 -10
- package/dist/Provider.mjs +11 -11
- package/dist/Radio.cjs +145 -145
- package/dist/Radio.css +78 -78
- package/dist/Radio.mjs +145 -145
- package/dist/RadioGroup.cjs +41 -41
- package/dist/RadioGroup.css +37 -37
- package/dist/RadioGroup.mjs +41 -41
- package/dist/RangeCalendar.cjs +7 -7
- package/dist/RangeCalendar.css +10 -10
- package/dist/RangeCalendar.mjs +7 -7
- package/dist/SearchField.cjs +41 -41
- package/dist/SearchField.css +45 -45
- package/dist/SearchField.mjs +41 -41
- package/dist/SegmentedControl.cjs +178 -178
- package/dist/SegmentedControl.css +123 -123
- package/dist/SegmentedControl.mjs +178 -178
- package/dist/SelectBoxGroup.cjs +142 -142
- package/dist/SelectBoxGroup.css +120 -120
- package/dist/SelectBoxGroup.mjs +142 -142
- package/dist/Slider.cjs +294 -294
- package/dist/Slider.css +154 -154
- package/dist/Slider.mjs +294 -294
- package/dist/StatusLight.cjs +115 -115
- package/dist/StatusLight.css +59 -59
- package/dist/StatusLight.mjs +115 -115
- package/dist/Switch.cjs +154 -154
- package/dist/Switch.css +74 -74
- package/dist/Switch.mjs +154 -154
- package/dist/TableView.cjs +444 -420
- package/dist/TableView.cjs.map +1 -1
- package/dist/TableView.css +232 -204
- package/dist/TableView.css.map +1 -1
- package/dist/TableView.mjs +446 -422
- package/dist/TableView.mjs.map +1 -1
- package/dist/Tabs.cjs +123 -123
- package/dist/Tabs.css +105 -105
- package/dist/Tabs.mjs +123 -123
- package/dist/TabsPicker.cjs +127 -127
- package/dist/TabsPicker.css +108 -108
- package/dist/TabsPicker.mjs +127 -127
- package/dist/TagGroup.cjs +203 -203
- package/dist/TagGroup.css +146 -146
- package/dist/TagGroup.mjs +203 -203
- package/dist/TextField.cjs +58 -58
- package/dist/TextField.css +54 -54
- package/dist/TextField.mjs +58 -58
- package/dist/TimeField.cjs +51 -51
- package/dist/TimeField.css +47 -47
- package/dist/TimeField.mjs +51 -51
- package/dist/Toast.cjs +121 -121
- package/dist/Toast.cjs.map +1 -1
- package/dist/Toast.css +110 -110
- package/dist/Toast.css.map +1 -1
- package/dist/Toast.mjs +122 -122
- package/dist/Toast.mjs.map +1 -1
- package/dist/ToggleButton.cjs +3 -3
- package/dist/ToggleButton.css +12 -12
- package/dist/ToggleButton.mjs +3 -3
- package/dist/Tooltip.cjs +78 -78
- package/dist/Tooltip.css +65 -65
- package/dist/Tooltip.mjs +78 -78
- package/dist/TreeView.cjs +179 -145
- package/dist/TreeView.cjs.map +1 -1
- package/dist/TreeView.css +140 -128
- package/dist/TreeView.css.map +1 -1
- package/dist/TreeView.mjs +179 -145
- package/dist/TreeView.mjs.map +1 -1
- package/dist/ar-AE.cjs +1 -0
- package/dist/ar-AE.cjs.map +1 -1
- package/dist/ar-AE.mjs +1 -0
- package/dist/ar-AE.mjs.map +1 -1
- package/dist/bg-BG.cjs +1 -0
- package/dist/bg-BG.cjs.map +1 -1
- package/dist/bg-BG.mjs +1 -0
- package/dist/bg-BG.mjs.map +1 -1
- package/dist/cs-CZ.cjs +1 -0
- package/dist/cs-CZ.cjs.map +1 -1
- package/dist/cs-CZ.mjs +1 -0
- package/dist/cs-CZ.mjs.map +1 -1
- package/dist/da-DK.cjs +1 -0
- package/dist/da-DK.cjs.map +1 -1
- package/dist/da-DK.mjs +1 -0
- package/dist/da-DK.mjs.map +1 -1
- package/dist/de-DE.cjs +1 -0
- package/dist/de-DE.cjs.map +1 -1
- package/dist/de-DE.mjs +1 -0
- package/dist/de-DE.mjs.map +1 -1
- package/dist/el-GR.cjs +1 -0
- package/dist/el-GR.cjs.map +1 -1
- package/dist/el-GR.mjs +1 -0
- package/dist/el-GR.mjs.map +1 -1
- package/dist/en-US.cjs +1 -0
- package/dist/en-US.cjs.map +1 -1
- package/dist/en-US.mjs +1 -0
- package/dist/en-US.mjs.map +1 -1
- package/dist/es-ES.cjs +1 -0
- package/dist/es-ES.cjs.map +1 -1
- package/dist/es-ES.mjs +1 -0
- package/dist/es-ES.mjs.map +1 -1
- package/dist/et-EE.cjs +1 -0
- package/dist/et-EE.cjs.map +1 -1
- package/dist/et-EE.mjs +1 -0
- package/dist/et-EE.mjs.map +1 -1
- package/dist/fi-FI.cjs +1 -0
- package/dist/fi-FI.cjs.map +1 -1
- package/dist/fi-FI.mjs +1 -0
- package/dist/fi-FI.mjs.map +1 -1
- package/dist/fr-FR.cjs +1 -0
- package/dist/fr-FR.cjs.map +1 -1
- package/dist/fr-FR.mjs +1 -0
- package/dist/fr-FR.mjs.map +1 -1
- package/dist/he-IL.cjs +1 -0
- package/dist/he-IL.cjs.map +1 -1
- package/dist/he-IL.mjs +1 -0
- package/dist/he-IL.mjs.map +1 -1
- package/dist/hr-HR.cjs +1 -0
- package/dist/hr-HR.cjs.map +1 -1
- package/dist/hr-HR.mjs +1 -0
- package/dist/hr-HR.mjs.map +1 -1
- package/dist/hu-HU.cjs +1 -0
- package/dist/hu-HU.cjs.map +1 -1
- package/dist/hu-HU.mjs +1 -0
- package/dist/hu-HU.mjs.map +1 -1
- package/dist/it-IT.cjs +1 -0
- package/dist/it-IT.cjs.map +1 -1
- package/dist/it-IT.mjs +1 -0
- package/dist/it-IT.mjs.map +1 -1
- package/dist/ja-JP.cjs +1 -0
- package/dist/ja-JP.cjs.map +1 -1
- package/dist/ja-JP.mjs +1 -0
- package/dist/ja-JP.mjs.map +1 -1
- package/dist/ko-KR.cjs +1 -0
- package/dist/ko-KR.cjs.map +1 -1
- package/dist/ko-KR.mjs +1 -0
- package/dist/ko-KR.mjs.map +1 -1
- package/dist/lt-LT.cjs +1 -0
- package/dist/lt-LT.cjs.map +1 -1
- package/dist/lt-LT.mjs +1 -0
- package/dist/lt-LT.mjs.map +1 -1
- package/dist/lv-LV.cjs +1 -0
- package/dist/lv-LV.cjs.map +1 -1
- package/dist/lv-LV.mjs +1 -0
- package/dist/lv-LV.mjs.map +1 -1
- package/dist/main.cjs +7 -0
- package/dist/main.cjs.map +1 -1
- package/dist/module.mjs +5 -3
- package/dist/module.mjs.map +1 -1
- package/dist/nb-NO.cjs +1 -0
- package/dist/nb-NO.cjs.map +1 -1
- package/dist/nb-NO.mjs +1 -0
- package/dist/nb-NO.mjs.map +1 -1
- package/dist/nl-NL.cjs +1 -0
- package/dist/nl-NL.cjs.map +1 -1
- package/dist/nl-NL.mjs +1 -0
- package/dist/nl-NL.mjs.map +1 -1
- package/dist/pl-PL.cjs +1 -0
- package/dist/pl-PL.cjs.map +1 -1
- package/dist/pl-PL.mjs +1 -0
- package/dist/pl-PL.mjs.map +1 -1
- package/dist/pt-BR.cjs +1 -0
- package/dist/pt-BR.cjs.map +1 -1
- package/dist/pt-BR.mjs +1 -0
- package/dist/pt-BR.mjs.map +1 -1
- package/dist/pt-PT.cjs +1 -0
- package/dist/pt-PT.cjs.map +1 -1
- package/dist/pt-PT.mjs +1 -0
- package/dist/pt-PT.mjs.map +1 -1
- package/dist/ro-RO.cjs +1 -0
- package/dist/ro-RO.cjs.map +1 -1
- package/dist/ro-RO.mjs +1 -0
- package/dist/ro-RO.mjs.map +1 -1
- package/dist/ru-RU.cjs +1 -0
- package/dist/ru-RU.cjs.map +1 -1
- package/dist/ru-RU.mjs +1 -0
- package/dist/ru-RU.mjs.map +1 -1
- package/dist/sk-SK.cjs +1 -0
- package/dist/sk-SK.cjs.map +1 -1
- package/dist/sk-SK.mjs +1 -0
- package/dist/sk-SK.mjs.map +1 -1
- package/dist/sl-SI.cjs +1 -0
- package/dist/sl-SI.cjs.map +1 -1
- package/dist/sl-SI.mjs +1 -0
- package/dist/sl-SI.mjs.map +1 -1
- package/dist/sr-SP.cjs +1 -0
- package/dist/sr-SP.cjs.map +1 -1
- package/dist/sr-SP.mjs +1 -0
- package/dist/sr-SP.mjs.map +1 -1
- package/dist/sv-SE.cjs +1 -0
- package/dist/sv-SE.cjs.map +1 -1
- package/dist/sv-SE.mjs +1 -0
- package/dist/sv-SE.mjs.map +1 -1
- package/dist/tr-TR.cjs +1 -0
- package/dist/tr-TR.cjs.map +1 -1
- package/dist/tr-TR.mjs +1 -0
- package/dist/tr-TR.mjs.map +1 -1
- package/dist/types.d.ts +77 -6
- package/dist/types.d.ts.map +1 -1
- package/dist/uk-UA.cjs +1 -0
- package/dist/uk-UA.cjs.map +1 -1
- package/dist/uk-UA.mjs +1 -0
- package/dist/uk-UA.mjs.map +1 -1
- package/dist/zh-CN.cjs +1 -0
- package/dist/zh-CN.cjs.map +1 -1
- package/dist/zh-CN.mjs +1 -0
- package/dist/zh-CN.mjs.map +1 -1
- package/dist/zh-TW.cjs +1 -0
- package/dist/zh-TW.cjs.map +1 -1
- package/dist/zh-TW.mjs +1 -0
- package/dist/zh-TW.mjs.map +1 -1
- package/icons/Icon.cjs +10 -10
- package/icons/Icon.css +9 -9
- package/icons/Icon.mjs +10 -10
- package/icons/Skeleton.cjs +2 -2
- package/icons/Skeleton.css +6 -6
- package/icons/Skeleton.mjs +2 -2
- package/package.json +21 -21
- package/src/ComboBox.tsx +4 -3
- package/src/ContextualHelp.tsx +81 -43
- package/src/Field.tsx +3 -3
- package/src/ListView.tsx +782 -0
- package/src/Menu.tsx +100 -16
- package/src/Picker.tsx +72 -11
- package/src/TableView.tsx +30 -12
- package/src/Toast.tsx +2 -2
- package/src/TreeView.tsx +43 -6
- package/src/index.ts +6 -3
- package/style/__tests__/style-macro.test.js +69 -69
package/src/ListView.tsx
ADDED
|
@@ -0,0 +1,782 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright 2026 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 REPRESENTATIONS
|
|
9
|
+
* OF ANY KIND, either express or implied. See the License for the specific language
|
|
10
|
+
* governing permissions and limitations under the License.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import {ActionButtonGroupContext} from './ActionButtonGroup';
|
|
14
|
+
import {ActionMenuContext} from './ActionMenu';
|
|
15
|
+
import {baseColor, colorMix, focusRing, fontRelative, space, style} from '../style' with {type: 'macro'};
|
|
16
|
+
import {centerBaseline} from './CenterBaseline';
|
|
17
|
+
import {Checkbox} from './Checkbox';
|
|
18
|
+
import {
|
|
19
|
+
CheckboxContext,
|
|
20
|
+
Collection,
|
|
21
|
+
CollectionRendererContext,
|
|
22
|
+
ContextValue,
|
|
23
|
+
DEFAULT_SLOT,
|
|
24
|
+
DefaultCollectionRenderer,
|
|
25
|
+
GridList,
|
|
26
|
+
GridListItem,
|
|
27
|
+
GridListItemProps,
|
|
28
|
+
GridListItemRenderProps,
|
|
29
|
+
GridListLoadMoreItem,
|
|
30
|
+
GridListProps,
|
|
31
|
+
GridListRenderProps,
|
|
32
|
+
Key,
|
|
33
|
+
ListLayout,
|
|
34
|
+
ListState,
|
|
35
|
+
Provider,
|
|
36
|
+
SlotProps,
|
|
37
|
+
useSlottedContext,
|
|
38
|
+
Virtualizer
|
|
39
|
+
} from 'react-aria-components';
|
|
40
|
+
import Chevron from '../ui-icons/Chevron';
|
|
41
|
+
import {controlFont, getAllowedOverrides, StylesPropWithHeight, UnsafeStyles} from './style-utils' with {type: 'macro'};
|
|
42
|
+
import {createContext, forwardRef, ReactElement, ReactNode, useContext, useRef} from 'react';
|
|
43
|
+
import {DOMProps, DOMRef, DOMRefValue, forwardRefType, GlobalDOMAttributes, LoadingState} from '@react-types/shared';
|
|
44
|
+
import {edgeToText} from '../style/spectrum-theme' with {type: 'macro'};
|
|
45
|
+
import {IconContext} from './Icon';
|
|
46
|
+
import {ImageContext} from './Image';
|
|
47
|
+
// @ts-ignore
|
|
48
|
+
import intlMessages from '../intl/*.json';
|
|
49
|
+
import LinkOutIcon from '../ui-icons/LinkOut';
|
|
50
|
+
import {ProgressCircle} from './ProgressCircle';
|
|
51
|
+
import {Text, TextContext} from './Content';
|
|
52
|
+
import {useActionBarContainer} from './ActionBar';
|
|
53
|
+
import {useDOMRef} from '@react-spectrum/utils';
|
|
54
|
+
import {useLocale, useLocalizedStringFormatter} from 'react-aria';
|
|
55
|
+
import {useScale} from './utils';
|
|
56
|
+
import {useSpectrumContextProps} from './useSpectrumContextProps';
|
|
57
|
+
|
|
58
|
+
export interface ListViewProps<T> extends Omit<GridListProps<T>, 'className' | 'style' | 'children' | 'selectionBehavior' | 'dragAndDropHooks' | 'layout' | 'render' | 'keyboardNavigationBehavior' | keyof GlobalDOMAttributes>, DOMProps, UnsafeStyles, ListViewStylesProps, SlotProps {
|
|
59
|
+
/** Spectrum-defined styles, returned by the `style()` macro. */
|
|
60
|
+
styles?: StylesPropWithHeight,
|
|
61
|
+
/** The current loading state of the ListView. */
|
|
62
|
+
loadingState?: LoadingState,
|
|
63
|
+
/** Handler that is called when more items should be loaded, e.g. while scrolling near the bottom. */
|
|
64
|
+
onLoadMore?: () => void,
|
|
65
|
+
/** The children of the ListView. */
|
|
66
|
+
children: ReactNode | ((item: T) => ReactNode),
|
|
67
|
+
/** Provides the ActionBar to display when items are selected in the ListView. */
|
|
68
|
+
renderActionBar?: (selectedKeys: 'all' | Set<Key>) => ReactElement,
|
|
69
|
+
/** Hides the default link out icons on items that open links in a new tab. */
|
|
70
|
+
hideLinkOutIcon?: boolean
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
interface ListViewStylesProps {
|
|
74
|
+
/** Whether the ListView should be displayed with a quiet style. */
|
|
75
|
+
isQuiet?: boolean,
|
|
76
|
+
/**
|
|
77
|
+
* How selection should be displayed.
|
|
78
|
+
* @default 'checkbox'
|
|
79
|
+
*/
|
|
80
|
+
selectionStyle?: 'highlight' | 'checkbox',
|
|
81
|
+
/**
|
|
82
|
+
* Sets the overflow behavior for item contents.
|
|
83
|
+
* @default 'truncate'
|
|
84
|
+
*/
|
|
85
|
+
overflowMode?: 'wrap' | 'truncate'
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export interface ListViewItemProps extends Omit<GridListItemProps, 'children' | 'className' | 'style' | 'render' | 'onClick' | keyof GlobalDOMAttributes> {
|
|
89
|
+
/**
|
|
90
|
+
* The contents of the item.
|
|
91
|
+
*/
|
|
92
|
+
children: ReactNode,
|
|
93
|
+
/** Whether the item has child items (renders a chevron indicator). */
|
|
94
|
+
hasChildItems?: boolean
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
export const ListViewContext = createContext<ContextValue<Partial<ListViewProps<any>>, DOMRefValue<HTMLDivElement>>>(null);
|
|
98
|
+
|
|
99
|
+
let InternalListViewContext = createContext<{isQuiet?: boolean, selectionStyle?: 'highlight' | 'checkbox', overflowMode?: 'wrap' | 'truncate', scale?: 'medium' | 'large', hideLinkOutIcon?: boolean}>({});
|
|
100
|
+
|
|
101
|
+
const listViewWrapper = style({
|
|
102
|
+
minHeight: 0,
|
|
103
|
+
minWidth: 0,
|
|
104
|
+
display: 'flex',
|
|
105
|
+
isolation: 'isolate',
|
|
106
|
+
disableTapHighlight: true,
|
|
107
|
+
position: 'relative',
|
|
108
|
+
// Clip ActionBar animation.
|
|
109
|
+
overflow: 'clip'
|
|
110
|
+
}, getAllowedOverrides({height: true}));
|
|
111
|
+
|
|
112
|
+
// When any row has a trailing icon, reserve space so actions align.
|
|
113
|
+
const hasTrailingIconRows = ':has([data-has-trailing-icon]) [role="row"]';
|
|
114
|
+
|
|
115
|
+
const listView = style<GridListRenderProps & {isQuiet?: boolean}>({
|
|
116
|
+
...focusRing(),
|
|
117
|
+
outlineOffset: {
|
|
118
|
+
default: -2,
|
|
119
|
+
isQuiet: -1
|
|
120
|
+
},
|
|
121
|
+
userSelect: 'none',
|
|
122
|
+
minHeight: 0,
|
|
123
|
+
minWidth: 0,
|
|
124
|
+
width: 'full',
|
|
125
|
+
height: 'full',
|
|
126
|
+
boxSizing: 'border-box',
|
|
127
|
+
overflow: 'auto',
|
|
128
|
+
fontSize: controlFont(),
|
|
129
|
+
backgroundColor: {
|
|
130
|
+
default: 'gray-25',
|
|
131
|
+
isQuiet: 'transparent',
|
|
132
|
+
forcedColors: 'Background'
|
|
133
|
+
},
|
|
134
|
+
borderRadius: {
|
|
135
|
+
default: 'default',
|
|
136
|
+
isQuiet: 'none'
|
|
137
|
+
},
|
|
138
|
+
borderColor: 'gray-300',
|
|
139
|
+
borderWidth: {
|
|
140
|
+
default: 1,
|
|
141
|
+
isQuiet: 0
|
|
142
|
+
},
|
|
143
|
+
borderStyle: 'solid',
|
|
144
|
+
'--trailing-icon-width': {
|
|
145
|
+
type: 'width',
|
|
146
|
+
value: {
|
|
147
|
+
default: 'auto',
|
|
148
|
+
[hasTrailingIconRows]: fontRelative(20)
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* A ListView displays a list of interactive items, and allows a user to navigate, select, or perform an action.
|
|
155
|
+
*/
|
|
156
|
+
export const ListView = /*#__PURE__*/ (forwardRef as forwardRefType)(function ListView<T extends object>(
|
|
157
|
+
props: ListViewProps<T>,
|
|
158
|
+
ref: DOMRef<HTMLDivElement>
|
|
159
|
+
) {
|
|
160
|
+
[props, ref] = useSpectrumContextProps(props, ref, ListViewContext);
|
|
161
|
+
let {children, isQuiet, selectionStyle = 'checkbox', overflowMode = 'truncate', loadingState, onLoadMore, renderEmptyState: userRenderEmptyState, hideLinkOutIcon = false, ...otherProps} = props;
|
|
162
|
+
let scale = useScale();
|
|
163
|
+
let stringFormatter = useLocalizedStringFormatter(intlMessages, '@react-spectrum/s2');
|
|
164
|
+
let rowHeight = scale === 'large' ? 50 : 40;
|
|
165
|
+
|
|
166
|
+
let domRef = useDOMRef(ref);
|
|
167
|
+
let scrollRef = useRef<HTMLElement | null>(null);
|
|
168
|
+
|
|
169
|
+
let isLoading = loadingState === 'loading' || loadingState === 'loadingMore';
|
|
170
|
+
let renderEmptyState: ListViewProps<T>['renderEmptyState'] | undefined;
|
|
171
|
+
if (userRenderEmptyState != null && !isLoading) {
|
|
172
|
+
renderEmptyState = (renderProps) => (
|
|
173
|
+
<div className={emptyStateWrapper}>
|
|
174
|
+
<CollectionRendererContext.Provider value={DefaultCollectionRenderer}>
|
|
175
|
+
{userRenderEmptyState!(renderProps)}
|
|
176
|
+
</CollectionRendererContext.Provider>
|
|
177
|
+
</div>
|
|
178
|
+
);
|
|
179
|
+
} else if (loadingState === 'loading') {
|
|
180
|
+
renderEmptyState = () => (
|
|
181
|
+
<div className={centeredWrapper}>
|
|
182
|
+
<div className={loadingSpinnerWrapper}>
|
|
183
|
+
<ProgressCircle
|
|
184
|
+
isIndeterminate
|
|
185
|
+
aria-label={stringFormatter.format('table.loading')} />
|
|
186
|
+
</div>
|
|
187
|
+
</div>
|
|
188
|
+
);
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
let loadMoreSpinner = onLoadMore ? (
|
|
192
|
+
<GridListLoadMoreItem isLoading={loadingState === 'loadingMore'} onLoadMore={onLoadMore} className={style({height: 'full', width: 'full', paddingY: 8})}>
|
|
193
|
+
<div className={centeredWrapper}>
|
|
194
|
+
<div className={loadingSpinnerWrapper}>
|
|
195
|
+
<ProgressCircle
|
|
196
|
+
isIndeterminate
|
|
197
|
+
aria-label={stringFormatter.format('table.loadingMore')} />
|
|
198
|
+
</div>
|
|
199
|
+
</div>
|
|
200
|
+
</GridListLoadMoreItem>
|
|
201
|
+
) : null;
|
|
202
|
+
|
|
203
|
+
let wrappedChildren: ReactNode;
|
|
204
|
+
let gridListProps = otherProps;
|
|
205
|
+
if (typeof children === 'function' && otherProps.items) {
|
|
206
|
+
let {items, dependencies = [], ...rest} = otherProps;
|
|
207
|
+
gridListProps = rest;
|
|
208
|
+
wrappedChildren = (
|
|
209
|
+
<>
|
|
210
|
+
<Collection items={items} dependencies={dependencies}>
|
|
211
|
+
{children}
|
|
212
|
+
</Collection>
|
|
213
|
+
{loadMoreSpinner}
|
|
214
|
+
</>
|
|
215
|
+
);
|
|
216
|
+
} else {
|
|
217
|
+
wrappedChildren = (
|
|
218
|
+
<>
|
|
219
|
+
{children}
|
|
220
|
+
{loadMoreSpinner}
|
|
221
|
+
</>
|
|
222
|
+
);
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
let {selectedKeys, onSelectionChange, actionBar, actionBarHeight} = useActionBarContainer({...props, scrollRef});
|
|
226
|
+
|
|
227
|
+
return (
|
|
228
|
+
<div
|
|
229
|
+
ref={domRef}
|
|
230
|
+
className={(props.UNSAFE_className || '') + listViewWrapper(null, props.styles)}
|
|
231
|
+
style={props.UNSAFE_style}>
|
|
232
|
+
<Virtualizer
|
|
233
|
+
layout={ListLayout}
|
|
234
|
+
layoutOptions={{
|
|
235
|
+
estimatedRowHeight: rowHeight,
|
|
236
|
+
loaderHeight: 60
|
|
237
|
+
}}>
|
|
238
|
+
<InternalListViewContext.Provider value={{isQuiet, selectionStyle, overflowMode, scale, hideLinkOutIcon}}>
|
|
239
|
+
<GridList
|
|
240
|
+
ref={scrollRef as any}
|
|
241
|
+
{...gridListProps}
|
|
242
|
+
selectionBehavior={selectionStyle === 'highlight' ? 'replace' : 'toggle'}
|
|
243
|
+
selectionMode={gridListProps.selectionMode}
|
|
244
|
+
renderEmptyState={renderEmptyState}
|
|
245
|
+
style={{
|
|
246
|
+
paddingBottom: actionBarHeight > 0 ? actionBarHeight + 8 : 0,
|
|
247
|
+
scrollPaddingBottom: actionBarHeight > 0 ? actionBarHeight + 8 : 0
|
|
248
|
+
}}
|
|
249
|
+
className={(renderProps) => listView({
|
|
250
|
+
...renderProps,
|
|
251
|
+
isQuiet
|
|
252
|
+
})}
|
|
253
|
+
selectedKeys={selectedKeys}
|
|
254
|
+
defaultSelectedKeys={undefined}
|
|
255
|
+
onSelectionChange={onSelectionChange}>
|
|
256
|
+
{wrappedChildren}
|
|
257
|
+
</GridList>
|
|
258
|
+
</InternalListViewContext.Provider>
|
|
259
|
+
</Virtualizer>
|
|
260
|
+
{actionBar}
|
|
261
|
+
</div>
|
|
262
|
+
);
|
|
263
|
+
});
|
|
264
|
+
|
|
265
|
+
const selectedBackground = colorMix('gray-25', 'gray-900', 7);
|
|
266
|
+
const selectedActiveBackground = colorMix('gray-25', 'gray-900', 10);
|
|
267
|
+
|
|
268
|
+
const listitem = style<GridListItemRenderProps & {
|
|
269
|
+
isFocused: boolean,
|
|
270
|
+
isLink?: boolean,
|
|
271
|
+
isQuiet?: boolean,
|
|
272
|
+
isFirstItem?: boolean,
|
|
273
|
+
isLastItem?: boolean,
|
|
274
|
+
isSelected?: boolean,
|
|
275
|
+
isDisabled?: boolean,
|
|
276
|
+
isNextSelected?: boolean,
|
|
277
|
+
isPrevSelected?: boolean,
|
|
278
|
+
isPrevNotSelected?: boolean,
|
|
279
|
+
isNextNotSelected?: boolean,
|
|
280
|
+
selectionStyle?: 'highlight' | 'checkbox',
|
|
281
|
+
scale?: 'medium' | 'large'
|
|
282
|
+
}>({
|
|
283
|
+
outlineStyle: 'none',
|
|
284
|
+
boxSizing: 'border-box',
|
|
285
|
+
columnGap: 0,
|
|
286
|
+
paddingX: 0,
|
|
287
|
+
paddingY: 8,
|
|
288
|
+
backgroundColor: 'transparent',
|
|
289
|
+
color: {
|
|
290
|
+
default: baseColor('neutral-subdued'),
|
|
291
|
+
isSelected: baseColor('neutral'),
|
|
292
|
+
isDisabled: {
|
|
293
|
+
default: 'disabled',
|
|
294
|
+
forcedColors: 'GrayText'
|
|
295
|
+
}
|
|
296
|
+
},
|
|
297
|
+
position: 'relative',
|
|
298
|
+
gridColumnStart: 1,
|
|
299
|
+
gridColumnEnd: -1,
|
|
300
|
+
display: 'grid',
|
|
301
|
+
gridTemplateAreas: [
|
|
302
|
+
'. checkmark icon label actions actionmenu trailing-icon .',
|
|
303
|
+
'. . . description actions actionmenu trailing-icon .'
|
|
304
|
+
],
|
|
305
|
+
gridTemplateColumns: [edgeToText(40), 'auto', 'auto', 'minmax(0, 1fr)', 'auto', 'auto', 'var(--trailing-icon-width)', edgeToText(40)],
|
|
306
|
+
gridTemplateRows: '1fr auto',
|
|
307
|
+
rowGap: {
|
|
308
|
+
':has([slot=description])': space(1)
|
|
309
|
+
},
|
|
310
|
+
alignItems: 'baseline',
|
|
311
|
+
minHeight: {
|
|
312
|
+
default: 40,
|
|
313
|
+
scale: {
|
|
314
|
+
large: 50
|
|
315
|
+
}
|
|
316
|
+
},
|
|
317
|
+
textDecoration: 'none',
|
|
318
|
+
cursor: {
|
|
319
|
+
default: 'default',
|
|
320
|
+
isLink: 'pointer'
|
|
321
|
+
},
|
|
322
|
+
'--borderColor': {
|
|
323
|
+
type: 'borderColor',
|
|
324
|
+
value: {
|
|
325
|
+
default: 'gray-300',
|
|
326
|
+
isSelected: {
|
|
327
|
+
selectionStyle: {
|
|
328
|
+
highlight: 'blue-900',
|
|
329
|
+
checkbox: 'gray-300'
|
|
330
|
+
}
|
|
331
|
+
},
|
|
332
|
+
forcedColors: 'ButtonBorder'
|
|
333
|
+
}
|
|
334
|
+
},
|
|
335
|
+
borderTopWidth: 0,
|
|
336
|
+
borderBottomWidth: {
|
|
337
|
+
default: 1,
|
|
338
|
+
isLastItem: {
|
|
339
|
+
default: 1,
|
|
340
|
+
isQuiet: 0
|
|
341
|
+
}
|
|
342
|
+
},
|
|
343
|
+
borderStartWidth: 0,
|
|
344
|
+
borderEndWidth: 0,
|
|
345
|
+
borderStyle: 'solid',
|
|
346
|
+
borderColor: {
|
|
347
|
+
default: '--borderColor',
|
|
348
|
+
isNextSelected: 'transparent',
|
|
349
|
+
isSelected: 'transparent'
|
|
350
|
+
}
|
|
351
|
+
});
|
|
352
|
+
|
|
353
|
+
const listRowBackground = style<GridListItemRenderProps & {
|
|
354
|
+
isFirstItem?: boolean,
|
|
355
|
+
isLastItem?: boolean,
|
|
356
|
+
isQuiet?: boolean,
|
|
357
|
+
isPrevSelected?: boolean,
|
|
358
|
+
isNextSelected?: boolean,
|
|
359
|
+
isPrevNotSelected?: boolean,
|
|
360
|
+
isNextNotSelected?: boolean,
|
|
361
|
+
selectionStyle?: 'highlight' | 'checkbox'
|
|
362
|
+
}>({
|
|
363
|
+
...focusRing(),
|
|
364
|
+
outlineOffset: -2,
|
|
365
|
+
position: 'absolute',
|
|
366
|
+
zIndex: -1,
|
|
367
|
+
top: {
|
|
368
|
+
default: 0,
|
|
369
|
+
isSelected: '[-1px]',
|
|
370
|
+
// Don't overlap focus ring of row above.
|
|
371
|
+
isPrevSelected: 0,
|
|
372
|
+
isFirstItem: 0
|
|
373
|
+
},
|
|
374
|
+
left: 0,
|
|
375
|
+
right: 0,
|
|
376
|
+
bottom: {
|
|
377
|
+
default: 0,
|
|
378
|
+
isSelected: '[-1px]'
|
|
379
|
+
},
|
|
380
|
+
backgroundColor: {
|
|
381
|
+
default: '--rowBackgroundColor',
|
|
382
|
+
isHovered: {
|
|
383
|
+
default: 'gray-900/5',
|
|
384
|
+
selectionStyle: {
|
|
385
|
+
checkbox: selectedBackground
|
|
386
|
+
}
|
|
387
|
+
},
|
|
388
|
+
isPressed: {
|
|
389
|
+
default: 'gray-900/10',
|
|
390
|
+
selectionStyle: {
|
|
391
|
+
checkbox: selectedActiveBackground
|
|
392
|
+
}
|
|
393
|
+
},
|
|
394
|
+
isSelected: {
|
|
395
|
+
selectionStyle: {
|
|
396
|
+
checkbox: {
|
|
397
|
+
default: selectedBackground,
|
|
398
|
+
isHovered: selectedActiveBackground,
|
|
399
|
+
isPressed: selectedActiveBackground,
|
|
400
|
+
isFocusVisible: selectedActiveBackground
|
|
401
|
+
},
|
|
402
|
+
highlight: {
|
|
403
|
+
// Use solid colors rather than transparent because the rows overlap.
|
|
404
|
+
default: colorMix('gray-25', 'blue-900', 10),
|
|
405
|
+
isHovered: colorMix('gray-25', 'blue-900', 15),
|
|
406
|
+
isPressed: colorMix('gray-25', 'blue-900', 15)
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
},
|
|
410
|
+
forcedColors: {
|
|
411
|
+
default: 'Background'
|
|
412
|
+
}
|
|
413
|
+
},
|
|
414
|
+
borderTopStartRadius: {
|
|
415
|
+
isFirstItem: {
|
|
416
|
+
isSelected: {
|
|
417
|
+
selectionStyle: {
|
|
418
|
+
checkbox: 'none',
|
|
419
|
+
highlight: 'default'
|
|
420
|
+
}
|
|
421
|
+
},
|
|
422
|
+
isQuiet: 'default',
|
|
423
|
+
isFocusVisible: 'default'
|
|
424
|
+
}
|
|
425
|
+
},
|
|
426
|
+
borderTopEndRadius: {
|
|
427
|
+
isFirstItem: {
|
|
428
|
+
isSelected: {
|
|
429
|
+
selectionStyle: {
|
|
430
|
+
checkbox: 'none',
|
|
431
|
+
highlight: 'default'
|
|
432
|
+
}
|
|
433
|
+
},
|
|
434
|
+
isQuiet: 'default',
|
|
435
|
+
isFocusVisible: 'default'
|
|
436
|
+
}
|
|
437
|
+
},
|
|
438
|
+
borderBottomStartRadius: {
|
|
439
|
+
isLastItem: {
|
|
440
|
+
isSelected: {
|
|
441
|
+
selectionStyle: {
|
|
442
|
+
checkbox: 'none',
|
|
443
|
+
highlight: 'default'
|
|
444
|
+
}
|
|
445
|
+
},
|
|
446
|
+
isQuiet: 'default',
|
|
447
|
+
isFocusVisible: 'default'
|
|
448
|
+
}
|
|
449
|
+
},
|
|
450
|
+
borderBottomEndRadius: {
|
|
451
|
+
isLastItem: {
|
|
452
|
+
isSelected: {
|
|
453
|
+
selectionStyle: {
|
|
454
|
+
checkbox: 'none',
|
|
455
|
+
highlight: 'default'
|
|
456
|
+
}
|
|
457
|
+
},
|
|
458
|
+
isQuiet: 'default',
|
|
459
|
+
isFocusVisible: 'default'
|
|
460
|
+
}
|
|
461
|
+
},
|
|
462
|
+
borderTopWidth: {
|
|
463
|
+
default: {
|
|
464
|
+
selectionStyle: {
|
|
465
|
+
checkbox: 0,
|
|
466
|
+
highlight: 1
|
|
467
|
+
}
|
|
468
|
+
},
|
|
469
|
+
isPrevSelected: 0
|
|
470
|
+
},
|
|
471
|
+
borderBottomWidth: {
|
|
472
|
+
default: {
|
|
473
|
+
selectionStyle: {
|
|
474
|
+
checkbox: 0,
|
|
475
|
+
highlight: 1
|
|
476
|
+
}
|
|
477
|
+
},
|
|
478
|
+
isNextSelected: 0
|
|
479
|
+
},
|
|
480
|
+
borderStartWidth: {
|
|
481
|
+
default: {
|
|
482
|
+
selectionStyle: {
|
|
483
|
+
checkbox: 0,
|
|
484
|
+
highlight: 1
|
|
485
|
+
}
|
|
486
|
+
}
|
|
487
|
+
},
|
|
488
|
+
borderEndWidth: {
|
|
489
|
+
default: {
|
|
490
|
+
selectionStyle: {
|
|
491
|
+
checkbox: 0,
|
|
492
|
+
highlight: 1
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
},
|
|
496
|
+
borderStyle: 'solid',
|
|
497
|
+
borderColor: {
|
|
498
|
+
default: 'transparent',
|
|
499
|
+
isSelected: {
|
|
500
|
+
selectionStyle: {
|
|
501
|
+
checkbox: 'transparent',
|
|
502
|
+
highlight: '--borderColor'
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
}
|
|
506
|
+
});
|
|
507
|
+
|
|
508
|
+
export let label = style({
|
|
509
|
+
gridArea: 'label',
|
|
510
|
+
alignSelf: 'center',
|
|
511
|
+
font: controlFont(),
|
|
512
|
+
color: 'inherit',
|
|
513
|
+
truncate: true,
|
|
514
|
+
whiteSpace: {
|
|
515
|
+
default: 'nowrap',
|
|
516
|
+
overflowMode: {
|
|
517
|
+
wrap: 'normal'
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
});
|
|
521
|
+
|
|
522
|
+
export let description = style({
|
|
523
|
+
gridArea: 'description',
|
|
524
|
+
alignSelf: 'center',
|
|
525
|
+
truncate: true,
|
|
526
|
+
whiteSpace: {
|
|
527
|
+
default: 'nowrap',
|
|
528
|
+
overflowMode: {
|
|
529
|
+
wrap: 'normal'
|
|
530
|
+
}
|
|
531
|
+
},
|
|
532
|
+
font: 'ui-sm',
|
|
533
|
+
color: {
|
|
534
|
+
default: baseColor('neutral-subdued'),
|
|
535
|
+
isDisabled: 'disabled'
|
|
536
|
+
},
|
|
537
|
+
transition: 'default'
|
|
538
|
+
});
|
|
539
|
+
|
|
540
|
+
export let iconCenterWrapper = style({
|
|
541
|
+
display: 'flex',
|
|
542
|
+
gridArea: 'icon',
|
|
543
|
+
gridRowEnd: 'span 2',
|
|
544
|
+
alignSelf: 'center',
|
|
545
|
+
alignItems: 'center'
|
|
546
|
+
});
|
|
547
|
+
|
|
548
|
+
export let icon = style({
|
|
549
|
+
display: 'block',
|
|
550
|
+
size: fontRelative(20),
|
|
551
|
+
// too small default icon size is wrong, it's like the icons are 1 tshirt size bigger than the rest of the component? check again after typography changes
|
|
552
|
+
// reminder, size of WF is applied via font size
|
|
553
|
+
marginEnd: 'text-to-visual',
|
|
554
|
+
'--iconPrimary': {
|
|
555
|
+
type: 'fill',
|
|
556
|
+
value: 'currentColor'
|
|
557
|
+
}
|
|
558
|
+
});
|
|
559
|
+
|
|
560
|
+
let image = style({
|
|
561
|
+
gridArea: 'icon',
|
|
562
|
+
gridRowEnd: 'span 2',
|
|
563
|
+
marginEnd: 'text-to-visual',
|
|
564
|
+
alignSelf: 'center',
|
|
565
|
+
borderRadius: 'sm',
|
|
566
|
+
width: 32,
|
|
567
|
+
aspectRatio: 'square',
|
|
568
|
+
objectFit: 'cover'
|
|
569
|
+
});
|
|
570
|
+
|
|
571
|
+
let actionButtonGroup = style({
|
|
572
|
+
gridArea: 'actions',
|
|
573
|
+
gridRowEnd: 'span 2',
|
|
574
|
+
alignSelf: 'center',
|
|
575
|
+
justifySelf: 'end',
|
|
576
|
+
marginStart: 'text-to-visual'
|
|
577
|
+
});
|
|
578
|
+
|
|
579
|
+
let listActionMenu = style({
|
|
580
|
+
gridArea: 'actionmenu',
|
|
581
|
+
gridRowEnd: 'span 2',
|
|
582
|
+
alignSelf: 'center'
|
|
583
|
+
});
|
|
584
|
+
|
|
585
|
+
const listCheckbox = style({
|
|
586
|
+
gridArea: 'checkmark',
|
|
587
|
+
gridRowEnd: 'span 2',
|
|
588
|
+
alignSelf: 'center',
|
|
589
|
+
marginEnd: 8,
|
|
590
|
+
visibility: {
|
|
591
|
+
default: 'visible',
|
|
592
|
+
isDisabled: 'hidden'
|
|
593
|
+
}
|
|
594
|
+
});
|
|
595
|
+
|
|
596
|
+
const listTrailingIcon = style({
|
|
597
|
+
gridArea: 'trailing-icon',
|
|
598
|
+
gridRowEnd: 'span 2',
|
|
599
|
+
alignSelf: 'center',
|
|
600
|
+
display: 'flex',
|
|
601
|
+
alignItems: 'center',
|
|
602
|
+
marginStart: 'text-to-visual'
|
|
603
|
+
});
|
|
604
|
+
|
|
605
|
+
const centeredWrapper = style({
|
|
606
|
+
display: 'flex',
|
|
607
|
+
alignItems: 'center',
|
|
608
|
+
justifyContent: 'center',
|
|
609
|
+
width: 'full',
|
|
610
|
+
height: 'full'
|
|
611
|
+
});
|
|
612
|
+
|
|
613
|
+
const loadingSpinnerWrapper = style({
|
|
614
|
+
padding: space(4)
|
|
615
|
+
});
|
|
616
|
+
|
|
617
|
+
const emptyStateWrapper = style({
|
|
618
|
+
display: 'flex',
|
|
619
|
+
alignItems: 'center',
|
|
620
|
+
justifyContent: 'center',
|
|
621
|
+
width: 'full',
|
|
622
|
+
height: 'full',
|
|
623
|
+
boxSizing: 'border-box',
|
|
624
|
+
padding: 16
|
|
625
|
+
});
|
|
626
|
+
|
|
627
|
+
function ListSelectionCheckbox({isDisabled}: {isDisabled: boolean}) {
|
|
628
|
+
let selectionContext = useSlottedContext(CheckboxContext, 'selection');
|
|
629
|
+
let isSelectionDisabled = isDisabled || !!selectionContext?.isDisabled;
|
|
630
|
+
return (
|
|
631
|
+
<div className={listCheckbox({isDisabled: isSelectionDisabled})}>
|
|
632
|
+
<Checkbox slot="selection" />
|
|
633
|
+
</div>
|
|
634
|
+
);
|
|
635
|
+
}
|
|
636
|
+
|
|
637
|
+
function isNextSelected(id: Key | undefined, state: ListState<unknown>) {
|
|
638
|
+
if (id == null || !state) {
|
|
639
|
+
return false;
|
|
640
|
+
}
|
|
641
|
+
let keyAfter = state.collection.getKeyAfter(id);
|
|
642
|
+
return keyAfter != null && state.selectionManager.isSelected(keyAfter);
|
|
643
|
+
}
|
|
644
|
+
function isPrevSelected(id: Key | undefined, state: ListState<unknown>) {
|
|
645
|
+
if (id == null || !state) {
|
|
646
|
+
return false;
|
|
647
|
+
}
|
|
648
|
+
let keyBefore = state.collection.getKeyBefore(id);
|
|
649
|
+
return keyBefore != null && state.selectionManager.isSelected(keyBefore);
|
|
650
|
+
}
|
|
651
|
+
|
|
652
|
+
function isFirstItem(id: Key | undefined, state: ListState<unknown>) {
|
|
653
|
+
if (id == null || !state) {
|
|
654
|
+
return false;
|
|
655
|
+
}
|
|
656
|
+
return state.collection.getFirstKey() === id;
|
|
657
|
+
}
|
|
658
|
+
function isLastItem(id: Key | undefined, state: ListState<unknown>) {
|
|
659
|
+
if (id == null || !state) {
|
|
660
|
+
return false;
|
|
661
|
+
}
|
|
662
|
+
return state.collection.getLastKey() === id;
|
|
663
|
+
}
|
|
664
|
+
|
|
665
|
+
export function ListViewItem(props: ListViewItemProps): ReactNode {
|
|
666
|
+
let ref = useRef(null);
|
|
667
|
+
let {hasChildItems, ...otherProps} = props;
|
|
668
|
+
let isLink = props.href != null;
|
|
669
|
+
let isLinkOut = isLink && props.target === '_blank';
|
|
670
|
+
let {isQuiet, selectionStyle, overflowMode, scale, hideLinkOutIcon = false} = useContext(InternalListViewContext);
|
|
671
|
+
let textValue = props.textValue || (typeof props.children === 'string' ? props.children : undefined);
|
|
672
|
+
let {direction} = useLocale();
|
|
673
|
+
let hasTrailingIcon = hasChildItems || (isLinkOut && !hideLinkOutIcon);
|
|
674
|
+
|
|
675
|
+
return (
|
|
676
|
+
<GridListItem
|
|
677
|
+
{...otherProps}
|
|
678
|
+
textValue={textValue}
|
|
679
|
+
ref={ref}
|
|
680
|
+
{...(hasTrailingIcon ? {'data-has-trailing-icon': ''} : {})}
|
|
681
|
+
className={renderProps => listitem({
|
|
682
|
+
...renderProps,
|
|
683
|
+
isLink,
|
|
684
|
+
isQuiet,
|
|
685
|
+
scale,
|
|
686
|
+
selectionStyle,
|
|
687
|
+
isPrevNotSelected: !isPrevSelected(renderProps.id, renderProps.state),
|
|
688
|
+
isNextSelected: isNextSelected(renderProps.id, renderProps.state),
|
|
689
|
+
isNextNotSelected: !isNextSelected(renderProps.id, renderProps.state),
|
|
690
|
+
isFirstItem: isFirstItem(renderProps.id, renderProps.state),
|
|
691
|
+
isLastItem: isLastItem(renderProps.id, renderProps.state)
|
|
692
|
+
})}>
|
|
693
|
+
{(renderProps) => {
|
|
694
|
+
let {children} = props;
|
|
695
|
+
let {selectionMode, selectionBehavior, isDisabled, id, state} = renderProps;
|
|
696
|
+
return (
|
|
697
|
+
<Provider
|
|
698
|
+
values={[
|
|
699
|
+
[TextContext, {
|
|
700
|
+
slots: {
|
|
701
|
+
[DEFAULT_SLOT]: {styles: label({...renderProps, overflowMode})},
|
|
702
|
+
label: {styles: label({...renderProps, overflowMode})},
|
|
703
|
+
description: {styles: description({...renderProps, overflowMode})}
|
|
704
|
+
}
|
|
705
|
+
}],
|
|
706
|
+
[IconContext, {
|
|
707
|
+
slots: {
|
|
708
|
+
icon: {render: centerBaseline({slot: 'icon', styles: iconCenterWrapper}), styles: icon}
|
|
709
|
+
}
|
|
710
|
+
}],
|
|
711
|
+
[ImageContext, {styles: image}],
|
|
712
|
+
[ActionButtonGroupContext, {
|
|
713
|
+
styles: actionButtonGroup,
|
|
714
|
+
size: 'S',
|
|
715
|
+
isQuiet: true
|
|
716
|
+
}],
|
|
717
|
+
[ActionMenuContext, {
|
|
718
|
+
styles: listActionMenu,
|
|
719
|
+
isQuiet: true,
|
|
720
|
+
size: 'S',
|
|
721
|
+
isDisabled
|
|
722
|
+
}]
|
|
723
|
+
]}>
|
|
724
|
+
<div
|
|
725
|
+
className={
|
|
726
|
+
listRowBackground({
|
|
727
|
+
...renderProps,
|
|
728
|
+
selectionStyle,
|
|
729
|
+
isQuiet,
|
|
730
|
+
isPrevSelected: isPrevSelected(id, state),
|
|
731
|
+
isNextSelected: isNextSelected(id, state),
|
|
732
|
+
isPrevNotSelected: !isPrevSelected(id, state),
|
|
733
|
+
isNextNotSelected: !isNextSelected(id, state),
|
|
734
|
+
isFirstItem: isFirstItem(id, state),
|
|
735
|
+
isLastItem: isLastItem(id, state)
|
|
736
|
+
})
|
|
737
|
+
} />
|
|
738
|
+
{selectionMode !== 'none' && selectionBehavior === 'toggle' && (
|
|
739
|
+
<ListSelectionCheckbox isDisabled={isDisabled} />
|
|
740
|
+
)}
|
|
741
|
+
{typeof children === 'string' ? <Text slot="label">{children}</Text> : children}
|
|
742
|
+
{isLinkOut && !hideLinkOutIcon && (
|
|
743
|
+
<div className={listTrailingIcon}>
|
|
744
|
+
<LinkOutIcon
|
|
745
|
+
size="M"
|
|
746
|
+
className={style({
|
|
747
|
+
scaleX: {
|
|
748
|
+
direction: {
|
|
749
|
+
rtl: -1
|
|
750
|
+
}
|
|
751
|
+
},
|
|
752
|
+
'--iconPrimary': {
|
|
753
|
+
type: 'fill',
|
|
754
|
+
value: 'currentColor'
|
|
755
|
+
}
|
|
756
|
+
})({direction})} />
|
|
757
|
+
</div>
|
|
758
|
+
)}
|
|
759
|
+
{hasChildItems && !isLinkOut && (
|
|
760
|
+
<div className={listTrailingIcon}>
|
|
761
|
+
<Chevron
|
|
762
|
+
className={style({
|
|
763
|
+
scale: {
|
|
764
|
+
direction: {
|
|
765
|
+
ltr: '1',
|
|
766
|
+
rtl: '-1'
|
|
767
|
+
}
|
|
768
|
+
},
|
|
769
|
+
'--iconPrimary': {
|
|
770
|
+
type: 'fill',
|
|
771
|
+
value: 'currentColor'
|
|
772
|
+
}
|
|
773
|
+
})({direction})} />
|
|
774
|
+
</div>
|
|
775
|
+
)}
|
|
776
|
+
</Provider>
|
|
777
|
+
);
|
|
778
|
+
}}
|
|
779
|
+
</GridListItem>
|
|
780
|
+
);
|
|
781
|
+
}
|
|
782
|
+
|