@react-spectrum/list 3.10.11 → 3.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 (229) hide show
  1. package/dist/import.mjs +3 -3
  2. package/dist/main.js +4 -4
  3. package/dist/main.js.map +1 -1
  4. package/dist/module.js +3 -3
  5. package/dist/module.js.map +1 -1
  6. package/dist/types/src/index.d.ts +3 -0
  7. package/package.json +13 -50
  8. package/src/index.ts +4 -3
  9. package/dist/DragPreview.main.js +0 -79
  10. package/dist/DragPreview.main.js.map +0 -1
  11. package/dist/DragPreview.mjs +0 -74
  12. package/dist/DragPreview.module.js +0 -74
  13. package/dist/DragPreview.module.js.map +0 -1
  14. package/dist/InsertionIndicator.main.js +0 -49
  15. package/dist/InsertionIndicator.main.js.map +0 -1
  16. package/dist/InsertionIndicator.mjs +0 -44
  17. package/dist/InsertionIndicator.module.js +0 -44
  18. package/dist/InsertionIndicator.module.js.map +0 -1
  19. package/dist/ListView.main.js +0 -300
  20. package/dist/ListView.main.js.map +0 -1
  21. package/dist/ListView.mjs +0 -294
  22. package/dist/ListView.module.js +0 -294
  23. package/dist/ListView.module.js.map +0 -1
  24. package/dist/ListViewItem.main.js +0 -245
  25. package/dist/ListViewItem.main.js.map +0 -1
  26. package/dist/ListViewItem.mjs +0 -240
  27. package/dist/ListViewItem.module.js +0 -240
  28. package/dist/ListViewItem.module.js.map +0 -1
  29. package/dist/ListViewLayout.main.js +0 -69
  30. package/dist/ListViewLayout.main.js.map +0 -1
  31. package/dist/ListViewLayout.mjs +0 -64
  32. package/dist/ListViewLayout.module.js +0 -64
  33. package/dist/ListViewLayout.module.js.map +0 -1
  34. package/dist/RootDropIndicator.main.js +0 -46
  35. package/dist/RootDropIndicator.main.js.map +0 -1
  36. package/dist/RootDropIndicator.mjs +0 -37
  37. package/dist/RootDropIndicator.module.js +0 -37
  38. package/dist/RootDropIndicator.module.js.map +0 -1
  39. package/dist/ar-AE.main.js +0 -7
  40. package/dist/ar-AE.main.js.map +0 -1
  41. package/dist/ar-AE.mjs +0 -9
  42. package/dist/ar-AE.module.js +0 -9
  43. package/dist/ar-AE.module.js.map +0 -1
  44. package/dist/bg-BG.main.js +0 -7
  45. package/dist/bg-BG.main.js.map +0 -1
  46. package/dist/bg-BG.mjs +0 -9
  47. package/dist/bg-BG.module.js +0 -9
  48. package/dist/bg-BG.module.js.map +0 -1
  49. package/dist/cs-CZ.main.js +0 -7
  50. package/dist/cs-CZ.main.js.map +0 -1
  51. package/dist/cs-CZ.mjs +0 -9
  52. package/dist/cs-CZ.module.js +0 -9
  53. package/dist/cs-CZ.module.js.map +0 -1
  54. package/dist/da-DK.main.js +0 -7
  55. package/dist/da-DK.main.js.map +0 -1
  56. package/dist/da-DK.mjs +0 -9
  57. package/dist/da-DK.module.js +0 -9
  58. package/dist/da-DK.module.js.map +0 -1
  59. package/dist/de-DE.main.js +0 -7
  60. package/dist/de-DE.main.js.map +0 -1
  61. package/dist/de-DE.mjs +0 -9
  62. package/dist/de-DE.module.js +0 -9
  63. package/dist/de-DE.module.js.map +0 -1
  64. package/dist/el-GR.main.js +0 -7
  65. package/dist/el-GR.main.js.map +0 -1
  66. package/dist/el-GR.mjs +0 -9
  67. package/dist/el-GR.module.js +0 -9
  68. package/dist/el-GR.module.js.map +0 -1
  69. package/dist/en-US.main.js +0 -7
  70. package/dist/en-US.main.js.map +0 -1
  71. package/dist/en-US.mjs +0 -9
  72. package/dist/en-US.module.js +0 -9
  73. package/dist/en-US.module.js.map +0 -1
  74. package/dist/es-ES.main.js +0 -7
  75. package/dist/es-ES.main.js.map +0 -1
  76. package/dist/es-ES.mjs +0 -9
  77. package/dist/es-ES.module.js +0 -9
  78. package/dist/es-ES.module.js.map +0 -1
  79. package/dist/et-EE.main.js +0 -7
  80. package/dist/et-EE.main.js.map +0 -1
  81. package/dist/et-EE.mjs +0 -9
  82. package/dist/et-EE.module.js +0 -9
  83. package/dist/et-EE.module.js.map +0 -1
  84. package/dist/fi-FI.main.js +0 -7
  85. package/dist/fi-FI.main.js.map +0 -1
  86. package/dist/fi-FI.mjs +0 -9
  87. package/dist/fi-FI.module.js +0 -9
  88. package/dist/fi-FI.module.js.map +0 -1
  89. package/dist/fr-FR.main.js +0 -7
  90. package/dist/fr-FR.main.js.map +0 -1
  91. package/dist/fr-FR.mjs +0 -9
  92. package/dist/fr-FR.module.js +0 -9
  93. package/dist/fr-FR.module.js.map +0 -1
  94. package/dist/he-IL.main.js +0 -7
  95. package/dist/he-IL.main.js.map +0 -1
  96. package/dist/he-IL.mjs +0 -9
  97. package/dist/he-IL.module.js +0 -9
  98. package/dist/he-IL.module.js.map +0 -1
  99. package/dist/hr-HR.main.js +0 -7
  100. package/dist/hr-HR.main.js.map +0 -1
  101. package/dist/hr-HR.mjs +0 -9
  102. package/dist/hr-HR.module.js +0 -9
  103. package/dist/hr-HR.module.js.map +0 -1
  104. package/dist/hu-HU.main.js +0 -7
  105. package/dist/hu-HU.main.js.map +0 -1
  106. package/dist/hu-HU.mjs +0 -9
  107. package/dist/hu-HU.module.js +0 -9
  108. package/dist/hu-HU.module.js.map +0 -1
  109. package/dist/intlStrings.main.js +0 -108
  110. package/dist/intlStrings.main.js.map +0 -1
  111. package/dist/intlStrings.mjs +0 -110
  112. package/dist/intlStrings.module.js +0 -110
  113. package/dist/intlStrings.module.js.map +0 -1
  114. package/dist/it-IT.main.js +0 -7
  115. package/dist/it-IT.main.js.map +0 -1
  116. package/dist/it-IT.mjs +0 -9
  117. package/dist/it-IT.module.js +0 -9
  118. package/dist/it-IT.module.js.map +0 -1
  119. package/dist/ja-JP.main.js +0 -7
  120. package/dist/ja-JP.main.js.map +0 -1
  121. package/dist/ja-JP.mjs +0 -9
  122. package/dist/ja-JP.module.js +0 -9
  123. package/dist/ja-JP.module.js.map +0 -1
  124. package/dist/ko-KR.main.js +0 -7
  125. package/dist/ko-KR.main.js.map +0 -1
  126. package/dist/ko-KR.mjs +0 -9
  127. package/dist/ko-KR.module.js +0 -9
  128. package/dist/ko-KR.module.js.map +0 -1
  129. package/dist/list.5918e378.css +0 -839
  130. package/dist/list.5918e378.css.map +0 -1
  131. package/dist/lt-LT.main.js +0 -7
  132. package/dist/lt-LT.main.js.map +0 -1
  133. package/dist/lt-LT.mjs +0 -9
  134. package/dist/lt-LT.module.js +0 -9
  135. package/dist/lt-LT.module.js.map +0 -1
  136. package/dist/lv-LV.main.js +0 -7
  137. package/dist/lv-LV.main.js.map +0 -1
  138. package/dist/lv-LV.mjs +0 -9
  139. package/dist/lv-LV.module.js +0 -9
  140. package/dist/lv-LV.module.js.map +0 -1
  141. package/dist/nb-NO.main.js +0 -7
  142. package/dist/nb-NO.main.js.map +0 -1
  143. package/dist/nb-NO.mjs +0 -9
  144. package/dist/nb-NO.module.js +0 -9
  145. package/dist/nb-NO.module.js.map +0 -1
  146. package/dist/nl-NL.main.js +0 -7
  147. package/dist/nl-NL.main.js.map +0 -1
  148. package/dist/nl-NL.mjs +0 -9
  149. package/dist/nl-NL.module.js +0 -9
  150. package/dist/nl-NL.module.js.map +0 -1
  151. package/dist/pl-PL.main.js +0 -7
  152. package/dist/pl-PL.main.js.map +0 -1
  153. package/dist/pl-PL.mjs +0 -9
  154. package/dist/pl-PL.module.js +0 -9
  155. package/dist/pl-PL.module.js.map +0 -1
  156. package/dist/pt-BR.main.js +0 -7
  157. package/dist/pt-BR.main.js.map +0 -1
  158. package/dist/pt-BR.mjs +0 -9
  159. package/dist/pt-BR.module.js +0 -9
  160. package/dist/pt-BR.module.js.map +0 -1
  161. package/dist/pt-PT.main.js +0 -7
  162. package/dist/pt-PT.main.js.map +0 -1
  163. package/dist/pt-PT.mjs +0 -9
  164. package/dist/pt-PT.module.js +0 -9
  165. package/dist/pt-PT.module.js.map +0 -1
  166. package/dist/ro-RO.main.js +0 -7
  167. package/dist/ro-RO.main.js.map +0 -1
  168. package/dist/ro-RO.mjs +0 -9
  169. package/dist/ro-RO.module.js +0 -9
  170. package/dist/ro-RO.module.js.map +0 -1
  171. package/dist/ru-RU.main.js +0 -7
  172. package/dist/ru-RU.main.js.map +0 -1
  173. package/dist/ru-RU.mjs +0 -9
  174. package/dist/ru-RU.module.js +0 -9
  175. package/dist/ru-RU.module.js.map +0 -1
  176. package/dist/sk-SK.main.js +0 -7
  177. package/dist/sk-SK.main.js.map +0 -1
  178. package/dist/sk-SK.mjs +0 -9
  179. package/dist/sk-SK.module.js +0 -9
  180. package/dist/sk-SK.module.js.map +0 -1
  181. package/dist/sl-SI.main.js +0 -7
  182. package/dist/sl-SI.main.js.map +0 -1
  183. package/dist/sl-SI.mjs +0 -9
  184. package/dist/sl-SI.module.js +0 -9
  185. package/dist/sl-SI.module.js.map +0 -1
  186. package/dist/sr-SP.main.js +0 -7
  187. package/dist/sr-SP.main.js.map +0 -1
  188. package/dist/sr-SP.mjs +0 -9
  189. package/dist/sr-SP.module.js +0 -9
  190. package/dist/sr-SP.module.js.map +0 -1
  191. package/dist/styles_css.main.js +0 -197
  192. package/dist/styles_css.main.js.map +0 -1
  193. package/dist/styles_css.mjs +0 -199
  194. package/dist/styles_css.module.js +0 -199
  195. package/dist/styles_css.module.js.map +0 -1
  196. package/dist/sv-SE.main.js +0 -7
  197. package/dist/sv-SE.main.js.map +0 -1
  198. package/dist/sv-SE.mjs +0 -9
  199. package/dist/sv-SE.module.js +0 -9
  200. package/dist/sv-SE.module.js.map +0 -1
  201. package/dist/tr-TR.main.js +0 -7
  202. package/dist/tr-TR.main.js.map +0 -1
  203. package/dist/tr-TR.mjs +0 -9
  204. package/dist/tr-TR.module.js +0 -9
  205. package/dist/tr-TR.module.js.map +0 -1
  206. package/dist/types.d.ts +0 -40
  207. package/dist/types.d.ts.map +0 -1
  208. package/dist/uk-UA.main.js +0 -7
  209. package/dist/uk-UA.main.js.map +0 -1
  210. package/dist/uk-UA.mjs +0 -9
  211. package/dist/uk-UA.module.js +0 -9
  212. package/dist/uk-UA.module.js.map +0 -1
  213. package/dist/zh-CN.main.js +0 -7
  214. package/dist/zh-CN.main.js.map +0 -1
  215. package/dist/zh-CN.mjs +0 -9
  216. package/dist/zh-CN.module.js +0 -9
  217. package/dist/zh-CN.module.js.map +0 -1
  218. package/dist/zh-TW.main.js +0 -7
  219. package/dist/zh-TW.main.js.map +0 -1
  220. package/dist/zh-TW.mjs +0 -9
  221. package/dist/zh-TW.module.js +0 -9
  222. package/dist/zh-TW.module.js.map +0 -1
  223. package/src/DragPreview.tsx +0 -72
  224. package/src/InsertionIndicator.tsx +0 -46
  225. package/src/ListView.tsx +0 -356
  226. package/src/ListViewItem.tsx +0 -284
  227. package/src/ListViewLayout.ts +0 -66
  228. package/src/RootDropIndicator.tsx +0 -27
  229. package/src/styles.css +0 -720
