@spark-web/data-table 5.2.0 → 5.2.1
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 +50 -0
- package/CLAUDE.md +217 -0
- package/dist/declarations/src/data-table.d.ts +6 -2
- package/dist/spark-web-data-table.cjs.dev.js +169 -117
- package/dist/spark-web-data-table.cjs.prod.js +169 -117
- package/dist/spark-web-data-table.esm.js +170 -118
- package/package.json +5 -4
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,55 @@
|
|
|
1
1
|
# @spark-web/data-table
|
|
2
2
|
|
|
3
|
+
## 5.2.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [#782](https://github.com/brighte-labs/spark-web/pull/782)
|
|
8
|
+
[`bb41800`](https://github.com/brighte-labs/spark-web/commit/bb418004d21165f72f4bf2456afea844ee04a21c)
|
|
9
|
+
Thanks [@jacobporci-brighte](https://github.com/jacobporci-brighte)! -
|
|
10
|
+
**docs:** add CLAUDE.md AI context files to foundation and form packages;
|
|
11
|
+
patch data-table with manual sort and spinner overlay patterns
|
|
12
|
+
|
|
13
|
+
- [#782](https://github.com/brighte-labs/spark-web/pull/782)
|
|
14
|
+
[`bb41800`](https://github.com/brighte-labs/spark-web/commit/bb418004d21165f72f4bf2456afea844ee04a21c)
|
|
15
|
+
Thanks [@jacobporci-brighte](https://github.com/jacobporci-brighte)! -
|
|
16
|
+
**data-table:** add `isLoading` and `emptyState` props — renders a spinner +
|
|
17
|
+
"Loading" text or a custom empty node below the table; table now fills its
|
|
18
|
+
container width by default (`width: 100%`)
|
|
19
|
+
|
|
20
|
+
- [#782](https://github.com/brighte-labs/spark-web/pull/782)
|
|
21
|
+
[`bb41800`](https://github.com/brighte-labs/spark-web/commit/bb418004d21165f72f4bf2456afea844ee04a21c)
|
|
22
|
+
Thanks [@jacobporci-brighte](https://github.com/jacobporci-brighte)! -
|
|
23
|
+
**data-table:** Fix token gaps in CLAUDE.md (header cell padding, font-family,
|
|
24
|
+
loading/empty state containers, sort icon margin); add Composition section;
|
|
25
|
+
clarify row hover only applies to clickable rows and must be suppressed when
|
|
26
|
+
hovering a button inside the row
|
|
27
|
+
|
|
28
|
+
**design-system:** Update internal-admin surface rules with MeatballMenu hover
|
|
29
|
+
suppression rule; fix list-page.md MultiSelect label pattern (gap and text
|
|
30
|
+
size were contradicting the rules text); update pattern file code examples to
|
|
31
|
+
match
|
|
32
|
+
|
|
33
|
+
**meatball-menu:** Rewrite CLAUDE.md with full structure — What this is NOT,
|
|
34
|
+
complete token usage table, Composition section, and Do NOTs
|
|
35
|
+
|
|
36
|
+
**status-badge:** Rewrite CLAUDE.md with full structure — What this is NOT,
|
|
37
|
+
complete token usage table with per-tone background mapping, Composition
|
|
38
|
+
section, and Do NOTs
|
|
39
|
+
|
|
40
|
+
- [#782](https://github.com/brighte-labs/spark-web/pull/782)
|
|
41
|
+
[`bb41800`](https://github.com/brighte-labs/spark-web/commit/bb418004d21165f72f4bf2456afea844ee04a21c)
|
|
42
|
+
Thanks [@jacobporci-brighte](https://github.com/jacobporci-brighte)! -
|
|
43
|
+
**data-table:** align color tokens with @spark-web/table conventions — use
|
|
44
|
+
`primarySoft` for selected rows, `inputPressed` for hover, `primaryActive` for
|
|
45
|
+
header text/border; switch sort icons to `SortAscending/DescendingIcon`; add
|
|
46
|
+
`aria-sort` accessibility attribute; add CLAUDE.md AI context
|
|
47
|
+
- Updated dependencies
|
|
48
|
+
[[`bb41800`](https://github.com/brighte-labs/spark-web/commit/bb418004d21165f72f4bf2456afea844ee04a21c)]:
|
|
49
|
+
- @spark-web/box@6.0.1
|
|
50
|
+
- @spark-web/spinner@5.1.1
|
|
51
|
+
- @spark-web/text@5.3.1
|
|
52
|
+
|
|
3
53
|
## 5.2.0
|
|
4
54
|
|
|
5
55
|
### Minor Changes
|
package/CLAUDE.md
ADDED
|
@@ -0,0 +1,217 @@
|
|
|
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. `DataTable` is a single monolithic component — there are no
|
|
16
|
+
composable sub-component alternatives in this design system.
|
|
17
|
+
|
|
18
|
+
## Component API
|
|
19
|
+
|
|
20
|
+
`DataTable<T>` accepts:
|
|
21
|
+
|
|
22
|
+
- `items: Array<T>` **(required)** — data rows
|
|
23
|
+
- `columns: ColumnDef<T>[]` **(required)** — TanStack column definitions
|
|
24
|
+
- `isLoading?: boolean` — controls the loading state row below the table body
|
|
25
|
+
- `emptyState?: ReactNode` — rendered when `isLoading` is false and `items` is
|
|
26
|
+
empty
|
|
27
|
+
- `state` — optional controlled state: `rowSelection`, `expanded`,
|
|
28
|
+
`columnVisibility`, `sorting`
|
|
29
|
+
- `onRowSelectionChange` — enables row selection
|
|
30
|
+
- `onRowClick` / `enableClickableRow` — row click behaviour
|
|
31
|
+
- `onSortingChange` + `enableSorting` + `manualSorting` — sorting
|
|
32
|
+
- `onExpandedChange` + `enableExpanding` + `expandedRowComponent` — expansion
|
|
33
|
+
- `showBottomSpinner` + `onBottomSpinnerShown` — infinite scroll trigge
|
|
34
|
+
- `renderRow` — full custom tbody replacement
|
|
35
|
+
- `className` / `headerClassName` / `footerClassName` / `rowClassName` — style
|
|
36
|
+
overrides
|
|
37
|
+
|
|
38
|
+
Always provide `isLoading` and `emptyState` in production usage — omitting them
|
|
39
|
+
leaves the table with no loading indicator or empty state feedback.
|
|
40
|
+
|
|
41
|
+
## Token usage
|
|
42
|
+
|
|
43
|
+
All values from `useTheme()` from `@spark-web/theme`. Never use raw hex, px, or
|
|
44
|
+
Tailwind.
|
|
45
|
+
|
|
46
|
+
### Row states
|
|
47
|
+
|
|
48
|
+
- Default: no background override (inherits surface)
|
|
49
|
+
- Selected/expanded: `theme.color.background.primarySoft`
|
|
50
|
+
- Hover: `theme.color.background.inputPressed` — applied only when
|
|
51
|
+
`enableClickableRow` is `true`. NEVER apply row hover to a non-clickable row.
|
|
52
|
+
- Hover suppression: when a row contains a `MeatballMenu`, hovering over the
|
|
53
|
+
meatball button must NOT trigger the row hover. Implement using CSS `:has()`:
|
|
54
|
+
```css
|
|
55
|
+
':hover:not(:has(button:hover))': {
|
|
56
|
+
backgroundcolor: theme.color.background.inputPressed;
|
|
57
|
+
}
|
|
58
|
+
```
|
|
59
|
+
This ensures the row highlight disappears when the cursor moves over any
|
|
60
|
+
button within the row, including the meatball trigger.
|
|
61
|
+
|
|
62
|
+
### Header
|
|
63
|
+
|
|
64
|
+
- Background: `theme.color.background.surface`
|
|
65
|
+
- Border bottom: `theme.color.background.primaryDark` (via inset box-shadow:
|
|
66
|
+
`inset 0 -2px 0 0 ${theme.color.background.primaryDark}`)
|
|
67
|
+
- Cell padding: `theme.spacing.medium` (via Box `padding="medium"` on `<th>`)
|
|
68
|
+
- Text color: `theme.color.background.primaryDark`
|
|
69
|
+
- Text transform: `capitalize` (inline CSS on `th`)
|
|
70
|
+
- Sort icon stroke: `theme.color.background.primaryDark` (inline CSS on `svg`)
|
|
71
|
+
- Font family: `theme.typography.fontFamily.sans.name`
|
|
72
|
+
- Font weight: `theme.typography.fontWeight.semibold`
|
|
73
|
+
- Sortable header hover: `theme.backgroundInteractions.primaryLowHover`
|
|
74
|
+
|
|
75
|
+
### Cell
|
|
76
|
+
|
|
77
|
+
- Padding: `theme.spacing.large` (all sides, via Box `padding="large"` on
|
|
78
|
+
`<td>`)
|
|
79
|
+
- Border bottom: `theme.border.width.standard` solid
|
|
80
|
+
`theme.border.color.standard`
|
|
81
|
+
- Vertical align: `middle` (inline CSS)
|
|
82
|
+
- Text align: `left` (inline CSS)
|
|
83
|
+
|
|
84
|
+
### Sort icons
|
|
85
|
+
|
|
86
|
+
Use `SortAscendingIcon` / `SortDescendingIcon` from `@spark-web/icon` at
|
|
87
|
+
`size="xxsmall"` `tone="primaryActive"`. Never `ChevronUpIcon` /
|
|
88
|
+
`ChevronDownIcon` for sort state.
|
|
89
|
+
|
|
90
|
+
- Icon left margin: `theme.spacing.xsmall` (inline CSS on the `svg` selector)
|
|
91
|
+
|
|
92
|
+
### Loading state (`isLoading`)
|
|
93
|
+
|
|
94
|
+
Renders below the table body when `isLoading` is `true`. Does not overlay the
|
|
95
|
+
table — replaces visible data feedback.
|
|
96
|
+
|
|
97
|
+
- Container padding: `padding="xlarge"` (Box prop)
|
|
98
|
+
- Container gap: `gap="small"` (Box prop)
|
|
99
|
+
- Container alignment: `alignItems="center"`, `justifyContent="center"` (Box
|
|
100
|
+
props)
|
|
101
|
+
- Text: `<Text tone="muted">Loading</Text>`
|
|
102
|
+
- Spinner: `<Spinner tone="primary" />` — no explicit size; uses Spinner default
|
|
103
|
+
|
|
104
|
+
### Empty state (`emptyState`)
|
|
105
|
+
|
|
106
|
+
Renders below the table body when `isLoading` is `false` and `items` is empty.
|
|
107
|
+
|
|
108
|
+
- Container padding: `padding="xlarge"` (Box prop)
|
|
109
|
+
- Container alignment: `justifyContent="center"` (Box prop)
|
|
110
|
+
- Content: caller-provided `ReactNode` — always pass
|
|
111
|
+
`<Text tone="muted" size="small">…</Text>`
|
|
112
|
+
|
|
113
|
+
## Composition
|
|
114
|
+
|
|
115
|
+
- `Box` from `@spark-web/box` — outer wrapper, `<table>`, `<thead>`, `<tbody>`,
|
|
116
|
+
`<tfoot>`, `<tr>`, `<th>`, `<td>` elements
|
|
117
|
+
- `SortAscendingIcon` / `SortDescendingIcon` from `@spark-web/icon` — sort state
|
|
118
|
+
icons in sortable header cells
|
|
119
|
+
- `Spinner` from `@spark-web/spinner` — loading overlay (via `isLoading`) and
|
|
120
|
+
infinite-scroll bottom spinner (via `showBottomSpinner`)
|
|
121
|
+
- `Text` from `@spark-web/text` — "Loading" label in `isLoading` state
|
|
122
|
+
- `InView` from `react-intersection-observer` — triggers `onBottomSpinnerShown`
|
|
123
|
+
when the bottom spinner enters the viewport
|
|
124
|
+
|
|
125
|
+
## Column definitions
|
|
126
|
+
|
|
127
|
+
Use `createColumnHelper<T>()` from this package for type-safe column defs:
|
|
128
|
+
|
|
129
|
+
```tsx
|
|
130
|
+
import { createColumnHelper } from '@spark-web/data-table';
|
|
131
|
+
const col = createColumnHelper<MyType>();
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
Cell renderers receive `info` (`CellContext`) — use `info.getValue()` or
|
|
135
|
+
`info.renderValue()`. Wrap cell content in `<Text size="small">` from
|
|
136
|
+
`@spark-web/text`.
|
|
137
|
+
|
|
138
|
+
## Manual sort state
|
|
139
|
+
|
|
140
|
+
When `manualSorting` is `true`, the parent owns sort state and must pass it back
|
|
141
|
+
to `DataTable` via `state.sorting`. Wire it up like this:
|
|
142
|
+
|
|
143
|
+
```tsx
|
|
144
|
+
const [sorting, setSorting] = useState<SortingState>([]);
|
|
145
|
+
|
|
146
|
+
<DataTable
|
|
147
|
+
items={data}
|
|
148
|
+
columns={columns}
|
|
149
|
+
enableSorting
|
|
150
|
+
manualSorting
|
|
151
|
+
state={{ sorting }}
|
|
152
|
+
onSortingChange={setSorting}
|
|
153
|
+
/>;
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
- `enableSorting` — enables the sort UI on column headers
|
|
157
|
+
- `manualSorting` — tells TanStack Table not to sort `items` itself; the parent
|
|
158
|
+
must re-fetch/re-sort when `onSortingChange` fires
|
|
159
|
+
- `onSortingChange` — receives the new `SortingState`; pass it to your query as
|
|
160
|
+
an `orderBy` parameter
|
|
161
|
+
- `state.sorting` — controlled sort state, keeps headers in sync with data
|
|
162
|
+
|
|
163
|
+
To make a specific column sortable, set `enableSorting: true` on its
|
|
164
|
+
`ColumnDef`. To disable sorting on a specific column, set
|
|
165
|
+
`enableSorting: false`.
|
|
166
|
+
|
|
167
|
+
## Spinner overlay (external loading, before table mounts)
|
|
168
|
+
|
|
169
|
+
Use `DataTable`'s `isLoading` prop for in-table loading. Only use an external
|
|
170
|
+
Spinner overlay when the table cannot mount yet — e.g. a full-region loading
|
|
171
|
+
state before you have any data at all, or a loading state that covers the entire
|
|
172
|
+
page section including the filter bar:
|
|
173
|
+
|
|
174
|
+
```tsx
|
|
175
|
+
{
|
|
176
|
+
isLoading ? (
|
|
177
|
+
<Box
|
|
178
|
+
display="flex"
|
|
179
|
+
flexDirection="column"
|
|
180
|
+
alignItems="center"
|
|
181
|
+
justifyContent="center"
|
|
182
|
+
gap="small"
|
|
183
|
+
padding="xlarge"
|
|
184
|
+
>
|
|
185
|
+
<Spinner tone="primary" size="xsmall" />
|
|
186
|
+
<Text tone="muted">Loading</Text>
|
|
187
|
+
</Box>
|
|
188
|
+
) : (
|
|
189
|
+
<DataTable items={data} columns={columns} isLoading={isFetching} />
|
|
190
|
+
);
|
|
191
|
+
}
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
The distinction:
|
|
195
|
+
|
|
196
|
+
- `isLoading` (initial, no table yet) → external Spinner overlay
|
|
197
|
+
- `isFetching` (refetch while table exists) → pass to `DataTable` `isLoading`
|
|
198
|
+
|
|
199
|
+
## Do NOTs
|
|
200
|
+
|
|
201
|
+
- NEVER raw hex values — always use theme color tokens
|
|
202
|
+
- NEVER raw pixel values — always use theme spacing/sizing tokens
|
|
203
|
+
- NEVER Tailwind classes
|
|
204
|
+
- NEVER `ChevronUp/DownIcon` for sort — use `SortAscending/DescendingIcon`
|
|
205
|
+
- NEVER `primaryMuted` for selected rows — use `primarySoft`
|
|
206
|
+
- NEVER `neutralHover` for row hover — use `color.background.inputPressed`
|
|
207
|
+
- NEVER apply row hover to a non-clickable row — only rows with
|
|
208
|
+
`enableClickableRow` get hover
|
|
209
|
+
- NEVER let row hover fire when the cursor is over a button inside the row — use
|
|
210
|
+
`:hover:not(:has(button:hover))` to suppress it
|
|
211
|
+
- NEVER put pagination inside `DataTable` — caller handles it externally
|
|
212
|
+
- NEVER render an external `<Spinner>` alongside a mounted `DataTable` — use the
|
|
213
|
+
`isLoading` prop instead. An external Spinner is only correct before the table
|
|
214
|
+
can mount (initial page load with no data yet).
|
|
215
|
+
- NEVER pass a string class from `@emotion/css` to `className` or
|
|
216
|
+
`headerClassName` — these props expect `SerializedStyles` from
|
|
217
|
+
`@emotion/react`'s `css` tagged template
|
|
@@ -2,13 +2,13 @@ import type { SerializedStyles } from '@emotion/react';
|
|
|
2
2
|
import { type DataAttributeMap } from '@spark-web/utils/internal';
|
|
3
3
|
import type { ColumnDef, ColumnHelper, ExpandedState, OnChangeFn, Row, SortingState, Table, TableOptions } from '@tanstack/react-table';
|
|
4
4
|
import { createColumnHelper, flexRender } from '@tanstack/react-table';
|
|
5
|
-
import type { ReactElement } from 'react';
|
|
5
|
+
import type { ReactElement, ReactNode } from 'react';
|
|
6
6
|
/**
|
|
7
7
|
* DataTable
|
|
8
8
|
*
|
|
9
9
|
* @see https://spark.brighte.com.au/package/data-table
|
|
10
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;
|
|
11
|
+
declare function DataTable<T>({ data, items, className, columns, enableExpanding, enableHiding, enableMultiRowSelection, enableClickableRow, headerClassName, footerClassName, showBottomSpinner: showSpinner, rowClassName, expandedRowComponent, onBottomSpinnerShown, onRowClick, onRowSelectionChange, renderRow, isLoading, emptyState, ...tableOptions }: DataTableProps<T>): import("@emotion/react/jsx-runtime").JSX.Element;
|
|
12
12
|
type TableSubsetOptions<T> = Pick<TableOptions<T>, 'columns' | 'enableExpanding' | 'enableHiding' | 'enableMultiRowSelection' | 'state' | 'onStateChange' | 'onExpandedChange' | 'onRowSelectionChange' | 'getRowId' | 'enableSorting' | 'manualSorting'>;
|
|
13
13
|
type DataTableProps<T> = TableSubsetOptions<T> & {
|
|
14
14
|
className?: SerializedStyles;
|
|
@@ -25,6 +25,10 @@ type DataTableProps<T> = TableSubsetOptions<T> & {
|
|
|
25
25
|
onRowClick?: (row: Row<T>) => void;
|
|
26
26
|
renderRow?: (table: Table<T>) => ReactElement<T>;
|
|
27
27
|
onSortingChange?: OnChangeFn<SortingState>;
|
|
28
|
+
/** When true, renders a centered spinner + "Loading" text below the table. */
|
|
29
|
+
isLoading?: boolean;
|
|
30
|
+
/** Rendered below the table when not loading and items is empty. */
|
|
31
|
+
emptyState?: ReactNode;
|
|
28
32
|
};
|
|
29
33
|
export { createColumnHelper, DataTable, flexRender };
|
|
30
34
|
export type { ColumnDef, ColumnHelper, DataTableProps, Row as DataTableRow, ExpandedState, OnChangeFn, };
|
|
@@ -8,6 +8,7 @@ var react = require('@emotion/react');
|
|
|
8
8
|
var box = require('@spark-web/box');
|
|
9
9
|
var icon = require('@spark-web/icon');
|
|
10
10
|
var spinner = require('@spark-web/spinner');
|
|
11
|
+
var text = require('@spark-web/text');
|
|
11
12
|
var theme = require('@spark-web/theme');
|
|
12
13
|
var internal = require('@spark-web/utils/internal');
|
|
13
14
|
var reactTable = require('@tanstack/react-table');
|
|
@@ -19,7 +20,22 @@ function _interopDefault (e) { return e && e.__esModule ? e : { 'default': e };
|
|
|
19
20
|
|
|
20
21
|
var React__default = /*#__PURE__*/_interopDefault(React);
|
|
21
22
|
|
|
22
|
-
var _excluded = ["data", "items", "className", "columns", "enableExpanding", "enableHiding", "enableMultiRowSelection", "enableClickableRow", "headerClassName", "footerClassName", "showBottomSpinner", "rowClassName", "expandedRowComponent", "onBottomSpinnerShown", "onRowClick", "onRowSelectionChange", "renderRow"];
|
|
23
|
+
var _excluded = ["data", "items", "className", "columns", "enableExpanding", "enableHiding", "enableMultiRowSelection", "enableClickableRow", "headerClassName", "footerClassName", "showBottomSpinner", "rowClassName", "expandedRowComponent", "onBottomSpinnerShown", "onRowClick", "onRowSelectionChange", "renderRow", "isLoading", "emptyState"];
|
|
24
|
+
function getAriaSort(column) {
|
|
25
|
+
if (!column.getCanSort()) return undefined;
|
|
26
|
+
if (column.getIsSorted() === 'asc') return 'ascending';
|
|
27
|
+
if (column.getIsSorted() === 'desc') return 'descending';
|
|
28
|
+
return 'none';
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
////////////////////////////////////////////////////////////////////////////////
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* DataTable
|
|
35
|
+
*
|
|
36
|
+
* @see https://spark.brighte.com.au/package/data-table
|
|
37
|
+
*/
|
|
38
|
+
|
|
23
39
|
function DataTable(_ref) {
|
|
24
40
|
var _tableOptions$enableS, _tableOptions$manualS;
|
|
25
41
|
var data = _ref.data,
|
|
@@ -42,6 +58,8 @@ function DataTable(_ref) {
|
|
|
42
58
|
onRowClick = _ref.onRowClick,
|
|
43
59
|
onRowSelectionChange = _ref.onRowSelectionChange,
|
|
44
60
|
renderRow = _ref.renderRow,
|
|
61
|
+
isLoading = _ref.isLoading,
|
|
62
|
+
emptyState = _ref.emptyState,
|
|
45
63
|
tableOptions = _objectWithoutProperties(_ref, _excluded);
|
|
46
64
|
var theme$1 = theme.useTheme();
|
|
47
65
|
var enableRowSelection = !!onRowSelectionChange;
|
|
@@ -64,130 +82,164 @@ function DataTable(_ref) {
|
|
|
64
82
|
var defaultOnRowClick = function defaultOnRowClick(row) {
|
|
65
83
|
return row.toggleSelected();
|
|
66
84
|
};
|
|
67
|
-
return jsxRuntime.jsxs(box.Box, _objectSpread(_objectSpread({
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
children: headerGroup.headers.map(function (header) {
|
|
84
|
-
var _asc$desc;
|
|
85
|
-
return jsxRuntime.jsxs(box.Box, {
|
|
86
|
-
as: "th",
|
|
87
|
-
color: theme$1.color.foreground.muted,
|
|
88
|
-
padding: "medium",
|
|
89
|
-
css: react.css({
|
|
90
|
-
fontFamily: theme$1.typography.fontFamily.sans.name,
|
|
91
|
-
fontWeight: theme$1.typography.fontWeight.semibold,
|
|
92
|
-
textAlign: 'left',
|
|
93
|
-
textTransform: 'uppercase',
|
|
94
|
-
width: "".concat(header.getSize(), "px"),
|
|
95
|
-
svg: {
|
|
96
|
-
marginLeft: theme$1.spacing.xsmall
|
|
97
|
-
}
|
|
98
|
-
}),
|
|
99
|
-
onClick: header.column.getToggleSortingHandler(),
|
|
100
|
-
children: [header.isPlaceholder ? null : reactTable.flexRender(header.column.columnDef.header, header.getContext()), (_asc$desc = {
|
|
101
|
-
asc: jsxRuntime.jsx(icon.ChevronUpIcon, {
|
|
102
|
-
size: "xsmall"
|
|
103
|
-
}),
|
|
104
|
-
desc: jsxRuntime.jsx(icon.ChevronDownIcon, {
|
|
105
|
-
size: "xsmall"
|
|
106
|
-
})
|
|
107
|
-
}[header.column.getIsSorted()]) !== null && _asc$desc !== void 0 ? _asc$desc : null]
|
|
108
|
-
}, header.id);
|
|
109
|
-
})
|
|
110
|
-
}, headerGroup.id);
|
|
111
|
-
})
|
|
112
|
-
}) : null, jsxRuntime.jsxs(box.Box, {
|
|
113
|
-
as: "tbody",
|
|
114
|
-
children: [!renderRow ? table.getRowModel().rows.map(function (row) {
|
|
115
|
-
return jsxRuntime.jsxs(React__default["default"].Fragment, {
|
|
116
|
-
children: [jsxRuntime.jsx(box.Box, {
|
|
85
|
+
return jsxRuntime.jsxs(box.Box, _objectSpread(_objectSpread({}, data ? internal.buildDataAttributes(data) : undefined), {}, {
|
|
86
|
+
children: [jsxRuntime.jsxs(box.Box, {
|
|
87
|
+
as: "table",
|
|
88
|
+
width: "full",
|
|
89
|
+
css: className,
|
|
90
|
+
children: [headerGroups.length > 0 ? jsxRuntime.jsx(box.Box, {
|
|
91
|
+
as: "thead",
|
|
92
|
+
css: react.css({
|
|
93
|
+
backgroundColor: theme$1.color.background.surface,
|
|
94
|
+
// we use box shadow instead of bottom border
|
|
95
|
+
// to allow the border to stay in the header on scroll
|
|
96
|
+
// when the table is sticky
|
|
97
|
+
boxShadow: "inset 0 -2px 0 ".concat(theme$1.border.color.primaryActive)
|
|
98
|
+
}, headerClassName),
|
|
99
|
+
children: headerGroups.map(function (headerGroup) {
|
|
100
|
+
return jsxRuntime.jsx(box.Box, {
|
|
117
101
|
as: "tr",
|
|
102
|
+
children: headerGroup.headers.map(function (header) {
|
|
103
|
+
var _asc$desc;
|
|
104
|
+
return jsxRuntime.jsxs(box.Box, {
|
|
105
|
+
as: "th",
|
|
106
|
+
padding: "medium",
|
|
107
|
+
css: react.css(_objectSpread(_objectSpread({
|
|
108
|
+
color: theme$1.color.foreground.primaryActive,
|
|
109
|
+
fontFamily: theme$1.typography.fontFamily.sans.name,
|
|
110
|
+
fontWeight: theme$1.typography.fontWeight.semibold,
|
|
111
|
+
textAlign: 'left',
|
|
112
|
+
width: "".concat(header.getSize(), "px"),
|
|
113
|
+
cursor: header.column.getCanSort() ? 'pointer' : undefined,
|
|
114
|
+
userSelect: header.column.getCanSort() ? 'none' : undefined
|
|
115
|
+
}, header.column.getCanSort() ? {
|
|
116
|
+
'&:hover': {
|
|
117
|
+
backgroundColor: theme$1.backgroundInteractions.primaryLowHover
|
|
118
|
+
}
|
|
119
|
+
} : {}), {}, {
|
|
120
|
+
svg: {
|
|
121
|
+
marginLeft: theme$1.spacing.xsmall
|
|
122
|
+
}
|
|
123
|
+
})),
|
|
124
|
+
onClick: header.column.getToggleSortingHandler(),
|
|
125
|
+
"aria-sort": getAriaSort(header.column),
|
|
126
|
+
children: [header.isPlaceholder ? null : reactTable.flexRender(header.column.columnDef.header, header.getContext()), (_asc$desc = {
|
|
127
|
+
asc: jsxRuntime.jsx(icon.SortAscendingIcon, {
|
|
128
|
+
size: "xxsmall",
|
|
129
|
+
tone: "primaryActive"
|
|
130
|
+
}),
|
|
131
|
+
desc: jsxRuntime.jsx(icon.SortDescendingIcon, {
|
|
132
|
+
size: "xxsmall",
|
|
133
|
+
tone: "primaryActive"
|
|
134
|
+
})
|
|
135
|
+
}[header.column.getIsSorted()]) !== null && _asc$desc !== void 0 ? _asc$desc : null]
|
|
136
|
+
}, header.id);
|
|
137
|
+
})
|
|
138
|
+
}, headerGroup.id);
|
|
139
|
+
})
|
|
140
|
+
}) : null, jsxRuntime.jsxs(box.Box, {
|
|
141
|
+
as: "tbody",
|
|
142
|
+
children: [!renderRow ? table.getRowModel().rows.map(function (row) {
|
|
143
|
+
return jsxRuntime.jsxs(React__default["default"].Fragment, {
|
|
144
|
+
children: [jsxRuntime.jsx(box.Box, {
|
|
145
|
+
as: "tr",
|
|
146
|
+
css: react.css(_objectSpread({
|
|
147
|
+
'&[data-is-selected="true"],&[data-is-expanded="true"]': {
|
|
148
|
+
backgroundColor: theme$1.color.background.primarySoft
|
|
149
|
+
}
|
|
150
|
+
}, enableClickableRow ? {
|
|
151
|
+
':hover:not(:has(button:hover))': {
|
|
152
|
+
backgroundColor: theme$1.color.background.inputPressed,
|
|
153
|
+
cursor: 'pointer'
|
|
154
|
+
}
|
|
155
|
+
} : {}), rowClassName ? rowClassName(row, row.index) : undefined),
|
|
156
|
+
onClick: function onClick() {
|
|
157
|
+
return enableClickableRow && (onRowClick ? onRowClick(row) : defaultOnRowClick(row));
|
|
158
|
+
},
|
|
159
|
+
"data-is-selected": row.getIsSelected(),
|
|
160
|
+
"data-is-expanded": row.getIsExpanded(),
|
|
161
|
+
children: row.getVisibleCells().map(function (cell) {
|
|
162
|
+
return jsxRuntime.jsx(box.Box, {
|
|
163
|
+
as: "td",
|
|
164
|
+
padding: "large",
|
|
165
|
+
css: react.css({
|
|
166
|
+
borderBottomWidth: theme$1.border.width.standard,
|
|
167
|
+
borderBottomStyle: 'solid',
|
|
168
|
+
borderColor: theme$1.border.color.standard,
|
|
169
|
+
verticalAlign: 'middle',
|
|
170
|
+
textAlign: 'left'
|
|
171
|
+
}),
|
|
172
|
+
children: reactTable.flexRender(cell.column.columnDef.cell, cell.getContext())
|
|
173
|
+
}, cell.id);
|
|
174
|
+
})
|
|
175
|
+
}), enableExpanding && row.getIsExpanded() && expandedRowComponent && expandedRowComponent(row, table)]
|
|
176
|
+
}, row.id);
|
|
177
|
+
}) : renderRow(table), showSpinner && jsxRuntime.jsx(reactIntersectionObserver.InView, {
|
|
178
|
+
as: "tr"
|
|
179
|
+
// @ts-ignore
|
|
180
|
+
,
|
|
181
|
+
css: react.css({
|
|
182
|
+
columnSpan: 'all'
|
|
183
|
+
}),
|
|
184
|
+
onChange: onBottomSpinnerShown,
|
|
185
|
+
children: jsxRuntime.jsx(box.Box, {
|
|
186
|
+
as: "td",
|
|
187
|
+
padding: "large",
|
|
188
|
+
colSpan: headerGroups.map(function (hg) {
|
|
189
|
+
return hg.headers.length;
|
|
190
|
+
}).reduce(function (sum, len) {
|
|
191
|
+
return len + 1;
|
|
192
|
+
}, 0),
|
|
118
193
|
css: react.css({
|
|
119
|
-
'
|
|
120
|
-
|
|
194
|
+
textAlign: 'center',
|
|
195
|
+
verticalAlign: 'middle'
|
|
196
|
+
}),
|
|
197
|
+
children: jsxRuntime.jsx(spinner.Spinner, {
|
|
198
|
+
data: {
|
|
199
|
+
testId: 'data-table-spinner'
|
|
121
200
|
},
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
"
|
|
132
|
-
children:
|
|
201
|
+
size: "xsmall"
|
|
202
|
+
})
|
|
203
|
+
})
|
|
204
|
+
})]
|
|
205
|
+
}), footerGroups.length > 0 ? jsxRuntime.jsx(box.Box, {
|
|
206
|
+
as: "tfoot",
|
|
207
|
+
css: react.css(footerClassName),
|
|
208
|
+
children: footerGroups.map(function (footerGroup) {
|
|
209
|
+
return jsxRuntime.jsx(box.Box, {
|
|
210
|
+
as: "tr",
|
|
211
|
+
children: footerGroup.headers.map(function (footer) {
|
|
133
212
|
return jsxRuntime.jsx(box.Box, {
|
|
134
213
|
as: "td",
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
borderBottom: '1px',
|
|
138
|
-
borderBottomStyle: 'solid',
|
|
139
|
-
borderColor: theme$1.border.color.standard,
|
|
140
|
-
verticalAlign: 'middle',
|
|
141
|
-
textAlign: 'left'
|
|
142
|
-
}),
|
|
143
|
-
children: reactTable.flexRender(cell.column.columnDef.cell, cell.getContext())
|
|
144
|
-
}, cell.id);
|
|
214
|
+
children: reactTable.flexRender(footer.column.columnDef.footer, footer.getContext())
|
|
215
|
+
}, footer.id);
|
|
145
216
|
})
|
|
146
|
-
}
|
|
147
|
-
}, row.id);
|
|
148
|
-
}) : renderRow(table), showSpinner && jsxRuntime.jsx(reactIntersectionObserver.InView, {
|
|
149
|
-
as: "tr"
|
|
150
|
-
// @ts-ignore
|
|
151
|
-
,
|
|
152
|
-
css: react.css({
|
|
153
|
-
columnSpan: 'all'
|
|
154
|
-
}),
|
|
155
|
-
onChange: onBottomSpinnerShown,
|
|
156
|
-
children: jsxRuntime.jsx(box.Box, {
|
|
157
|
-
as: "td",
|
|
158
|
-
padding: "large",
|
|
159
|
-
colSpan: headerGroups.map(function (hg) {
|
|
160
|
-
return hg.headers.length;
|
|
161
|
-
}).reduce(function (sum, len) {
|
|
162
|
-
return len + 1;
|
|
163
|
-
}, 0),
|
|
164
|
-
css: react.css({
|
|
165
|
-
textAlign: 'center',
|
|
166
|
-
verticalAlign: 'middle'
|
|
167
|
-
}),
|
|
168
|
-
children: jsxRuntime.jsx(spinner.Spinner, {
|
|
169
|
-
data: {
|
|
170
|
-
testId: 'data-table-spinner'
|
|
171
|
-
},
|
|
172
|
-
size: "xsmall"
|
|
173
|
-
})
|
|
217
|
+
}, footerGroup.id);
|
|
174
218
|
})
|
|
219
|
+
}) : null]
|
|
220
|
+
}), isLoading && jsxRuntime.jsxs(box.Box, {
|
|
221
|
+
display: "flex",
|
|
222
|
+
alignItems: "center",
|
|
223
|
+
justifyContent: "center",
|
|
224
|
+
padding: "xlarge",
|
|
225
|
+
gap: "small",
|
|
226
|
+
width: "full",
|
|
227
|
+
children: [jsxRuntime.jsx(text.Text, {
|
|
228
|
+
tone: "muted",
|
|
229
|
+
children: "Loading"
|
|
230
|
+
}), jsxRuntime.jsx(spinner.Spinner, {
|
|
231
|
+
data: {
|
|
232
|
+
testId: 'data-table-loading-spinner'
|
|
233
|
+
},
|
|
234
|
+
tone: "primary"
|
|
175
235
|
})]
|
|
176
|
-
}),
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
return jsxRuntime.jsx(box.Box, {
|
|
184
|
-
as: "td",
|
|
185
|
-
children: reactTable.flexRender(footer.column.columnDef.footer, footer.getContext())
|
|
186
|
-
}, footer.id);
|
|
187
|
-
})
|
|
188
|
-
}, footerGroup.id);
|
|
189
|
-
})
|
|
190
|
-
}) : null]
|
|
236
|
+
}), !isLoading && items.length === 0 && emptyState != null && jsxRuntime.jsx(box.Box, {
|
|
237
|
+
display: "flex",
|
|
238
|
+
justifyContent: "center",
|
|
239
|
+
padding: "xlarge",
|
|
240
|
+
width: "full",
|
|
241
|
+
children: emptyState
|
|
242
|
+
})]
|
|
191
243
|
}));
|
|
192
244
|
}
|
|
193
245
|
|
|
@@ -8,6 +8,7 @@ var react = require('@emotion/react');
|
|
|
8
8
|
var box = require('@spark-web/box');
|
|
9
9
|
var icon = require('@spark-web/icon');
|
|
10
10
|
var spinner = require('@spark-web/spinner');
|
|
11
|
+
var text = require('@spark-web/text');
|
|
11
12
|
var theme = require('@spark-web/theme');
|
|
12
13
|
var internal = require('@spark-web/utils/internal');
|
|
13
14
|
var reactTable = require('@tanstack/react-table');
|
|
@@ -19,7 +20,22 @@ function _interopDefault (e) { return e && e.__esModule ? e : { 'default': e };
|
|
|
19
20
|
|
|
20
21
|
var React__default = /*#__PURE__*/_interopDefault(React);
|
|
21
22
|
|
|
22
|
-
var _excluded = ["data", "items", "className", "columns", "enableExpanding", "enableHiding", "enableMultiRowSelection", "enableClickableRow", "headerClassName", "footerClassName", "showBottomSpinner", "rowClassName", "expandedRowComponent", "onBottomSpinnerShown", "onRowClick", "onRowSelectionChange", "renderRow"];
|
|
23
|
+
var _excluded = ["data", "items", "className", "columns", "enableExpanding", "enableHiding", "enableMultiRowSelection", "enableClickableRow", "headerClassName", "footerClassName", "showBottomSpinner", "rowClassName", "expandedRowComponent", "onBottomSpinnerShown", "onRowClick", "onRowSelectionChange", "renderRow", "isLoading", "emptyState"];
|
|
24
|
+
function getAriaSort(column) {
|
|
25
|
+
if (!column.getCanSort()) return undefined;
|
|
26
|
+
if (column.getIsSorted() === 'asc') return 'ascending';
|
|
27
|
+
if (column.getIsSorted() === 'desc') return 'descending';
|
|
28
|
+
return 'none';
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
////////////////////////////////////////////////////////////////////////////////
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* DataTable
|
|
35
|
+
*
|
|
36
|
+
* @see https://spark.brighte.com.au/package/data-table
|
|
37
|
+
*/
|
|
38
|
+
|
|
23
39
|
function DataTable(_ref) {
|
|
24
40
|
var _tableOptions$enableS, _tableOptions$manualS;
|
|
25
41
|
var data = _ref.data,
|
|
@@ -42,6 +58,8 @@ function DataTable(_ref) {
|
|
|
42
58
|
onRowClick = _ref.onRowClick,
|
|
43
59
|
onRowSelectionChange = _ref.onRowSelectionChange,
|
|
44
60
|
renderRow = _ref.renderRow,
|
|
61
|
+
isLoading = _ref.isLoading,
|
|
62
|
+
emptyState = _ref.emptyState,
|
|
45
63
|
tableOptions = _objectWithoutProperties(_ref, _excluded);
|
|
46
64
|
var theme$1 = theme.useTheme();
|
|
47
65
|
var enableRowSelection = !!onRowSelectionChange;
|
|
@@ -64,130 +82,164 @@ function DataTable(_ref) {
|
|
|
64
82
|
var defaultOnRowClick = function defaultOnRowClick(row) {
|
|
65
83
|
return row.toggleSelected();
|
|
66
84
|
};
|
|
67
|
-
return jsxRuntime.jsxs(box.Box, _objectSpread(_objectSpread({
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
children: headerGroup.headers.map(function (header) {
|
|
84
|
-
var _asc$desc;
|
|
85
|
-
return jsxRuntime.jsxs(box.Box, {
|
|
86
|
-
as: "th",
|
|
87
|
-
color: theme$1.color.foreground.muted,
|
|
88
|
-
padding: "medium",
|
|
89
|
-
css: react.css({
|
|
90
|
-
fontFamily: theme$1.typography.fontFamily.sans.name,
|
|
91
|
-
fontWeight: theme$1.typography.fontWeight.semibold,
|
|
92
|
-
textAlign: 'left',
|
|
93
|
-
textTransform: 'uppercase',
|
|
94
|
-
width: "".concat(header.getSize(), "px"),
|
|
95
|
-
svg: {
|
|
96
|
-
marginLeft: theme$1.spacing.xsmall
|
|
97
|
-
}
|
|
98
|
-
}),
|
|
99
|
-
onClick: header.column.getToggleSortingHandler(),
|
|
100
|
-
children: [header.isPlaceholder ? null : reactTable.flexRender(header.column.columnDef.header, header.getContext()), (_asc$desc = {
|
|
101
|
-
asc: jsxRuntime.jsx(icon.ChevronUpIcon, {
|
|
102
|
-
size: "xsmall"
|
|
103
|
-
}),
|
|
104
|
-
desc: jsxRuntime.jsx(icon.ChevronDownIcon, {
|
|
105
|
-
size: "xsmall"
|
|
106
|
-
})
|
|
107
|
-
}[header.column.getIsSorted()]) !== null && _asc$desc !== void 0 ? _asc$desc : null]
|
|
108
|
-
}, header.id);
|
|
109
|
-
})
|
|
110
|
-
}, headerGroup.id);
|
|
111
|
-
})
|
|
112
|
-
}) : null, jsxRuntime.jsxs(box.Box, {
|
|
113
|
-
as: "tbody",
|
|
114
|
-
children: [!renderRow ? table.getRowModel().rows.map(function (row) {
|
|
115
|
-
return jsxRuntime.jsxs(React__default["default"].Fragment, {
|
|
116
|
-
children: [jsxRuntime.jsx(box.Box, {
|
|
85
|
+
return jsxRuntime.jsxs(box.Box, _objectSpread(_objectSpread({}, data ? internal.buildDataAttributes(data) : undefined), {}, {
|
|
86
|
+
children: [jsxRuntime.jsxs(box.Box, {
|
|
87
|
+
as: "table",
|
|
88
|
+
width: "full",
|
|
89
|
+
css: className,
|
|
90
|
+
children: [headerGroups.length > 0 ? jsxRuntime.jsx(box.Box, {
|
|
91
|
+
as: "thead",
|
|
92
|
+
css: react.css({
|
|
93
|
+
backgroundColor: theme$1.color.background.surface,
|
|
94
|
+
// we use box shadow instead of bottom border
|
|
95
|
+
// to allow the border to stay in the header on scroll
|
|
96
|
+
// when the table is sticky
|
|
97
|
+
boxShadow: "inset 0 -2px 0 ".concat(theme$1.border.color.primaryActive)
|
|
98
|
+
}, headerClassName),
|
|
99
|
+
children: headerGroups.map(function (headerGroup) {
|
|
100
|
+
return jsxRuntime.jsx(box.Box, {
|
|
117
101
|
as: "tr",
|
|
102
|
+
children: headerGroup.headers.map(function (header) {
|
|
103
|
+
var _asc$desc;
|
|
104
|
+
return jsxRuntime.jsxs(box.Box, {
|
|
105
|
+
as: "th",
|
|
106
|
+
padding: "medium",
|
|
107
|
+
css: react.css(_objectSpread(_objectSpread({
|
|
108
|
+
color: theme$1.color.foreground.primaryActive,
|
|
109
|
+
fontFamily: theme$1.typography.fontFamily.sans.name,
|
|
110
|
+
fontWeight: theme$1.typography.fontWeight.semibold,
|
|
111
|
+
textAlign: 'left',
|
|
112
|
+
width: "".concat(header.getSize(), "px"),
|
|
113
|
+
cursor: header.column.getCanSort() ? 'pointer' : undefined,
|
|
114
|
+
userSelect: header.column.getCanSort() ? 'none' : undefined
|
|
115
|
+
}, header.column.getCanSort() ? {
|
|
116
|
+
'&:hover': {
|
|
117
|
+
backgroundColor: theme$1.backgroundInteractions.primaryLowHover
|
|
118
|
+
}
|
|
119
|
+
} : {}), {}, {
|
|
120
|
+
svg: {
|
|
121
|
+
marginLeft: theme$1.spacing.xsmall
|
|
122
|
+
}
|
|
123
|
+
})),
|
|
124
|
+
onClick: header.column.getToggleSortingHandler(),
|
|
125
|
+
"aria-sort": getAriaSort(header.column),
|
|
126
|
+
children: [header.isPlaceholder ? null : reactTable.flexRender(header.column.columnDef.header, header.getContext()), (_asc$desc = {
|
|
127
|
+
asc: jsxRuntime.jsx(icon.SortAscendingIcon, {
|
|
128
|
+
size: "xxsmall",
|
|
129
|
+
tone: "primaryActive"
|
|
130
|
+
}),
|
|
131
|
+
desc: jsxRuntime.jsx(icon.SortDescendingIcon, {
|
|
132
|
+
size: "xxsmall",
|
|
133
|
+
tone: "primaryActive"
|
|
134
|
+
})
|
|
135
|
+
}[header.column.getIsSorted()]) !== null && _asc$desc !== void 0 ? _asc$desc : null]
|
|
136
|
+
}, header.id);
|
|
137
|
+
})
|
|
138
|
+
}, headerGroup.id);
|
|
139
|
+
})
|
|
140
|
+
}) : null, jsxRuntime.jsxs(box.Box, {
|
|
141
|
+
as: "tbody",
|
|
142
|
+
children: [!renderRow ? table.getRowModel().rows.map(function (row) {
|
|
143
|
+
return jsxRuntime.jsxs(React__default["default"].Fragment, {
|
|
144
|
+
children: [jsxRuntime.jsx(box.Box, {
|
|
145
|
+
as: "tr",
|
|
146
|
+
css: react.css(_objectSpread({
|
|
147
|
+
'&[data-is-selected="true"],&[data-is-expanded="true"]': {
|
|
148
|
+
backgroundColor: theme$1.color.background.primarySoft
|
|
149
|
+
}
|
|
150
|
+
}, enableClickableRow ? {
|
|
151
|
+
':hover:not(:has(button:hover))': {
|
|
152
|
+
backgroundColor: theme$1.color.background.inputPressed,
|
|
153
|
+
cursor: 'pointer'
|
|
154
|
+
}
|
|
155
|
+
} : {}), rowClassName ? rowClassName(row, row.index) : undefined),
|
|
156
|
+
onClick: function onClick() {
|
|
157
|
+
return enableClickableRow && (onRowClick ? onRowClick(row) : defaultOnRowClick(row));
|
|
158
|
+
},
|
|
159
|
+
"data-is-selected": row.getIsSelected(),
|
|
160
|
+
"data-is-expanded": row.getIsExpanded(),
|
|
161
|
+
children: row.getVisibleCells().map(function (cell) {
|
|
162
|
+
return jsxRuntime.jsx(box.Box, {
|
|
163
|
+
as: "td",
|
|
164
|
+
padding: "large",
|
|
165
|
+
css: react.css({
|
|
166
|
+
borderBottomWidth: theme$1.border.width.standard,
|
|
167
|
+
borderBottomStyle: 'solid',
|
|
168
|
+
borderColor: theme$1.border.color.standard,
|
|
169
|
+
verticalAlign: 'middle',
|
|
170
|
+
textAlign: 'left'
|
|
171
|
+
}),
|
|
172
|
+
children: reactTable.flexRender(cell.column.columnDef.cell, cell.getContext())
|
|
173
|
+
}, cell.id);
|
|
174
|
+
})
|
|
175
|
+
}), enableExpanding && row.getIsExpanded() && expandedRowComponent && expandedRowComponent(row, table)]
|
|
176
|
+
}, row.id);
|
|
177
|
+
}) : renderRow(table), showSpinner && jsxRuntime.jsx(reactIntersectionObserver.InView, {
|
|
178
|
+
as: "tr"
|
|
179
|
+
// @ts-ignore
|
|
180
|
+
,
|
|
181
|
+
css: react.css({
|
|
182
|
+
columnSpan: 'all'
|
|
183
|
+
}),
|
|
184
|
+
onChange: onBottomSpinnerShown,
|
|
185
|
+
children: jsxRuntime.jsx(box.Box, {
|
|
186
|
+
as: "td",
|
|
187
|
+
padding: "large",
|
|
188
|
+
colSpan: headerGroups.map(function (hg) {
|
|
189
|
+
return hg.headers.length;
|
|
190
|
+
}).reduce(function (sum, len) {
|
|
191
|
+
return len + 1;
|
|
192
|
+
}, 0),
|
|
118
193
|
css: react.css({
|
|
119
|
-
'
|
|
120
|
-
|
|
194
|
+
textAlign: 'center',
|
|
195
|
+
verticalAlign: 'middle'
|
|
196
|
+
}),
|
|
197
|
+
children: jsxRuntime.jsx(spinner.Spinner, {
|
|
198
|
+
data: {
|
|
199
|
+
testId: 'data-table-spinner'
|
|
121
200
|
},
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
"
|
|
132
|
-
children:
|
|
201
|
+
size: "xsmall"
|
|
202
|
+
})
|
|
203
|
+
})
|
|
204
|
+
})]
|
|
205
|
+
}), footerGroups.length > 0 ? jsxRuntime.jsx(box.Box, {
|
|
206
|
+
as: "tfoot",
|
|
207
|
+
css: react.css(footerClassName),
|
|
208
|
+
children: footerGroups.map(function (footerGroup) {
|
|
209
|
+
return jsxRuntime.jsx(box.Box, {
|
|
210
|
+
as: "tr",
|
|
211
|
+
children: footerGroup.headers.map(function (footer) {
|
|
133
212
|
return jsxRuntime.jsx(box.Box, {
|
|
134
213
|
as: "td",
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
borderBottom: '1px',
|
|
138
|
-
borderBottomStyle: 'solid',
|
|
139
|
-
borderColor: theme$1.border.color.standard,
|
|
140
|
-
verticalAlign: 'middle',
|
|
141
|
-
textAlign: 'left'
|
|
142
|
-
}),
|
|
143
|
-
children: reactTable.flexRender(cell.column.columnDef.cell, cell.getContext())
|
|
144
|
-
}, cell.id);
|
|
214
|
+
children: reactTable.flexRender(footer.column.columnDef.footer, footer.getContext())
|
|
215
|
+
}, footer.id);
|
|
145
216
|
})
|
|
146
|
-
}
|
|
147
|
-
}, row.id);
|
|
148
|
-
}) : renderRow(table), showSpinner && jsxRuntime.jsx(reactIntersectionObserver.InView, {
|
|
149
|
-
as: "tr"
|
|
150
|
-
// @ts-ignore
|
|
151
|
-
,
|
|
152
|
-
css: react.css({
|
|
153
|
-
columnSpan: 'all'
|
|
154
|
-
}),
|
|
155
|
-
onChange: onBottomSpinnerShown,
|
|
156
|
-
children: jsxRuntime.jsx(box.Box, {
|
|
157
|
-
as: "td",
|
|
158
|
-
padding: "large",
|
|
159
|
-
colSpan: headerGroups.map(function (hg) {
|
|
160
|
-
return hg.headers.length;
|
|
161
|
-
}).reduce(function (sum, len) {
|
|
162
|
-
return len + 1;
|
|
163
|
-
}, 0),
|
|
164
|
-
css: react.css({
|
|
165
|
-
textAlign: 'center',
|
|
166
|
-
verticalAlign: 'middle'
|
|
167
|
-
}),
|
|
168
|
-
children: jsxRuntime.jsx(spinner.Spinner, {
|
|
169
|
-
data: {
|
|
170
|
-
testId: 'data-table-spinner'
|
|
171
|
-
},
|
|
172
|
-
size: "xsmall"
|
|
173
|
-
})
|
|
217
|
+
}, footerGroup.id);
|
|
174
218
|
})
|
|
219
|
+
}) : null]
|
|
220
|
+
}), isLoading && jsxRuntime.jsxs(box.Box, {
|
|
221
|
+
display: "flex",
|
|
222
|
+
alignItems: "center",
|
|
223
|
+
justifyContent: "center",
|
|
224
|
+
padding: "xlarge",
|
|
225
|
+
gap: "small",
|
|
226
|
+
width: "full",
|
|
227
|
+
children: [jsxRuntime.jsx(text.Text, {
|
|
228
|
+
tone: "muted",
|
|
229
|
+
children: "Loading"
|
|
230
|
+
}), jsxRuntime.jsx(spinner.Spinner, {
|
|
231
|
+
data: {
|
|
232
|
+
testId: 'data-table-loading-spinner'
|
|
233
|
+
},
|
|
234
|
+
tone: "primary"
|
|
175
235
|
})]
|
|
176
|
-
}),
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
return jsxRuntime.jsx(box.Box, {
|
|
184
|
-
as: "td",
|
|
185
|
-
children: reactTable.flexRender(footer.column.columnDef.footer, footer.getContext())
|
|
186
|
-
}, footer.id);
|
|
187
|
-
})
|
|
188
|
-
}, footerGroup.id);
|
|
189
|
-
})
|
|
190
|
-
}) : null]
|
|
236
|
+
}), !isLoading && items.length === 0 && emptyState != null && jsxRuntime.jsx(box.Box, {
|
|
237
|
+
display: "flex",
|
|
238
|
+
justifyContent: "center",
|
|
239
|
+
padding: "xlarge",
|
|
240
|
+
width: "full",
|
|
241
|
+
children: emptyState
|
|
242
|
+
})]
|
|
191
243
|
}));
|
|
192
244
|
}
|
|
193
245
|
|
|
@@ -2,8 +2,9 @@ import _objectSpread from '@babel/runtime/helpers/esm/objectSpread2';
|
|
|
2
2
|
import _objectWithoutProperties from '@babel/runtime/helpers/esm/objectWithoutProperties';
|
|
3
3
|
import { css } from '@emotion/react';
|
|
4
4
|
import { Box } from '@spark-web/box';
|
|
5
|
-
import {
|
|
5
|
+
import { SortAscendingIcon, SortDescendingIcon } from '@spark-web/icon';
|
|
6
6
|
import { Spinner } from '@spark-web/spinner';
|
|
7
|
+
import { Text } from '@spark-web/text';
|
|
7
8
|
import { useTheme } from '@spark-web/theme';
|
|
8
9
|
import { buildDataAttributes } from '@spark-web/utils/internal';
|
|
9
10
|
import { useReactTable, getCoreRowModel, flexRender } from '@tanstack/react-table';
|
|
@@ -12,7 +13,22 @@ import React from 'react';
|
|
|
12
13
|
import { InView } from 'react-intersection-observer';
|
|
13
14
|
import { jsxs, jsx } from '@emotion/react/jsx-runtime';
|
|
14
15
|
|
|
15
|
-
var _excluded = ["data", "items", "className", "columns", "enableExpanding", "enableHiding", "enableMultiRowSelection", "enableClickableRow", "headerClassName", "footerClassName", "showBottomSpinner", "rowClassName", "expandedRowComponent", "onBottomSpinnerShown", "onRowClick", "onRowSelectionChange", "renderRow"];
|
|
16
|
+
var _excluded = ["data", "items", "className", "columns", "enableExpanding", "enableHiding", "enableMultiRowSelection", "enableClickableRow", "headerClassName", "footerClassName", "showBottomSpinner", "rowClassName", "expandedRowComponent", "onBottomSpinnerShown", "onRowClick", "onRowSelectionChange", "renderRow", "isLoading", "emptyState"];
|
|
17
|
+
function getAriaSort(column) {
|
|
18
|
+
if (!column.getCanSort()) return undefined;
|
|
19
|
+
if (column.getIsSorted() === 'asc') return 'ascending';
|
|
20
|
+
if (column.getIsSorted() === 'desc') return 'descending';
|
|
21
|
+
return 'none';
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
////////////////////////////////////////////////////////////////////////////////
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* DataTable
|
|
28
|
+
*
|
|
29
|
+
* @see https://spark.brighte.com.au/package/data-table
|
|
30
|
+
*/
|
|
31
|
+
|
|
16
32
|
function DataTable(_ref) {
|
|
17
33
|
var _tableOptions$enableS, _tableOptions$manualS;
|
|
18
34
|
var data = _ref.data,
|
|
@@ -35,6 +51,8 @@ function DataTable(_ref) {
|
|
|
35
51
|
onRowClick = _ref.onRowClick,
|
|
36
52
|
onRowSelectionChange = _ref.onRowSelectionChange,
|
|
37
53
|
renderRow = _ref.renderRow,
|
|
54
|
+
isLoading = _ref.isLoading,
|
|
55
|
+
emptyState = _ref.emptyState,
|
|
38
56
|
tableOptions = _objectWithoutProperties(_ref, _excluded);
|
|
39
57
|
var theme = useTheme();
|
|
40
58
|
var enableRowSelection = !!onRowSelectionChange;
|
|
@@ -57,130 +75,164 @@ function DataTable(_ref) {
|
|
|
57
75
|
var defaultOnRowClick = function defaultOnRowClick(row) {
|
|
58
76
|
return row.toggleSelected();
|
|
59
77
|
};
|
|
60
|
-
return jsxs(Box, _objectSpread(_objectSpread({
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
children: headerGroup.headers.map(function (header) {
|
|
77
|
-
var _asc$desc;
|
|
78
|
-
return jsxs(Box, {
|
|
79
|
-
as: "th",
|
|
80
|
-
color: theme.color.foreground.muted,
|
|
81
|
-
padding: "medium",
|
|
82
|
-
css: css({
|
|
83
|
-
fontFamily: theme.typography.fontFamily.sans.name,
|
|
84
|
-
fontWeight: theme.typography.fontWeight.semibold,
|
|
85
|
-
textAlign: 'left',
|
|
86
|
-
textTransform: 'uppercase',
|
|
87
|
-
width: "".concat(header.getSize(), "px"),
|
|
88
|
-
svg: {
|
|
89
|
-
marginLeft: theme.spacing.xsmall
|
|
90
|
-
}
|
|
91
|
-
}),
|
|
92
|
-
onClick: header.column.getToggleSortingHandler(),
|
|
93
|
-
children: [header.isPlaceholder ? null : flexRender(header.column.columnDef.header, header.getContext()), (_asc$desc = {
|
|
94
|
-
asc: jsx(ChevronUpIcon, {
|
|
95
|
-
size: "xsmall"
|
|
96
|
-
}),
|
|
97
|
-
desc: jsx(ChevronDownIcon, {
|
|
98
|
-
size: "xsmall"
|
|
99
|
-
})
|
|
100
|
-
}[header.column.getIsSorted()]) !== null && _asc$desc !== void 0 ? _asc$desc : null]
|
|
101
|
-
}, header.id);
|
|
102
|
-
})
|
|
103
|
-
}, headerGroup.id);
|
|
104
|
-
})
|
|
105
|
-
}) : null, jsxs(Box, {
|
|
106
|
-
as: "tbody",
|
|
107
|
-
children: [!renderRow ? table.getRowModel().rows.map(function (row) {
|
|
108
|
-
return jsxs(React.Fragment, {
|
|
109
|
-
children: [jsx(Box, {
|
|
78
|
+
return jsxs(Box, _objectSpread(_objectSpread({}, data ? buildDataAttributes(data) : undefined), {}, {
|
|
79
|
+
children: [jsxs(Box, {
|
|
80
|
+
as: "table",
|
|
81
|
+
width: "full",
|
|
82
|
+
css: className,
|
|
83
|
+
children: [headerGroups.length > 0 ? jsx(Box, {
|
|
84
|
+
as: "thead",
|
|
85
|
+
css: css({
|
|
86
|
+
backgroundColor: theme.color.background.surface,
|
|
87
|
+
// we use box shadow instead of bottom border
|
|
88
|
+
// to allow the border to stay in the header on scroll
|
|
89
|
+
// when the table is sticky
|
|
90
|
+
boxShadow: "inset 0 -2px 0 ".concat(theme.border.color.primaryActive)
|
|
91
|
+
}, headerClassName),
|
|
92
|
+
children: headerGroups.map(function (headerGroup) {
|
|
93
|
+
return jsx(Box, {
|
|
110
94
|
as: "tr",
|
|
95
|
+
children: headerGroup.headers.map(function (header) {
|
|
96
|
+
var _asc$desc;
|
|
97
|
+
return jsxs(Box, {
|
|
98
|
+
as: "th",
|
|
99
|
+
padding: "medium",
|
|
100
|
+
css: css(_objectSpread(_objectSpread({
|
|
101
|
+
color: theme.color.foreground.primaryActive,
|
|
102
|
+
fontFamily: theme.typography.fontFamily.sans.name,
|
|
103
|
+
fontWeight: theme.typography.fontWeight.semibold,
|
|
104
|
+
textAlign: 'left',
|
|
105
|
+
width: "".concat(header.getSize(), "px"),
|
|
106
|
+
cursor: header.column.getCanSort() ? 'pointer' : undefined,
|
|
107
|
+
userSelect: header.column.getCanSort() ? 'none' : undefined
|
|
108
|
+
}, header.column.getCanSort() ? {
|
|
109
|
+
'&:hover': {
|
|
110
|
+
backgroundColor: theme.backgroundInteractions.primaryLowHover
|
|
111
|
+
}
|
|
112
|
+
} : {}), {}, {
|
|
113
|
+
svg: {
|
|
114
|
+
marginLeft: theme.spacing.xsmall
|
|
115
|
+
}
|
|
116
|
+
})),
|
|
117
|
+
onClick: header.column.getToggleSortingHandler(),
|
|
118
|
+
"aria-sort": getAriaSort(header.column),
|
|
119
|
+
children: [header.isPlaceholder ? null : flexRender(header.column.columnDef.header, header.getContext()), (_asc$desc = {
|
|
120
|
+
asc: jsx(SortAscendingIcon, {
|
|
121
|
+
size: "xxsmall",
|
|
122
|
+
tone: "primaryActive"
|
|
123
|
+
}),
|
|
124
|
+
desc: jsx(SortDescendingIcon, {
|
|
125
|
+
size: "xxsmall",
|
|
126
|
+
tone: "primaryActive"
|
|
127
|
+
})
|
|
128
|
+
}[header.column.getIsSorted()]) !== null && _asc$desc !== void 0 ? _asc$desc : null]
|
|
129
|
+
}, header.id);
|
|
130
|
+
})
|
|
131
|
+
}, headerGroup.id);
|
|
132
|
+
})
|
|
133
|
+
}) : null, jsxs(Box, {
|
|
134
|
+
as: "tbody",
|
|
135
|
+
children: [!renderRow ? table.getRowModel().rows.map(function (row) {
|
|
136
|
+
return jsxs(React.Fragment, {
|
|
137
|
+
children: [jsx(Box, {
|
|
138
|
+
as: "tr",
|
|
139
|
+
css: css(_objectSpread({
|
|
140
|
+
'&[data-is-selected="true"],&[data-is-expanded="true"]': {
|
|
141
|
+
backgroundColor: theme.color.background.primarySoft
|
|
142
|
+
}
|
|
143
|
+
}, enableClickableRow ? {
|
|
144
|
+
':hover:not(:has(button:hover))': {
|
|
145
|
+
backgroundColor: theme.color.background.inputPressed,
|
|
146
|
+
cursor: 'pointer'
|
|
147
|
+
}
|
|
148
|
+
} : {}), rowClassName ? rowClassName(row, row.index) : undefined),
|
|
149
|
+
onClick: function onClick() {
|
|
150
|
+
return enableClickableRow && (onRowClick ? onRowClick(row) : defaultOnRowClick(row));
|
|
151
|
+
},
|
|
152
|
+
"data-is-selected": row.getIsSelected(),
|
|
153
|
+
"data-is-expanded": row.getIsExpanded(),
|
|
154
|
+
children: row.getVisibleCells().map(function (cell) {
|
|
155
|
+
return jsx(Box, {
|
|
156
|
+
as: "td",
|
|
157
|
+
padding: "large",
|
|
158
|
+
css: css({
|
|
159
|
+
borderBottomWidth: theme.border.width.standard,
|
|
160
|
+
borderBottomStyle: 'solid',
|
|
161
|
+
borderColor: theme.border.color.standard,
|
|
162
|
+
verticalAlign: 'middle',
|
|
163
|
+
textAlign: 'left'
|
|
164
|
+
}),
|
|
165
|
+
children: flexRender(cell.column.columnDef.cell, cell.getContext())
|
|
166
|
+
}, cell.id);
|
|
167
|
+
})
|
|
168
|
+
}), enableExpanding && row.getIsExpanded() && expandedRowComponent && expandedRowComponent(row, table)]
|
|
169
|
+
}, row.id);
|
|
170
|
+
}) : renderRow(table), showSpinner && jsx(InView, {
|
|
171
|
+
as: "tr"
|
|
172
|
+
// @ts-ignore
|
|
173
|
+
,
|
|
174
|
+
css: css({
|
|
175
|
+
columnSpan: 'all'
|
|
176
|
+
}),
|
|
177
|
+
onChange: onBottomSpinnerShown,
|
|
178
|
+
children: jsx(Box, {
|
|
179
|
+
as: "td",
|
|
180
|
+
padding: "large",
|
|
181
|
+
colSpan: headerGroups.map(function (hg) {
|
|
182
|
+
return hg.headers.length;
|
|
183
|
+
}).reduce(function (sum, len) {
|
|
184
|
+
return len + 1;
|
|
185
|
+
}, 0),
|
|
111
186
|
css: css({
|
|
112
|
-
'
|
|
113
|
-
|
|
187
|
+
textAlign: 'center',
|
|
188
|
+
verticalAlign: 'middle'
|
|
189
|
+
}),
|
|
190
|
+
children: jsx(Spinner, {
|
|
191
|
+
data: {
|
|
192
|
+
testId: 'data-table-spinner'
|
|
114
193
|
},
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
"
|
|
125
|
-
children:
|
|
194
|
+
size: "xsmall"
|
|
195
|
+
})
|
|
196
|
+
})
|
|
197
|
+
})]
|
|
198
|
+
}), footerGroups.length > 0 ? jsx(Box, {
|
|
199
|
+
as: "tfoot",
|
|
200
|
+
css: css(footerClassName),
|
|
201
|
+
children: footerGroups.map(function (footerGroup) {
|
|
202
|
+
return jsx(Box, {
|
|
203
|
+
as: "tr",
|
|
204
|
+
children: footerGroup.headers.map(function (footer) {
|
|
126
205
|
return jsx(Box, {
|
|
127
206
|
as: "td",
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
borderBottom: '1px',
|
|
131
|
-
borderBottomStyle: 'solid',
|
|
132
|
-
borderColor: theme.border.color.standard,
|
|
133
|
-
verticalAlign: 'middle',
|
|
134
|
-
textAlign: 'left'
|
|
135
|
-
}),
|
|
136
|
-
children: flexRender(cell.column.columnDef.cell, cell.getContext())
|
|
137
|
-
}, cell.id);
|
|
207
|
+
children: flexRender(footer.column.columnDef.footer, footer.getContext())
|
|
208
|
+
}, footer.id);
|
|
138
209
|
})
|
|
139
|
-
}
|
|
140
|
-
}, row.id);
|
|
141
|
-
}) : renderRow(table), showSpinner && jsx(InView, {
|
|
142
|
-
as: "tr"
|
|
143
|
-
// @ts-ignore
|
|
144
|
-
,
|
|
145
|
-
css: css({
|
|
146
|
-
columnSpan: 'all'
|
|
147
|
-
}),
|
|
148
|
-
onChange: onBottomSpinnerShown,
|
|
149
|
-
children: jsx(Box, {
|
|
150
|
-
as: "td",
|
|
151
|
-
padding: "large",
|
|
152
|
-
colSpan: headerGroups.map(function (hg) {
|
|
153
|
-
return hg.headers.length;
|
|
154
|
-
}).reduce(function (sum, len) {
|
|
155
|
-
return len + 1;
|
|
156
|
-
}, 0),
|
|
157
|
-
css: css({
|
|
158
|
-
textAlign: 'center',
|
|
159
|
-
verticalAlign: 'middle'
|
|
160
|
-
}),
|
|
161
|
-
children: jsx(Spinner, {
|
|
162
|
-
data: {
|
|
163
|
-
testId: 'data-table-spinner'
|
|
164
|
-
},
|
|
165
|
-
size: "xsmall"
|
|
166
|
-
})
|
|
210
|
+
}, footerGroup.id);
|
|
167
211
|
})
|
|
212
|
+
}) : null]
|
|
213
|
+
}), isLoading && jsxs(Box, {
|
|
214
|
+
display: "flex",
|
|
215
|
+
alignItems: "center",
|
|
216
|
+
justifyContent: "center",
|
|
217
|
+
padding: "xlarge",
|
|
218
|
+
gap: "small",
|
|
219
|
+
width: "full",
|
|
220
|
+
children: [jsx(Text, {
|
|
221
|
+
tone: "muted",
|
|
222
|
+
children: "Loading"
|
|
223
|
+
}), jsx(Spinner, {
|
|
224
|
+
data: {
|
|
225
|
+
testId: 'data-table-loading-spinner'
|
|
226
|
+
},
|
|
227
|
+
tone: "primary"
|
|
168
228
|
})]
|
|
169
|
-
}),
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
return jsx(Box, {
|
|
177
|
-
as: "td",
|
|
178
|
-
children: flexRender(footer.column.columnDef.footer, footer.getContext())
|
|
179
|
-
}, footer.id);
|
|
180
|
-
})
|
|
181
|
-
}, footerGroup.id);
|
|
182
|
-
})
|
|
183
|
-
}) : null]
|
|
229
|
+
}), !isLoading && items.length === 0 && emptyState != null && jsx(Box, {
|
|
230
|
+
display: "flex",
|
|
231
|
+
justifyContent: "center",
|
|
232
|
+
padding: "xlarge",
|
|
233
|
+
width: "full",
|
|
234
|
+
children: emptyState
|
|
235
|
+
})]
|
|
184
236
|
}));
|
|
185
237
|
}
|
|
186
238
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@spark-web/data-table",
|
|
3
|
-
"version": "5.2.
|
|
3
|
+
"version": "5.2.1",
|
|
4
4
|
"homepage": "https://github.com/brighte-labs/spark-web#readme",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
"module": "dist/spark-web-data-table.esm.js",
|
|
13
13
|
"files": [
|
|
14
14
|
"CHANGELOG.md",
|
|
15
|
+
"CLAUDE.md",
|
|
15
16
|
"dist",
|
|
16
17
|
"README.md"
|
|
17
18
|
],
|
|
@@ -19,11 +20,11 @@
|
|
|
19
20
|
"@babel/runtime": "^7.25.0",
|
|
20
21
|
"@emotion/react": "^11.14.0",
|
|
21
22
|
"@spark-web/a11y": "^5.3.0",
|
|
22
|
-
"@spark-web/box": "^6.0.
|
|
23
|
+
"@spark-web/box": "^6.0.1",
|
|
23
24
|
"@spark-web/checkbox": "^5.1.0",
|
|
24
25
|
"@spark-web/icon": "^5.1.0",
|
|
25
|
-
"@spark-web/spinner": "^5.1.
|
|
26
|
-
"@spark-web/text": "^5.3.
|
|
26
|
+
"@spark-web/spinner": "^5.1.1",
|
|
27
|
+
"@spark-web/text": "^5.3.1",
|
|
27
28
|
"@spark-web/theme": "^5.13.0",
|
|
28
29
|
"@spark-web/utils": "^5.1.0",
|
|
29
30
|
"@tanstack/react-table": "^8.14.0",
|