@kayord/ui 2.0.13 → 2.1.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/dist/components/custom/data-grid/DataGrid.svelte +183 -0
- package/dist/components/custom/data-grid/DataGrid.svelte.d.ts +43 -0
- package/dist/components/custom/data-grid/DataGridCheckbox.svelte +15 -0
- package/dist/components/custom/data-grid/DataGridCheckbox.svelte.d.ts +10 -0
- package/dist/components/custom/data-grid/DataGridFooter.svelte +35 -0
- package/dist/components/custom/data-grid/DataGridFooter.svelte.d.ts +28 -0
- package/dist/components/custom/data-grid/DataGridHeader.svelte +48 -0
- package/dist/components/custom/data-grid/DataGridHeader.svelte.d.ts +30 -0
- package/dist/components/custom/data-grid/DataGridView.svelte +77 -0
- package/dist/components/custom/data-grid/DataGridView.svelte.d.ts +29 -0
- package/dist/components/custom/data-grid/Pagination.svelte +89 -0
- package/dist/components/custom/data-grid/Pagination.svelte.d.ts +31 -0
- package/dist/components/custom/data-grid/createGrid.svelte.d.ts +3 -0
- package/dist/components/custom/data-grid/createGrid.svelte.js +292 -0
- package/dist/components/custom/data-grid/index.d.ts +5 -0
- package/dist/components/custom/data-grid/index.js +4 -0
- package/dist/components/custom/data-grid/types.d.ts +43 -0
- package/dist/components/custom/data-grid/types.js +15 -0
- package/dist/components/ui/separator/separator.svelte +1 -1
- package/dist/data-grid/index.d.ts +2 -0
- package/dist/data-grid/index.js +2 -0
- package/package.json +11 -6
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
<script lang="ts" generics="T">
|
|
2
|
+
import { type Table as TableType } from "@tanstack/table-core";
|
|
3
|
+
import { FlexRender } from "../../ui/data-table";
|
|
4
|
+
import { Skeleton, Table } from "../../ui";
|
|
5
|
+
import Pagination from "./Pagination.svelte";
|
|
6
|
+
import { onMount, type Snippet } from "svelte";
|
|
7
|
+
import { fade } from "svelte/transition";
|
|
8
|
+
import { ProgressLoading } from "../progress-loading";
|
|
9
|
+
import { cn } from "../../../utils";
|
|
10
|
+
import DataGridHeader from "./DataGridHeader.svelte";
|
|
11
|
+
import DataGridFooter from "./DataGridFooter.svelte";
|
|
12
|
+
import { defaultDataGridProps, defaultSearchParamSchema, type DataGridProps } from "./types";
|
|
13
|
+
import DataGridView from "./DataGridView.svelte";
|
|
14
|
+
import { useSearchParams } from "runed/kit";
|
|
15
|
+
import { untrack } from "svelte";
|
|
16
|
+
import { decodeColumnFilters, decodeSorting, encodeColumnFilters, encodeSorting } from "../data-table";
|
|
17
|
+
|
|
18
|
+
interface Props<T> {
|
|
19
|
+
table: TableType<T>;
|
|
20
|
+
dataGridProps?: DataGridProps;
|
|
21
|
+
isLoading?: boolean;
|
|
22
|
+
header?: Snippet;
|
|
23
|
+
subHeader?: Snippet;
|
|
24
|
+
footer?: Snippet;
|
|
25
|
+
leftToolbar?: Snippet;
|
|
26
|
+
rightToolbar?: Snippet;
|
|
27
|
+
noDataMessage?: string;
|
|
28
|
+
hideHeader?: boolean;
|
|
29
|
+
enableVisibility?: boolean;
|
|
30
|
+
class?: string;
|
|
31
|
+
headerClass?: string;
|
|
32
|
+
disableUISorting?: boolean;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
let {
|
|
36
|
+
table,
|
|
37
|
+
dataGridProps = defaultDataGridProps,
|
|
38
|
+
isLoading = false,
|
|
39
|
+
header,
|
|
40
|
+
subHeader,
|
|
41
|
+
footer,
|
|
42
|
+
leftToolbar,
|
|
43
|
+
rightToolbar,
|
|
44
|
+
noDataMessage = "No data",
|
|
45
|
+
hideHeader = false,
|
|
46
|
+
enableVisibility = false,
|
|
47
|
+
class: className,
|
|
48
|
+
headerClass,
|
|
49
|
+
disableUISorting = false,
|
|
50
|
+
}: Props<T> = $props();
|
|
51
|
+
|
|
52
|
+
let end: HTMLElement | undefined = $state();
|
|
53
|
+
|
|
54
|
+
const tableState = $derived(table.getState());
|
|
55
|
+
const columnVisibility = $derived(tableState.columnVisibility);
|
|
56
|
+
|
|
57
|
+
const params = useSearchParams(defaultSearchParamSchema, { pushHistory: false });
|
|
58
|
+
|
|
59
|
+
// Load current url search params
|
|
60
|
+
onMount(() => {
|
|
61
|
+
if (dataGridProps.useURLSearchParams) {
|
|
62
|
+
table.setGlobalFilter(params.search);
|
|
63
|
+
table.setSorting(decodeSorting() ?? []);
|
|
64
|
+
table.setPageIndex(params.page);
|
|
65
|
+
table.setColumnFilters(decodeColumnFilters() ?? []);
|
|
66
|
+
}
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
// Set url search params
|
|
70
|
+
$effect(() => {
|
|
71
|
+
if (dataGridProps.useURLSearchParams) {
|
|
72
|
+
const tableState = table.getState();
|
|
73
|
+
untrack(() => {
|
|
74
|
+
params.search = tableState.globalFilter;
|
|
75
|
+
params.page = tableState.pagination.pageIndex;
|
|
76
|
+
params.sort = encodeSorting(tableState);
|
|
77
|
+
params.filter = encodeColumnFilters(tableState);
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
});
|
|
81
|
+
</script>
|
|
82
|
+
|
|
83
|
+
<div class={cn("w-full", className)}>
|
|
84
|
+
<div class={cn(headerClass)}>
|
|
85
|
+
{#if header}
|
|
86
|
+
{@render header()}
|
|
87
|
+
{:else}
|
|
88
|
+
<div class="flex items-center justify-between gap-2 pb-2">
|
|
89
|
+
<div>
|
|
90
|
+
{#if leftToolbar}
|
|
91
|
+
{@render leftToolbar()}
|
|
92
|
+
{/if}
|
|
93
|
+
</div>
|
|
94
|
+
<div></div>
|
|
95
|
+
<div class="flex items-center justify-between gap-2">
|
|
96
|
+
{#if rightToolbar}
|
|
97
|
+
{@render rightToolbar()}
|
|
98
|
+
{/if}
|
|
99
|
+
{#if enableVisibility}
|
|
100
|
+
<DataGridView {table} />
|
|
101
|
+
{/if}
|
|
102
|
+
</div>
|
|
103
|
+
</div>
|
|
104
|
+
{/if}
|
|
105
|
+
</div>
|
|
106
|
+
|
|
107
|
+
<div class="rounded-md border">
|
|
108
|
+
{#if isLoading}
|
|
109
|
+
<span in:fade={{ duration: 300 }}>
|
|
110
|
+
<ProgressLoading class="h-1" />
|
|
111
|
+
</span>
|
|
112
|
+
{/if}
|
|
113
|
+
|
|
114
|
+
{#if subHeader}
|
|
115
|
+
{@render subHeader()}
|
|
116
|
+
{/if}
|
|
117
|
+
|
|
118
|
+
<Table.Root class="table-auto">
|
|
119
|
+
{#if !hideHeader}
|
|
120
|
+
<Table.Header>
|
|
121
|
+
{#each table.getHeaderGroups() as headerGroup (headerGroup.id)}
|
|
122
|
+
<Table.Row>
|
|
123
|
+
{#each headerGroup.headers.filter((h) => columnVisibility[h.column.id] !== false) as header (header.id)}
|
|
124
|
+
<DataGridHeader {header} {table} {disableUISorting} />
|
|
125
|
+
{/each}
|
|
126
|
+
</Table.Row>
|
|
127
|
+
{/each}
|
|
128
|
+
</Table.Header>
|
|
129
|
+
{/if}
|
|
130
|
+
|
|
131
|
+
<Table.Body>
|
|
132
|
+
{#if isLoading && table.getRowModel().rows.length == 0}
|
|
133
|
+
{#each { length: 5 }}
|
|
134
|
+
<Table.Row>
|
|
135
|
+
{#each table.getAllColumns() as _cell (_cell.id)}
|
|
136
|
+
<Table.Cell>
|
|
137
|
+
<Skeleton class="h-4" />
|
|
138
|
+
</Table.Cell>
|
|
139
|
+
{/each}
|
|
140
|
+
</Table.Row>
|
|
141
|
+
{/each}
|
|
142
|
+
{:else}
|
|
143
|
+
{#if table.getRowModel().rows.length == 0}
|
|
144
|
+
<Table.Row>
|
|
145
|
+
<Table.Cell colspan={table.getAllColumns().length}>
|
|
146
|
+
<div class="text-center">{noDataMessage}</div>
|
|
147
|
+
</Table.Cell>
|
|
148
|
+
</Table.Row>
|
|
149
|
+
{/if}
|
|
150
|
+
{#each table.getRowModel().rows as row (row.id)}
|
|
151
|
+
<Table.Row data-state={row.getIsSelected() && "selected"}>
|
|
152
|
+
{#each row.getVisibleCells() as cell (cell.id)}
|
|
153
|
+
<Table.Cell
|
|
154
|
+
class={cell.column.columnDef.meta?.className}
|
|
155
|
+
style={`width: ${cell.column.getSize()}px; min-width:${cell.column.columnDef.minSize}px; max-width:${cell.column.columnDef.maxSize}px`}
|
|
156
|
+
>
|
|
157
|
+
<FlexRender content={cell.column.columnDef.cell} context={cell.getContext()} />
|
|
158
|
+
</Table.Cell>
|
|
159
|
+
{/each}
|
|
160
|
+
</Table.Row>
|
|
161
|
+
{/each}
|
|
162
|
+
{/if}
|
|
163
|
+
</Table.Body>
|
|
164
|
+
<DataGridFooter {table} />
|
|
165
|
+
</Table.Root>
|
|
166
|
+
{#if isLoading}
|
|
167
|
+
<span in:fade={{ duration: 300 }}>
|
|
168
|
+
<ProgressLoading class="h-1" />
|
|
169
|
+
</span>
|
|
170
|
+
{/if}
|
|
171
|
+
</div>
|
|
172
|
+
{#if dataGridProps.isPaginationEnabled}
|
|
173
|
+
<Pagination {table} {dataGridProps} />
|
|
174
|
+
{/if}
|
|
175
|
+
|
|
176
|
+
{#if footer}
|
|
177
|
+
<div class="overflow-hidden rounded-b-md">
|
|
178
|
+
{@render footer()}
|
|
179
|
+
</div>
|
|
180
|
+
{/if}
|
|
181
|
+
</div>
|
|
182
|
+
|
|
183
|
+
<div bind:this={end} aria-hidden="true"></div>
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { type Table as TableType } from "@tanstack/table-core";
|
|
2
|
+
import { type Snippet } from "svelte";
|
|
3
|
+
import { type DataGridProps } from "./types";
|
|
4
|
+
interface Props<T> {
|
|
5
|
+
table: TableType<T>;
|
|
6
|
+
dataGridProps?: DataGridProps;
|
|
7
|
+
isLoading?: boolean;
|
|
8
|
+
header?: Snippet;
|
|
9
|
+
subHeader?: Snippet;
|
|
10
|
+
footer?: Snippet;
|
|
11
|
+
leftToolbar?: Snippet;
|
|
12
|
+
rightToolbar?: Snippet;
|
|
13
|
+
noDataMessage?: string;
|
|
14
|
+
hideHeader?: boolean;
|
|
15
|
+
enableVisibility?: boolean;
|
|
16
|
+
class?: string;
|
|
17
|
+
headerClass?: string;
|
|
18
|
+
disableUISorting?: boolean;
|
|
19
|
+
}
|
|
20
|
+
declare function $$render<T>(): {
|
|
21
|
+
props: Props<T>;
|
|
22
|
+
exports: {};
|
|
23
|
+
bindings: "";
|
|
24
|
+
slots: {};
|
|
25
|
+
events: {};
|
|
26
|
+
};
|
|
27
|
+
declare class __sveltets_Render<T> {
|
|
28
|
+
props(): ReturnType<typeof $$render<T>>['props'];
|
|
29
|
+
events(): ReturnType<typeof $$render<T>>['events'];
|
|
30
|
+
slots(): ReturnType<typeof $$render<T>>['slots'];
|
|
31
|
+
bindings(): "";
|
|
32
|
+
exports(): {};
|
|
33
|
+
}
|
|
34
|
+
interface $$IsomorphicComponent {
|
|
35
|
+
new <T>(options: import('svelte').ComponentConstructorOptions<ReturnType<__sveltets_Render<T>['props']>>): import('svelte').SvelteComponent<ReturnType<__sveltets_Render<T>['props']>, ReturnType<__sveltets_Render<T>['events']>, ReturnType<__sveltets_Render<T>['slots']>> & {
|
|
36
|
+
$$bindings?: ReturnType<__sveltets_Render<T>['bindings']>;
|
|
37
|
+
} & ReturnType<__sveltets_Render<T>['exports']>;
|
|
38
|
+
<T>(internal: unknown, props: ReturnType<__sveltets_Render<T>['props']> & {}): ReturnType<__sveltets_Render<T>['exports']>;
|
|
39
|
+
z_$$bindings?: ReturnType<__sveltets_Render<any>['bindings']>;
|
|
40
|
+
}
|
|
41
|
+
declare const DataGrid: $$IsomorphicComponent;
|
|
42
|
+
type DataGrid<T> = InstanceType<typeof DataGrid<T>>;
|
|
43
|
+
export default DataGrid;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { Checkbox } from "../../ui/checkbox";
|
|
3
|
+
import { cn } from "../../../utils";
|
|
4
|
+
import type { ComponentProps } from "svelte";
|
|
5
|
+
|
|
6
|
+
interface Props extends ComponentProps<typeof Checkbox> {
|
|
7
|
+
checked?: boolean;
|
|
8
|
+
indeterminate?: boolean;
|
|
9
|
+
class?: string;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
let { checked, class: className, ...rest }: Props = $props();
|
|
13
|
+
</script>
|
|
14
|
+
|
|
15
|
+
<Checkbox bind:checked class={cn("rounded-[5px]", className)} {...rest} />
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { Checkbox } from "../../ui/checkbox";
|
|
2
|
+
import type { ComponentProps } from "svelte";
|
|
3
|
+
interface Props extends ComponentProps<typeof Checkbox> {
|
|
4
|
+
checked?: boolean;
|
|
5
|
+
indeterminate?: boolean;
|
|
6
|
+
class?: string;
|
|
7
|
+
}
|
|
8
|
+
declare const DataGridCheckbox: import("svelte").Component<Props, {}, "">;
|
|
9
|
+
type DataGridCheckbox = ReturnType<typeof DataGridCheckbox>;
|
|
10
|
+
export default DataGridCheckbox;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
<script lang="ts" generics="T">
|
|
2
|
+
import { Table } from "../../..";
|
|
3
|
+
import { FlexRender } from "../../../data-table";
|
|
4
|
+
import { type Table as TypeType } from "@tanstack/table-core";
|
|
5
|
+
|
|
6
|
+
interface Props<T> {
|
|
7
|
+
table: TypeType<T>;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
let { table }: Props<T> = $props();
|
|
11
|
+
|
|
12
|
+
const hasFooterContent = $derived(
|
|
13
|
+
table
|
|
14
|
+
.getFooterGroups()
|
|
15
|
+
.some((footerGroup) =>
|
|
16
|
+
footerGroup.headers.some((header) => !header.isPlaceholder && header.column.columnDef.footer)
|
|
17
|
+
)
|
|
18
|
+
);
|
|
19
|
+
</script>
|
|
20
|
+
|
|
21
|
+
{#if hasFooterContent}
|
|
22
|
+
<Table.Footer class="bg-muted/20 border-t-1 font-bold">
|
|
23
|
+
{#each table.getFooterGroups() as footerGroup}
|
|
24
|
+
<Table.Row>
|
|
25
|
+
{#each footerGroup.headers as header}
|
|
26
|
+
<Table.Cell colspan={header.colSpan}>
|
|
27
|
+
{#if !header.isPlaceholder}
|
|
28
|
+
<FlexRender content={header.column.columnDef.footer} context={header.getContext()} />
|
|
29
|
+
{/if}
|
|
30
|
+
</Table.Cell>
|
|
31
|
+
{/each}
|
|
32
|
+
</Table.Row>
|
|
33
|
+
{/each}
|
|
34
|
+
</Table.Footer>
|
|
35
|
+
{/if}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { type Table as TypeType } from "@tanstack/table-core";
|
|
2
|
+
interface Props<T> {
|
|
3
|
+
table: TypeType<T>;
|
|
4
|
+
}
|
|
5
|
+
declare function $$render<T>(): {
|
|
6
|
+
props: Props<T>;
|
|
7
|
+
exports: {};
|
|
8
|
+
bindings: "";
|
|
9
|
+
slots: {};
|
|
10
|
+
events: {};
|
|
11
|
+
};
|
|
12
|
+
declare class __sveltets_Render<T> {
|
|
13
|
+
props(): ReturnType<typeof $$render<T>>['props'];
|
|
14
|
+
events(): ReturnType<typeof $$render<T>>['events'];
|
|
15
|
+
slots(): ReturnType<typeof $$render<T>>['slots'];
|
|
16
|
+
bindings(): "";
|
|
17
|
+
exports(): {};
|
|
18
|
+
}
|
|
19
|
+
interface $$IsomorphicComponent {
|
|
20
|
+
new <T>(options: import('svelte').ComponentConstructorOptions<ReturnType<__sveltets_Render<T>['props']>>): import('svelte').SvelteComponent<ReturnType<__sveltets_Render<T>['props']>, ReturnType<__sveltets_Render<T>['events']>, ReturnType<__sveltets_Render<T>['slots']>> & {
|
|
21
|
+
$$bindings?: ReturnType<__sveltets_Render<T>['bindings']>;
|
|
22
|
+
} & ReturnType<__sveltets_Render<T>['exports']>;
|
|
23
|
+
<T>(internal: unknown, props: ReturnType<__sveltets_Render<T>['props']> & {}): ReturnType<__sveltets_Render<T>['exports']>;
|
|
24
|
+
z_$$bindings?: ReturnType<__sveltets_Render<any>['bindings']>;
|
|
25
|
+
}
|
|
26
|
+
declare const DataGridFooter: $$IsomorphicComponent;
|
|
27
|
+
type DataGridFooter<T> = InstanceType<typeof DataGridFooter<T>>;
|
|
28
|
+
export default DataGridFooter;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
<script lang="ts" generics="T">
|
|
2
|
+
import { Table } from "../../..";
|
|
3
|
+
import { FlexRender } from "../../../data-table";
|
|
4
|
+
import { type Header, type Table as TypeType } from "@tanstack/table-core";
|
|
5
|
+
import { ArrowUpDownIcon, ArrowDownIcon, ArrowUpIcon } from "@lucide/svelte";
|
|
6
|
+
|
|
7
|
+
interface Props<T> {
|
|
8
|
+
header: Header<T, unknown>;
|
|
9
|
+
table: TypeType<T>;
|
|
10
|
+
disableUISorting?: boolean;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
let { header, table, disableUISorting = false }: Props<T> = $props();
|
|
14
|
+
|
|
15
|
+
const isSortingEnabled = $derived(table.options.getSortedRowModel !== undefined && disableUISorting !== true);
|
|
16
|
+
|
|
17
|
+
const column = $derived(header.column);
|
|
18
|
+
|
|
19
|
+
const currentSort = $derived.by(() => {
|
|
20
|
+
const sortState = table.getState().sorting;
|
|
21
|
+
return sortState.find((sort) => sort.id === column.id);
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
const sortDirection = $derived(currentSort ? (currentSort.desc ? "desc" : "asc") : null);
|
|
25
|
+
</script>
|
|
26
|
+
|
|
27
|
+
<Table.Head
|
|
28
|
+
colspan={header.colSpan}
|
|
29
|
+
class="bg-muted/20"
|
|
30
|
+
style={`width: ${header.getSize()}px; min-width:${header.column.columnDef.minSize}px; max-width:${header.column.columnDef.maxSize}px`}
|
|
31
|
+
>
|
|
32
|
+
{#if !header.isPlaceholder}
|
|
33
|
+
<div class="flex items-center gap-1">
|
|
34
|
+
<FlexRender content={header.column.columnDef.header} context={header.getContext()} />
|
|
35
|
+
{#if isSortingEnabled && header.column.getCanSort()}
|
|
36
|
+
<button onclick={header.column.getToggleSortingHandler()}>
|
|
37
|
+
{#if sortDirection == "asc"}
|
|
38
|
+
<ArrowDownIcon class="size-4" />
|
|
39
|
+
{:else if sortDirection == "desc"}
|
|
40
|
+
<ArrowUpIcon class="size-4" />
|
|
41
|
+
{:else}
|
|
42
|
+
<ArrowUpDownIcon class="text-muted size-4" />
|
|
43
|
+
{/if}
|
|
44
|
+
</button>
|
|
45
|
+
{/if}
|
|
46
|
+
</div>
|
|
47
|
+
{/if}
|
|
48
|
+
</Table.Head>
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { type Header, type Table as TypeType } from "@tanstack/table-core";
|
|
2
|
+
interface Props<T> {
|
|
3
|
+
header: Header<T, unknown>;
|
|
4
|
+
table: TypeType<T>;
|
|
5
|
+
disableUISorting?: boolean;
|
|
6
|
+
}
|
|
7
|
+
declare function $$render<T>(): {
|
|
8
|
+
props: Props<T>;
|
|
9
|
+
exports: {};
|
|
10
|
+
bindings: "";
|
|
11
|
+
slots: {};
|
|
12
|
+
events: {};
|
|
13
|
+
};
|
|
14
|
+
declare class __sveltets_Render<T> {
|
|
15
|
+
props(): ReturnType<typeof $$render<T>>['props'];
|
|
16
|
+
events(): ReturnType<typeof $$render<T>>['events'];
|
|
17
|
+
slots(): ReturnType<typeof $$render<T>>['slots'];
|
|
18
|
+
bindings(): "";
|
|
19
|
+
exports(): {};
|
|
20
|
+
}
|
|
21
|
+
interface $$IsomorphicComponent {
|
|
22
|
+
new <T>(options: import('svelte').ComponentConstructorOptions<ReturnType<__sveltets_Render<T>['props']>>): import('svelte').SvelteComponent<ReturnType<__sveltets_Render<T>['props']>, ReturnType<__sveltets_Render<T>['events']>, ReturnType<__sveltets_Render<T>['slots']>> & {
|
|
23
|
+
$$bindings?: ReturnType<__sveltets_Render<T>['bindings']>;
|
|
24
|
+
} & ReturnType<__sveltets_Render<T>['exports']>;
|
|
25
|
+
<T>(internal: unknown, props: ReturnType<__sveltets_Render<T>['props']> & {}): ReturnType<__sveltets_Render<T>['exports']>;
|
|
26
|
+
z_$$bindings?: ReturnType<__sveltets_Render<any>['bindings']>;
|
|
27
|
+
}
|
|
28
|
+
declare const DataGridHeader: $$IsomorphicComponent;
|
|
29
|
+
type DataGridHeader<T> = InstanceType<typeof DataGridHeader<T>>;
|
|
30
|
+
export default DataGridHeader;
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
<script lang="ts" generics="TData">
|
|
2
|
+
import type { Table } from "@tanstack/table-core";
|
|
3
|
+
import { cn } from "../../../utils.js";
|
|
4
|
+
import { Button } from "../../ui/button";
|
|
5
|
+
import { Popover, PopoverContent, PopoverTrigger } from "../../ui/popover";
|
|
6
|
+
import {
|
|
7
|
+
Command,
|
|
8
|
+
CommandEmpty,
|
|
9
|
+
CommandGroup,
|
|
10
|
+
CommandInput,
|
|
11
|
+
CommandItem,
|
|
12
|
+
CommandList,
|
|
13
|
+
} from "../../ui/command/index.js";
|
|
14
|
+
|
|
15
|
+
// Icons
|
|
16
|
+
import Settings2 from "@lucide/svelte/icons/settings-2";
|
|
17
|
+
import Check from "@lucide/svelte/icons/check";
|
|
18
|
+
|
|
19
|
+
interface Props {
|
|
20
|
+
table: Table<TData>;
|
|
21
|
+
align?: "start" | "center" | "end";
|
|
22
|
+
class?: string;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
let { table, align = "start", class: className }: Props = $props();
|
|
26
|
+
|
|
27
|
+
// Get columns - table.getAllColumns() is reactive via our wrapper
|
|
28
|
+
const columns = $derived(
|
|
29
|
+
table.getAllColumns().filter((column) => typeof column.accessorFn !== "undefined" && column.getCanHide())
|
|
30
|
+
);
|
|
31
|
+
|
|
32
|
+
// Get visibility state reactively
|
|
33
|
+
const columnVisibility = $derived(table.getState().columnVisibility);
|
|
34
|
+
|
|
35
|
+
// Helper to check if column is visible - reads from reactive state
|
|
36
|
+
function isColumnVisible(columnId: string): boolean {
|
|
37
|
+
// If not in visibility state, default to visible (true)
|
|
38
|
+
return columnVisibility[columnId] !== false;
|
|
39
|
+
}
|
|
40
|
+
</script>
|
|
41
|
+
|
|
42
|
+
<Popover>
|
|
43
|
+
<PopoverTrigger>
|
|
44
|
+
{#snippet child({ props })}
|
|
45
|
+
<Button
|
|
46
|
+
{...props}
|
|
47
|
+
aria-label="Toggle columns"
|
|
48
|
+
role="combobox"
|
|
49
|
+
variant="outline"
|
|
50
|
+
size="sm"
|
|
51
|
+
class={cn("ml-auto hidden h-8 font-normal lg:flex", className)}
|
|
52
|
+
>
|
|
53
|
+
<Settings2 class="text-muted-foreground" />
|
|
54
|
+
View
|
|
55
|
+
</Button>
|
|
56
|
+
{/snippet}
|
|
57
|
+
</PopoverTrigger>
|
|
58
|
+
<PopoverContent {align} class="w-44 p-0">
|
|
59
|
+
<Command>
|
|
60
|
+
<CommandInput placeholder="Search columns..." />
|
|
61
|
+
<CommandList>
|
|
62
|
+
<CommandEmpty>No columns found.</CommandEmpty>
|
|
63
|
+
<CommandGroup>
|
|
64
|
+
{#each columns as column (column.id)}
|
|
65
|
+
{@const isVisible = isColumnVisible(column.id)}
|
|
66
|
+
<CommandItem value={column.id} onSelect={() => column.toggleVisibility(!isVisible)}>
|
|
67
|
+
<span class="truncate">
|
|
68
|
+
{column.id}
|
|
69
|
+
</span>
|
|
70
|
+
<Check class={cn("ml-auto size-4 shrink-0", isVisible ? "opacity-100" : "opacity-0")} />
|
|
71
|
+
</CommandItem>
|
|
72
|
+
{/each}
|
|
73
|
+
</CommandGroup>
|
|
74
|
+
</CommandList>
|
|
75
|
+
</Command>
|
|
76
|
+
</PopoverContent>
|
|
77
|
+
</Popover>
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { Table } from "@tanstack/table-core";
|
|
2
|
+
declare function $$render<TData>(): {
|
|
3
|
+
props: {
|
|
4
|
+
table: Table<TData>;
|
|
5
|
+
align?: "start" | "center" | "end";
|
|
6
|
+
class?: string;
|
|
7
|
+
};
|
|
8
|
+
exports: {};
|
|
9
|
+
bindings: "";
|
|
10
|
+
slots: {};
|
|
11
|
+
events: {};
|
|
12
|
+
};
|
|
13
|
+
declare class __sveltets_Render<TData> {
|
|
14
|
+
props(): ReturnType<typeof $$render<TData>>['props'];
|
|
15
|
+
events(): ReturnType<typeof $$render<TData>>['events'];
|
|
16
|
+
slots(): ReturnType<typeof $$render<TData>>['slots'];
|
|
17
|
+
bindings(): "";
|
|
18
|
+
exports(): {};
|
|
19
|
+
}
|
|
20
|
+
interface $$IsomorphicComponent {
|
|
21
|
+
new <TData>(options: import('svelte').ComponentConstructorOptions<ReturnType<__sveltets_Render<TData>['props']>>): import('svelte').SvelteComponent<ReturnType<__sveltets_Render<TData>['props']>, ReturnType<__sveltets_Render<TData>['events']>, ReturnType<__sveltets_Render<TData>['slots']>> & {
|
|
22
|
+
$$bindings?: ReturnType<__sveltets_Render<TData>['bindings']>;
|
|
23
|
+
} & ReturnType<__sveltets_Render<TData>['exports']>;
|
|
24
|
+
<TData>(internal: unknown, props: ReturnType<__sveltets_Render<TData>['props']> & {}): ReturnType<__sveltets_Render<TData>['exports']>;
|
|
25
|
+
z_$$bindings?: ReturnType<__sveltets_Render<any>['bindings']>;
|
|
26
|
+
}
|
|
27
|
+
declare const DataGridView: $$IsomorphicComponent;
|
|
28
|
+
type DataGridView<TData> = InstanceType<typeof DataGridView<TData>>;
|
|
29
|
+
export default DataGridView;
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
<script lang="ts" generics="T">
|
|
2
|
+
import type { Table } from "@tanstack/table-core";
|
|
3
|
+
import ChevronLeft from "@lucide/svelte/icons/chevron-left";
|
|
4
|
+
import ChevronRight from "@lucide/svelte/icons/chevron-right";
|
|
5
|
+
import DoubleArrowLeft from "@lucide/svelte/icons/arrow-left";
|
|
6
|
+
import DoubleArrowRight from "@lucide/svelte/icons/arrow-right";
|
|
7
|
+
import { Select, Button } from "../../..";
|
|
8
|
+
import type { DataGridProps } from "./types";
|
|
9
|
+
|
|
10
|
+
interface Props<T> {
|
|
11
|
+
table: Table<T>;
|
|
12
|
+
dataGridProps?: DataGridProps;
|
|
13
|
+
canChangePageSize?: boolean;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
let { table, dataGridProps, canChangePageSize = false }: Props<T> = $props();
|
|
17
|
+
|
|
18
|
+
// svelte-ignore state_referenced_locally
|
|
19
|
+
let value = $state(table.getState().pagination.pageSize.toString());
|
|
20
|
+
</script>
|
|
21
|
+
|
|
22
|
+
<div class="flex items-center justify-between py-2">
|
|
23
|
+
<div class="text-muted-foreground flex-1 text-sm">
|
|
24
|
+
{#if dataGridProps?.enableRowSelectionUI}
|
|
25
|
+
{table.getFilteredSelectedRowModel().rows.length} of
|
|
26
|
+
{table.getFilteredRowModel().rows.length} row(s) selected.
|
|
27
|
+
{/if}
|
|
28
|
+
</div>
|
|
29
|
+
<div class="flex items-center space-x-6 lg:space-x-8">
|
|
30
|
+
<div class="flex items-center space-x-2">
|
|
31
|
+
{#if canChangePageSize}
|
|
32
|
+
<p class="text-sm font-medium">Page size</p>
|
|
33
|
+
<Select.Root
|
|
34
|
+
type="single"
|
|
35
|
+
bind:value
|
|
36
|
+
onValueChange={(value) => {
|
|
37
|
+
table.setPageSize(Number(value));
|
|
38
|
+
}}
|
|
39
|
+
>
|
|
40
|
+
<Select.Trigger class="h-8 w-20">Rows</Select.Trigger>
|
|
41
|
+
<Select.Content side="top">
|
|
42
|
+
{#each [10, 20, 30, 40, 50] as pageSize (pageSize)}
|
|
43
|
+
<Select.Item value={pageSize.toString()}>
|
|
44
|
+
{pageSize}
|
|
45
|
+
</Select.Item>
|
|
46
|
+
{/each}
|
|
47
|
+
</Select.Content>
|
|
48
|
+
</Select.Root>
|
|
49
|
+
{/if}
|
|
50
|
+
</div>
|
|
51
|
+
<div class="flex w-25 items-center justify-center text-sm font-medium">
|
|
52
|
+
Page {table.getState().pagination.pageIndex + 1} of
|
|
53
|
+
{table.getPageCount()}
|
|
54
|
+
</div>
|
|
55
|
+
<div class="flex items-center space-x-2">
|
|
56
|
+
<Button
|
|
57
|
+
variant="outline"
|
|
58
|
+
class="hidden size-8 p-0 lg:flex"
|
|
59
|
+
onclick={() => table.setPageIndex(0)}
|
|
60
|
+
disabled={!table.getCanPreviousPage()}
|
|
61
|
+
>
|
|
62
|
+
<span class="sr-only">Go to first page</span>
|
|
63
|
+
<DoubleArrowLeft class="size-4" />
|
|
64
|
+
</Button>
|
|
65
|
+
<Button
|
|
66
|
+
variant="outline"
|
|
67
|
+
class="size-8 p-0"
|
|
68
|
+
onclick={() => table.previousPage()}
|
|
69
|
+
disabled={!table.getCanPreviousPage()}
|
|
70
|
+
>
|
|
71
|
+
<span class="sr-only">Go to previous page</span>
|
|
72
|
+
<ChevronLeft class="size-4" />
|
|
73
|
+
</Button>
|
|
74
|
+
<Button variant="outline" class="size-8 p-0" onclick={() => table.nextPage()} disabled={!table.getCanNextPage()}>
|
|
75
|
+
<span class="sr-only">Go to next page</span>
|
|
76
|
+
<ChevronRight class="size-4" />
|
|
77
|
+
</Button>
|
|
78
|
+
<Button
|
|
79
|
+
variant="outline"
|
|
80
|
+
class="hidden size-8 p-0 lg:flex"
|
|
81
|
+
onclick={() => table.setPageIndex(table.getPageCount() - 1)}
|
|
82
|
+
disabled={!table.getCanNextPage()}
|
|
83
|
+
>
|
|
84
|
+
<span class="sr-only">Go to last page</span>
|
|
85
|
+
<DoubleArrowRight class="size-4" />
|
|
86
|
+
</Button>
|
|
87
|
+
</div>
|
|
88
|
+
</div>
|
|
89
|
+
</div>
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { Table } from "@tanstack/table-core";
|
|
2
|
+
import type { DataGridProps } from "./types";
|
|
3
|
+
interface Props<T> {
|
|
4
|
+
table: Table<T>;
|
|
5
|
+
dataGridProps?: DataGridProps;
|
|
6
|
+
canChangePageSize?: boolean;
|
|
7
|
+
}
|
|
8
|
+
declare function $$render<T>(): {
|
|
9
|
+
props: Props<T>;
|
|
10
|
+
exports: {};
|
|
11
|
+
bindings: "";
|
|
12
|
+
slots: {};
|
|
13
|
+
events: {};
|
|
14
|
+
};
|
|
15
|
+
declare class __sveltets_Render<T> {
|
|
16
|
+
props(): ReturnType<typeof $$render<T>>['props'];
|
|
17
|
+
events(): ReturnType<typeof $$render<T>>['events'];
|
|
18
|
+
slots(): ReturnType<typeof $$render<T>>['slots'];
|
|
19
|
+
bindings(): "";
|
|
20
|
+
exports(): {};
|
|
21
|
+
}
|
|
22
|
+
interface $$IsomorphicComponent {
|
|
23
|
+
new <T>(options: import('svelte').ComponentConstructorOptions<ReturnType<__sveltets_Render<T>['props']>>): import('svelte').SvelteComponent<ReturnType<__sveltets_Render<T>['props']>, ReturnType<__sveltets_Render<T>['events']>, ReturnType<__sveltets_Render<T>['slots']>> & {
|
|
24
|
+
$$bindings?: ReturnType<__sveltets_Render<T>['bindings']>;
|
|
25
|
+
} & ReturnType<__sveltets_Render<T>['exports']>;
|
|
26
|
+
<T>(internal: unknown, props: ReturnType<__sveltets_Render<T>['props']> & {}): ReturnType<__sveltets_Render<T>['exports']>;
|
|
27
|
+
z_$$bindings?: ReturnType<__sveltets_Render<any>['bindings']>;
|
|
28
|
+
}
|
|
29
|
+
declare const Pagination: $$IsomorphicComponent;
|
|
30
|
+
type Pagination<T> = InstanceType<typeof Pagination<T>>;
|
|
31
|
+
export default Pagination;
|
|
@@ -0,0 +1,292 @@
|
|
|
1
|
+
import { createSubscriber } from "svelte/reactivity";
|
|
2
|
+
import { createTable, getCoreRowModel, getSortedRowModel, getFilteredRowModel, getPaginationRowModel, } from "@tanstack/table-core";
|
|
3
|
+
import { defaultDataGridProps } from "./types";
|
|
4
|
+
import { renderComponent } from "../../../data-table";
|
|
5
|
+
import DataGridCheckbox from "./DataGridCheckbox.svelte";
|
|
6
|
+
export function createGrid(options) {
|
|
7
|
+
// Merge provided dataGridProps with defaults. If none provided, use defaults.
|
|
8
|
+
options.dataGridProps = { ...defaultDataGridProps, ...(options.dataGridProps ?? {}) };
|
|
9
|
+
const { columns, data: dataProp, initialState, dataGridProps } = options;
|
|
10
|
+
// Support both direct data array and getter function for reactivity
|
|
11
|
+
// Using a getter function () => data allows Svelte 5 to track changes
|
|
12
|
+
const getData = typeof dataProp === "function" ? dataProp : () => dataProp;
|
|
13
|
+
// ========================================
|
|
14
|
+
// Reactive State using Svelte 5 runes
|
|
15
|
+
// ========================================
|
|
16
|
+
// Table state - use initialState if provided
|
|
17
|
+
let sorting = $state(initialState?.sorting ?? []);
|
|
18
|
+
let globalFilter = $state(initialState?.globalFilter);
|
|
19
|
+
let pagination = $state(initialState?.pagination ?? { pageIndex: 0, pageSize: 10 });
|
|
20
|
+
let columnFilters = $state(initialState?.columnFilters ?? []);
|
|
21
|
+
let rowSelection = $state(initialState?.rowSelection ?? {});
|
|
22
|
+
let columnPinning = $state(initialState?.columnPinning ?? {});
|
|
23
|
+
let columnVisibility = $state(initialState?.columnVisibility ?? {});
|
|
24
|
+
let columnSizing = $state(initialState?.columnSizing ?? {});
|
|
25
|
+
let columnSizingInfo = $state({
|
|
26
|
+
startOffset: null,
|
|
27
|
+
startSize: null,
|
|
28
|
+
deltaOffset: null,
|
|
29
|
+
deltaPercentage: null,
|
|
30
|
+
isResizingColumn: false,
|
|
31
|
+
columnSizingStart: [],
|
|
32
|
+
});
|
|
33
|
+
// ========================================
|
|
34
|
+
// Create TanStack Table
|
|
35
|
+
// ========================================
|
|
36
|
+
// Initialize column sizing state from column definitions (only if not provided in initialState)
|
|
37
|
+
$effect.pre(() => {
|
|
38
|
+
if (Object.keys(columnSizing).length === 0) {
|
|
39
|
+
const sizing = {};
|
|
40
|
+
for (const col of columns) {
|
|
41
|
+
if (col.size) {
|
|
42
|
+
sizing[col.id] = col.size;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
if (Object.keys(sizing).length > 0) {
|
|
46
|
+
columnSizing = sizing;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
// Row Selection
|
|
51
|
+
if (dataGridProps.enableRowSelectionUI) {
|
|
52
|
+
const rowSelectionColumn = {
|
|
53
|
+
id: "select",
|
|
54
|
+
header: () => {
|
|
55
|
+
subscribeToTable();
|
|
56
|
+
return renderComponent(DataGridCheckbox, {
|
|
57
|
+
checked: table.getIsAllPageRowsSelected(),
|
|
58
|
+
indeterminate: table.getIsSomePageRowsSelected(),
|
|
59
|
+
onCheckedChange: () => table.toggleAllPageRowsSelected(),
|
|
60
|
+
});
|
|
61
|
+
},
|
|
62
|
+
cell: (r) => {
|
|
63
|
+
subscribeToTable();
|
|
64
|
+
return renderComponent(DataGridCheckbox, {
|
|
65
|
+
checked: r.row.getIsSelected(),
|
|
66
|
+
onCheckedChange: () => r.row.toggleSelected(),
|
|
67
|
+
});
|
|
68
|
+
},
|
|
69
|
+
enableResizing: false,
|
|
70
|
+
enableSorting: false,
|
|
71
|
+
size: 0,
|
|
72
|
+
};
|
|
73
|
+
options.columns.unshift(rowSelectionColumn);
|
|
74
|
+
}
|
|
75
|
+
// Create the base table options
|
|
76
|
+
const baseTableOptions = {
|
|
77
|
+
data: getData(),
|
|
78
|
+
columns,
|
|
79
|
+
state: {
|
|
80
|
+
sorting,
|
|
81
|
+
pagination,
|
|
82
|
+
columnFilters,
|
|
83
|
+
rowSelection,
|
|
84
|
+
columnPinning,
|
|
85
|
+
columnVisibility,
|
|
86
|
+
columnSizing,
|
|
87
|
+
columnSizingInfo,
|
|
88
|
+
globalFilter,
|
|
89
|
+
},
|
|
90
|
+
onColumnSizingChange: (updater) => {
|
|
91
|
+
columnSizing = typeof updater === "function" ? updater(columnSizing) : updater;
|
|
92
|
+
},
|
|
93
|
+
onColumnSizingInfoChange: (updater) => {
|
|
94
|
+
columnSizingInfo = typeof updater === "function" ? updater(columnSizingInfo) : updater;
|
|
95
|
+
},
|
|
96
|
+
onColumnPinningChange: (updater) => {
|
|
97
|
+
columnPinning = typeof updater === "function" ? updater(columnPinning) : updater;
|
|
98
|
+
},
|
|
99
|
+
onColumnVisibilityChange: (updater) => {
|
|
100
|
+
columnVisibility = typeof updater === "function" ? updater(columnVisibility) : updater;
|
|
101
|
+
// No version counter needed - visibilityKey is derived from columnVisibility
|
|
102
|
+
// and will automatically update when visibility changes
|
|
103
|
+
},
|
|
104
|
+
onSortingChange: (updater) => {
|
|
105
|
+
sorting = typeof updater === "function" ? updater(sorting) : updater;
|
|
106
|
+
},
|
|
107
|
+
onPaginationChange: (updater) => {
|
|
108
|
+
pagination = typeof updater === "function" ? updater(pagination) : updater;
|
|
109
|
+
},
|
|
110
|
+
onColumnFiltersChange: (updater) => {
|
|
111
|
+
columnFilters = typeof updater === "function" ? updater(columnFilters) : updater;
|
|
112
|
+
},
|
|
113
|
+
onRowSelectionChange: (updater) => {
|
|
114
|
+
rowSelection = typeof updater === "function" ? updater(rowSelection) : updater;
|
|
115
|
+
},
|
|
116
|
+
onGlobalFilterChange: (updater) => {
|
|
117
|
+
globalFilter = typeof updater === "function" ? updater(globalFilter) : updater;
|
|
118
|
+
},
|
|
119
|
+
getCoreRowModel: getCoreRowModel(),
|
|
120
|
+
getPaginationRowModel: getPaginationRowModel(),
|
|
121
|
+
getSortedRowModel: getSortedRowModel(),
|
|
122
|
+
getFilteredRowModel: getFilteredRowModel(),
|
|
123
|
+
globalFilterFn: "auto",
|
|
124
|
+
manualFiltering: dataGridProps.manualFiltering,
|
|
125
|
+
manualPagination: (dataGridProps?.isPaginationEnabled ?? true) == false ? true : dataGridProps?.manualPagination,
|
|
126
|
+
manualSorting: dataGridProps.manualSorting,
|
|
127
|
+
columnResizeMode: "onChange",
|
|
128
|
+
enableColumnResizing: true,
|
|
129
|
+
defaultColumn: {
|
|
130
|
+
minSize: 0,
|
|
131
|
+
maxSize: 1000,
|
|
132
|
+
size: 150,
|
|
133
|
+
},
|
|
134
|
+
enableRowSelection: true,
|
|
135
|
+
enableColumnFilters: true,
|
|
136
|
+
enableFilters: true,
|
|
137
|
+
enableGlobalFilter: true,
|
|
138
|
+
renderFallbackValue: null,
|
|
139
|
+
onStateChange: () => { },
|
|
140
|
+
mergeOptions: (defaultOptions, newOptions) => {
|
|
141
|
+
return { ...defaultOptions, ...newOptions };
|
|
142
|
+
},
|
|
143
|
+
};
|
|
144
|
+
const table = createTable(baseTableOptions);
|
|
145
|
+
// Create a subscriber to notify effects when table data changes
|
|
146
|
+
// This is the key to making TanStack Table reactive in Svelte 5
|
|
147
|
+
// When data comes from async sources (like database queries), the table needs
|
|
148
|
+
// to notify consuming components that data has changed so they can re-render
|
|
149
|
+
let notifyTableUpdate;
|
|
150
|
+
const subscribeToTable = createSubscriber((update) => {
|
|
151
|
+
notifyTableUpdate = update;
|
|
152
|
+
return () => { };
|
|
153
|
+
});
|
|
154
|
+
// This is the key to reactivity: update table options in $effect.pre
|
|
155
|
+
// whenever any of the state values change
|
|
156
|
+
$effect.pre(() => {
|
|
157
|
+
// Read all reactive state to create dependencies
|
|
158
|
+
const currentState = {
|
|
159
|
+
sorting,
|
|
160
|
+
pagination,
|
|
161
|
+
columnFilters,
|
|
162
|
+
rowSelection,
|
|
163
|
+
columnPinning,
|
|
164
|
+
columnVisibility,
|
|
165
|
+
columnSizing,
|
|
166
|
+
columnSizingInfo,
|
|
167
|
+
globalFilter,
|
|
168
|
+
};
|
|
169
|
+
const currentData = getData();
|
|
170
|
+
// Update table with current state
|
|
171
|
+
table.setOptions((prev) => ({
|
|
172
|
+
...prev,
|
|
173
|
+
data: currentData,
|
|
174
|
+
state: {
|
|
175
|
+
...prev.state,
|
|
176
|
+
...currentState,
|
|
177
|
+
},
|
|
178
|
+
}));
|
|
179
|
+
// Notify any subscribers that table data has changed
|
|
180
|
+
// This triggers re-runs of effects/derived that called subscribeToTable()
|
|
181
|
+
notifyTableUpdate?.();
|
|
182
|
+
});
|
|
183
|
+
// ========================================
|
|
184
|
+
// Return
|
|
185
|
+
// ========================================
|
|
186
|
+
// Create a reactive table wrapper that exposes state-dependent getters
|
|
187
|
+
// This is key to making the table reactive in Svelte 5
|
|
188
|
+
// We use subscribeToTable() to register effects as subscribers, so they
|
|
189
|
+
// re-run when notifyTableUpdate() is called after data changes
|
|
190
|
+
const reactiveTable = {
|
|
191
|
+
// Expose all original table methods and properties
|
|
192
|
+
...table,
|
|
193
|
+
// Override methods that depend on state to create reactive dependencies
|
|
194
|
+
getRowModel: () => {
|
|
195
|
+
subscribeToTable();
|
|
196
|
+
return table.getRowModel();
|
|
197
|
+
},
|
|
198
|
+
getHeaderGroups: () => {
|
|
199
|
+
subscribeToTable();
|
|
200
|
+
return table.getHeaderGroups();
|
|
201
|
+
},
|
|
202
|
+
getAllColumns: () => {
|
|
203
|
+
subscribeToTable();
|
|
204
|
+
return table.getAllColumns();
|
|
205
|
+
},
|
|
206
|
+
getVisibleLeafColumns: () => {
|
|
207
|
+
subscribeToTable();
|
|
208
|
+
return table.getVisibleLeafColumns();
|
|
209
|
+
},
|
|
210
|
+
getState: () => {
|
|
211
|
+
subscribeToTable();
|
|
212
|
+
return table.getState();
|
|
213
|
+
},
|
|
214
|
+
getColumn: (columnId) => {
|
|
215
|
+
subscribeToTable();
|
|
216
|
+
return table.getColumn(columnId);
|
|
217
|
+
},
|
|
218
|
+
// Forward all other methods to the original table
|
|
219
|
+
setColumnFilters: table.setColumnFilters.bind(table),
|
|
220
|
+
setSorting: table.setSorting.bind(table),
|
|
221
|
+
setPagination: table.setPagination.bind(table),
|
|
222
|
+
setPageIndex: table.setPageIndex.bind(table),
|
|
223
|
+
setPageSize: table.setPageSize.bind(table),
|
|
224
|
+
setColumnPinning: table.setColumnPinning.bind(table),
|
|
225
|
+
setColumnVisibility: table.setColumnVisibility.bind(table),
|
|
226
|
+
setRowSelection: table.setRowSelection.bind(table),
|
|
227
|
+
setColumnSizing: table.setColumnSizing.bind(table),
|
|
228
|
+
setOptions: table.setOptions.bind(table),
|
|
229
|
+
// setGlobalFilter: table.setGlobalFilter.bind(table),
|
|
230
|
+
getFlatHeaders: () => {
|
|
231
|
+
subscribeToTable();
|
|
232
|
+
return table.getFlatHeaders();
|
|
233
|
+
},
|
|
234
|
+
getTotalSize: () => {
|
|
235
|
+
subscribeToTable();
|
|
236
|
+
return table.getTotalSize();
|
|
237
|
+
},
|
|
238
|
+
getLeftLeafColumns: () => {
|
|
239
|
+
subscribeToTable();
|
|
240
|
+
return table.getLeftLeafColumns();
|
|
241
|
+
},
|
|
242
|
+
getRightLeafColumns: () => {
|
|
243
|
+
subscribeToTable();
|
|
244
|
+
return table.getRightLeafColumns();
|
|
245
|
+
},
|
|
246
|
+
getCenterLeafColumns: () => {
|
|
247
|
+
subscribeToTable();
|
|
248
|
+
return table.getCenterLeafColumns();
|
|
249
|
+
},
|
|
250
|
+
getIsAllRowsSelected: () => {
|
|
251
|
+
subscribeToTable();
|
|
252
|
+
return table.getIsAllRowsSelected();
|
|
253
|
+
},
|
|
254
|
+
getIsSomeRowsSelected: () => {
|
|
255
|
+
subscribeToTable();
|
|
256
|
+
return table.getIsSomeRowsSelected();
|
|
257
|
+
},
|
|
258
|
+
getIsAllPageRowsSelected: () => {
|
|
259
|
+
subscribeToTable();
|
|
260
|
+
return table.getIsAllPageRowsSelected();
|
|
261
|
+
},
|
|
262
|
+
getIsSomePageRowsSelected: () => {
|
|
263
|
+
subscribeToTable();
|
|
264
|
+
return table.getIsSomePageRowsSelected();
|
|
265
|
+
},
|
|
266
|
+
getCanPreviousPage: () => {
|
|
267
|
+
subscribeToTable();
|
|
268
|
+
return table.getCanPreviousPage();
|
|
269
|
+
},
|
|
270
|
+
getCanNextPage: () => {
|
|
271
|
+
subscribeToTable();
|
|
272
|
+
return table.getCanNextPage();
|
|
273
|
+
},
|
|
274
|
+
getFilteredSelectedRowModel: () => {
|
|
275
|
+
subscribeToTable();
|
|
276
|
+
return table.getFilteredSelectedRowModel();
|
|
277
|
+
},
|
|
278
|
+
toggleAllRowsSelected: table.toggleAllRowsSelected.bind(table),
|
|
279
|
+
toggleAllPageRowsSelected: table.toggleAllPageRowsSelected.bind(table),
|
|
280
|
+
// Keep table reference for any other property access
|
|
281
|
+
_getDefaultColumnDef: table._getDefaultColumnDef.bind(table),
|
|
282
|
+
get options() {
|
|
283
|
+
subscribeToTable();
|
|
284
|
+
return table.options;
|
|
285
|
+
},
|
|
286
|
+
initialState: table.initialState,
|
|
287
|
+
};
|
|
288
|
+
return {
|
|
289
|
+
table: reactiveTable,
|
|
290
|
+
dataGridProps: dataGridProps,
|
|
291
|
+
};
|
|
292
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { default as DataGrid } from "./DataGrid.svelte";
|
|
2
|
+
export { createGrid } from "./createGrid.svelte";
|
|
3
|
+
export { aggregationFns } from "../data-table/data-table-utils";
|
|
4
|
+
export { decodeColumnFilters, decodeGlobalFilter, decodePageIndex, decodeSorting, decodeTableState, encodeColumnFilters, encodeGlobalFilter, encodePageIndex, encodeSorting, encodeTableState, } from "../data-table/table-search-params";
|
|
5
|
+
export type { CustomColumnMeta, CustomOptions } from "./types";
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export { default as DataGrid } from "./DataGrid.svelte";
|
|
2
|
+
export { createGrid } from "./createGrid.svelte";
|
|
3
|
+
export { aggregationFns } from "../data-table/data-table-utils";
|
|
4
|
+
export { decodeColumnFilters, decodeGlobalFilter, decodePageIndex, decodeSorting, decodeTableState, encodeColumnFilters, encodeGlobalFilter, encodePageIndex, encodeSorting, encodeTableState, } from "../data-table/table-search-params";
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import type { ColumnDef, ColumnFiltersState, ColumnPinningState, ColumnSizingState, GlobalFilterTableState, PaginationState, RowData, RowSelectionState, SortingState, Table, VisibilityState } from "@tanstack/table-core";
|
|
2
|
+
import z from "zod";
|
|
3
|
+
export interface DataGridOptions<TData extends RowData> {
|
|
4
|
+
columns: ColumnDef<TData, unknown>[];
|
|
5
|
+
data: TData[] | (() => TData[]);
|
|
6
|
+
initialState?: {
|
|
7
|
+
sorting?: SortingState;
|
|
8
|
+
pagination?: PaginationState;
|
|
9
|
+
columnFilters?: ColumnFiltersState;
|
|
10
|
+
columnVisibility?: VisibilityState;
|
|
11
|
+
columnPinning?: ColumnPinningState;
|
|
12
|
+
columnSizing?: ColumnSizingState;
|
|
13
|
+
rowSelection?: RowSelectionState;
|
|
14
|
+
globalFilter?: GlobalFilterTableState;
|
|
15
|
+
};
|
|
16
|
+
dataGridProps?: DataGridProps;
|
|
17
|
+
}
|
|
18
|
+
export interface DataGridProps {
|
|
19
|
+
isPaginationEnabled?: boolean;
|
|
20
|
+
manualPagination?: boolean;
|
|
21
|
+
enableRowSelectionUI?: boolean;
|
|
22
|
+
manualFiltering?: boolean;
|
|
23
|
+
manualSorting?: boolean;
|
|
24
|
+
useURLSearchParams?: boolean;
|
|
25
|
+
}
|
|
26
|
+
export declare const defaultDataGridProps: DataGridProps;
|
|
27
|
+
export interface DataGridResponse<TData extends RowData> {
|
|
28
|
+
table: Table<TData>;
|
|
29
|
+
dataGridProps?: DataGridProps;
|
|
30
|
+
}
|
|
31
|
+
export declare const defaultSearchParamSchema: z.ZodObject<{
|
|
32
|
+
search: z.ZodDefault<z.ZodAny>;
|
|
33
|
+
page: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
34
|
+
filter: z.ZodDefault<z.ZodString>;
|
|
35
|
+
sort: z.ZodDefault<z.ZodString>;
|
|
36
|
+
}, z.core.$strip>;
|
|
37
|
+
export type SearchParamSchema = z.infer<typeof defaultSearchParamSchema>;
|
|
38
|
+
export interface CustomOptions {
|
|
39
|
+
useURLSearchParams?: boolean;
|
|
40
|
+
}
|
|
41
|
+
export interface CustomColumnMeta {
|
|
42
|
+
className?: string;
|
|
43
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import z from "zod";
|
|
2
|
+
export const defaultDataGridProps = {
|
|
3
|
+
isPaginationEnabled: true,
|
|
4
|
+
manualPagination: false,
|
|
5
|
+
enableRowSelectionUI: false,
|
|
6
|
+
manualFiltering: false,
|
|
7
|
+
manualSorting: false,
|
|
8
|
+
useURLSearchParams: false,
|
|
9
|
+
};
|
|
10
|
+
export const defaultSearchParamSchema = z.object({
|
|
11
|
+
search: z.any().default(""),
|
|
12
|
+
page: z.coerce.number().default(0),
|
|
13
|
+
filter: z.string().default(""),
|
|
14
|
+
sort: z.string().default(""),
|
|
15
|
+
});
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
bind:ref
|
|
15
15
|
data-slot={dataSlot}
|
|
16
16
|
class={cn(
|
|
17
|
-
"bg-border shrink-0 data-[orientation=horizontal]:h-px data-[orientation=horizontal]:w-full data-[orientation=vertical]:h-full data-[orientation=vertical]:w-px",
|
|
17
|
+
"bg-border shrink-0 data-[orientation=horizontal]:h-px data-[orientation=horizontal]:w-full data-[orientation=vertical]:min-h-full data-[orientation=vertical]:w-px",
|
|
18
18
|
className
|
|
19
19
|
)}
|
|
20
20
|
{...restProps}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kayord/ui",
|
|
3
3
|
"private": false,
|
|
4
|
-
"version": "2.
|
|
4
|
+
"version": "2.1.1",
|
|
5
5
|
"exports": {
|
|
6
6
|
".": {
|
|
7
7
|
"types": "./dist/index.d.ts",
|
|
@@ -23,6 +23,10 @@
|
|
|
23
23
|
"types": "./dist/data-table/index.d.ts",
|
|
24
24
|
"default": "./dist/data-table/index.js"
|
|
25
25
|
},
|
|
26
|
+
"./data-grid": {
|
|
27
|
+
"types": "./dist/data-grid/index.d.ts",
|
|
28
|
+
"default": "./dist/data-grid/index.js"
|
|
29
|
+
},
|
|
26
30
|
"./drawer": {
|
|
27
31
|
"types": "./dist/drawer/index.d.ts",
|
|
28
32
|
"default": "./dist/drawer/index.js"
|
|
@@ -110,9 +114,9 @@
|
|
|
110
114
|
"@eslint/compat": "^2.0.1",
|
|
111
115
|
"@eslint/js": "^9.39.2",
|
|
112
116
|
"@internationalized/date": "^3.10.1",
|
|
113
|
-
"@lucide/svelte": "^0.
|
|
117
|
+
"@lucide/svelte": "^0.562.0",
|
|
114
118
|
"@sveltejs/adapter-auto": "^7.0.0",
|
|
115
|
-
"@sveltejs/kit": "^2.
|
|
119
|
+
"@sveltejs/kit": "^2.50.0",
|
|
116
120
|
"@sveltejs/package": "^2.5.7",
|
|
117
121
|
"@sveltejs/vite-plugin-svelte": "^6.2.4",
|
|
118
122
|
"@tailwindcss/vite": "^4.1.18",
|
|
@@ -131,11 +135,12 @@
|
|
|
131
135
|
"layerchart": "2.0.0-next.40",
|
|
132
136
|
"mode-watcher": "^1.1.0",
|
|
133
137
|
"paneforge": "^1.0.2",
|
|
134
|
-
"prettier": "^3.
|
|
138
|
+
"prettier": "^3.8.0",
|
|
135
139
|
"prettier-plugin-svelte": "^3.4.1",
|
|
136
140
|
"prettier-plugin-tailwindcss": "^0.7.2",
|
|
137
141
|
"publint": "^0.3.16",
|
|
138
|
-
"
|
|
142
|
+
"runed": "^0.37.1",
|
|
143
|
+
"svelte": "5.47.1",
|
|
139
144
|
"svelte-check": "^4.3.5",
|
|
140
145
|
"svelte-sonner": "^1.0.7",
|
|
141
146
|
"sveltekit-superforms": "^2.29.1",
|
|
@@ -143,7 +148,7 @@
|
|
|
143
148
|
"tslib": "^2.8.1",
|
|
144
149
|
"tw-animate-css": "1.4.0",
|
|
145
150
|
"typescript": "^5.9.3",
|
|
146
|
-
"typescript-eslint": "^8.53.
|
|
151
|
+
"typescript-eslint": "^8.53.1",
|
|
147
152
|
"vaul-svelte": "1.0.0-next.7",
|
|
148
153
|
"vite": "^7.3.1",
|
|
149
154
|
"vitest": "^4.0.17",
|