@@ -1,46 +0,0 @@
1
- import {classNames} from '@react-spectrum/utils';
2
- import {ItemDropTarget} from '@react-types/shared';
3
- import listStyles from './styles.css';
4
- import {ListViewContext} from './ListView';
5
- import React, {JSX, useContext, useRef} from 'react';
6
- import {useVisuallyHidden} from '@react-aria/visually-hidden';
7
-
8
- interface InsertionIndicatorProps {
9
- target: ItemDropTarget,
10
- isPresentationOnly?: boolean
11
- }
12
-
13
- export default function InsertionIndicator(props: InsertionIndicatorProps): JSX.Element | null {
14
- let {dropState, dragAndDropHooks} = useContext(ListViewContext)!;
15
- const {target, isPresentationOnly} = props;
16
-
17
- let ref = useRef<HTMLDivElement | null>(null);
18
- let {dropIndicatorProps} = dragAndDropHooks!.useDropIndicator!(props, dropState!, ref);
19
- let {visuallyHiddenProps} = useVisuallyHidden();
20
-
21
- let isDropTarget = dropState!.isDropTarget(target);
22
-
23
- if (!isDropTarget && dropIndicatorProps['aria-hidden']) {
24
- return null;
25
- }
26
-
27
- return (
28
- <div role="row" aria-hidden={dropIndicatorProps['aria-hidden']}>
29
- <div
30
- role="gridcell"
31
- aria-selected="false"
32
- className={
33
- classNames(
34
- listStyles,
35
- 'react-spectrum-ListViewInsertionIndicator',
36
- {
37
- 'react-spectrum-ListViewInsertionIndicator--dropTarget': isDropTarget
38
- }
39
- )}>
40
- {!isPresentationOnly &&
41
- <div {...visuallyHiddenProps} role="button" {...dropIndicatorProps} ref={ref} />
42
- }
43
- </div>
44
- </div>
45
- );
46
- }
package/src/ListView.tsx DELETED
@@ -1,356 +0,0 @@
1
- /*
2
- * Copyright 2021 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 {AriaGridListProps, useGridList} from '@react-aria/gridlist';
14
- import {AsyncLoadable, DOMRef, Key, LoadingState, Node, SpectrumSelectionProps, StyleProps} from '@react-types/shared';
15
- import {classNames, useDOMRef, useStyleProps} from '@react-spectrum/utils';
16
- import type {DragAndDropHooks} from '@react-spectrum/dnd';
17
- import type {DraggableCollectionState, DroppableCollectionState} from '@react-stately/dnd';
18
- import type {DroppableCollectionResult} from '@react-aria/dnd';
19
- import {filterDOMProps, mergeProps, useLayoutEffect} from '@react-aria/utils';
20
- import {FocusRing, FocusScope} from '@react-aria/focus';
21
- import InsertionIndicator from './InsertionIndicator';
22
- // @ts-ignore
23
- import intlMessages from '../intl/*.json';
24
- import {ListKeyboardDelegate} from '@react-aria/selection';
25
- import {ListState, useListState} from '@react-stately/list';
26
- import listStyles from './styles.css';
27
- import {ListViewItem} from './ListViewItem';
28
- import {ListViewLayout} from './ListViewLayout';
29
- import {ProgressCircle} from '@react-spectrum/progress';
30
- import React, {JSX, ReactElement, useCallback, useContext, useEffect, useMemo, useRef, useState} from 'react';
31
- import RootDropIndicator from './RootDropIndicator';
32
- import {DragPreview as SpectrumDragPreview} from './DragPreview';
33
- import {useLocalizedStringFormatter} from '@react-aria/i18n';
34
- import {useProvider} from '@react-spectrum/provider';
35
- import {Virtualizer} from '@react-aria/virtualizer';
36
-
37
- export interface SpectrumListViewProps<T> extends Omit<AriaGridListProps<T>, 'keyboardNavigationBehavior'>, StyleProps, SpectrumSelectionProps, Omit<AsyncLoadable, 'isLoading'> {
38
- /**
39
- * Sets the amount of vertical padding within each cell.
40
- * @default 'regular'
41
- */
42
- density?: 'compact' | 'regular' | 'spacious',
43
- /** Whether the ListView should be displayed with a quiet style. */
44
- isQuiet?: boolean,
45
- /** The current loading state of the ListView. Determines whether or not the progress circle should be shown. */
46
- loadingState?: LoadingState,
47
- /**
48
- * Sets the text behavior for the row contents.
49
- * @default 'truncate'
50
- */
51
- overflowMode?: 'truncate' | 'wrap',
52
- /** Sets what the ListView should render when there is no content to display. */
53
- renderEmptyState?: () => JSX.Element,
54
- /**
55
- * Handler that is called when a user performs an action on an item. The exact user event depends on
56
- * the collection's `selectionStyle` prop and the interaction modality.
57
- */
58
- onAction?: (key: Key) => void,
59
- /**
60
- * The drag and drop hooks returned by `useDragAndDrop` used to enable drag and drop behavior for the ListView.
61
- */
62
- dragAndDropHooks?: DragAndDropHooks<NoInfer<T>>['dragAndDropHooks']
63
- }
64
-
65
- interface ListViewContextValue<T> {
66
- state: ListState<T>,
67
- dragState: DraggableCollectionState | null,
68
- dropState: DroppableCollectionState | null,
69
- dragAndDropHooks?: DragAndDropHooks<T>['dragAndDropHooks'],
70
- onAction?: (key: Key) => void,
71
- isListDraggable: boolean,
72
- isListDroppable: boolean,
73
- layout: ListViewLayout<T>,
74
- loadingState?: LoadingState,
75
- renderEmptyState?: () => JSX.Element
76
- }
77
-
78
- export const ListViewContext = React.createContext<ListViewContextValue<unknown> | null>(null);
79
-
80
- const ROW_HEIGHTS = {
81
- compact: {
82
- medium: 32,
83
- large: 40
84
- },
85
- regular: {
86
- medium: 40,
87
- large: 50
88
- },
89
- spacious: {
90
- medium: 48,
91
- large: 60
92
- }
93
- };
94
-
95
- function useListLayout<T>(state: ListState<T>, density: SpectrumListViewProps<T>['density'], overflowMode: SpectrumListViewProps<T>['overflowMode']) {
96
- let {scale} = useProvider();
97
- let layout = useMemo(() =>
98
- new ListViewLayout<T>({
99
- estimatedRowHeight: ROW_HEIGHTS[density || 'regular'][scale]
100
- })
101
- // eslint-disable-next-line react-hooks/exhaustive-deps
102
- , [scale, density, overflowMode]);
103
-
104
- return layout;
105
- }
106
-
107
- /**
108
- * A ListView displays a list of interactive items, and allows a user to navigate, select, or perform an action.
109
- */
110
- export const ListView = React.forwardRef(function ListView<T extends object>(props: SpectrumListViewProps<T>, ref: DOMRef<HTMLDivElement>) {
111
- let {
112
- density = 'regular',
113
- loadingState,
114
- onLoadMore,
115
- isQuiet,
116
- overflowMode = 'truncate',
117
- onAction,
118
- dragAndDropHooks,
119
- renderEmptyState,
120
- ...otherProps
121
- } = props;
122
- let isListDraggable = !!dragAndDropHooks?.useDraggableCollectionState;
123
- let isListDroppable = !!dragAndDropHooks?.useDroppableCollectionState;
124
- let dragHooksProvided = useRef(isListDraggable);
125
- let dropHooksProvided = useRef(isListDroppable);
126
- useEffect(() => {
127
- if (dragHooksProvided.current !== isListDraggable && process.env.NODE_ENV !== 'production') {
128
- console.warn('Drag hooks were provided during one render, but not another. This should be avoided as it may produce unexpected behavior.');
129
- }
130
- if (dropHooksProvided.current !== isListDroppable && process.env.NODE_ENV !== 'production') {
131
- console.warn('Drop hooks were provided during one render, but not another. This should be avoided as it may produce unexpected behavior.');
132
- }
133
- }, [isListDraggable, isListDroppable]);
134
-
135
- let domRef = useDOMRef(ref);
136
- let state = useListState({
137
- ...props,
138
- selectionBehavior: props.selectionStyle === 'highlight' ? 'replace' : 'toggle'
139
- });
140
- let {collection, selectionManager} = state;
141
- let isLoading = loadingState === 'loading' || loadingState === 'loadingMore';
142
-
143
- let {styleProps} = useStyleProps(props);
144
- let dragState: DraggableCollectionState | null = null;
145
- let preview = useRef(null);
146
- if (isListDraggable && dragAndDropHooks) {
147
- dragState = dragAndDropHooks.useDraggableCollectionState!({
148
- collection,
149
- selectionManager,
150
- preview
151
- });
152
- dragAndDropHooks.useDraggableCollection!({}, dragState, domRef);
153
- }
154
- let layout = useListLayout(
155
- state,
156
- props.density || 'regular',
157
- overflowMode
158
- );
159
-
160
- let DragPreview = dragAndDropHooks?.DragPreview;
161
- let dropState: DroppableCollectionState | null = null;
162
- let droppableCollection: DroppableCollectionResult | null = null;
163
- let isRootDropTarget = false;
164
- if (isListDroppable && dragAndDropHooks) {
165
- dropState = dragAndDropHooks.useDroppableCollectionState!({
166
- collection,
167
- selectionManager
168
- });
169
- droppableCollection = dragAndDropHooks.useDroppableCollection!({
170
- keyboardDelegate: new ListKeyboardDelegate({
171
- collection,
172
- disabledKeys: dragState?.draggingKeys.size ? undefined : selectionManager.disabledKeys,
173
- ref: domRef,
174
- layoutDelegate: layout
175
- }),
176
- dropTargetDelegate: layout
177
- }, dropState, domRef);
178
-
179
- isRootDropTarget = dropState.isDropTarget({type: 'root'});
180
- }
181
-
182
- let {gridProps} = useGridList({
183
- ...props,
184
- isVirtualized: true,
185
- layoutDelegate: layout,
186
- onAction
187
- }, state, domRef);
188
-
189
- let focusedKey = selectionManager.focusedKey;
190
- let dropTargetKey: Key | null = null;
191
- if (dropState?.target?.type === 'item') {
192
- dropTargetKey = dropState.target.key;
193
- if (dropState.target.dropPosition === 'after') {
194
- // Normalize to the "before" drop position since we only render those in the DOM.
195
- dropTargetKey = state.collection.getKeyAfter(dropTargetKey) ?? dropTargetKey;
196
- }
197
- }
198
-
199
- let persistedKeys = useMemo(() => {
200
- return new Set([focusedKey, dropTargetKey].filter(k => k !== null));
201
- }, [focusedKey, dropTargetKey]);
202
-
203
- // wait for layout to get accurate measurements
204
- let [isVerticalScrollbarVisible, setVerticalScollbarVisible] = useState(false);
205
- let [isHorizontalScrollbarVisible, setHorizontalScollbarVisible] = useState(false);
206
- // eslint-disable-next-line react-hooks/exhaustive-deps
207
- useLayoutEffect(() => {
208
- if (domRef.current) {
209
- // 2 is the width of the border which is not part of the box size
210
- setVerticalScollbarVisible(domRef.current.clientWidth + 2 < domRef.current.offsetWidth);
211
- setHorizontalScollbarVisible(domRef.current.clientHeight + 2 < domRef.current.offsetHeight);
212
- }
213
- });
214
-
215
- let hasAnyChildren = useMemo(() => [...collection].some(item => item.hasChildNodes), [collection]);
216
-
217
- return (
218
- <ListViewContext.Provider value={{state, dragState, dropState, dragAndDropHooks, onAction, isListDraggable, isListDroppable, layout, loadingState, renderEmptyState}}>
219
- <FocusScope>
220
- <FocusRing focusRingClass={classNames(listStyles, 'focus-ring')}>
221
- <Virtualizer
222
- {...mergeProps(isListDroppable ? droppableCollection?.collectionProps : null, gridProps)}
223
- {...filterDOMProps(otherProps)}
224
- {...gridProps}
225
- {...styleProps}
226
- isLoading={isLoading}
227
- onLoadMore={onLoadMore}
228
- ref={domRef}
229
- persistedKeys={persistedKeys}
230
- scrollDirection="vertical"
231
- className={
232
- classNames(
233
- listStyles,
234
- 'react-spectrum-ListView',
235
- `react-spectrum-ListView--${density}`,
236
- 'react-spectrum-ListView--emphasized',
237
- {
238
- 'react-spectrum-ListView--quiet': isQuiet,
239
- 'react-spectrum-ListView--loadingMore': loadingState === 'loadingMore',
240
- 'react-spectrum-ListView--draggable': !!isListDraggable,
241
- 'react-spectrum-ListView--dropTarget': !!isRootDropTarget,
242
- 'react-spectrum-ListView--isVerticalScrollbarVisible': isVerticalScrollbarVisible,
243
- 'react-spectrum-ListView--isHorizontalScrollbarVisible': isHorizontalScrollbarVisible,
244
- 'react-spectrum-ListView--hasAnyChildren': hasAnyChildren,
245
- 'react-spectrum-ListView--wrap': overflowMode === 'wrap'
246
- },
247
- styleProps.className
248
- )
249
- }
250
- layout={layout}
251
- layoutOptions={useMemo(() => ({isLoading}), [isLoading])}
252
- collection={collection}>
253
- {useCallback((type, item: Node<T>) => {
254
- if (type === 'item') {
255
- return <Item item={item} />;
256
- } else if (type === 'loader') {
257
- return <LoadingView />;
258
- } else if (type === 'placeholder') {
259
- return <EmptyState />;
260
- }
261
- }, [])}
262
- </Virtualizer>
263
- </FocusRing>
264
- </FocusScope>
265
- {DragPreview && isListDraggable && dragAndDropHooks && dragState &&
266
- <DragPreview ref={preview}>
267
- {() => {
268
- if (dragState.draggedKey == null) {
269
- return null;
270
- }
271
- if (dragAndDropHooks.renderPreview) {
272
- return dragAndDropHooks.renderPreview(dragState.draggingKeys, dragState.draggedKey);
273
- }
274
- let item = state.collection.getItem(dragState.draggedKey);
275
- if (!item) {
276
- return null;
277
- }
278
- let itemCount = dragState.draggingKeys.size;
279
- let itemHeight = layout.getLayoutInfo(dragState.draggedKey)?.rect.height ?? 0;
280
- return <SpectrumDragPreview item={item} itemCount={itemCount} itemHeight={itemHeight} density={density} />;
281
- }}
282
- </DragPreview>
283
- }
284
- </ListViewContext.Provider>
285
- );
286
- }) as <T>(props: SpectrumListViewProps<T> & {ref?: DOMRef<HTMLDivElement>}) => ReactElement;
287
-
288
- function Item({item}: {item: Node<unknown>}) {
289
- let {isListDroppable, state, onAction} = useContext(ListViewContext)!;
290
- return (
291
- <>
292
- {isListDroppable && state.collection.getKeyBefore(item.key) == null &&
293
- <RootDropIndicator key="root" />
294
- }
295
- {isListDroppable &&
296
- <InsertionIndicator
297
- key={`${item.key}-before`}
298
- target={{key: item.key, type: 'item', dropPosition: 'before'}} />
299
- }
300
- <ListViewItem item={item} isEmphasized hasActions={!!onAction} />
301
- {isListDroppable &&
302
- <InsertionIndicator
303
- key={`${item.key}-after`}
304
- target={{key: item.key, type: 'item', dropPosition: 'after'}}
305
- isPresentationOnly={state.collection.getKeyAfter(item.key) != null} />
306
- }
307
- </>
308
- );
309
- }
310
-
311
- function LoadingView() {
312
- let {state} = useContext(ListViewContext)!;
313
- let stringFormatter = useLocalizedStringFormatter(intlMessages, '@react-spectrum/list');
314
- return (
315
- <CenteredWrapper>
316
- <ProgressCircle
317
- isIndeterminate
318
- aria-label={state.collection.size > 0 ? stringFormatter.format('loadingMore') : stringFormatter.format('loading')} />
319
- </CenteredWrapper>
320
- );
321
- }
322
-
323
- function EmptyState() {
324
- let {renderEmptyState} = useContext(ListViewContext)!;
325
- let emptyState = renderEmptyState ? renderEmptyState() : null;
326
- if (emptyState == null) {
327
- return null;
328
- }
329
-
330
- return (
331
- <CenteredWrapper>
332
- {emptyState}
333
- </CenteredWrapper>
334
- );
335
- }
336
-
337
- function CenteredWrapper({children}) {
338
- let {state} = useContext(ListViewContext)!;
339
- return (
340
- <div
341
- role="row"
342
- aria-rowindex={state.collection.size + 1}
343
- className={
344
- classNames(
345
- listStyles,
346
- 'react-spectrum-ListView-centeredWrapper',
347
- {
348
- 'react-spectrum-ListView-centeredWrapper--loadingMore': state.collection.size > 0
349
- }
350
- )}>
351
- <div role="gridcell">
352
- {children}
353
- </div>
354
- </div>
355
- );
356
- }
@@ -1,284 +0,0 @@
1
- /*
2
- * Copyright 2021 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
- import {Checkbox} from '@react-spectrum/checkbox';
13
- import ChevronLeftMedium from '@spectrum-icons/ui/ChevronLeftMedium';
14
- import ChevronRightMedium from '@spectrum-icons/ui/ChevronRightMedium';
15
- import {classNames, ClearSlots, SlotProvider, useHasChild} from '@react-spectrum/utils';
16
- import {CSSTransition} from 'react-transition-group';
17
- import type {DraggableItemResult, DropIndicatorAria} from '@react-aria/dnd';
18
- import {DropTarget, Node} from '@react-types/shared';
19
- import {FocusRing, useFocusRing} from '@react-aria/focus';
20
- import {Grid} from '@react-spectrum/layout';
21
- import {isFocusVisible as isGlobalFocusVisible, useHover} from '@react-aria/interactions';
22
- import ListGripper from '@spectrum-icons/ui/ListGripper';
23
- import listStyles from './styles.css';
24
- import {ListViewContext} from './ListView';
25
- import {mergeProps} from '@react-aria/utils';
26
- import {Provider} from '@react-spectrum/provider';
27
- import React, {JSX, useContext, useRef} from 'react';
28
- import {Text} from '@react-spectrum/text';
29
- import {useButton} from '@react-aria/button';
30
- import {useGridListItem, useGridListSelectionCheckbox} from '@react-aria/gridlist';
31
- import {useLocale} from '@react-aria/i18n';
32
- import {useVisuallyHidden} from '@react-aria/visually-hidden';
33
-
34
- interface ListViewItemProps<T> {
35
- item: Node<T>,
36
- isEmphasized: boolean,
37
- hasActions: boolean
38
- }
39
-
40
- export function ListViewItem<T>(props: ListViewItemProps<T>): JSX.Element {
41
- let {
42
- item,
43
- isEmphasized
44
- } = props;
45
- let {
46
- state,
47
- dragState,
48
- dropState,
49
- isListDraggable,
50
- isListDroppable,
51
- layout,
52
- dragAndDropHooks,
53
- loadingState
54
- } = useContext(ListViewContext)!;
55
- let {direction} = useLocale();
56
- let rowRef = useRef<HTMLDivElement | null>(null);
57
- let checkboxWrapperRef = useRef<HTMLDivElement | null>(null);
58
- let {
59
- isFocusVisible: isFocusVisibleWithin,
60
- focusProps: focusWithinProps
61
- } = useFocusRing({within: true});
62
- let {isFocusVisible, focusProps} = useFocusRing();
63
- let {
64
- rowProps,
65
- gridCellProps,
66
- isPressed,
67
- descriptionProps,
68
- isSelected,
69
- isDisabled,
70
- allowsSelection,
71
- hasAction
72
- } = useGridListItem({
73
- node: item,
74
- isVirtualized: true,
75
- shouldSelectOnPressUp: isListDraggable
76
- }, state, rowRef);
77
- let {hoverProps, isHovered} = useHover({isDisabled: !allowsSelection && !hasAction});
78
-
79
- let {checkboxProps} = useGridListSelectionCheckbox({key: item.key}, state);
80
- let hasDescription = useHasChild(`.${listStyles['react-spectrum-ListViewItem-description']}`, rowRef);
81
-
82
- let draggableItem: DraggableItemResult | null = null;
83
- if (isListDraggable && dragAndDropHooks && dragState) {
84
-
85
- draggableItem = dragAndDropHooks.useDraggableItem!({key: item.key, hasDragButton: true}, dragState);
86
- if (isDisabled) {
87
- draggableItem = null;
88
- }
89
- }
90
- let isDropTarget = false;
91
- let dropIndicator: DropIndicatorAria | null = null;
92
- let dropIndicatorRef = useRef<HTMLDivElement | null>(null);
93
- if (isListDroppable && dragAndDropHooks && dropState) {
94
- let target = {type: 'item', key: item.key, dropPosition: 'on'} as DropTarget;
95
- isDropTarget = dropState.isDropTarget(target);
96
-
97
- dropIndicator = dragAndDropHooks.useDropIndicator!({target}, dropState, dropIndicatorRef);
98
- }
99
-
100
- let dragButtonRef = React.useRef<HTMLDivElement | null>(null);
101
- let {buttonProps} = useButton({
102
- ...draggableItem?.dragButtonProps,
103
- elementType: 'div'
104
- }, dragButtonRef);
105
-
106
- let chevron = direction === 'ltr'
107
- ? (
108
- <ChevronRightMedium
109
- aria-hidden="true"
110
- UNSAFE_className={
111
- classNames(
112
- listStyles,
113
- 'react-spectrum-ListViewItem-parentIndicator',
114
- {
115
- 'react-spectrum-ListViewItem-parentIndicator--hasChildItems': item.props.hasChildItems,
116
- 'is-disabled': !hasAction
117
- }
118
- )
119
- } />
120
- )
121
- : (
122
- <ChevronLeftMedium
123
- aria-hidden="true"
124
- UNSAFE_className={
125
- classNames(
126
- listStyles,
127
- 'react-spectrum-ListViewItem-parentIndicator',
128
- {
129
- 'react-spectrum-ListViewItem-parentIndicator--hasChildItems': item.props.hasChildItems,
130
- 'is-disabled': !hasAction
131
- }
132
- )
133
- } />
134
- );
135
-
136
- let showCheckbox = state.selectionManager.selectionMode !== 'none' && state.selectionManager.selectionBehavior === 'toggle';
137
- let {visuallyHiddenProps} = useVisuallyHidden();
138
-
139
- const mergedProps = mergeProps(
140
- rowProps,
141
- draggableItem?.dragProps,
142
- hoverProps,
143
- focusWithinProps,
144
- focusProps
145
- );
146
-
147
- // Remove tab index from list row if performing a screenreader drag. This prevents TalkBack from focusing the row,
148
- // allowing for single swipe navigation between row drop indicator
149
- if (dragAndDropHooks?.isVirtualDragging?.()) {
150
- mergedProps.tabIndex = undefined;
151
- }
152
-
153
- let isFirstRow = item.prevKey == null;
154
- let isLastRow = item.nextKey == null;
155
- // Figure out if the ListView content is equal or greater in height to the container. If so, we'll need to round the bottom
156
- // border corners of the last row when selected and we can get rid of the bottom border if it isn't selected to avoid border overlap
157
- // with bottom border
158
- let isFlushWithContainerBottom = false;
159
- if (isLastRow && loadingState !== 'loadingMore') {
160
- if (layout.getContentSize()?.height >= (layout.virtualizer?.visibleRect.height ?? 0)) {
161
- isFlushWithContainerBottom = true;
162
- }
163
- }
164
- // previous item isn't selected
165
- // and the previous item isn't focused or, if it is focused, then if focus globally isn't visible or just focus isn't in the listview
166
- let roundTops = (!(item.prevKey != null && state.selectionManager.isSelected(item.prevKey))
167
- && (state.selectionManager.focusedKey !== item.prevKey || !(isGlobalFocusVisible() && state.selectionManager.isFocused)));
168
- let roundBottoms = (!(item.nextKey != null && state.selectionManager.isSelected(item.nextKey))
169
- && (state.selectionManager.focusedKey !== item.nextKey || !(isGlobalFocusVisible() && state.selectionManager.isFocused)));
170
-
171
- let content = typeof item.rendered === 'string' ? <Text>{item.rendered}</Text> : item.rendered;
172
- if (isDisabled) {
173
- content = <Provider isDisabled>{content}</Provider>;
174
- }
175
-
176
- return (
177
- <div
178
- {...mergedProps}
179
- className={
180
- classNames(
181
- listStyles,
182
- 'react-spectrum-ListView-row',
183
- {
184
- 'focus-ring': isFocusVisible,
185
- 'round-tops':
186
- roundTops || (isHovered && !isSelected && state.selectionManager.focusedKey !== item.key),
187
- 'round-bottoms':
188
- roundBottoms || (isHovered && !isSelected && state.selectionManager.focusedKey !== item.key)
189
- }
190
- )
191
- }
192
- ref={rowRef}>
193
- <div
194
- // TODO: refactor the css here now that we are focusing the row?
195
- className={
196
- classNames(
197
- listStyles,
198
- 'react-spectrum-ListViewItem',
199
- {
200
- 'is-active': isPressed,
201
- 'is-focused': isFocusVisibleWithin,
202
- 'focus-ring': isFocusVisible,
203
- 'is-hovered': isHovered,
204
- 'is-selected': isSelected,
205
- 'is-disabled': isDisabled,
206
- 'is-prev-selected': item.prevKey != null && state.selectionManager.isSelected(item.prevKey),
207
- 'is-next-selected': item.nextKey != null && state.selectionManager.isSelected(item.nextKey),
208
- 'react-spectrum-ListViewItem--highlightSelection': state.selectionManager.selectionBehavior === 'replace' && (isSelected || (item.nextKey != null && state.selectionManager.isSelected(item.nextKey))),
209
- 'react-spectrum-ListViewItem--dropTarget': !!isDropTarget,
210
- 'react-spectrum-ListViewItem--firstRow': isFirstRow,
211
- 'react-spectrum-ListViewItem--lastRow': isLastRow,
212
- 'react-spectrum-ListViewItem--isFlushBottom': isFlushWithContainerBottom,
213
- 'react-spectrum-ListViewItem--hasDescription': hasDescription
214
- }
215
- )
216
- }
217
- {...gridCellProps}>
218
- <Grid UNSAFE_className={listStyles['react-spectrum-ListViewItem-grid']}>
219
- {isListDraggable &&
220
- <div className={listStyles['react-spectrum-ListViewItem-draghandle-container']}>
221
- {!isDisabled &&
222
- <FocusRing focusRingClass={classNames(listStyles, 'focus-ring')}>
223
- <div
224
- {...buttonProps as React.HTMLAttributes<HTMLElement>}
225
- className={
226
- classNames(
227
- listStyles,
228
- 'react-spectrum-ListViewItem-draghandle-button'
229
- )
230
- }
231
- style={!isFocusVisibleWithin ? {...visuallyHiddenProps.style} : {}}
232
- ref={dragButtonRef}
233
- draggable="true">
234
- <ListGripper />
235
- </div>
236
- </FocusRing>
237
- }
238
- </div>
239
- }
240
- {isListDroppable && !dropIndicator?.isHidden &&
241
- <div role="button" {...visuallyHiddenProps} {...dropIndicator?.dropIndicatorProps} ref={dropIndicatorRef} />
242
- }
243
- <CSSTransition
244
- in={showCheckbox}
245
- unmountOnExit
246
- classNames={{
247
- enter: listStyles['react-spectrum-ListViewItem-checkbox--enter'],
248
- enterActive: listStyles['react-spectrum-ListViewItem-checkbox--enterActive'],
249
- exit: listStyles['react-spectrum-ListViewItem-checkbox--exit'],
250
- exitActive: listStyles['react-spectrum-ListViewItem-checkbox--exitActive']
251
- }}
252
- timeout={160}
253
- nodeRef={checkboxWrapperRef} >
254
- <div ref={checkboxWrapperRef} className={listStyles['react-spectrum-ListViewItem-checkboxWrapper']}>
255
- <Checkbox
256
- {...checkboxProps}
257
- UNSAFE_className={listStyles['react-spectrum-ListViewItem-checkbox']}
258
- isEmphasized={isEmphasized} />
259
- </div>
260
- </CSSTransition>
261
- <SlotProvider
262
- slots={{
263
- text: {UNSAFE_className: listStyles['react-spectrum-ListViewItem-content']},
264
- description: {UNSAFE_className: listStyles['react-spectrum-ListViewItem-description'], ...descriptionProps},
265
- illustration: {UNSAFE_className: listStyles['react-spectrum-ListViewItem-thumbnail']},
266
- image: {UNSAFE_className: listStyles['react-spectrum-ListViewItem-thumbnail']},
267
- actionButton: {UNSAFE_className: listStyles['react-spectrum-ListViewItem-actions'], isQuiet: true},
268
- actionGroup: {
269
- UNSAFE_className: listStyles['react-spectrum-ListViewItem-actions'],
270
- isQuiet: true,
271
- density: 'compact'
272
- },
273
- actionMenu: {UNSAFE_className: listStyles['react-spectrum-ListViewItem-actionmenu'], isQuiet: true}
274
- }}>
275
- {content}
276
- <ClearSlots>
277
- {chevron}
278
- </ClearSlots>
279
- </SlotProvider>
280
- </Grid>
281
- </div>
282
- </div>
283
- );
284
- }