@react-spectrum/table 3.0.0-beta.0 → 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 -936
  153. package/dist/main.js.map +1 -1
  154. package/dist/module.js +17 -844
  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 -682
  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 +193 -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,696 +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, useTableRow, useTableRowGroup, useTableRowHeader, 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
- ref: domRef,
110
- isVirtualized: true,
111
- layout
112
- }, state);
113
-
114
- // This overrides collection view's renderWrapper to support DOM heirarchy.
115
- type View = ReusableView<GridNode<T>, unknown>;
116
- let renderWrapper = (parent: View, reusableView: View, children: View[], renderChildren: (views: View[]) => ReactElement[]) => {
117
- let style = layoutInfoToStyle(reusableView.layoutInfo, direction, parent && parent.layoutInfo);
118
- if (style.overflow === 'hidden') {
119
- style.overflow = 'visible'; // needed to support position: sticky
120
- }
121
-
122
- if (reusableView.viewType === 'rowgroup') {
123
- return (
124
- <TableRowGroup
125
- key={reusableView.key}
126
- style={style}>
127
- {renderChildren(children)}
128
- </TableRowGroup>
129
- );
130
- }
131
-
132
- if (reusableView.viewType === 'header') {
133
- return (
134
- <TableHeader
135
- key={reusableView.key}
136
- style={style}>
137
- {renderChildren(children)}
138
- </TableHeader>
139
- );
140
- }
141
-
142
- if (reusableView.viewType === 'row') {
143
- return (
144
- <TableRow
145
- key={reusableView.key}
146
- item={reusableView.content}
147
- style={style}>
148
- {renderChildren(children)}
149
- </TableRow>
150
- );
151
- }
152
-
153
- if (reusableView.viewType === 'headerrow') {
154
- return (
155
- <TableHeaderRow
156
- key={reusableView.key}
157
- style={style}
158
- item={reusableView.content}>
159
- {renderChildren(children)}
160
- </TableHeaderRow>
161
- );
162
- }
163
-
164
- return (
165
- <VirtualizerItem
166
- key={reusableView.key}
167
- reusableView={reusableView}
168
- parent={parent}
169
- className={
170
- classNames(
171
- styles,
172
- 'spectrum-Table-cellWrapper',
173
- classNames(
174
- stylesOverrides,
175
- {
176
- 'react-spectrum-Table-cellWrapper': !reusableView.layoutInfo.estimatedSize
177
- }
178
- )
179
- )
180
- } />
181
- );
182
- };
183
-
184
- let renderView = (type: string, item: GridNode<T>) => {
185
- switch (type) {
186
- case 'header':
187
- case 'rowgroup':
188
- case 'section':
189
- case 'row':
190
- case 'headerrow':
191
- return null;
192
- case 'cell': {
193
- if (item.props.isSelectionCell) {
194
- return <TableCheckboxCell cell={item} />;
195
- }
196
-
197
- if (state.collection.rowHeaderColumnKeys.has(item.column.key)) {
198
- return <TableRowHeader cell={item} />;
199
- }
200
-
201
- return <TableCell cell={item} />;
202
- }
203
- case 'placeholder':
204
- // TODO: move to react-aria?
205
- return (
206
- <div
207
- role="gridcell"
208
- aria-colindex={item.index + 1}
209
- aria-colspan={item.colspan > 1 ? item.colspan : null} />
210
- );
211
- case 'column':
212
- if (item.props.isSelectionCell) {
213
- return <TableSelectAllCell column={item} />;
214
- }
215
-
216
- if (item.props.hideHeader) {
217
- return (
218
- <TooltipTrigger placement="top" trigger="focus">
219
- <TableColumnHeader column={item} />
220
- <Tooltip placement="top">{item.rendered}</Tooltip>
221
- </TooltipTrigger>
222
- );
223
- }
224
-
225
- return <TableColumnHeader column={item} />;
226
- case 'loader':
227
- return (
228
- <CenteredWrapper>
229
- <ProgressCircle
230
- isIndeterminate
231
- aria-label={state.collection.size > 0 ? formatMessage('loadingMore') : formatMessage('loading')} />
232
- </CenteredWrapper>
233
- );
234
- case 'empty': {
235
- let emptyState = props.renderEmptyState ? props.renderEmptyState() : null;
236
- if (emptyState == null) {
237
- return null;
238
- }
239
-
240
- return (
241
- <CenteredWrapper>
242
- {emptyState}
243
- </CenteredWrapper>
244
- );
245
- }
246
- }
247
- };
248
-
249
- return (
250
- <TableContext.Provider value={state}>
251
- <TableVirtualizer
252
- {...gridProps}
253
- {...styleProps}
254
- className={
255
- classNames(
256
- styles,
257
- 'spectrum-Table',
258
- `spectrum-Table--${density}`,
259
- {
260
- 'spectrum-Table--quiet': isQuiet,
261
- 'spectrum-Table--wrap': props.overflowMode === 'wrap'
262
- },
263
- classNames(
264
- stylesOverrides,
265
- 'react-spectrum-Table'
266
- )
267
- )
268
- }
269
- layout={layout}
270
- collection={state.collection}
271
- focusedKey={state.selectionManager.focusedKey}
272
- renderView={renderView}
273
- renderWrapper={renderWrapper}
274
- domRef={domRef} />
275
- </TableContext.Provider>
276
- );
277
- }
278
-
279
- // This is a custom Virtualizer that also has a header that syncs its scroll position with the body.
280
- function TableVirtualizer({layout, collection, focusedKey, renderView, renderWrapper, domRef, ...otherProps}) {
281
- let {direction} = useLocale();
282
- let headerRef = useRef<HTMLDivElement>();
283
- let bodyRef = useRef<HTMLDivElement>();
284
- let loadingState = collection.body.props.loadingState;
285
- let isLoading = loadingState === 'loading' || loadingState === 'loadingMore';
286
- let onLoadMore = collection.body.props.onLoadMore;
287
- let state = useVirtualizerState({
288
- layout,
289
- collection,
290
- renderView,
291
- renderWrapper,
292
- onVisibleRectChange(rect) {
293
- bodyRef.current.scrollTop = rect.y;
294
- setScrollLeft(bodyRef.current, direction, rect.x);
295
- },
296
- transitionDuration: isLoading ? 160 : 220
30
+ showSelectionCheckboxes,
31
+ showDragButtons: isTableDraggable,
32
+ selectionBehavior: props.selectionStyle === 'highlight' ? 'replace' : 'toggle'
297
33
  });
298
34
 
299
- let {virtualizerProps} = useVirtualizer({
300
- focusedKey,
301
- scrollToItem(key) {
302
- let item = collection.getItem(key);
303
- let column = collection.columns[0];
304
- state.virtualizer.scrollToItem(key, {
305
- duration: 0,
306
- // Prevent scrolling to the top when clicking on column headers.
307
- shouldScrollY: item?.type !== 'column',
308
- // Offset scroll position by width of selection cell
309
- // (which is sticky and will overlap the cell we're scrolling to).
310
- offsetX: column.props.isSelectionCell
311
- ? layout.columnWidths.get(column.key)
312
- : 0
313
- });
314
- }
315
- }, state, domRef);
316
-
317
- let headerHeight = layout.getLayoutInfo('header')?.rect.height || 0;
318
- let visibleRect = state.virtualizer.visibleRect;
319
-
320
- // Sync the scroll position from the table body to the header container.
321
- let onScroll = useCallback(() => {
322
- headerRef.current.scrollLeft = bodyRef.current.scrollLeft;
323
- }, [bodyRef]);
324
-
325
- let onVisibleRectChange = useCallback((rect: Rect) => {
326
- state.setVisibleRect(rect);
327
-
328
- if (!isLoading && onLoadMore) {
329
- let scrollOffset = state.virtualizer.contentSize.height - rect.height * 2;
330
- if (rect.y > scrollOffset) {
331
- onLoadMore();
332
- }
333
- }
334
- }, [onLoadMore, isLoading, state.setVisibleRect, state.virtualizer]);
335
-
336
- useLayoutEffect(() => {
337
- if (!isLoading && onLoadMore && !state.isAnimating) {
338
- if (state.contentSize.height <= state.virtualizer.visibleRect.height) {
339
- onLoadMore();
340
- }
341
- }
342
- }, [state.contentSize, state.virtualizer, state.isAnimating, onLoadMore, isLoading]);
343
-
344
- return (
345
- <div
346
- {...mergeProps(otherProps, virtualizerProps)}
347
- ref={domRef}>
348
- <div
349
- role="presentation"
350
- style={{
351
- width: visibleRect.width,
352
- height: headerHeight,
353
- overflow: 'hidden',
354
- position: 'relative',
355
- willChange: state.isScrolling ? 'scroll-position' : '',
356
- transition: state.isAnimating ? `none ${state.virtualizer.transitionDuration}ms` : undefined
357
- }}
358
- ref={headerRef}>
359
- {state.visibleViews[0]}
360
- </div>
361
- <ScrollView
362
- role="presentation"
363
- className={classNames(styles, 'spectrum-Table-body')}
364
- style={{flex: 1}}
365
- innerStyle={{overflow: 'visible', transition: state.isAnimating ? `none ${state.virtualizer.transitionDuration}ms` : undefined}}
366
- ref={bodyRef}
367
- contentSize={state.contentSize}
368
- onVisibleRectChange={onVisibleRectChange}
369
- onScrollStart={state.startScrolling}
370
- onScrollEnd={state.endScrolling}
371
- onScroll={onScroll}>
372
- {state.visibleViews[1]}
373
- </ScrollView>
374
- </div>
375
- );
376
- }
377
-
378
- function TableHeader({children, ...otherProps}) {
379
- let {rowGroupProps} = useTableRowGroup();
380
-
381
- return (
382
- <div {...rowGroupProps} {...otherProps} className={classNames(styles, 'spectrum-Table-head')}>
383
- {children}
384
- </div>
385
- );
386
- }
387
-
388
- function TableColumnHeader({column}) {
389
- let ref = useRef();
390
- let state = useTableContext();
391
- let {columnHeaderProps} = useTableColumnHeader({
392
- node: column,
393
- ref,
394
- colspan: column.colspan,
395
- isVirtualized: true
396
- }, state);
397
-
398
- let columnProps = column.props as SpectrumColumnProps<unknown>;
399
- let {hoverProps, isHovered} = useHover({});
400
-
401
- return (
402
- <FocusRing focusRingClass={classNames(styles, 'focus-ring')}>
403
- <div
404
- {...mergeProps(columnHeaderProps, hoverProps)}
405
- ref={ref}
406
- className={
407
- classNames(
408
- styles,
409
- 'spectrum-Table-headCell',
410
- {
411
- 'is-sortable': columnProps.allowsSorting,
412
- 'is-sorted-desc': state.sortDescriptor?.column === column.key && state.sortDescriptor?.direction === 'descending',
413
- 'is-sorted-asc': state.sortDescriptor?.column === column.key && state.sortDescriptor?.direction === 'ascending',
414
- 'is-hovered': isHovered,
415
- 'spectrum-Table-cell--hideHeader': columnProps.hideHeader
416
- },
417
- classNames(
418
- stylesOverrides,
419
- 'react-spectrum-Table-cell',
420
- {
421
- 'react-spectrum-Table-cell--alignCenter': columnProps.align === 'center' || column.colspan > 1,
422
- 'react-spectrum-Table-cell--alignEnd': columnProps.align === 'end'
423
- }
424
- )
425
- )
426
- }>
427
- {columnProps.hideHeader ?
428
- <VisuallyHidden>{column.rendered}</VisuallyHidden> :
429
- column.rendered
430
- }
431
- {columnProps.allowsSorting &&
432
- <ArrowDownSmall UNSAFE_className={classNames(styles, 'spectrum-Table-sortedIcon')} />
433
- }
434
-
435
- </div>
436
- </FocusRing>
437
- );
438
- }
439
-
440
- function TableSelectAllCell({column}) {
441
- let ref = useRef();
442
- let state = useTableContext();
443
- let isSingleSelectionMode = state.selectionManager.selectionMode === 'single';
444
- let {columnHeaderProps} = useTableColumnHeader({
445
- node: column,
446
- ref,
447
- colspan: column.colspan,
448
- isVirtualized: true,
449
- // Disable click from focusing the div for selectionMode = "single" since there won't be a "Select All" checkbox available
450
- isDisabled: isSingleSelectionMode
451
- }, state);
452
-
453
- let {checkboxProps} = useTableSelectAllCheckbox(state);
454
- let {hoverProps, isHovered} = useHover({});
455
-
456
- return (
457
- <FocusRing focusRingClass={classNames(styles, 'focus-ring')}>
458
- <div
459
- {...mergeProps(columnHeaderProps, hoverProps)}
460
- aria-disabled={isSingleSelectionMode}
461
- ref={ref}
462
- className={
463
- classNames(
464
- styles,
465
- 'spectrum-Table-headCell',
466
- 'spectrum-Table-checkboxCell',
467
- {
468
- 'is-hovered': isHovered
469
- }
470
- )
471
- }>
472
- <Checkbox
473
- {...checkboxProps}
474
- isDisabled={isSingleSelectionMode}
475
- isEmphasized
476
- UNSAFE_style={{visibility: isSingleSelectionMode ? 'hidden' : 'visible'}}
477
- UNSAFE_className={classNames(styles, 'spectrum-Table-checkbox')} />
478
- </div>
479
- </FocusRing>
480
- );
481
- }
482
-
483
- function TableRowGroup({children, ...otherProps}) {
484
- let {rowGroupProps} = useTableRowGroup();
485
-
486
- return (
487
- <div {...rowGroupProps} {...otherProps}>
488
- {children}
489
- </div>
490
- );
491
- }
492
-
493
- function TableRow({item, children, ...otherProps}) {
494
- let ref = useRef();
495
- let state = useTableContext();
496
- let allowsSelection = state.selectionManager.selectionMode !== 'none';
497
- let isDisabled = state.disabledKeys.has(item.key);
498
- let isSelected = state.selectionManager.isSelected(item.key) && !isDisabled;
499
- let {rowProps} = useTableRow({
500
- node: item,
501
- isSelected,
502
- ref,
503
- isVirtualized: true,
504
- isDisabled
505
- }, state);
506
-
507
- let {pressProps, isPressed} = usePress({isDisabled});
508
- // The row should show the focus background style when any cell inside it is focused.
509
- // If the row itself is focused, then it should have a blue focus indicator on the left.
510
- let {
511
- isFocusVisible: isFocusVisibleWithin,
512
- focusProps: focusWithinProps
513
- } = useFocusRing({within: true});
514
- let {isFocusVisible, focusProps} = useFocusRing();
515
- let {hoverProps, isHovered} = useHover({isDisabled});
516
- let props = mergeProps(
517
- rowProps,
518
- otherProps,
519
- focusWithinProps,
520
- focusProps,
521
- hoverProps,
522
- allowsSelection && pressProps
523
- );
524
-
525
- return (
526
- <div
527
- {...props}
528
- ref={ref}
529
- className={
530
- classNames(
531
- styles,
532
- 'spectrum-Table-row',
533
- {
534
- 'is-active': isPressed,
535
- 'is-selected': isSelected,
536
- 'is-focused': isFocusVisibleWithin,
537
- 'focus-ring': isFocusVisible,
538
- 'is-hovered': isHovered && allowsSelection,
539
- 'is-disabled': isDisabled
540
- }
541
- )
542
- }>
543
- {children}
544
- </div>
545
- );
546
- }
547
-
548
- function TableHeaderRow({item, children, ...otherProps}) {
549
- // TODO: move to react-aria?
550
- return (
551
- <div role="row" aria-rowindex={item.index + 1} {...otherProps}>
552
- {children}
553
- </div>
554
- );
555
- }
556
-
557
- function TableCheckboxCell({cell}) {
558
- let ref = useRef();
559
- let state = useTableContext();
560
- let isDisabled = state.disabledKeys.has(cell.parentKey);
561
- let {gridCellProps} = useTableCell({
562
- node: cell,
563
- ref,
564
- isVirtualized: true,
565
- isDisabled
566
- }, state);
567
-
568
- let {checkboxProps} = useTableSelectionCheckbox(
569
- {
570
- key: cell.parentKey,
571
- isDisabled
572
- },
573
- state
574
- );
575
-
576
- return (
577
- <FocusRing focusRingClass={classNames(styles, 'focus-ring')}>
578
- <div
579
- {...gridCellProps}
580
- ref={ref}
581
- className={
582
- classNames(
583
- styles,
584
- 'spectrum-Table-cell',
585
- 'spectrum-Table-checkboxCell',
586
- {
587
- 'is-disabled': isDisabled
588
- },
589
- classNames(
590
- stylesOverrides,
591
- 'react-spectrum-Table-cell'
592
- )
593
- )}>
594
- {state.selectionManager.selectionMode !== 'none' &&
595
- <Checkbox
596
- {...checkboxProps}
597
- isEmphasized
598
- isDisabled={isDisabled}
599
- UNSAFE_className={classNames(styles, 'spectrum-Table-checkbox')} />
600
- }
601
- </div>
602
- </FocusRing>
603
- );
604
- }
605
-
606
- function TableCell({cell}) {
607
- let ref = useRef();
608
- let state = useTableContext();
609
- let isDisabled = state.disabledKeys.has(cell.parentKey);
610
- let {gridCellProps} = useTableCell({
611
- node: cell,
612
- ref,
613
- isVirtualized: true,
614
- isDisabled
615
- }, state);
616
-
617
- return (
618
- <TableCellBase
619
- {...gridCellProps}
620
- cell={cell}
621
- cellRef={ref} />
622
- );
623
- }
624
-
625
- function TableRowHeader({cell}) {
626
- let ref = useRef();
627
- let state = useTableContext();
628
- let isDisabled = state.disabledKeys.has(cell.parentKey);
629
- let {rowHeaderProps} = useTableRowHeader({
630
- node: cell,
631
- ref,
632
- isVirtualized: true,
633
- isDisabled
634
- }, state);
635
-
636
- return (
637
- <TableCellBase
638
- {...rowHeaderProps}
639
- cell={cell}
640
- cellRef={ref} />
641
- );
642
- }
643
-
644
- function TableCellBase({cell, cellRef, ...otherProps}) {
645
- let state = useTableContext();
646
- let columnProps = cell.column.props as SpectrumColumnProps<unknown>;
647
- let isDisabled = state.disabledKeys.has(cell.parentKey);
648
-
649
- return (
650
- <FocusRing focusRingClass={classNames(styles, 'focus-ring')}>
651
- <div
652
- {...otherProps}
653
- ref={cellRef}
654
- className={
655
- classNames(
656
- styles,
657
- 'spectrum-Table-cell',
658
- {
659
- 'spectrum-Table-cell--divider': columnProps.showDivider,
660
- 'spectrum-Table-cell--hideHeader': columnProps.hideHeader,
661
- 'is-disabled': isDisabled
662
- },
663
- classNames(
664
- stylesOverrides,
665
- 'react-spectrum-Table-cell',
666
- {
667
- 'react-spectrum-Table-cell--alignCenter': columnProps.align === 'center',
668
- 'react-spectrum-Table-cell--alignEnd': columnProps.align === 'end'
669
- }
670
- )
671
- )
672
- }>
673
- <span
674
- className={
675
- classNames(
676
- styles,
677
- 'spectrum-Table-cellContents'
678
- )
679
- }>
680
- {cell.rendered}
681
- </span>
682
- </div>
683
- </FocusRing>
684
- );
685
- }
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
+ }
686
40
 
687
- function CenteredWrapper({children}) {
688
- let state = useTableContext();
689
41
  return (
690
- <div
691
- role="row"
692
- aria-rowindex={state.collection.headerRows.length + state.collection.size + 1}
693
- className={classNames(stylesOverrides, 'react-spectrum-Table-centeredWrapper')}>
694
- <div role="rowheader" aria-colspan={state.collection.columns.length}>
695
- {children}
696
- </div>
697
- </div>
42
+ <TableViewBase {...props} state={state} ref={ref} />
698
43
  );
699
44
  }
700
45
 
701
- /**
702
- * Tables are containers for displaying information. They allow users to quickly scan, sort, compare, and take action on large amounts of data.
703
- */
704
- 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;
705
47
  export {_TableView as TableView};