@react-spectrum/table 3.0.0-beta.1 → 3.0.0-nightly-641446f65-240905

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 (266) hide show
  1. package/dist/DragPreview.main.js +54 -0
  2. package/dist/DragPreview.main.js.map +1 -0
  3. package/dist/DragPreview.mjs +49 -0
  4. package/dist/DragPreview.module.js +49 -0
  5. package/dist/DragPreview.module.js.map +1 -0
  6. package/dist/InsertionIndicator.main.js +63 -0
  7. package/dist/InsertionIndicator.main.js.map +1 -0
  8. package/dist/InsertionIndicator.mjs +58 -0
  9. package/dist/InsertionIndicator.module.js +58 -0
  10. package/dist/InsertionIndicator.module.js.map +1 -0
  11. package/dist/Nubbin.main.js +62 -0
  12. package/dist/Nubbin.main.js.map +1 -0
  13. package/dist/Nubbin.mjs +53 -0
  14. package/dist/Nubbin.module.js +53 -0
  15. package/dist/Nubbin.module.js.map +1 -0
  16. package/dist/Resizer.main.js +150 -0
  17. package/dist/Resizer.main.js.map +1 -0
  18. package/dist/Resizer.mjs +144 -0
  19. package/dist/Resizer.module.js +144 -0
  20. package/dist/Resizer.module.js.map +1 -0
  21. package/dist/RootDropIndicator.main.js +57 -0
  22. package/dist/RootDropIndicator.main.js.map +1 -0
  23. package/dist/RootDropIndicator.mjs +48 -0
  24. package/dist/RootDropIndicator.module.js +48 -0
  25. package/dist/RootDropIndicator.module.js.map +1 -0
  26. package/dist/TableView.main.js +50 -0
  27. package/dist/TableView.main.js.map +1 -0
  28. package/dist/TableView.mjs +41 -0
  29. package/dist/TableView.module.js +41 -0
  30. package/dist/TableView.module.js.map +1 -0
  31. package/dist/TableViewBase.main.js +1238 -0
  32. package/dist/TableViewBase.main.js.map +1 -0
  33. package/dist/TableViewBase.mjs +1231 -0
  34. package/dist/TableViewBase.module.js +1231 -0
  35. package/dist/TableViewBase.module.js.map +1 -0
  36. package/dist/TableViewLayout.main.js +97 -0
  37. package/dist/TableViewLayout.main.js.map +1 -0
  38. package/dist/TableViewLayout.mjs +92 -0
  39. package/dist/TableViewLayout.module.js +92 -0
  40. package/dist/TableViewLayout.module.js.map +1 -0
  41. package/dist/TableViewWrapper.main.js +46 -0
  42. package/dist/TableViewWrapper.main.js.map +1 -0
  43. package/dist/TableViewWrapper.mjs +37 -0
  44. package/dist/TableViewWrapper.module.js +37 -0
  45. package/dist/TableViewWrapper.module.js.map +1 -0
  46. package/dist/TreeGridTableView.main.js +50 -0
  47. package/dist/TreeGridTableView.main.js.map +1 -0
  48. package/dist/TreeGridTableView.mjs +41 -0
  49. package/dist/TreeGridTableView.module.js +41 -0
  50. package/dist/TreeGridTableView.module.js.map +1 -0
  51. package/dist/ar-AE.main.js +14 -0
  52. package/dist/ar-AE.main.js.map +1 -0
  53. package/dist/ar-AE.mjs +16 -0
  54. package/dist/ar-AE.module.js +16 -0
  55. package/dist/ar-AE.module.js.map +1 -0
  56. package/dist/bg-BG.main.js +14 -0
  57. package/dist/bg-BG.main.js.map +1 -0
  58. package/dist/bg-BG.mjs +16 -0
  59. package/dist/bg-BG.module.js +16 -0
  60. package/dist/bg-BG.module.js.map +1 -0
  61. package/dist/cs-CZ.main.js +14 -0
  62. package/dist/cs-CZ.main.js.map +1 -0
  63. package/dist/cs-CZ.mjs +16 -0
  64. package/dist/cs-CZ.module.js +16 -0
  65. package/dist/cs-CZ.module.js.map +1 -0
  66. package/dist/da-DK.main.js +14 -0
  67. package/dist/da-DK.main.js.map +1 -0
  68. package/dist/da-DK.mjs +16 -0
  69. package/dist/da-DK.module.js +16 -0
  70. package/dist/da-DK.module.js.map +1 -0
  71. package/dist/de-DE.main.js +14 -0
  72. package/dist/de-DE.main.js.map +1 -0
  73. package/dist/de-DE.mjs +16 -0
  74. package/dist/de-DE.module.js +16 -0
  75. package/dist/de-DE.module.js.map +1 -0
  76. package/dist/el-GR.main.js +14 -0
  77. package/dist/el-GR.main.js.map +1 -0
  78. package/dist/el-GR.mjs +16 -0
  79. package/dist/el-GR.module.js +16 -0
  80. package/dist/el-GR.module.js.map +1 -0
  81. package/dist/en-US.main.js +14 -0
  82. package/dist/en-US.main.js.map +1 -0
  83. package/dist/en-US.mjs +16 -0
  84. package/dist/en-US.module.js +16 -0
  85. package/dist/en-US.module.js.map +1 -0
  86. package/dist/es-ES.main.js +14 -0
  87. package/dist/es-ES.main.js.map +1 -0
  88. package/dist/es-ES.mjs +16 -0
  89. package/dist/es-ES.module.js +16 -0
  90. package/dist/es-ES.module.js.map +1 -0
  91. package/dist/et-EE.main.js +14 -0
  92. package/dist/et-EE.main.js.map +1 -0
  93. package/dist/et-EE.mjs +16 -0
  94. package/dist/et-EE.module.js +16 -0
  95. package/dist/et-EE.module.js.map +1 -0
  96. package/dist/fi-FI.main.js +14 -0
  97. package/dist/fi-FI.main.js.map +1 -0
  98. package/dist/fi-FI.mjs +16 -0
  99. package/dist/fi-FI.module.js +16 -0
  100. package/dist/fi-FI.module.js.map +1 -0
  101. package/dist/fr-FR.main.js +14 -0
  102. package/dist/fr-FR.main.js.map +1 -0
  103. package/dist/fr-FR.mjs +16 -0
  104. package/dist/fr-FR.module.js +16 -0
  105. package/dist/fr-FR.module.js.map +1 -0
  106. package/dist/he-IL.main.js +14 -0
  107. package/dist/he-IL.main.js.map +1 -0
  108. package/dist/he-IL.mjs +16 -0
  109. package/dist/he-IL.module.js +16 -0
  110. package/dist/he-IL.module.js.map +1 -0
  111. package/dist/hr-HR.main.js +14 -0
  112. package/dist/hr-HR.main.js.map +1 -0
  113. package/dist/hr-HR.mjs +16 -0
  114. package/dist/hr-HR.module.js +16 -0
  115. package/dist/hr-HR.module.js.map +1 -0
  116. package/dist/hu-HU.main.js +14 -0
  117. package/dist/hu-HU.main.js.map +1 -0
  118. package/dist/hu-HU.mjs +16 -0
  119. package/dist/hu-HU.module.js +16 -0
  120. package/dist/hu-HU.module.js.map +1 -0
  121. package/dist/import.mjs +22 -0
  122. package/dist/intlStrings.main.js +108 -0
  123. package/dist/intlStrings.main.js.map +1 -0
  124. package/dist/intlStrings.mjs +110 -0
  125. package/dist/intlStrings.module.js +110 -0
  126. package/dist/intlStrings.module.js.map +1 -0
  127. package/dist/it-IT.main.js +14 -0
  128. package/dist/it-IT.main.js.map +1 -0
  129. package/dist/it-IT.mjs +16 -0
  130. package/dist/it-IT.module.js +16 -0
  131. package/dist/it-IT.module.js.map +1 -0
  132. package/dist/ja-JP.main.js +14 -0
  133. package/dist/ja-JP.main.js.map +1 -0
  134. package/dist/ja-JP.mjs +16 -0
  135. package/dist/ja-JP.module.js +16 -0
  136. package/dist/ja-JP.module.js.map +1 -0
  137. package/dist/ko-KR.main.js +14 -0
  138. package/dist/ko-KR.main.js.map +1 -0
  139. package/dist/ko-KR.mjs +16 -0
  140. package/dist/ko-KR.module.js +16 -0
  141. package/dist/ko-KR.module.js.map +1 -0
  142. package/dist/lt-LT.main.js +14 -0
  143. package/dist/lt-LT.main.js.map +1 -0
  144. package/dist/lt-LT.mjs +16 -0
  145. package/dist/lt-LT.module.js +16 -0
  146. package/dist/lt-LT.module.js.map +1 -0
  147. package/dist/lv-LV.main.js +14 -0
  148. package/dist/lv-LV.main.js.map +1 -0
  149. package/dist/lv-LV.mjs +16 -0
  150. package/dist/lv-LV.module.js +16 -0
  151. package/dist/lv-LV.module.js.map +1 -0
  152. package/dist/main.js +28 -884
  153. package/dist/main.js.map +1 -1
  154. package/dist/module.js +17 -792
  155. package/dist/module.js.map +1 -1
  156. package/dist/nb-NO.main.js +14 -0
  157. package/dist/nb-NO.main.js.map +1 -0
  158. package/dist/nb-NO.mjs +16 -0
  159. package/dist/nb-NO.module.js +16 -0
  160. package/dist/nb-NO.module.js.map +1 -0
  161. package/dist/nl-NL.main.js +14 -0
  162. package/dist/nl-NL.main.js.map +1 -0
  163. package/dist/nl-NL.mjs +16 -0
  164. package/dist/nl-NL.module.js +16 -0
  165. package/dist/nl-NL.module.js.map +1 -0
  166. package/dist/pl-PL.main.js +14 -0
  167. package/dist/pl-PL.main.js.map +1 -0
  168. package/dist/pl-PL.mjs +16 -0
  169. package/dist/pl-PL.module.js +16 -0
  170. package/dist/pl-PL.module.js.map +1 -0
  171. package/dist/pt-BR.main.js +14 -0
  172. package/dist/pt-BR.main.js.map +1 -0
  173. package/dist/pt-BR.mjs +16 -0
  174. package/dist/pt-BR.module.js +16 -0
  175. package/dist/pt-BR.module.js.map +1 -0
  176. package/dist/pt-PT.main.js +14 -0
  177. package/dist/pt-PT.main.js.map +1 -0
  178. package/dist/pt-PT.mjs +16 -0
  179. package/dist/pt-PT.module.js +16 -0
  180. package/dist/pt-PT.module.js.map +1 -0
  181. package/dist/ro-RO.main.js +14 -0
  182. package/dist/ro-RO.main.js.map +1 -0
  183. package/dist/ro-RO.mjs +16 -0
  184. package/dist/ro-RO.module.js +16 -0
  185. package/dist/ro-RO.module.js.map +1 -0
  186. package/dist/ru-RU.main.js +14 -0
  187. package/dist/ru-RU.main.js.map +1 -0
  188. package/dist/ru-RU.mjs +16 -0
  189. package/dist/ru-RU.module.js +16 -0
  190. package/dist/ru-RU.module.js.map +1 -0
  191. package/dist/sk-SK.main.js +14 -0
  192. package/dist/sk-SK.main.js.map +1 -0
  193. package/dist/sk-SK.mjs +16 -0
  194. package/dist/sk-SK.module.js +16 -0
  195. package/dist/sk-SK.module.js.map +1 -0
  196. package/dist/sl-SI.main.js +14 -0
  197. package/dist/sl-SI.main.js.map +1 -0
  198. package/dist/sl-SI.mjs +16 -0
  199. package/dist/sl-SI.module.js +16 -0
  200. package/dist/sl-SI.module.js.map +1 -0
  201. package/dist/sr-SP.main.js +14 -0
  202. package/dist/sr-SP.main.js.map +1 -0
  203. package/dist/sr-SP.mjs +16 -0
  204. package/dist/sr-SP.module.js +16 -0
  205. package/dist/sr-SP.module.js.map +1 -0
  206. package/dist/sv-SE.main.js +14 -0
  207. package/dist/sv-SE.main.js.map +1 -0
  208. package/dist/sv-SE.mjs +16 -0
  209. package/dist/sv-SE.module.js +16 -0
  210. package/dist/sv-SE.module.js.map +1 -0
  211. package/dist/table.b13eee90.css +220 -0
  212. package/dist/table.b13eee90.css.map +1 -0
  213. package/dist/table_css.main.js +74 -0
  214. package/dist/table_css.main.js.map +1 -0
  215. package/dist/table_css.mjs +76 -0
  216. package/dist/table_css.module.js +76 -0
  217. package/dist/table_css.module.js.map +1 -0
  218. package/dist/table_vars_css.main.js +197 -0
  219. package/dist/table_vars_css.main.js.map +1 -0
  220. package/dist/table_vars_css.mjs +199 -0
  221. package/dist/table_vars_css.module.js +199 -0
  222. package/dist/table_vars_css.module.js.map +1 -0
  223. package/dist/tr-TR.main.js +14 -0
  224. package/dist/tr-TR.main.js.map +1 -0
  225. package/dist/tr-TR.mjs +16 -0
  226. package/dist/tr-TR.module.js +16 -0
  227. package/dist/tr-TR.module.js.map +1 -0
  228. package/dist/types.d.ts +77 -4
  229. package/dist/types.d.ts.map +1 -1
  230. package/dist/uk-UA.main.js +14 -0
  231. package/dist/uk-UA.main.js.map +1 -0
  232. package/dist/uk-UA.mjs +16 -0
  233. package/dist/uk-UA.module.js +16 -0
  234. package/dist/uk-UA.module.js.map +1 -0
  235. package/dist/vars.ce47d5ba.css +992 -0
  236. package/dist/vars.ce47d5ba.css.map +1 -0
  237. package/dist/zh-CN.main.js +14 -0
  238. package/dist/zh-CN.main.js.map +1 -0
  239. package/dist/zh-CN.mjs +16 -0
  240. package/dist/zh-CN.module.js +16 -0
  241. package/dist/zh-CN.module.js.map +1 -0
  242. package/dist/zh-TW.main.js +14 -0
  243. package/dist/zh-TW.main.js.map +1 -0
  244. package/dist/zh-TW.mjs +16 -0
  245. package/dist/zh-TW.module.js +16 -0
  246. package/dist/zh-TW.module.js.map +1 -0
  247. package/package.json +40 -28
  248. package/src/DragPreview.tsx +77 -0
  249. package/src/InsertionIndicator.tsx +62 -0
  250. package/src/Nubbin.tsx +28 -0
  251. package/src/Resizer.tsx +139 -0
  252. package/src/RootDropIndicator.tsx +40 -0
  253. package/src/TableView.tsx +24 -630
  254. package/src/TableViewBase.tsx +1552 -0
  255. package/src/TableViewLayout.ts +95 -0
  256. package/src/TableViewWrapper.tsx +106 -0
  257. package/src/TreeGridTableView.tsx +47 -0
  258. package/src/cursors/Cur_MoveHorizontal_9_9.svg +10 -0
  259. package/src/cursors/Cur_MoveToLeft_9_9.svg +10 -0
  260. package/src/cursors/Cur_MoveToRight_9_9.svg +10 -0
  261. package/src/index.ts +5 -1
  262. package/src/table.css +191 -0
  263. package/LICENSE +0 -201
  264. package/dist/main.css +0 -2
  265. package/dist/main.css.map +0 -1
  266. package/src/.DS_Store +0 -0
