compote-ui 0.42.7 → 0.43.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/data-table/column-helper.ts.md +96 -0
- package/dist/components/data-table/create-table.ts.md +386 -0
- package/dist/components/data-table/data-table-column-filter.svelte.md +249 -0
- package/dist/components/data-table/data-table-column-visibility.svelte.md +74 -0
- package/dist/components/data-table/{data-table-head.svelte → data-table-head.svelte.md} +1 -1
- package/dist/components/data-table/data-table-new.svelte.md +245 -0
- package/dist/components/data-table/data-table-title.svelte.md +16 -0
- package/dist/components/data-table/data-table-toolbar.svelte.md +40 -0
- package/dist/components/data-table/data-table-utils.ts.md +179 -0
- package/dist/components/data-table/{data-table-virtual-rows.svelte → data-table-virtual-rows.svelte.md} +1 -1
- package/dist/components/data-table/data-table-virtualized.svelte.md +108 -0
- package/dist/components/data-table/data-table.svelte.md +214 -0
- package/dist/components/data-table/index.ts.md +22 -0
- package/dist/components/data-table/types.ts.md +101 -0
- package/dist/components/data-table/virtual/index.ts.md +26 -0
- package/dist/components/{data-table → data-table-v8}/column-helper.d.ts +1 -1
- package/dist/components/data-table-v8/create-svelte-table.svelte.d.ts +8 -0
- package/dist/components/data-table-v8/create-svelte-table.svelte.js +85 -0
- package/dist/components/data-table-v8/create-table.svelte.d.ts +35 -0
- package/dist/components/{data-table/create-table.js → data-table-v8/create-table.svelte.js} +25 -55
- package/dist/components/data-table-v8/data-table-checkbox.css +44 -0
- package/dist/components/{data-table → data-table-v8}/data-table-column-filter.svelte +16 -19
- package/dist/components/{data-table → data-table-v8}/data-table-column-filter.svelte.d.ts +2 -2
- package/dist/components/{data-table → data-table-v8}/data-table-column-visibility.svelte +15 -14
- package/dist/components/{data-table → data-table-v8}/data-table-column-visibility.svelte.d.ts +2 -2
- package/dist/components/data-table-v8/data-table-head.svelte +200 -0
- package/dist/components/{data-table → data-table-v8}/data-table-head.svelte.d.ts +3 -3
- package/dist/components/{data-table → data-table-v8}/data-table-utils.d.ts +10 -15
- package/dist/components/{data-table → data-table-v8}/data-table-utils.js +18 -12
- package/dist/components/data-table-v8/data-table-virtual-rows.svelte +170 -0
- package/dist/components/{data-table → data-table-v8}/data-table-virtual-rows.svelte.d.ts +3 -3
- package/dist/components/{data-table → data-table-v8}/data-table-virtualized.svelte +15 -14
- package/dist/components/{data-table → data-table-v8}/data-table-virtualized.svelte.d.ts +2 -2
- package/dist/components/{data-table → data-table-v8}/data-table.svelte +41 -26
- package/dist/components/{data-table → data-table-v8}/data-table.svelte.d.ts +2 -2
- package/dist/components/data-table-v8/flex-render.svelte +35 -0
- package/dist/components/data-table-v8/flex-render.svelte.d.ts +28 -0
- package/dist/components/{data-table → data-table-v8}/index.d.ts +4 -2
- package/dist/components/{data-table → data-table-v8}/index.js +3 -1
- package/dist/components/data-table-v8/render-helpers.d.ts +13 -0
- package/dist/components/data-table-v8/render-helpers.js +23 -0
- package/dist/components/{data-table → data-table-v8}/types.d.ts +12 -2
- package/dist/components/data-table-v8/virtual/index.d.ts +3 -0
- package/dist/components/data-table-v8/virtual/index.js +2 -0
- package/package.json +9 -9
- package/dist/components/data-table/create-table.d.ts +0 -41
- package/dist/components/data-table/virtual/index.d.ts +0 -3
- package/dist/components/data-table/virtual/index.js +0 -2
- /package/dist/components/{data-table → data-table-v8}/column-helper.js +0 -0
- /package/dist/components/{data-table → data-table-v8}/data-table-title.svelte +0 -0
- /package/dist/components/{data-table → data-table-v8}/data-table-title.svelte.d.ts +0 -0
- /package/dist/components/{data-table → data-table-v8}/data-table-toolbar.svelte +0 -0
- /package/dist/components/{data-table → data-table-v8}/data-table-toolbar.svelte.d.ts +0 -0
- /package/dist/components/{data-table → data-table-v8}/types.js +0 -0
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
import type { CellData, ColumnPinningPosition, Header, RowData } from '@tanstack/svelte-table';
|
|
2
|
+
import { cn } from 'tailwind-variants';
|
|
3
|
+
import type { DataTableFeatures, DataTableInstance } from './create-table';
|
|
4
|
+
import type { DataTableColumnMeta } from './types';
|
|
5
|
+
|
|
6
|
+
export type DataTablePinnableColumn = {
|
|
7
|
+
getIsPinned(): ColumnPinningPosition;
|
|
8
|
+
getStart(position?: ColumnPinningPosition): number;
|
|
9
|
+
getAfter(position?: ColumnPinningPosition): number;
|
|
10
|
+
getIsLastColumn(position?: ColumnPinningPosition): boolean;
|
|
11
|
+
getIsFirstColumn(position?: ColumnPinningPosition): boolean;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export function alignClass(align: DataTableColumnMeta['align']) {
|
|
15
|
+
return align === 'right' ? 'text-right' : align === 'center' ? 'text-center' : 'text-left';
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export function justifyClass(align: DataTableColumnMeta['align']) {
|
|
19
|
+
return align === 'right'
|
|
20
|
+
? 'justify-end'
|
|
21
|
+
: align === 'center'
|
|
22
|
+
? 'justify-center'
|
|
23
|
+
: 'justify-start';
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export function sortButtonDirectionClass(align: DataTableColumnMeta['align']) {
|
|
27
|
+
return align === 'right' ? 'flex-row-reverse' : 'flex-row';
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export function columnSizeStyle(size: number) {
|
|
31
|
+
return `width: ${size}px`;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export function selectionColumnSizeStyle() {
|
|
35
|
+
return 'width: 40px';
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export function virtualColumnSizeStyle(size: number) {
|
|
39
|
+
return `display: flex; flex: 0 0 ${size}px; width: ${size}px`;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export function virtualSelectionColumnSizeStyle() {
|
|
43
|
+
return 'display: flex; flex: 0 0 40px; width: 40px';
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export function tableSizeStyle<T extends RowData>(
|
|
47
|
+
table: DataTableInstance<T>,
|
|
48
|
+
isRowSelectionEnabled: boolean
|
|
49
|
+
) {
|
|
50
|
+
return `width: max(100%, ${table.getTotalSize() + (isRowSelectionEnabled ? 40 : 0)}px)`;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export function virtualGrowColumnSizeStyle() {
|
|
54
|
+
return 'display: flex; flex: 1; min-width: 0';
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export function virtualGroupWithGrowSizeStyle(fixedPortion: number) {
|
|
58
|
+
return `display: flex; flex: 1 0 ${fixedPortion}px; width: ${fixedPortion}px`;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export function resizeHandleStyle<T extends RowData>(
|
|
62
|
+
table: DataTableInstance<T>,
|
|
63
|
+
header: Header<DataTableFeatures, T, CellData>
|
|
64
|
+
) {
|
|
65
|
+
if (table.options.columnResizeMode !== 'onEnd') return undefined;
|
|
66
|
+
const deltaOffset = table.store.state.columnResizing.deltaOffset;
|
|
67
|
+
if (!header.column.getIsResizing() || deltaOffset === null) return undefined;
|
|
68
|
+
return `transform: translateX(${deltaOffset}px)`;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export function resizeHandleClass(headerIndex: number, headerCount: number) {
|
|
72
|
+
return cn(
|
|
73
|
+
'absolute top-0 z-10 flex h-full w-2 cursor-col-resize touch-none items-center justify-center select-none before:h-4 before:w-px before:bg-border before:content-[""]',
|
|
74
|
+
headerIndex === headerCount - 1 ? 'right-0' : '-right-1'
|
|
75
|
+
);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export function getHeaderSortDirection<T extends RowData>(
|
|
79
|
+
header: Header<DataTableFeatures, T, CellData>,
|
|
80
|
+
sortingState: unknown
|
|
81
|
+
) {
|
|
82
|
+
void sortingState;
|
|
83
|
+
return header.column.getIsSorted();
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export function getHeaderSortLabel(sortDirection: false | 'asc' | 'desc') {
|
|
87
|
+
if (sortDirection === 'asc') return 'Sorted ascending';
|
|
88
|
+
if (sortDirection === 'desc') return 'Sorted descending';
|
|
89
|
+
return 'Not sorted';
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
export function getHeaderAriaSort(sortDirection: false | 'asc' | 'desc') {
|
|
93
|
+
if (sortDirection === 'asc') return 'ascending';
|
|
94
|
+
if (sortDirection === 'desc') return 'descending';
|
|
95
|
+
return 'none';
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
export function getAllRowsSelectionState<T extends RowData>(
|
|
99
|
+
table: DataTableInstance<T>,
|
|
100
|
+
rowSelection: unknown
|
|
101
|
+
) {
|
|
102
|
+
void rowSelection;
|
|
103
|
+
const allRowsSelected = table.getIsAllRowsSelected();
|
|
104
|
+
const someRowsSelected = table.getIsSomeRowsSelected();
|
|
105
|
+
return allRowsSelected ? true : someRowsSelected ? 'indeterminate' : false;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
export function getRowSelectionState<T extends RowData>(
|
|
109
|
+
table: DataTableInstance<T>,
|
|
110
|
+
rowSelection: unknown,
|
|
111
|
+
rowId: string
|
|
112
|
+
) {
|
|
113
|
+
void rowSelection;
|
|
114
|
+
return table.getRow(rowId).getIsSelected();
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
export function getSelectedRowCount<T extends RowData>(
|
|
118
|
+
table: DataTableInstance<T>,
|
|
119
|
+
rowSelection: unknown
|
|
120
|
+
) {
|
|
121
|
+
void rowSelection;
|
|
122
|
+
return table.getSelectedRowModel().rows.length;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
export function getBooleanCellValue(value: unknown) {
|
|
126
|
+
if (value === true) return true;
|
|
127
|
+
if (value === false) return false;
|
|
128
|
+
return undefined;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
export function getPinningStyle(
|
|
132
|
+
column: DataTablePinnableColumn,
|
|
133
|
+
isHeader = false,
|
|
134
|
+
isRowSelectionEnabled = false
|
|
135
|
+
): string | undefined {
|
|
136
|
+
const isPinned = column.getIsPinned();
|
|
137
|
+
if (!isPinned) return undefined;
|
|
138
|
+
|
|
139
|
+
const zIndex = isHeader ? 15 : 1;
|
|
140
|
+
const selectionOffset = isRowSelectionEnabled ? 40 : 0;
|
|
141
|
+
|
|
142
|
+
if (isPinned === 'left') {
|
|
143
|
+
const left = column.getStart('left') + selectionOffset;
|
|
144
|
+
const shadow =
|
|
145
|
+
!isHeader && column.getIsLastColumn('left')
|
|
146
|
+
? 'box-shadow: -4px 0 4px -4px var(--compote-border) inset'
|
|
147
|
+
: undefined;
|
|
148
|
+
return ['position: sticky', `z-index: ${zIndex}`, `left: ${left}px`, shadow]
|
|
149
|
+
.filter(Boolean)
|
|
150
|
+
.join('; ');
|
|
151
|
+
} else {
|
|
152
|
+
const right = column.getAfter('right');
|
|
153
|
+
const shadow =
|
|
154
|
+
!isHeader && column.getIsFirstColumn('right')
|
|
155
|
+
? 'box-shadow: 4px 0 4px -4px var(--compote-border) inset'
|
|
156
|
+
: undefined;
|
|
157
|
+
return ['position: sticky', `z-index: ${zIndex}`, `right: ${right}px`, shadow]
|
|
158
|
+
.filter(Boolean)
|
|
159
|
+
.join('; ');
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
export function getUrlCellValue(value: unknown) {
|
|
165
|
+
if (typeof value !== 'string' || value.trim() === '') return undefined;
|
|
166
|
+
return value;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
export function openUrlCell(value: string) {
|
|
170
|
+
window.open(value, '\_blank', 'noopener,noreferrer');
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
export function getColumnMeta(columnDef: { meta?: unknown }): DataTableColumnMeta | undefined {
|
|
174
|
+
return columnDef.meta as DataTableColumnMeta | undefined;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
export function joinStyles(...styles: Array<string | undefined>) {
|
|
178
|
+
return styles.filter(Boolean).join('; ');
|
|
179
|
+
}
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
import { createVirtualizer } from '@tanstack/svelte-virtual';
|
|
5
5
|
import { get } from 'svelte/store';
|
|
6
6
|
import { cn } from 'tailwind-variants';
|
|
7
|
-
import { PhArrowSquareOut, PhCheck, PhX } from '
|
|
7
|
+
import { PhArrowSquareOut, PhCheck, PhX } from '$lib/icons';
|
|
8
8
|
import Checkbox from '../checkbox/checkbox.svelte';
|
|
9
9
|
import type { DataTableFeatures, DataTableInstance } from './create-table';
|
|
10
10
|
import {
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
<script lang="ts" generics="T extends RowData">
|
|
2
|
+
import type { RowData } from '@tanstack/svelte-table';
|
|
3
|
+
import type { HTMLAttributes } from 'svelte/elements';
|
|
4
|
+
import { cn, type ClassValue } from 'tailwind-variants';
|
|
5
|
+
import { type DataTableInstance } from './create-table';
|
|
6
|
+
import DataTableHead from './data-table-head.svelte';
|
|
7
|
+
import DataTableVirtualRows from './data-table-virtual-rows.svelte';
|
|
8
|
+
import {
|
|
9
|
+
getAllRowsSelectionState,
|
|
10
|
+
getSelectedRowCount,
|
|
11
|
+
tableSizeStyle
|
|
12
|
+
} from './data-table-utils';
|
|
13
|
+
|
|
14
|
+
type Props = Omit<HTMLAttributes<HTMLDivElement>, 'class'> & {
|
|
15
|
+
table: DataTableInstance<T>;
|
|
16
|
+
caption?: string;
|
|
17
|
+
emptyMessage?: string;
|
|
18
|
+
class?: ClassValue;
|
|
19
|
+
onRowClick?: (details: { row: T; event: MouseEvent }) => void;
|
|
20
|
+
onRowDoubleClick?: (details: { row: T; event: MouseEvent }) => void;
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
let {
|
|
24
|
+
table,
|
|
25
|
+
caption,
|
|
26
|
+
emptyMessage = 'No rows found',
|
|
27
|
+
class: className,
|
|
28
|
+
onRowClick,
|
|
29
|
+
onRowDoubleClick,
|
|
30
|
+
...rest
|
|
31
|
+
}: Props = $props();
|
|
32
|
+
|
|
33
|
+
let scrollContainerRef = $state<HTMLDivElement | undefined>(undefined);
|
|
34
|
+
|
|
35
|
+
const tableStateKey = $derived(JSON.stringify(table.store.state));
|
|
36
|
+
function trackTableState() {
|
|
37
|
+
return tableStateKey;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const rowModel = $derived.by(() => {
|
|
41
|
+
trackTableState();
|
|
42
|
+
return table.getRowModel();
|
|
43
|
+
});
|
|
44
|
+
const headerGroups = $derived.by(() => {
|
|
45
|
+
trackTableState();
|
|
46
|
+
return table.getHeaderGroups();
|
|
47
|
+
});
|
|
48
|
+
const isRowSelectionEnabled = $derived(Boolean(table.options.enableRowSelection));
|
|
49
|
+
const isMultiRowSelectionEnabled = $derived(table.options.enableMultiRowSelection !== false);
|
|
50
|
+
const headerGroupCount = $derived(headerGroups.length);
|
|
51
|
+
const allRowsSelectionState = $derived(
|
|
52
|
+
getAllRowsSelectionState(table, table.store.state.rowSelection)
|
|
53
|
+
);
|
|
54
|
+
const selectedRowCount = $derived(getSelectedRowCount(table, table.store.state.rowSelection));
|
|
55
|
+
const isColumnResizing = $derived(table.store.state.columnResizing.isResizingColumn !== false);
|
|
56
|
+
</script>
|
|
57
|
+
|
|
58
|
+
<div
|
|
59
|
+
class={cn(
|
|
60
|
+
'flex max-h-full min-h-0 flex-col overflow-hidden rounded-lg border border-surface-3 bg-surface-1',
|
|
61
|
+
className
|
|
62
|
+
)}
|
|
63
|
+
{...rest}
|
|
64
|
+
>
|
|
65
|
+
{#if isColumnResizing}
|
|
66
|
+
<div aria-hidden="true" class="fixed inset-0 z-50 cursor-col-resize select-none"></div>
|
|
67
|
+
{/if}
|
|
68
|
+
|
|
69
|
+
<div class="min-h-0 flex-1 overflow-auto" bind:this={scrollContainerRef}>
|
|
70
|
+
<table
|
|
71
|
+
class="table-fixed border-separate border-spacing-0 text-sm"
|
|
72
|
+
style="display: grid; {tableSizeStyle(table, isRowSelectionEnabled)}"
|
|
73
|
+
>
|
|
74
|
+
{#if caption}
|
|
75
|
+
<caption class="sr-only">{caption}</caption>
|
|
76
|
+
{/if}
|
|
77
|
+
<DataTableHead
|
|
78
|
+
{table}
|
|
79
|
+
{headerGroups}
|
|
80
|
+
{headerGroupCount}
|
|
81
|
+
{isRowSelectionEnabled}
|
|
82
|
+
{isMultiRowSelectionEnabled}
|
|
83
|
+
{allRowsSelectionState}
|
|
84
|
+
isVirtual
|
|
85
|
+
/>
|
|
86
|
+
{#if scrollContainerRef}
|
|
87
|
+
<DataTableVirtualRows
|
|
88
|
+
rows={rowModel.rows}
|
|
89
|
+
scrollContainer={scrollContainerRef}
|
|
90
|
+
{isRowSelectionEnabled}
|
|
91
|
+
{table}
|
|
92
|
+
{emptyMessage}
|
|
93
|
+
{onRowClick}
|
|
94
|
+
{onRowDoubleClick}
|
|
95
|
+
/>
|
|
96
|
+
{/if}
|
|
97
|
+
</table>
|
|
98
|
+
</div>
|
|
99
|
+
|
|
100
|
+
<div class="shrink-0 border-t border-surface-3 bg-surface-2 px-3 py-2 text-sm text-ink-dim">
|
|
101
|
+
{#if isRowSelectionEnabled}
|
|
102
|
+
{selectedRowCount} of {rowModel.rows.length} rows selected
|
|
103
|
+
{:else}
|
|
104
|
+
{rowModel.rows.length} rows
|
|
105
|
+
{/if}
|
|
106
|
+
</div>
|
|
107
|
+
|
|
108
|
+
</div>
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
<script lang="ts" generics="T extends RowData">
|
|
2
|
+
import { FlexRender } from '@tanstack/svelte-table';
|
|
3
|
+
import type { RowData } from '@tanstack/svelte-table';
|
|
4
|
+
import type { HTMLAttributes } from 'svelte/elements';
|
|
5
|
+
import { cn, type ClassValue } from 'tailwind-variants';
|
|
6
|
+
import { PhArrowSquareOut, PhCheck, PhX } from '$lib/icons';
|
|
7
|
+
import Checkbox from '../checkbox/checkbox.svelte';
|
|
8
|
+
import { type DataTableInstance } from './create-table';
|
|
9
|
+
import DataTableHead from './data-table-head.svelte';
|
|
10
|
+
import {
|
|
11
|
+
alignClass,
|
|
12
|
+
columnSizeStyle,
|
|
13
|
+
// getAllRowsSelectionState,
|
|
14
|
+
getBooleanCellValue,
|
|
15
|
+
getColumnMeta,
|
|
16
|
+
getPinningStyle,
|
|
17
|
+
getRowSelectionState,
|
|
18
|
+
// getSelectedRowCount,
|
|
19
|
+
getUrlCellValue,
|
|
20
|
+
justifyClass,
|
|
21
|
+
openUrlCell,
|
|
22
|
+
selectionColumnSizeStyle,
|
|
23
|
+
tableSizeStyle
|
|
24
|
+
} from './data-table-utils';
|
|
25
|
+
|
|
26
|
+
type Props = Omit<HTMLAttributes<HTMLDivElement>, 'class'> & {
|
|
27
|
+
table: DataTableInstance<T>;
|
|
28
|
+
caption?: string;
|
|
29
|
+
emptyMessage?: string;
|
|
30
|
+
class?: ClassValue;
|
|
31
|
+
onRowClick?: (details: { row: T; event: MouseEvent }) => void;
|
|
32
|
+
onRowDoubleClick?: (details: { row: T; event: MouseEvent }) => void;
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
let {
|
|
36
|
+
table,
|
|
37
|
+
caption,
|
|
38
|
+
emptyMessage = 'No rows found',
|
|
39
|
+
class: className,
|
|
40
|
+
onRowClick,
|
|
41
|
+
onRowDoubleClick,
|
|
42
|
+
...rest
|
|
43
|
+
}: Props = $props();
|
|
44
|
+
|
|
45
|
+
const rowModel = $derived(table.getRowModel());
|
|
46
|
+
const headerGroups = $derived(table.getHeaderGroups());
|
|
47
|
+
const visibleLeafColumns = $derived(table.getVisibleLeafColumns());
|
|
48
|
+
const growColumn = $derived(visibleLeafColumns.find((col) => getColumnMeta(col.columnDef)?.grow));
|
|
49
|
+
const hasGrowColumn = $derived(growColumn !== undefined);
|
|
50
|
+
const visibleColumnCount = $derived(visibleLeafColumns.length);
|
|
51
|
+
const isRowSelectionEnabled = $derived(Boolean(table.options.enableRowSelection));
|
|
52
|
+
const isMultiRowSelectionEnabled = $derived(table.options.enableMultiRowSelection !== false);
|
|
53
|
+
const tableColumnCount = $derived(visibleColumnCount + (isRowSelectionEnabled ? 1 : 0));
|
|
54
|
+
const renderedColumnCount = $derived(tableColumnCount + 1);
|
|
55
|
+
const headerGroupCount = $derived(headerGroups.length);
|
|
56
|
+
// const allRowsSelectionState = $derived(
|
|
57
|
+
// getAllRowsSelectionState(table, table.store.state.rowSelection)
|
|
58
|
+
// );
|
|
59
|
+
// const selectedRowCount = $derived(getSelectedRowCount(table, table.store.state.rowSelection));
|
|
60
|
+
// const isColumnResizing = $derived(table.store.state.columnResizing.isResizingColumn !== false);
|
|
61
|
+
const allRowsSelectionState = $derived<boolean | 'indeterminate'>(false);
|
|
62
|
+
const selectedRowCount = $derived(0);
|
|
63
|
+
const isColumnResizing = $derived(false);
|
|
64
|
+
</script>
|
|
65
|
+
|
|
66
|
+
<div
|
|
67
|
+
class={cn(
|
|
68
|
+
'flex max-h-full min-h-0 flex-col overflow-hidden rounded-lg border border-surface-3 bg-surface-1',
|
|
69
|
+
className
|
|
70
|
+
)}
|
|
71
|
+
{...rest}
|
|
72
|
+
>
|
|
73
|
+
{#if isColumnResizing}
|
|
74
|
+
<div aria-hidden="true" class="fixed inset-0 z-50 cursor-col-resize select-none"></div>
|
|
75
|
+
{/if}
|
|
76
|
+
|
|
77
|
+
<div class="min-h-0 flex-1 overflow-auto">
|
|
78
|
+
<table
|
|
79
|
+
class="table-fixed border-separate border-spacing-0 text-sm"
|
|
80
|
+
style={tableSizeStyle(table, isRowSelectionEnabled)}
|
|
81
|
+
>
|
|
82
|
+
<colgroup>
|
|
83
|
+
{#if isRowSelectionEnabled}
|
|
84
|
+
<col style={selectionColumnSizeStyle()} />
|
|
85
|
+
{/if}
|
|
86
|
+
{#each visibleLeafColumns as column (column.id)}
|
|
87
|
+
<col
|
|
88
|
+
style={getColumnMeta(column.columnDef)?.grow
|
|
89
|
+
? undefined
|
|
90
|
+
: columnSizeStyle(column.getSize())}
|
|
91
|
+
/>
|
|
92
|
+
{/each}
|
|
93
|
+
{#if !hasGrowColumn}
|
|
94
|
+
<col />
|
|
95
|
+
{/if}
|
|
96
|
+
</colgroup>
|
|
97
|
+
{#if caption}
|
|
98
|
+
<caption class="sr-only">{caption}</caption>
|
|
99
|
+
{/if}
|
|
100
|
+
<DataTableHead
|
|
101
|
+
{table}
|
|
102
|
+
{headerGroups}
|
|
103
|
+
{headerGroupCount}
|
|
104
|
+
{isRowSelectionEnabled}
|
|
105
|
+
{isMultiRowSelectionEnabled}
|
|
106
|
+
{allRowsSelectionState}
|
|
107
|
+
{hasGrowColumn}
|
|
108
|
+
/>
|
|
109
|
+
<tbody>
|
|
110
|
+
{#each rowModel.rows as row (row.id)}
|
|
111
|
+
{@const rowSelected = getRowSelectionState(table, table.store.state.rowSelection, row.id)}
|
|
112
|
+
<tr
|
|
113
|
+
class={cn(
|
|
114
|
+
'group/row',
|
|
115
|
+
'[--row-bg:var(--compote-surface-1)]',
|
|
116
|
+
'hover:bg-well/60 hover:[--row-bg:color-mix(in_srgb,var(--compote-well)_60%,var(--compote-surface-1))]',
|
|
117
|
+
rowSelected &&
|
|
118
|
+
'bg-well/60 [--row-bg:color-mix(in_srgb,var(--compote-well)_60%,var(--compote-surface-1))]'
|
|
119
|
+
)}
|
|
120
|
+
onclick={(event) => onRowClick?.({ row: row.original, event })}
|
|
121
|
+
ondblclick={(event) => onRowDoubleClick?.({ row: row.original, event })}
|
|
122
|
+
>
|
|
123
|
+
{#if isRowSelectionEnabled}
|
|
124
|
+
<td
|
|
125
|
+
class="border-b border-surface-2 bg-(--row-bg) px-3 py-2 text-center align-middle group-last/row:border-b-0"
|
|
126
|
+
style="position: sticky; left: 0; z-index: 1"
|
|
127
|
+
>
|
|
128
|
+
<Checkbox
|
|
129
|
+
size="sm"
|
|
130
|
+
aria-label="Select row"
|
|
131
|
+
class="mx-auto size-4"
|
|
132
|
+
checked={rowSelected}
|
|
133
|
+
disabled={!row.getCanSelect()}
|
|
134
|
+
onCheckedChange={({ checked }) => row.toggleSelected(checked === true)}
|
|
135
|
+
/>
|
|
136
|
+
</td>
|
|
137
|
+
{/if}
|
|
138
|
+
{#each row.getVisibleCells() as cell (cell.id)}
|
|
139
|
+
{@const columnDef = getColumnMeta(cell.column.columnDef)}
|
|
140
|
+
<td
|
|
141
|
+
class={cn(
|
|
142
|
+
'truncate border-b border-b-surface-2 px-3 py-2 group-last/row:border-b-0',
|
|
143
|
+
alignClass(columnDef?.align),
|
|
144
|
+
cell.column.getIsPinned() && 'bg-(--row-bg)'
|
|
145
|
+
)}
|
|
146
|
+
style={getPinningStyle(cell.column, false, isRowSelectionEnabled)}
|
|
147
|
+
>
|
|
148
|
+
{#if columnDef?.type === 'boolean'}
|
|
149
|
+
{@const value = getBooleanCellValue(cell.getValue())}
|
|
150
|
+
{#if value === true}
|
|
151
|
+
<span
|
|
152
|
+
class="inline-flex size-5 items-center justify-center text-success"
|
|
153
|
+
role="img"
|
|
154
|
+
aria-label="Yes"
|
|
155
|
+
>
|
|
156
|
+
<PhCheck class="size-4" />
|
|
157
|
+
</span>
|
|
158
|
+
{:else if value === false}
|
|
159
|
+
<span
|
|
160
|
+
class="inline-flex size-5 items-center justify-center text-danger"
|
|
161
|
+
role="img"
|
|
162
|
+
aria-label="No"
|
|
163
|
+
>
|
|
164
|
+
<PhX class="size-4" />
|
|
165
|
+
</span>
|
|
166
|
+
{:else}
|
|
167
|
+
-
|
|
168
|
+
{/if}
|
|
169
|
+
{:else if columnDef?.type === 'url'}
|
|
170
|
+
{@const value = getUrlCellValue(cell.getValue())}
|
|
171
|
+
{#if value}
|
|
172
|
+
<button
|
|
173
|
+
type="button"
|
|
174
|
+
class={cn(
|
|
175
|
+
'inline-flex max-w-full appearance-none items-center gap-1.5 rounded-sm border-0 bg-transparent p-0 align-middle leading-5 font-medium text-ink underline decoration-border decoration-dotted underline-offset-4 outline-none hover:text-primary focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ring',
|
|
176
|
+
justifyClass(columnDef.align)
|
|
177
|
+
)}
|
|
178
|
+
onclick={() => openUrlCell(value)}
|
|
179
|
+
>
|
|
180
|
+
<PhArrowSquareOut class="size-3.5 shrink-0" />
|
|
181
|
+
</button>
|
|
182
|
+
{:else}
|
|
183
|
+
-
|
|
184
|
+
{/if}
|
|
185
|
+
{:else}
|
|
186
|
+
<FlexRender {cell} />
|
|
187
|
+
{/if}
|
|
188
|
+
</td>
|
|
189
|
+
{/each}
|
|
190
|
+
{#if !hasGrowColumn}
|
|
191
|
+
<td aria-hidden="true" class="border-b border-surface-2 p-0 group-last/row:border-b-0"
|
|
192
|
+
></td>
|
|
193
|
+
{/if}
|
|
194
|
+
</tr>
|
|
195
|
+
{:else}
|
|
196
|
+
<tr>
|
|
197
|
+
<td class="px-3 py-10 text-center text-sm text-ink-dim" colspan={renderedColumnCount}>
|
|
198
|
+
{emptyMessage}
|
|
199
|
+
</td>
|
|
200
|
+
</tr>
|
|
201
|
+
{/each}
|
|
202
|
+
</tbody>
|
|
203
|
+
</table>
|
|
204
|
+
</div>
|
|
205
|
+
|
|
206
|
+
<div class="shrink-0 border-t border-surface-3 bg-surface-2 px-3 py-2 text-sm text-ink-dim">
|
|
207
|
+
{#if isRowSelectionEnabled}
|
|
208
|
+
{selectedRowCount} of {rowModel.rows.length} rows selected
|
|
209
|
+
{:else}
|
|
210
|
+
{rowModel.rows.length} rows
|
|
211
|
+
{/if}
|
|
212
|
+
</div>
|
|
213
|
+
|
|
214
|
+
</div>
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export { createDataTableColumnHelper } from './column-helper';
|
|
2
|
+
export { createTable } from './create-table';
|
|
3
|
+
export { default as Root } from './data-table.svelte';
|
|
4
|
+
export { default as Toolbar } from './data-table-toolbar.svelte';
|
|
5
|
+
export { default as Title } from './data-table-title.svelte';
|
|
6
|
+
export { default as ColumnVisibility } from './data-table-column-visibility.svelte';
|
|
7
|
+
export { default as ColumnFilter } from './data-table-column-filter.svelte';
|
|
8
|
+
export type { CreateDataTableOptions, DataTableFeatures, DataTableInstance } from './create-table';
|
|
9
|
+
export type {
|
|
10
|
+
DataTableAlign,
|
|
11
|
+
DataTableAccessorFnColumn,
|
|
12
|
+
DataTableAccessorKeyColumn,
|
|
13
|
+
DataTableColumn,
|
|
14
|
+
DataTableColumnBase,
|
|
15
|
+
DataTableColumnOptions,
|
|
16
|
+
DataTableColumnType,
|
|
17
|
+
DataTableCellPropsResolver,
|
|
18
|
+
DataTableCellRenderProps,
|
|
19
|
+
DataTableGroupColumn,
|
|
20
|
+
DataTableLeafColumnBase,
|
|
21
|
+
DataTableLeafColumn
|
|
22
|
+
} from './types';
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import type { CellData, ColumnDef, RowData, TableFeatures } from '@tanstack/svelte-table';
|
|
2
|
+
import type { Snippet } from 'svelte';
|
|
3
|
+
|
|
4
|
+
export type DataTableAlign = 'left' | 'center' | 'right';
|
|
5
|
+
export type DataTableColumnType =
|
|
6
|
+
| 'text'
|
|
7
|
+
| 'number'
|
|
8
|
+
| 'currency'
|
|
9
|
+
| 'percent'
|
|
10
|
+
| 'boolean'
|
|
11
|
+
| 'select'
|
|
12
|
+
| 'url'
|
|
13
|
+
| 'date'
|
|
14
|
+
| 'time'
|
|
15
|
+
| 'date-time';
|
|
16
|
+
export type DataTableCellRenderer<T extends RowData> = (
|
|
17
|
+
value: unknown,
|
|
18
|
+
row: T
|
|
19
|
+
) => string | number | boolean | null | undefined;
|
|
20
|
+
export type DataTableCellRenderProps<T extends RowData> = {
|
|
21
|
+
value: unknown;
|
|
22
|
+
row: T;
|
|
23
|
+
};
|
|
24
|
+
export type DataTableCellPropsResolver<T extends RowData> = (
|
|
25
|
+
value: unknown,
|
|
26
|
+
row: T
|
|
27
|
+
) => Record<string, unknown>;
|
|
28
|
+
|
|
29
|
+
export type DataTableColumnOptions<T extends RowData> = Partial<
|
|
30
|
+
Pick<
|
|
31
|
+
ColumnDef<TableFeatures, T, CellData>,
|
|
32
|
+
| 'size'
|
|
33
|
+
| 'minSize'
|
|
34
|
+
| 'maxSize'
|
|
35
|
+
| 'enableResizing'
|
|
36
|
+
| 'enableHiding'
|
|
37
|
+
| 'enableSorting'
|
|
38
|
+
| 'sortDescFirst'
|
|
39
|
+
| 'enableColumnFilter'
|
|
40
|
+
| 'filterFn' >
|
|
41
|
+
|
|
42
|
+
> ;
|
|
43
|
+
|
|
44
|
+
export type DataTableColumnBase = {
|
|
45
|
+
header: string;
|
|
46
|
+
align?: DataTableAlign;
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
export type DataTableLeafColumnBase<T extends RowData> = DataTableColumnOptions<T> &
|
|
50
|
+
DataTableColumnBase & {
|
|
51
|
+
cell?: DataTableCellRenderer<T>;
|
|
52
|
+
cellComponent?: unknown;
|
|
53
|
+
cellProps?: DataTableCellPropsResolver<T>;
|
|
54
|
+
cellSnippet?: Snippet<[DataTableCellRenderProps<T>]>;
|
|
55
|
+
type?: DataTableColumnType;
|
|
56
|
+
formatOptions?: Intl.NumberFormatOptions | Intl.DateTimeFormatOptions;
|
|
57
|
+
formatLocale?: string;
|
|
58
|
+
pinned?: 'left' | 'right';
|
|
59
|
+
grow?: boolean;
|
|
60
|
+
columns?: never;
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
export type DataTableAccessorKeyColumn<T extends RowData> = DataTableLeafColumnBase<T> & {
|
|
64
|
+
accessorKey: Extract<keyof T, string>;
|
|
65
|
+
id?: string;
|
|
66
|
+
accessorFn?: never;
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
export type DataTableAccessorFnColumn<T extends RowData> = DataTableLeafColumnBase<T> & {
|
|
70
|
+
accessorFn: (row: T) => unknown;
|
|
71
|
+
id: string;
|
|
72
|
+
accessorKey?: never;
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
export type DataTableLeafColumn<T extends RowData> =
|
|
76
|
+
| DataTableAccessorKeyColumn<T>
|
|
77
|
+
| DataTableAccessorFnColumn<T>;
|
|
78
|
+
|
|
79
|
+
export type DataTableGroupColumn<T extends RowData> = DataTableColumnBase & {
|
|
80
|
+
id?: string;
|
|
81
|
+
columns: DataTableColumn<T>[];
|
|
82
|
+
accessorKey?: never;
|
|
83
|
+
accessorFn?: never;
|
|
84
|
+
cell?: never;
|
|
85
|
+
cellComponent?: never;
|
|
86
|
+
cellProps?: never;
|
|
87
|
+
cellSnippet?: never;
|
|
88
|
+
type?: never;
|
|
89
|
+
formatOptions?: never;
|
|
90
|
+
formatLocale?: never;
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
export type DataTableColumn<T extends RowData> = DataTableLeafColumn<T> | DataTableGroupColumn<T>;
|
|
94
|
+
|
|
95
|
+
export type DataTableColumnMeta = {
|
|
96
|
+
align?: DataTableAlign;
|
|
97
|
+
type?: DataTableColumnType;
|
|
98
|
+
formatOptions?: Intl.NumberFormatOptions | Intl.DateTimeFormatOptions;
|
|
99
|
+
formatLocale?: string;
|
|
100
|
+
grow?: boolean;
|
|
101
|
+
};
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export { default as Root } from '../data-table-virtualized.svelte';
|
|
2
|
+
export {
|
|
3
|
+
ColumnFilter,
|
|
4
|
+
ColumnVisibility,
|
|
5
|
+
Title,
|
|
6
|
+
Toolbar,
|
|
7
|
+
createDataTableColumnHelper,
|
|
8
|
+
createTable
|
|
9
|
+
} from '../index';
|
|
10
|
+
export type {
|
|
11
|
+
CreateDataTableOptions,
|
|
12
|
+
DataTableAccessorFnColumn,
|
|
13
|
+
DataTableAccessorKeyColumn,
|
|
14
|
+
DataTableAlign,
|
|
15
|
+
DataTableCellPropsResolver,
|
|
16
|
+
DataTableCellRenderProps,
|
|
17
|
+
DataTableColumn,
|
|
18
|
+
DataTableColumnBase,
|
|
19
|
+
DataTableColumnOptions,
|
|
20
|
+
DataTableColumnType,
|
|
21
|
+
DataTableFeatures,
|
|
22
|
+
DataTableGroupColumn,
|
|
23
|
+
DataTableInstance,
|
|
24
|
+
DataTableLeafColumn,
|
|
25
|
+
DataTableLeafColumnBase
|
|
26
|
+
} from '../index';
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { RowData } from '@tanstack/
|
|
1
|
+
import type { RowData } from '@tanstack/table-core';
|
|
2
2
|
import type { DataTableAccessorFnColumn, DataTableAccessorKeyColumn, DataTableColumn, DataTableGroupColumn } from './types';
|
|
3
3
|
type AccessorKeyColumnOptions<T extends RowData> = Omit<DataTableAccessorKeyColumn<T>, 'accessorKey' | 'accessorFn' | 'columns'>;
|
|
4
4
|
type AccessorFnColumnOptions<T extends RowData> = Omit<DataTableAccessorFnColumn<T>, 'accessorFn' | 'accessorKey' | 'columns'>;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { type RowData, type TableOptions } from '@tanstack/table-core';
|
|
2
|
+
export declare function createSvelteTable<TData extends RowData>(options: TableOptions<TData>): import("@tanstack/table-core").Table<TData>;
|
|
3
|
+
type MaybeThunk<T extends object> = T | (() => T | null | undefined);
|
|
4
|
+
type Intersection<T extends readonly unknown[]> = (T extends [infer H, ...infer R] ? H & Intersection<R> : unknown) & {};
|
|
5
|
+
export declare function mergeObjects<Sources extends readonly MaybeThunk<any>[]>(...sources: Sources): Intersection<{
|
|
6
|
+
[K in keyof Sources]: Sources[K];
|
|
7
|
+
}>;
|
|
8
|
+
export {};
|