@spark-web/data-table 0.0.0-snapshot-release-20260408010050
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +733 -0
- package/CLAUDE.md +89 -0
- package/README.md +76 -0
- package/dist/declarations/src/data-table.d.ts +30 -0
- package/dist/declarations/src/index.d.ts +2 -0
- package/dist/spark-web-data-table.cjs.d.ts +2 -0
- package/dist/spark-web-data-table.cjs.dev.js +226 -0
- package/dist/spark-web-data-table.cjs.js +7 -0
- package/dist/spark-web-data-table.cjs.prod.js +226 -0
- package/dist/spark-web-data-table.esm.js +211 -0
- package/package.json +43 -0
package/CLAUDE.md
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
# @spark-web/data-table — AI Context
|
|
2
|
+
|
|
3
|
+
## What this package is
|
|
4
|
+
|
|
5
|
+
A headless data table built on TanStack React Table v8. One component
|
|
6
|
+
(`DataTable`) accepts column definitions and data, and renders a styled table
|
|
7
|
+
with support for row selection, row expansion, column visibility, sorting, and
|
|
8
|
+
infinite scroll.
|
|
9
|
+
|
|
10
|
+
## What this package is NOT
|
|
11
|
+
|
|
12
|
+
- Not responsible for data fetching, sorting logic, filtering, or pagination.
|
|
13
|
+
The parent owns those — `DataTable` surfaces sort state changes via
|
|
14
|
+
`onSortingChange`.
|
|
15
|
+
- Not composable. Unlike `@spark-web/table`, `DataTable` is a single monolithic
|
|
16
|
+
component. Use `@spark-web/table` when you need composable sub-components
|
|
17
|
+
without TanStack.
|
|
18
|
+
|
|
19
|
+
## Component API
|
|
20
|
+
|
|
21
|
+
`DataTable<T>` accepts:
|
|
22
|
+
|
|
23
|
+
- `items: Array<T>` — data rows
|
|
24
|
+
- `columns: ColumnDef<T>[]` — TanStack column definitions
|
|
25
|
+
- `state` — optional controlled state: `rowSelection`, `expanded`,
|
|
26
|
+
`columnVisibility`, `sorting`
|
|
27
|
+
- `onRowSelectionChange` — enables row selection
|
|
28
|
+
- `onRowClick` / `enableClickableRow` — row click behaviour
|
|
29
|
+
- `onSortingChange` + `enableSorting` + `manualSorting` — sorting
|
|
30
|
+
- `onExpandedChange` + `enableExpanding` + `expandedRowComponent` — expansion
|
|
31
|
+
- `showBottomSpinner` + `onBottomSpinnerShown` — infinite scroll trigger
|
|
32
|
+
- `renderRow` — full custom tbody replacement
|
|
33
|
+
- `className` / `headerClassName` / `footerClassName` / `rowClassName` — style
|
|
34
|
+
overrides
|
|
35
|
+
|
|
36
|
+
## Token usage
|
|
37
|
+
|
|
38
|
+
All values from `useTheme()` from `@spark-web/theme`. Never use raw hex, px, or
|
|
39
|
+
Tailwind.
|
|
40
|
+
|
|
41
|
+
### Row states
|
|
42
|
+
|
|
43
|
+
- Default: no background override (inherits surface)
|
|
44
|
+
- Selected/expanded: `theme.color.background.primarySoft`
|
|
45
|
+
- Hover: `theme.color.background.inputPressed` (CSS `:hover`, not a prop)
|
|
46
|
+
|
|
47
|
+
### Header
|
|
48
|
+
|
|
49
|
+
- Background: `theme.color.background.surface`
|
|
50
|
+
- Border bottom: `theme.border.color.primaryActive` (via inset box-shadow for
|
|
51
|
+
sticky support)
|
|
52
|
+
- Text color: `theme.color.foreground.primaryActive`
|
|
53
|
+
- Font weight: `theme.typography.fontWeight.semibold`
|
|
54
|
+
- Sortable header hover: `theme.backgroundInteractions.primaryLowHover`
|
|
55
|
+
|
|
56
|
+
### Cell
|
|
57
|
+
|
|
58
|
+
- Padding: `theme.spacing.large` (all sides, via Box `padding` prop)
|
|
59
|
+
- Border bottom: `theme.border.width.standard` solid
|
|
60
|
+
`theme.border.color.standard`
|
|
61
|
+
|
|
62
|
+
### Sort icons
|
|
63
|
+
|
|
64
|
+
Use `SortAscendingIcon` / `SortDescendingIcon` from `@spark-web/icon` at
|
|
65
|
+
`size="xxsmall"` `tone="primaryActive"`. Never `ChevronUpIcon` /
|
|
66
|
+
`ChevronDownIcon` for sort state.
|
|
67
|
+
|
|
68
|
+
## Column definitions
|
|
69
|
+
|
|
70
|
+
Use `createColumnHelper<T>()` from this package for type-safe column defs:
|
|
71
|
+
|
|
72
|
+
```tsx
|
|
73
|
+
import { createColumnHelper } from '@spark-web/data-table';
|
|
74
|
+
const col = createColumnHelper<MyType>();
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
Cell renderers receive `info` (`CellContext`) — use `info.getValue()` or
|
|
78
|
+
`info.renderValue()`. Wrap cell content in `<Text size="small">` from
|
|
79
|
+
`@spark-web/text`.
|
|
80
|
+
|
|
81
|
+
## Do NOTs
|
|
82
|
+
|
|
83
|
+
- NEVER raw hex values — always use theme color tokens
|
|
84
|
+
- NEVER raw pixel values — always use theme spacing/sizing tokens
|
|
85
|
+
- NEVER Tailwind classes
|
|
86
|
+
- NEVER `ChevronUp/DownIcon` for sort — use `SortAscending/DescendingIcon`
|
|
87
|
+
- NEVER `primaryMuted` for selected rows — use `primarySoft`
|
|
88
|
+
- NEVER `neutralHover` for row hover — use `color.background.inputPressed`
|
|
89
|
+
- NEVER put pagination inside `DataTable` — caller handles it externally
|
package/README.md
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: DataTable
|
|
3
|
+
storybookPath: data-display-data-table
|
|
4
|
+
isExperimentalPackage: true
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
The **`DataTable`** component presents a list of data in table form.
|
|
8
|
+
|
|
9
|
+
It uses _`@tanstack/react-table`_ as a dependency to implement data selection
|
|
10
|
+
and filtering capabilities. As such, certain table options are available as
|
|
11
|
+
`DataTable` props. For example, the `items` and `columns` prop are required
|
|
12
|
+
options.
|
|
13
|
+
|
|
14
|
+
Currently supported features from `@tanstack/react-table` are the following:
|
|
15
|
+
|
|
16
|
+
1. Row selection
|
|
17
|
+
2. Multi-row selection
|
|
18
|
+
3. Row expansion
|
|
19
|
+
4. Column visibility
|
|
20
|
+
|
|
21
|
+
However, certain defaults have been set for the component:
|
|
22
|
+
|
|
23
|
+
1. `enableHiding` is enabled by default;
|
|
24
|
+
2. `enableMultiRowSelection` is disabled by default, meaning row selection
|
|
25
|
+
defaults to single-row;
|
|
26
|
+
3. `enableRowSelection` is automatically enabled when a callback value is passed
|
|
27
|
+
in `onRowSelectionChange`.
|
|
28
|
+
4. The `data` property in React Table options is renamed to `items` to align
|
|
29
|
+
with the rest of Spark Web's usage of `data` as a data attribute.
|
|
30
|
+
|
|
31
|
+
## Example
|
|
32
|
+
|
|
33
|
+
```jsx live
|
|
34
|
+
<DataTable
|
|
35
|
+
items={[
|
|
36
|
+
{
|
|
37
|
+
id: 1,
|
|
38
|
+
name: 'Ken Adams',
|
|
39
|
+
category: 'Solar System',
|
|
40
|
+
amount: 3500,
|
|
41
|
+
},
|
|
42
|
+
]}
|
|
43
|
+
columns={[
|
|
44
|
+
{
|
|
45
|
+
id: 'id',
|
|
46
|
+
accessorKey: 'id',
|
|
47
|
+
header: 'ID',
|
|
48
|
+
cell: info => <Text size="small">{info.renderValue()}</Text>,
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
id: 'name',
|
|
52
|
+
accessorKey: 'name',
|
|
53
|
+
header: 'Name',
|
|
54
|
+
cell: info => <Text size="small">{info.renderValue()}</Text>,
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
id: 'category',
|
|
58
|
+
accessorKey: 'category',
|
|
59
|
+
header: 'Category',
|
|
60
|
+
cell: info => <Text size="small">{info.renderValue()}</Text>,
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
id: 'amount',
|
|
64
|
+
accessorKey: 'amount',
|
|
65
|
+
header: 'Amount',
|
|
66
|
+
cell: info => <Text size="small">{info.renderValue()}</Text>,
|
|
67
|
+
},
|
|
68
|
+
]}
|
|
69
|
+
/>
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
## Props
|
|
73
|
+
|
|
74
|
+
### DataTable
|
|
75
|
+
|
|
76
|
+
<PropsTable displayName="DataTable" />
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { SerializedStyles } from '@emotion/react';
|
|
2
|
+
import { type DataAttributeMap } from '@spark-web/utils/internal';
|
|
3
|
+
import type { ColumnDef, ColumnHelper, ExpandedState, OnChangeFn, Row, SortingState, Table, TableOptions } from '@tanstack/react-table';
|
|
4
|
+
import { createColumnHelper, flexRender } from '@tanstack/react-table';
|
|
5
|
+
import type { ReactElement } from 'react';
|
|
6
|
+
/**
|
|
7
|
+
* DataTable
|
|
8
|
+
*
|
|
9
|
+
* @see https://spark.brighte.com.au/package/data-table
|
|
10
|
+
*/
|
|
11
|
+
declare function DataTable<T>({ data, items, className, columns, enableExpanding, enableHiding, enableMultiRowSelection, enableClickableRow, headerClassName, footerClassName, showBottomSpinner: showSpinner, rowClassName, expandedRowComponent, onBottomSpinnerShown, onRowClick, onRowSelectionChange, renderRow, ...tableOptions }: DataTableProps<T>): import("@emotion/react/jsx-runtime").JSX.Element;
|
|
12
|
+
type TableSubsetOptions<T> = Pick<TableOptions<T>, 'columns' | 'enableExpanding' | 'enableHiding' | 'enableMultiRowSelection' | 'state' | 'onStateChange' | 'onExpandedChange' | 'onRowSelectionChange' | 'getRowId' | 'enableSorting' | 'manualSorting'>;
|
|
13
|
+
type DataTableProps<T> = TableSubsetOptions<T> & {
|
|
14
|
+
className?: SerializedStyles;
|
|
15
|
+
headerClassName?: SerializedStyles;
|
|
16
|
+
footerClassName?: SerializedStyles;
|
|
17
|
+
rowClassName?: (row: Row<T>, index: number) => SerializedStyles;
|
|
18
|
+
/** Map of data attributes. */
|
|
19
|
+
data?: DataAttributeMap;
|
|
20
|
+
items: Array<T>;
|
|
21
|
+
enableClickableRow?: boolean;
|
|
22
|
+
showBottomSpinner?: boolean;
|
|
23
|
+
expandedRowComponent?: (row: Row<T>, table?: Table<T>) => ReactElement<T>;
|
|
24
|
+
onBottomSpinnerShown?: (isInView: boolean) => void;
|
|
25
|
+
onRowClick?: (row: Row<T>) => void;
|
|
26
|
+
renderRow?: (table: Table<T>) => ReactElement<T>;
|
|
27
|
+
onSortingChange?: OnChangeFn<SortingState>;
|
|
28
|
+
};
|
|
29
|
+
export { createColumnHelper, DataTable, flexRender };
|
|
30
|
+
export type { ColumnDef, ColumnHelper, DataTableProps, Row as DataTableRow, ExpandedState, OnChangeFn, };
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
export * from "./declarations/src/index.js";
|
|
2
|
+
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3Bhcmstd2ViLWRhdGEtdGFibGUuY2pzLmQudHMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuL2RlY2xhcmF0aW9ucy9zcmMvaW5kZXguZC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSJ9
|
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
+
|
|
5
|
+
var _objectSpread = require('@babel/runtime/helpers/objectSpread2');
|
|
6
|
+
var _objectWithoutProperties = require('@babel/runtime/helpers/objectWithoutProperties');
|
|
7
|
+
var react = require('@emotion/react');
|
|
8
|
+
var box = require('@spark-web/box');
|
|
9
|
+
var icon = require('@spark-web/icon');
|
|
10
|
+
var spinner = require('@spark-web/spinner');
|
|
11
|
+
var theme = require('@spark-web/theme');
|
|
12
|
+
var internal = require('@spark-web/utils/internal');
|
|
13
|
+
var reactTable = require('@tanstack/react-table');
|
|
14
|
+
var React = require('react');
|
|
15
|
+
var reactIntersectionObserver = require('react-intersection-observer');
|
|
16
|
+
var jsxRuntime = require('@emotion/react/jsx-runtime');
|
|
17
|
+
|
|
18
|
+
function _interopDefault (e) { return e && e.__esModule ? e : { 'default': e }; }
|
|
19
|
+
|
|
20
|
+
var React__default = /*#__PURE__*/_interopDefault(React);
|
|
21
|
+
|
|
22
|
+
var _excluded = ["data", "items", "className", "columns", "enableExpanding", "enableHiding", "enableMultiRowSelection", "enableClickableRow", "headerClassName", "footerClassName", "showBottomSpinner", "rowClassName", "expandedRowComponent", "onBottomSpinnerShown", "onRowClick", "onRowSelectionChange", "renderRow"];
|
|
23
|
+
function getAriaSort(column) {
|
|
24
|
+
if (!column.getCanSort()) return undefined;
|
|
25
|
+
if (column.getIsSorted() === 'asc') return 'ascending';
|
|
26
|
+
if (column.getIsSorted() === 'desc') return 'descending';
|
|
27
|
+
return 'none';
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
////////////////////////////////////////////////////////////////////////////////
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* DataTable
|
|
34
|
+
*
|
|
35
|
+
* @see https://spark.brighte.com.au/package/data-table
|
|
36
|
+
*/
|
|
37
|
+
|
|
38
|
+
function DataTable(_ref) {
|
|
39
|
+
var _tableOptions$enableS, _tableOptions$manualS;
|
|
40
|
+
var data = _ref.data,
|
|
41
|
+
items = _ref.items,
|
|
42
|
+
className = _ref.className,
|
|
43
|
+
columns = _ref.columns,
|
|
44
|
+
_ref$enableExpanding = _ref.enableExpanding,
|
|
45
|
+
enableExpanding = _ref$enableExpanding === void 0 ? false : _ref$enableExpanding,
|
|
46
|
+
_ref$enableHiding = _ref.enableHiding,
|
|
47
|
+
enableHiding = _ref$enableHiding === void 0 ? true : _ref$enableHiding,
|
|
48
|
+
_ref$enableMultiRowSe = _ref.enableMultiRowSelection,
|
|
49
|
+
enableMultiRowSelection = _ref$enableMultiRowSe === void 0 ? false : _ref$enableMultiRowSe,
|
|
50
|
+
enableClickableRow = _ref.enableClickableRow,
|
|
51
|
+
headerClassName = _ref.headerClassName,
|
|
52
|
+
footerClassName = _ref.footerClassName,
|
|
53
|
+
showSpinner = _ref.showBottomSpinner,
|
|
54
|
+
rowClassName = _ref.rowClassName,
|
|
55
|
+
expandedRowComponent = _ref.expandedRowComponent,
|
|
56
|
+
onBottomSpinnerShown = _ref.onBottomSpinnerShown,
|
|
57
|
+
onRowClick = _ref.onRowClick,
|
|
58
|
+
onRowSelectionChange = _ref.onRowSelectionChange,
|
|
59
|
+
renderRow = _ref.renderRow,
|
|
60
|
+
tableOptions = _objectWithoutProperties(_ref, _excluded);
|
|
61
|
+
var theme$1 = theme.useTheme();
|
|
62
|
+
var enableRowSelection = !!onRowSelectionChange;
|
|
63
|
+
var table = reactTable.useReactTable(_objectSpread(_objectSpread({
|
|
64
|
+
data: items,
|
|
65
|
+
enableExpanding: enableExpanding,
|
|
66
|
+
enableMultiRowSelection: enableMultiRowSelection,
|
|
67
|
+
enableHiding: enableHiding,
|
|
68
|
+
enableRowSelection: enableRowSelection,
|
|
69
|
+
onRowSelectionChange: onRowSelectionChange,
|
|
70
|
+
columns: columns
|
|
71
|
+
}, tableOptions), {}, {
|
|
72
|
+
getCoreRowModel: reactTable.getCoreRowModel(),
|
|
73
|
+
getExpandedRowModel: enableExpanding ? reactTable.getCoreRowModel() : undefined,
|
|
74
|
+
enableSorting: (_tableOptions$enableS = tableOptions.enableSorting) !== null && _tableOptions$enableS !== void 0 ? _tableOptions$enableS : false,
|
|
75
|
+
manualSorting: (_tableOptions$manualS = tableOptions.manualSorting) !== null && _tableOptions$manualS !== void 0 ? _tableOptions$manualS : false
|
|
76
|
+
}));
|
|
77
|
+
var headerGroups = table.getHeaderGroups();
|
|
78
|
+
var footerGroups = table.getFooterGroups();
|
|
79
|
+
var defaultOnRowClick = function defaultOnRowClick(row) {
|
|
80
|
+
return row.toggleSelected();
|
|
81
|
+
};
|
|
82
|
+
return jsxRuntime.jsxs(box.Box, _objectSpread(_objectSpread({
|
|
83
|
+
as: "table"
|
|
84
|
+
}, data ? internal.buildDataAttributes(data) : undefined), {}, {
|
|
85
|
+
css: className,
|
|
86
|
+
children: [headerGroups.length > 0 ? jsxRuntime.jsx(box.Box, {
|
|
87
|
+
as: "thead",
|
|
88
|
+
css: react.css({
|
|
89
|
+
backgroundColor: theme$1.color.background.surface,
|
|
90
|
+
// we use box shadow instead of bottom border
|
|
91
|
+
// to allow the border to stay in the header on scroll
|
|
92
|
+
// when the table is sticky
|
|
93
|
+
boxShadow: "inset 0 -2px 0 ".concat(theme$1.border.color.primaryActive)
|
|
94
|
+
}, headerClassName),
|
|
95
|
+
children: headerGroups.map(function (headerGroup) {
|
|
96
|
+
return jsxRuntime.jsx(box.Box, {
|
|
97
|
+
as: "tr",
|
|
98
|
+
children: headerGroup.headers.map(function (header) {
|
|
99
|
+
var _asc$desc;
|
|
100
|
+
return jsxRuntime.jsxs(box.Box, {
|
|
101
|
+
as: "th",
|
|
102
|
+
padding: "medium",
|
|
103
|
+
css: react.css(_objectSpread(_objectSpread({
|
|
104
|
+
color: theme$1.color.foreground.primaryActive,
|
|
105
|
+
fontFamily: theme$1.typography.fontFamily.sans.name,
|
|
106
|
+
fontWeight: theme$1.typography.fontWeight.semibold,
|
|
107
|
+
textAlign: 'left',
|
|
108
|
+
width: "".concat(header.getSize(), "px"),
|
|
109
|
+
cursor: header.column.getCanSort() ? 'pointer' : undefined,
|
|
110
|
+
userSelect: header.column.getCanSort() ? 'none' : undefined
|
|
111
|
+
}, header.column.getCanSort() ? {
|
|
112
|
+
'&:hover': {
|
|
113
|
+
backgroundColor: theme$1.backgroundInteractions.primaryLowHover
|
|
114
|
+
}
|
|
115
|
+
} : {}), {}, {
|
|
116
|
+
svg: {
|
|
117
|
+
marginLeft: theme$1.spacing.xsmall
|
|
118
|
+
}
|
|
119
|
+
})),
|
|
120
|
+
onClick: header.column.getToggleSortingHandler(),
|
|
121
|
+
"aria-sort": getAriaSort(header.column),
|
|
122
|
+
children: [header.isPlaceholder ? null : reactTable.flexRender(header.column.columnDef.header, header.getContext()), (_asc$desc = {
|
|
123
|
+
asc: jsxRuntime.jsx(icon.SortAscendingIcon, {
|
|
124
|
+
size: "xxsmall",
|
|
125
|
+
tone: "primaryActive"
|
|
126
|
+
}),
|
|
127
|
+
desc: jsxRuntime.jsx(icon.SortDescendingIcon, {
|
|
128
|
+
size: "xxsmall",
|
|
129
|
+
tone: "primaryActive"
|
|
130
|
+
})
|
|
131
|
+
}[header.column.getIsSorted()]) !== null && _asc$desc !== void 0 ? _asc$desc : null]
|
|
132
|
+
}, header.id);
|
|
133
|
+
})
|
|
134
|
+
}, headerGroup.id);
|
|
135
|
+
})
|
|
136
|
+
}) : null, jsxRuntime.jsxs(box.Box, {
|
|
137
|
+
as: "tbody",
|
|
138
|
+
children: [!renderRow ? table.getRowModel().rows.map(function (row) {
|
|
139
|
+
return jsxRuntime.jsxs(React__default["default"].Fragment, {
|
|
140
|
+
children: [jsxRuntime.jsx(box.Box, {
|
|
141
|
+
as: "tr",
|
|
142
|
+
css: react.css({
|
|
143
|
+
'&[data-is-selected="true"],&[data-is-expanded="true"]': {
|
|
144
|
+
backgroundColor: theme$1.color.background.primarySoft
|
|
145
|
+
},
|
|
146
|
+
':hover': {
|
|
147
|
+
backgroundColor: theme$1.color.background.inputPressed,
|
|
148
|
+
cursor: enableClickableRow ? 'pointer' : undefined
|
|
149
|
+
}
|
|
150
|
+
}, rowClassName ? rowClassName(row, row.index) : undefined),
|
|
151
|
+
onClick: function onClick() {
|
|
152
|
+
return enableClickableRow && (onRowClick ? onRowClick(row) : defaultOnRowClick(row));
|
|
153
|
+
},
|
|
154
|
+
"data-is-selected": row.getIsSelected(),
|
|
155
|
+
"data-is-expanded": row.getIsExpanded(),
|
|
156
|
+
children: row.getVisibleCells().map(function (cell) {
|
|
157
|
+
return jsxRuntime.jsx(box.Box, {
|
|
158
|
+
as: "td",
|
|
159
|
+
padding: "large",
|
|
160
|
+
css: react.css({
|
|
161
|
+
borderBottomWidth: theme$1.border.width.standard,
|
|
162
|
+
borderBottomStyle: 'solid',
|
|
163
|
+
borderColor: theme$1.border.color.standard,
|
|
164
|
+
verticalAlign: 'middle',
|
|
165
|
+
textAlign: 'left'
|
|
166
|
+
}),
|
|
167
|
+
children: reactTable.flexRender(cell.column.columnDef.cell, cell.getContext())
|
|
168
|
+
}, cell.id);
|
|
169
|
+
})
|
|
170
|
+
}), enableExpanding && row.getIsExpanded() && expandedRowComponent && expandedRowComponent(row, table)]
|
|
171
|
+
}, row.id);
|
|
172
|
+
}) : renderRow(table), showSpinner && jsxRuntime.jsx(reactIntersectionObserver.InView, {
|
|
173
|
+
as: "tr"
|
|
174
|
+
// @ts-ignore
|
|
175
|
+
,
|
|
176
|
+
css: react.css({
|
|
177
|
+
columnSpan: 'all'
|
|
178
|
+
}),
|
|
179
|
+
onChange: onBottomSpinnerShown,
|
|
180
|
+
children: jsxRuntime.jsx(box.Box, {
|
|
181
|
+
as: "td",
|
|
182
|
+
padding: "large",
|
|
183
|
+
colSpan: headerGroups.map(function (hg) {
|
|
184
|
+
return hg.headers.length;
|
|
185
|
+
}).reduce(function (sum, len) {
|
|
186
|
+
return len + 1;
|
|
187
|
+
}, 0),
|
|
188
|
+
css: react.css({
|
|
189
|
+
textAlign: 'center',
|
|
190
|
+
verticalAlign: 'middle'
|
|
191
|
+
}),
|
|
192
|
+
children: jsxRuntime.jsx(spinner.Spinner, {
|
|
193
|
+
data: {
|
|
194
|
+
testId: 'data-table-spinner'
|
|
195
|
+
},
|
|
196
|
+
size: "xsmall"
|
|
197
|
+
})
|
|
198
|
+
})
|
|
199
|
+
})]
|
|
200
|
+
}), footerGroups.length > 0 ? jsxRuntime.jsx(box.Box, {
|
|
201
|
+
as: "tfoot",
|
|
202
|
+
css: react.css(footerClassName),
|
|
203
|
+
children: footerGroups.map(function (footerGroup) {
|
|
204
|
+
return jsxRuntime.jsx(box.Box, {
|
|
205
|
+
as: "tr",
|
|
206
|
+
children: footerGroup.headers.map(function (footer) {
|
|
207
|
+
return jsxRuntime.jsx(box.Box, {
|
|
208
|
+
as: "td",
|
|
209
|
+
children: reactTable.flexRender(footer.column.columnDef.footer, footer.getContext())
|
|
210
|
+
}, footer.id);
|
|
211
|
+
})
|
|
212
|
+
}, footerGroup.id);
|
|
213
|
+
})
|
|
214
|
+
}) : null]
|
|
215
|
+
}));
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
Object.defineProperty(exports, 'createColumnHelper', {
|
|
219
|
+
enumerable: true,
|
|
220
|
+
get: function () { return reactTable.createColumnHelper; }
|
|
221
|
+
});
|
|
222
|
+
Object.defineProperty(exports, 'flexRender', {
|
|
223
|
+
enumerable: true,
|
|
224
|
+
get: function () { return reactTable.flexRender; }
|
|
225
|
+
});
|
|
226
|
+
exports.DataTable = DataTable;
|
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
+
|
|
5
|
+
var _objectSpread = require('@babel/runtime/helpers/objectSpread2');
|
|
6
|
+
var _objectWithoutProperties = require('@babel/runtime/helpers/objectWithoutProperties');
|
|
7
|
+
var react = require('@emotion/react');
|
|
8
|
+
var box = require('@spark-web/box');
|
|
9
|
+
var icon = require('@spark-web/icon');
|
|
10
|
+
var spinner = require('@spark-web/spinner');
|
|
11
|
+
var theme = require('@spark-web/theme');
|
|
12
|
+
var internal = require('@spark-web/utils/internal');
|
|
13
|
+
var reactTable = require('@tanstack/react-table');
|
|
14
|
+
var React = require('react');
|
|
15
|
+
var reactIntersectionObserver = require('react-intersection-observer');
|
|
16
|
+
var jsxRuntime = require('@emotion/react/jsx-runtime');
|
|
17
|
+
|
|
18
|
+
function _interopDefault (e) { return e && e.__esModule ? e : { 'default': e }; }
|
|
19
|
+
|
|
20
|
+
var React__default = /*#__PURE__*/_interopDefault(React);
|
|
21
|
+
|
|
22
|
+
var _excluded = ["data", "items", "className", "columns", "enableExpanding", "enableHiding", "enableMultiRowSelection", "enableClickableRow", "headerClassName", "footerClassName", "showBottomSpinner", "rowClassName", "expandedRowComponent", "onBottomSpinnerShown", "onRowClick", "onRowSelectionChange", "renderRow"];
|
|
23
|
+
function getAriaSort(column) {
|
|
24
|
+
if (!column.getCanSort()) return undefined;
|
|
25
|
+
if (column.getIsSorted() === 'asc') return 'ascending';
|
|
26
|
+
if (column.getIsSorted() === 'desc') return 'descending';
|
|
27
|
+
return 'none';
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
////////////////////////////////////////////////////////////////////////////////
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* DataTable
|
|
34
|
+
*
|
|
35
|
+
* @see https://spark.brighte.com.au/package/data-table
|
|
36
|
+
*/
|
|
37
|
+
|
|
38
|
+
function DataTable(_ref) {
|
|
39
|
+
var _tableOptions$enableS, _tableOptions$manualS;
|
|
40
|
+
var data = _ref.data,
|
|
41
|
+
items = _ref.items,
|
|
42
|
+
className = _ref.className,
|
|
43
|
+
columns = _ref.columns,
|
|
44
|
+
_ref$enableExpanding = _ref.enableExpanding,
|
|
45
|
+
enableExpanding = _ref$enableExpanding === void 0 ? false : _ref$enableExpanding,
|
|
46
|
+
_ref$enableHiding = _ref.enableHiding,
|
|
47
|
+
enableHiding = _ref$enableHiding === void 0 ? true : _ref$enableHiding,
|
|
48
|
+
_ref$enableMultiRowSe = _ref.enableMultiRowSelection,
|
|
49
|
+
enableMultiRowSelection = _ref$enableMultiRowSe === void 0 ? false : _ref$enableMultiRowSe,
|
|
50
|
+
enableClickableRow = _ref.enableClickableRow,
|
|
51
|
+
headerClassName = _ref.headerClassName,
|
|
52
|
+
footerClassName = _ref.footerClassName,
|
|
53
|
+
showSpinner = _ref.showBottomSpinner,
|
|
54
|
+
rowClassName = _ref.rowClassName,
|
|
55
|
+
expandedRowComponent = _ref.expandedRowComponent,
|
|
56
|
+
onBottomSpinnerShown = _ref.onBottomSpinnerShown,
|
|
57
|
+
onRowClick = _ref.onRowClick,
|
|
58
|
+
onRowSelectionChange = _ref.onRowSelectionChange,
|
|
59
|
+
renderRow = _ref.renderRow,
|
|
60
|
+
tableOptions = _objectWithoutProperties(_ref, _excluded);
|
|
61
|
+
var theme$1 = theme.useTheme();
|
|
62
|
+
var enableRowSelection = !!onRowSelectionChange;
|
|
63
|
+
var table = reactTable.useReactTable(_objectSpread(_objectSpread({
|
|
64
|
+
data: items,
|
|
65
|
+
enableExpanding: enableExpanding,
|
|
66
|
+
enableMultiRowSelection: enableMultiRowSelection,
|
|
67
|
+
enableHiding: enableHiding,
|
|
68
|
+
enableRowSelection: enableRowSelection,
|
|
69
|
+
onRowSelectionChange: onRowSelectionChange,
|
|
70
|
+
columns: columns
|
|
71
|
+
}, tableOptions), {}, {
|
|
72
|
+
getCoreRowModel: reactTable.getCoreRowModel(),
|
|
73
|
+
getExpandedRowModel: enableExpanding ? reactTable.getCoreRowModel() : undefined,
|
|
74
|
+
enableSorting: (_tableOptions$enableS = tableOptions.enableSorting) !== null && _tableOptions$enableS !== void 0 ? _tableOptions$enableS : false,
|
|
75
|
+
manualSorting: (_tableOptions$manualS = tableOptions.manualSorting) !== null && _tableOptions$manualS !== void 0 ? _tableOptions$manualS : false
|
|
76
|
+
}));
|
|
77
|
+
var headerGroups = table.getHeaderGroups();
|
|
78
|
+
var footerGroups = table.getFooterGroups();
|
|
79
|
+
var defaultOnRowClick = function defaultOnRowClick(row) {
|
|
80
|
+
return row.toggleSelected();
|
|
81
|
+
};
|
|
82
|
+
return jsxRuntime.jsxs(box.Box, _objectSpread(_objectSpread({
|
|
83
|
+
as: "table"
|
|
84
|
+
}, data ? internal.buildDataAttributes(data) : undefined), {}, {
|
|
85
|
+
css: className,
|
|
86
|
+
children: [headerGroups.length > 0 ? jsxRuntime.jsx(box.Box, {
|
|
87
|
+
as: "thead",
|
|
88
|
+
css: react.css({
|
|
89
|
+
backgroundColor: theme$1.color.background.surface,
|
|
90
|
+
// we use box shadow instead of bottom border
|
|
91
|
+
// to allow the border to stay in the header on scroll
|
|
92
|
+
// when the table is sticky
|
|
93
|
+
boxShadow: "inset 0 -2px 0 ".concat(theme$1.border.color.primaryActive)
|
|
94
|
+
}, headerClassName),
|
|
95
|
+
children: headerGroups.map(function (headerGroup) {
|
|
96
|
+
return jsxRuntime.jsx(box.Box, {
|
|
97
|
+
as: "tr",
|
|
98
|
+
children: headerGroup.headers.map(function (header) {
|
|
99
|
+
var _asc$desc;
|
|
100
|
+
return jsxRuntime.jsxs(box.Box, {
|
|
101
|
+
as: "th",
|
|
102
|
+
padding: "medium",
|
|
103
|
+
css: react.css(_objectSpread(_objectSpread({
|
|
104
|
+
color: theme$1.color.foreground.primaryActive,
|
|
105
|
+
fontFamily: theme$1.typography.fontFamily.sans.name,
|
|
106
|
+
fontWeight: theme$1.typography.fontWeight.semibold,
|
|
107
|
+
textAlign: 'left',
|
|
108
|
+
width: "".concat(header.getSize(), "px"),
|
|
109
|
+
cursor: header.column.getCanSort() ? 'pointer' : undefined,
|
|
110
|
+
userSelect: header.column.getCanSort() ? 'none' : undefined
|
|
111
|
+
}, header.column.getCanSort() ? {
|
|
112
|
+
'&:hover': {
|
|
113
|
+
backgroundColor: theme$1.backgroundInteractions.primaryLowHover
|
|
114
|
+
}
|
|
115
|
+
} : {}), {}, {
|
|
116
|
+
svg: {
|
|
117
|
+
marginLeft: theme$1.spacing.xsmall
|
|
118
|
+
}
|
|
119
|
+
})),
|
|
120
|
+
onClick: header.column.getToggleSortingHandler(),
|
|
121
|
+
"aria-sort": getAriaSort(header.column),
|
|
122
|
+
children: [header.isPlaceholder ? null : reactTable.flexRender(header.column.columnDef.header, header.getContext()), (_asc$desc = {
|
|
123
|
+
asc: jsxRuntime.jsx(icon.SortAscendingIcon, {
|
|
124
|
+
size: "xxsmall",
|
|
125
|
+
tone: "primaryActive"
|
|
126
|
+
}),
|
|
127
|
+
desc: jsxRuntime.jsx(icon.SortDescendingIcon, {
|
|
128
|
+
size: "xxsmall",
|
|
129
|
+
tone: "primaryActive"
|
|
130
|
+
})
|
|
131
|
+
}[header.column.getIsSorted()]) !== null && _asc$desc !== void 0 ? _asc$desc : null]
|
|
132
|
+
}, header.id);
|
|
133
|
+
})
|
|
134
|
+
}, headerGroup.id);
|
|
135
|
+
})
|
|
136
|
+
}) : null, jsxRuntime.jsxs(box.Box, {
|
|
137
|
+
as: "tbody",
|
|
138
|
+
children: [!renderRow ? table.getRowModel().rows.map(function (row) {
|
|
139
|
+
return jsxRuntime.jsxs(React__default["default"].Fragment, {
|
|
140
|
+
children: [jsxRuntime.jsx(box.Box, {
|
|
141
|
+
as: "tr",
|
|
142
|
+
css: react.css({
|
|
143
|
+
'&[data-is-selected="true"],&[data-is-expanded="true"]': {
|
|
144
|
+
backgroundColor: theme$1.color.background.primarySoft
|
|
145
|
+
},
|
|
146
|
+
':hover': {
|
|
147
|
+
backgroundColor: theme$1.color.background.inputPressed,
|
|
148
|
+
cursor: enableClickableRow ? 'pointer' : undefined
|
|
149
|
+
}
|
|
150
|
+
}, rowClassName ? rowClassName(row, row.index) : undefined),
|
|
151
|
+
onClick: function onClick() {
|
|
152
|
+
return enableClickableRow && (onRowClick ? onRowClick(row) : defaultOnRowClick(row));
|
|
153
|
+
},
|
|
154
|
+
"data-is-selected": row.getIsSelected(),
|
|
155
|
+
"data-is-expanded": row.getIsExpanded(),
|
|
156
|
+
children: row.getVisibleCells().map(function (cell) {
|
|
157
|
+
return jsxRuntime.jsx(box.Box, {
|
|
158
|
+
as: "td",
|
|
159
|
+
padding: "large",
|
|
160
|
+
css: react.css({
|
|
161
|
+
borderBottomWidth: theme$1.border.width.standard,
|
|
162
|
+
borderBottomStyle: 'solid',
|
|
163
|
+
borderColor: theme$1.border.color.standard,
|
|
164
|
+
verticalAlign: 'middle',
|
|
165
|
+
textAlign: 'left'
|
|
166
|
+
}),
|
|
167
|
+
children: reactTable.flexRender(cell.column.columnDef.cell, cell.getContext())
|
|
168
|
+
}, cell.id);
|
|
169
|
+
})
|
|
170
|
+
}), enableExpanding && row.getIsExpanded() && expandedRowComponent && expandedRowComponent(row, table)]
|
|
171
|
+
}, row.id);
|
|
172
|
+
}) : renderRow(table), showSpinner && jsxRuntime.jsx(reactIntersectionObserver.InView, {
|
|
173
|
+
as: "tr"
|
|
174
|
+
// @ts-ignore
|
|
175
|
+
,
|
|
176
|
+
css: react.css({
|
|
177
|
+
columnSpan: 'all'
|
|
178
|
+
}),
|
|
179
|
+
onChange: onBottomSpinnerShown,
|
|
180
|
+
children: jsxRuntime.jsx(box.Box, {
|
|
181
|
+
as: "td",
|
|
182
|
+
padding: "large",
|
|
183
|
+
colSpan: headerGroups.map(function (hg) {
|
|
184
|
+
return hg.headers.length;
|
|
185
|
+
}).reduce(function (sum, len) {
|
|
186
|
+
return len + 1;
|
|
187
|
+
}, 0),
|
|
188
|
+
css: react.css({
|
|
189
|
+
textAlign: 'center',
|
|
190
|
+
verticalAlign: 'middle'
|
|
191
|
+
}),
|
|
192
|
+
children: jsxRuntime.jsx(spinner.Spinner, {
|
|
193
|
+
data: {
|
|
194
|
+
testId: 'data-table-spinner'
|
|
195
|
+
},
|
|
196
|
+
size: "xsmall"
|
|
197
|
+
})
|
|
198
|
+
})
|
|
199
|
+
})]
|
|
200
|
+
}), footerGroups.length > 0 ? jsxRuntime.jsx(box.Box, {
|
|
201
|
+
as: "tfoot",
|
|
202
|
+
css: react.css(footerClassName),
|
|
203
|
+
children: footerGroups.map(function (footerGroup) {
|
|
204
|
+
return jsxRuntime.jsx(box.Box, {
|
|
205
|
+
as: "tr",
|
|
206
|
+
children: footerGroup.headers.map(function (footer) {
|
|
207
|
+
return jsxRuntime.jsx(box.Box, {
|
|
208
|
+
as: "td",
|
|
209
|
+
children: reactTable.flexRender(footer.column.columnDef.footer, footer.getContext())
|
|
210
|
+
}, footer.id);
|
|
211
|
+
})
|
|
212
|
+
}, footerGroup.id);
|
|
213
|
+
})
|
|
214
|
+
}) : null]
|
|
215
|
+
}));
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
Object.defineProperty(exports, 'createColumnHelper', {
|
|
219
|
+
enumerable: true,
|
|
220
|
+
get: function () { return reactTable.createColumnHelper; }
|
|
221
|
+
});
|
|
222
|
+
Object.defineProperty(exports, 'flexRender', {
|
|
223
|
+
enumerable: true,
|
|
224
|
+
get: function () { return reactTable.flexRender; }
|
|
225
|
+
});
|
|
226
|
+
exports.DataTable = DataTable;
|