package/src/TableView.tsx CHANGED
@@ -1,5 +1,5 @@
1
1
  /*
2
- * Copyright 2020 Adobe. All rights reserved.
2
+ * Copyright 2023 Adobe. All rights reserved.
3
3
  * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4
4
  * you may not use this file except in compliance with the License. You may obtain a copy
5
5
  * of the License at http://www.apache.org/licenses/LICENSE-2.0
@@ -10,644 +10,38 @@
10
10
  * governing permissions and limitations under the License.
11
11
  */
12
12
 
13
- import ArrowDownSmall from '@spectrum-icons/ui/ArrowDownSmall';
14
- import {Checkbox} from '@react-spectrum/checkbox';
15
- import {classNames, useDOMRef, useStyleProps} from '@react-spectrum/utils';
16
13
  import {DOMRef} from '@react-types/shared';
17
- import {FocusRing, useFocusRing} from '@react-aria/focus';
18
- import {GridNode} from '@react-types/grid';
19
- // @ts-ignore
20
- import intlMessages from '../intl/*.json';
21
- import {layoutInfoToStyle, ScrollView, setScrollLeft, useVirtualizer, VirtualizerItem} from '@react-aria/virtualizer';
22
- import {mergeProps, useLayoutEffect} from '@react-aria/utils';
23
- import {ProgressCircle} from '@react-spectrum/progress';
24
- import React, {ReactElement, useCallback, useContext, useMemo, useRef} from 'react';
25
- import {Rect, ReusableView, useVirtualizerState} from '@react-stately/virtualizer';
26
- import {SpectrumColumnProps, SpectrumTableProps} from '@react-types/table';
27
- import styles from '@adobe/spectrum-css-temp/components/table/vars.css';
28
- import stylesOverrides from './table.css';
29
- import {TableLayout} from '@react-stately/layout';
30
- import {TableState, useTableState} from '@react-stately/table';
31
- import {Tooltip, TooltipTrigger} from '@react-spectrum/tooltip';
32
- import {useHover} from '@react-aria/interactions';
33
- import {useLocale, useMessageFormatter} from '@react-aria/i18n';
34
- import {usePress} from '@react-aria/interactions';
35
- import {useProvider, useProviderProps} from '@react-spectrum/provider';
36
- import {useTable, useTableCell, useTableColumnHeader, useTableHeaderRow, useTableRow, useTableRowGroup, useTableSelectAllCheckbox, useTableSelectionCheckbox} from '@react-aria/table';
37
- import {VisuallyHidden} from '@react-aria/visually-hidden';
14
+ import React, {ReactElement, useState} from 'react';
15
+ import {SpectrumTableProps} from './TableViewWrapper';
16
+ import {TableViewBase} from './TableViewBase';
17
+ import {useTableState} from '@react-stately/table';
38
18
 
39
- const DEFAULT_HEADER_HEIGHT = {
40
- medium: 34,
41
- large: 40
42
- };
19
+ interface TableProps<T> extends Omit<SpectrumTableProps<T>, 'UNSTABLE_allowsExpandableRows'> {}
43
20
 
44
- const DEFAULT_HIDE_HEADER_CELL_WIDTH = {
45
- medium: 36,
46
- large: 44
47
- };
48
-
49
- const ROW_HEIGHTS = {
50
- compact: {
51
- medium: 32,
52
- large: 40
53
- },
54
- regular: {
55
- medium: 40,
56
- large: 50
57
- },
58
- spacious: {
59
- medium: 48,
60
- large: 60
61
- }
62
- };
63
-
64
- const SELECTION_CELL_DEFAULT_WIDTH = 55;
65
-
66
- const TableContext = React.createContext<TableState<unknown>>(null);
67
- function useTableContext() {
68
- return useContext(TableContext);
69
- }
70
-
71
- function TableView<T extends object>(props: SpectrumTableProps<T>, ref: DOMRef<HTMLDivElement>) {
72
- props = useProviderProps(props);
73
- let {isQuiet} = props;
74
- let {styleProps} = useStyleProps(props);
75
- let state = useTableState({...props, showSelectionCheckboxes: true});
76
- let domRef = useDOMRef(ref);
77
- let formatMessage = useMessageFormatter(intlMessages);
78
-
79
- let {scale} = useProvider();
80
- let density = props.density || 'regular';
81
- let layout = useMemo(() => new TableLayout({
82
- // If props.rowHeight is auto, then use estimated heights based on scale, otherwise use fixed heights.
83
- rowHeight: props.overflowMode === 'wrap'
84
- ? null
85
- : ROW_HEIGHTS[density][scale],
86
- estimatedRowHeight: props.overflowMode === 'wrap'
87
- ? ROW_HEIGHTS[density][scale]
88
- : null,
89
- headingHeight: props.overflowMode === 'wrap'
90
- ? null
91
- : DEFAULT_HEADER_HEIGHT[scale],
92
- estimatedHeadingHeight: props.overflowMode === 'wrap'
93
- ? DEFAULT_HEADER_HEIGHT[scale]
94
- : null,
95
- getDefaultWidth: ({hideHeader, isSelectionCell, showDivider}) => {
96
- if (hideHeader) {
97
- let width = DEFAULT_HIDE_HEADER_CELL_WIDTH[scale];
98
- return showDivider ? width + 1 : width;
99
- } else if (isSelectionCell) {
100
- return SELECTION_CELL_DEFAULT_WIDTH;
101
- }
102
- }
103
- }), [props.overflowMode, scale, density]);
104
- let {direction} = useLocale();
105
- layout.collection = state.collection;
106
-
107
- let {gridProps} = useTable({
21
+ function TableView<T extends object>(props: TableProps<T>, ref: DOMRef<HTMLDivElement>) {
22
+ let {
23
+ selectionStyle,
24
+ dragAndDropHooks
25
+ } = props;
26
+ let [showSelectionCheckboxes, setShowSelectionCheckboxes] = useState(selectionStyle !== 'highlight');
27
+ let isTableDraggable = !!dragAndDropHooks?.useDraggableCollectionState;
28
+ let state = useTableState({
108
29
  ...props,
109
- isVirtualized: true,
110
- layout
111
- }, state, domRef);
112
-
113
- // This overrides collection view's renderWrapper to support DOM heirarchy.
114
- type View = ReusableView<GridNode<T>, unknown>;
115
- let renderWrapper = (parent: View, reusableView: View, children: View[], renderChildren: (views: View[]) => ReactElement[]) => {
116
- let style = layoutInfoToStyle(reusableView.layoutInfo, direction, parent && parent.layoutInfo);
117
- if (style.overflow === 'hidden') {
118
- style.overflow = 'visible'; // needed to support position: sticky
119
- }
120
-
121
- if (reusableView.viewType === 'rowgroup') {
122
- return (
123
- <TableRowGroup
124
- key={reusableView.key}
125
- style={style}>
126
- {renderChildren(children)}
127
- </TableRowGroup>
128
- );
129
- }
130
-
131
- if (reusableView.viewType === 'header') {
132
- return (
133
- <TableHeader
134
- key={reusableView.key}
135
- style={style}>
136
- {renderChildren(children)}
137
- </TableHeader>
138
- );
139
- }
140
-
141
- if (reusableView.viewType === 'row') {
142
- return (
143
- <TableRow
144
- key={reusableView.key}
145
- item={reusableView.content}
146
- style={style}>
147
- {renderChildren(children)}
148
- </TableRow>
149
- );
150
- }
151
-
152
- if (reusableView.viewType === 'headerrow') {
153
- return (
154
- <TableHeaderRow
155
- key={reusableView.key}
156
- style={style}
157
- item={reusableView.content}>
158
- {renderChildren(children)}
159
- </TableHeaderRow>
160
- );
161
- }
162
-
163
- return (
164
- <VirtualizerItem
165
- key={reusableView.key}
166
- reusableView={reusableView}
167
- parent={parent}
168
- className={
169
- classNames(
170
- styles,
171
- 'spectrum-Table-cellWrapper',
172
- classNames(
173
- stylesOverrides,
174
- {
175
- 'react-spectrum-Table-cellWrapper': !reusableView.layoutInfo.estimatedSize
176
- }
177
- )
178
- )
179
- } />
180
- );
181
- };
182
-
183
- let renderView = (type: string, item: GridNode<T>) => {
184
- switch (type) {
185
- case 'header':
186
- case 'rowgroup':
187
- case 'section':
188
- case 'row':
189
- case 'headerrow':
190
- return null;
191
- case 'cell': {
192
- if (item.props.isSelectionCell) {
193
- return <TableCheckboxCell cell={item} />;
194
- }
195
-
196
- return <TableCell cell={item} />;
197
- }
198
- case 'placeholder':
199
- // TODO: move to react-aria?
200
- return (
201
- <div
202
- role="gridcell"
203
- aria-colindex={item.index + 1}
204
- aria-colspan={item.colspan > 1 ? item.colspan : null} />
205
- );
206
- case 'column':
207
- if (item.props.isSelectionCell) {
208
- return <TableSelectAllCell column={item} />;
209
- }
210
-
211
- if (item.props.hideHeader) {
212
- return (
213
- <TooltipTrigger placement="top" trigger="focus">
214
- <TableColumnHeader column={item} />
215
- <Tooltip placement="top">{item.rendered}</Tooltip>
216
- </TooltipTrigger>
217
- );
218
- }
219
-
220
- return <TableColumnHeader column={item} />;
221
- case 'loader':
222
- return (
223
- <CenteredWrapper>
224
- <ProgressCircle
225
- isIndeterminate
226
- aria-label={state.collection.size > 0 ? formatMessage('loadingMore') : formatMessage('loading')} />
227
- </CenteredWrapper>
228
- );
229
- case 'empty': {
230
- let emptyState = props.renderEmptyState ? props.renderEmptyState() : null;
231
- if (emptyState == null) {
232
- return null;
233
- }
234
-
235
- return (
236
- <CenteredWrapper>
237
- {emptyState}
238
- </CenteredWrapper>
239
- );
240
- }
241
- }
242
- };
243
-
244
- return (
245
- <TableContext.Provider value={state}>
246
- <TableVirtualizer
247
- {...gridProps}
248
- {...styleProps}
249
- className={
250
- classNames(
251
- styles,
252
- 'spectrum-Table',
253
- `spectrum-Table--${density}`,
254
- {
255
- 'spectrum-Table--quiet': isQuiet,
256
- 'spectrum-Table--wrap': props.overflowMode === 'wrap'
257
- },
258
- classNames(
259
- stylesOverrides,
260
- 'react-spectrum-Table'
261
- )
262
- )
263
- }
264
- layout={layout}
265
- collection={state.collection}
266
- focusedKey={state.selectionManager.focusedKey}
267
- renderView={renderView}
268
- renderWrapper={renderWrapper}
269
- domRef={domRef} />
270
- </TableContext.Provider>
271
- );
272
- }
273
-
274
- // This is a custom Virtualizer that also has a header that syncs its scroll position with the body.
275
- function TableVirtualizer({layout, collection, focusedKey, renderView, renderWrapper, domRef, ...otherProps}) {
276
- let {direction} = useLocale();
277
- let headerRef = useRef<HTMLDivElement>();
278
- let bodyRef = useRef<HTMLDivElement>();
279
- let loadingState = collection.body.props.loadingState;
280
- let isLoading = loadingState === 'loading' || loadingState === 'loadingMore';
281
- let onLoadMore = collection.body.props.onLoadMore;
282
- let state = useVirtualizerState({
283
- layout,
284
- collection,
285
- renderView,
286
- renderWrapper,
287
- onVisibleRectChange(rect) {
288
- bodyRef.current.scrollTop = rect.y;
289
- setScrollLeft(bodyRef.current, direction, rect.x);
290
- },
291
- transitionDuration: isLoading ? 160 : 220
30
+ showSelectionCheckboxes,
31
+ showDragButtons: isTableDraggable,
32
+ selectionBehavior: props.selectionStyle === 'highlight' ? 'replace' : 'toggle'
292
33
  });
293
34
 
294
- let {virtualizerProps} = useVirtualizer({
295
- focusedKey,
296
- scrollToItem(key) {
297
- let item = collection.getItem(key);
298
- let column = collection.columns[0];
299
- state.virtualizer.scrollToItem(key, {
300
- duration: 0,
301
- // Prevent scrolling to the top when clicking on column headers.
302
- shouldScrollY: item?.type !== 'column',
303
- // Offset scroll position by width of selection cell
304
- // (which is sticky and will overlap the cell we're scrolling to).
305
- offsetX: column.props.isSelectionCell
306
- ? layout.columnWidths.get(column.key)
307
- : 0
308
- });
309
- }
310
- }, state, domRef);
311
-
312
- let headerHeight = layout.getLayoutInfo('header')?.rect.height || 0;
313
- let visibleRect = state.virtualizer.visibleRect;
314
-
315
- // Sync the scroll position from the table body to the header container.
316
- let onScroll = useCallback(() => {
317
- headerRef.current.scrollLeft = bodyRef.current.scrollLeft;
318
- }, [bodyRef]);
319
-
320
- let onVisibleRectChange = useCallback((rect: Rect) => {
321
- state.setVisibleRect(rect);
322
-
323
- if (!isLoading && onLoadMore) {
324
- let scrollOffset = state.virtualizer.contentSize.height - rect.height * 2;
325
- if (rect.y > scrollOffset) {
326
- onLoadMore();
327
- }
328
- }
329
- }, [onLoadMore, isLoading, state.setVisibleRect, state.virtualizer]);
330
-
331
- useLayoutEffect(() => {
332
- if (!isLoading && onLoadMore && !state.isAnimating) {
333
- if (state.contentSize.height <= state.virtualizer.visibleRect.height) {
334
- onLoadMore();
335
- }
336
- }
337
- }, [state.contentSize, state.virtualizer, state.isAnimating, onLoadMore, isLoading]);
338
-
339
- return (
340
- <div
341
- {...mergeProps(otherProps, virtualizerProps)}
342
- ref={domRef}>
343
- <div
344
- role="presentation"
345
- style={{
346
- width: visibleRect.width,
347
- height: headerHeight,
348
- overflow: 'hidden',
349
- position: 'relative',
350
- willChange: state.isScrolling ? 'scroll-position' : '',
351
- transition: state.isAnimating ? `none ${state.virtualizer.transitionDuration}ms` : undefined
352
- }}
353
- ref={headerRef}>
354
- {state.visibleViews[0]}
355
- </div>
356
- <ScrollView
357
- role="presentation"
358
- className={classNames(styles, 'spectrum-Table-body')}
359
- style={{flex: 1}}
360
- innerStyle={{overflow: 'visible', transition: state.isAnimating ? `none ${state.virtualizer.transitionDuration}ms` : undefined}}
361
- ref={bodyRef}
362
- contentSize={state.contentSize}
363
- onVisibleRectChange={onVisibleRectChange}
364
- onScrollStart={state.startScrolling}
365
- onScrollEnd={state.endScrolling}
366
- onScroll={onScroll}>
367
- {state.visibleViews[1]}
368
- </ScrollView>
369
- </div>
370
- );
371
- }
372
-
373
- function TableHeader({children, ...otherProps}) {
374
- let {rowGroupProps} = useTableRowGroup();
375
-
376
- return (
377
- <div {...rowGroupProps} {...otherProps} className={classNames(styles, 'spectrum-Table-head')}>
378
- {children}
379
- </div>
380
- );
381
- }
382
-
383
- function TableColumnHeader({column}) {
384
- let ref = useRef();
385
- let state = useTableContext();
386
- let {columnHeaderProps} = useTableColumnHeader({
387
- node: column,
388
- isVirtualized: true
389
- }, state, ref);
390
-
391
- let columnProps = column.props as SpectrumColumnProps<unknown>;
392
- let {hoverProps, isHovered} = useHover({});
393
-
394
- return (
395
- <FocusRing focusRingClass={classNames(styles, 'focus-ring')}>
396
- <div
397
- {...mergeProps(columnHeaderProps, hoverProps)}
398
- ref={ref}
399
- className={
400
- classNames(
401
- styles,
402
- 'spectrum-Table-headCell',
403
- {
404
- 'is-sortable': columnProps.allowsSorting,
405
- 'is-sorted-desc': state.sortDescriptor?.column === column.key && state.sortDescriptor?.direction === 'descending',
406
- 'is-sorted-asc': state.sortDescriptor?.column === column.key && state.sortDescriptor?.direction === 'ascending',
407
- 'is-hovered': isHovered,
408
- 'spectrum-Table-cell--hideHeader': columnProps.hideHeader
409
- },
410
- classNames(
411
- stylesOverrides,
412
- 'react-spectrum-Table-cell',
413
- {
414
- 'react-spectrum-Table-cell--alignCenter': columnProps.align === 'center' || column.colspan > 1,
415
- 'react-spectrum-Table-cell--alignEnd': columnProps.align === 'end'
416
- }
417
- )
418
- )
419
- }>
420
- {columnProps.hideHeader ?
421
- <VisuallyHidden>{column.rendered}</VisuallyHidden> :
422
- column.rendered
423
- }
424
- {columnProps.allowsSorting &&
425
- <ArrowDownSmall UNSAFE_className={classNames(styles, 'spectrum-Table-sortedIcon')} />
426
- }
427
-
428
- </div>
429
- </FocusRing>
430
- );
431
- }
432
-
433
- function TableSelectAllCell({column}) {
434
- let ref = useRef();
435
- let state = useTableContext();
436
- let isSingleSelectionMode = state.selectionManager.selectionMode === 'single';
437
- let {columnHeaderProps} = useTableColumnHeader({
438
- node: column,
439
- isVirtualized: true
440
- }, state, ref);
441
-
442
- let {checkboxProps} = useTableSelectAllCheckbox(state);
443
- let {hoverProps, isHovered} = useHover({});
444
-
445
- return (
446
- <FocusRing focusRingClass={classNames(styles, 'focus-ring')}>
447
- <div
448
- {...mergeProps(columnHeaderProps, hoverProps)}
449
- ref={ref}
450
- className={
451
- classNames(
452
- styles,
453
- 'spectrum-Table-headCell',
454
- 'spectrum-Table-checkboxCell',
455
- {
456
- 'is-hovered': isHovered
457
- }
458
- )
459
- }>
460
- <Checkbox
461
- {...checkboxProps}
462
- isDisabled={isSingleSelectionMode}
463
- isEmphasized
464
- UNSAFE_style={{visibility: isSingleSelectionMode ? 'hidden' : 'visible'}}
465
- UNSAFE_className={classNames(styles, 'spectrum-Table-checkbox')} />
466
- </div>
467
- </FocusRing>
468
- );
469
- }
470
-
471
- function TableRowGroup({children, ...otherProps}) {
472
- let {rowGroupProps} = useTableRowGroup();
473
-
474
- return (
475
- <div {...rowGroupProps} {...otherProps}>
476
- {children}
477
- </div>
478
- );
479
- }
480
-
481
- function TableRow({item, children, ...otherProps}) {
482
- let ref = useRef();
483
- let state = useTableContext();
484
- let allowsSelection = state.selectionManager.selectionMode !== 'none';
485
- let isDisabled = state.disabledKeys.has(item.key);
486
- let isSelected = state.selectionManager.isSelected(item.key);
487
- let {rowProps} = useTableRow({
488
- node: item,
489
- isVirtualized: true
490
- }, state, ref);
491
-
492
- let {pressProps, isPressed} = usePress({isDisabled});
493
-
494
- // The row should show the focus background style when any cell inside it is focused.
495
- // If the row itself is focused, then it should have a blue focus indicator on the left.
496
- let {
497
- isFocusVisible: isFocusVisibleWithin,
498
- focusProps: focusWithinProps
499
- } = useFocusRing({within: true});
500
- let {isFocusVisible, focusProps} = useFocusRing();
501
- let {hoverProps, isHovered} = useHover({isDisabled});
502
- let props = mergeProps(
503
- rowProps,
504
- otherProps,
505
- focusWithinProps,
506
- focusProps,
507
- hoverProps,
508
- allowsSelection && pressProps
509
- );
510
-
511
- return (
512
- <div
513
- {...props}
514
- ref={ref}
515
- className={
516
- classNames(
517
- styles,
518
- 'spectrum-Table-row',
519
- {
520
- 'is-active': isPressed,
521
- 'is-selected': isSelected,
522
- 'is-focused': isFocusVisibleWithin,
523
- 'focus-ring': isFocusVisible,
524
- 'is-hovered': isHovered && allowsSelection,
525
- 'is-disabled': isDisabled
526
- }
527
- )
528
- }>
529
- {children}
530
- </div>
531
- );
532
- }
533
-
534
- function TableHeaderRow({item, children, style}) {
535
- let state = useTableContext();
536
- let ref = useRef();
537
- let {rowProps} = useTableHeaderRow({node: item, isVirtualized: true}, state, ref);
538
-
539
- return (
540
- <div {...rowProps} ref={ref} style={style}>
541
- {children}
542
- </div>
543
- );
544
- }
545
-
546
- function TableCheckboxCell({cell}) {
547
- let ref = useRef();
548
- let state = useTableContext();
549
- let isDisabled = state.disabledKeys.has(cell.parentKey);
550
- let {gridCellProps} = useTableCell({
551
- node: cell,
552
- isVirtualized: true
553
- }, state, ref);
554
-
555
- let {checkboxProps} = useTableSelectionCheckbox({key: cell.parentKey}, state);
556
-
557
- return (
558
- <FocusRing focusRingClass={classNames(styles, 'focus-ring')}>
559
- <div
560
- {...gridCellProps}
561
- ref={ref}
562
- className={
563
- classNames(
564
- styles,
565
- 'spectrum-Table-cell',
566
- 'spectrum-Table-checkboxCell',
567
- {
568
- 'is-disabled': isDisabled
569
- },
570
- classNames(
571
- stylesOverrides,
572
- 'react-spectrum-Table-cell'
573
- )
574
- )}>
575
- {state.selectionManager.selectionMode !== 'none' &&
576
- <Checkbox
577
- {...checkboxProps}
578
- isEmphasized
579
- isDisabled={isDisabled}
580
- UNSAFE_className={classNames(styles, 'spectrum-Table-checkbox')} />
581
- }
582
- </div>
583
- </FocusRing>
584
- );
585
- }
586
-
587
- function TableCell({cell}) {
588
- let state = useTableContext();
589
- let ref = useRef();
590
- let columnProps = cell.column.props as SpectrumColumnProps<unknown>;
591
- let isDisabled = state.disabledKeys.has(cell.parentKey);
592
- let {gridCellProps} = useTableCell({
593
- node: cell,
594
- isVirtualized: true
595
- }, state, ref);
596
-
597
- return (
598
- <FocusRing focusRingClass={classNames(styles, 'focus-ring')}>
599
- <div
600
- {...gridCellProps}
601
- ref={ref}
602
- className={
603
- classNames(
604
- styles,
605
- 'spectrum-Table-cell',
606
- {
607
- 'spectrum-Table-cell--divider': columnProps.showDivider,
608
- 'spectrum-Table-cell--hideHeader': columnProps.hideHeader,
609
- 'is-disabled': isDisabled
610
- },
611
- classNames(
612
- stylesOverrides,
613
- 'react-spectrum-Table-cell',
614
- {
615
- 'react-spectrum-Table-cell--alignCenter': columnProps.align === 'center',
616
- 'react-spectrum-Table-cell--alignEnd': columnProps.align === 'end'
617
- }
618
- )
619
- )
620
- }>
621
- <span
622
- className={
623
- classNames(
624
- styles,
625
- 'spectrum-Table-cellContents'
626
- )
627
- }>
628
- {cell.rendered}
629
- </span>
630
- </div>
631
- </FocusRing>
632
- );
633
- }
35
+ // If the selection behavior changes in state, we need to update showSelectionCheckboxes here due to the circular dependency...
36
+ let shouldShowCheckboxes = state.selectionManager.selectionBehavior !== 'replace';
37
+ if (shouldShowCheckboxes !== showSelectionCheckboxes) {
38
+ setShowSelectionCheckboxes(shouldShowCheckboxes);
39
+ }
634
40
 
635
- function CenteredWrapper({children}) {
636
- let state = useTableContext();
637
41
  return (
638
- <div
639
- role="row"
640
- aria-rowindex={state.collection.headerRows.length + state.collection.size + 1}
641
- className={classNames(stylesOverrides, 'react-spectrum-Table-centeredWrapper')}>
642
- <div role="rowheader" aria-colspan={state.collection.columns.length}>
643
- {children}
644
- </div>
645
- </div>
42
+ <TableViewBase {...props} state={state} ref={ref} />
646
43
  );
647
44
  }
648
45
 
649
- /**
650
- * Tables are containers for displaying information. They allow users to quickly scan, sort, compare, and take action on large amounts of data.
651
- */
652
- const _TableView = React.forwardRef(TableView) as <T>(props: SpectrumTableProps<T> & {ref?: DOMRef<HTMLDivElement>}) => ReactElement;
46
+ const _TableView = React.forwardRef(TableView) as <T>(props: TableProps<T> & {ref?: DOMRef<HTMLDivElement>}) => ReactElement;
653
47
  export {_TableView as TableView};