compote-ui 0.80.0 → 0.81.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.
Files changed (32) hide show
  1. package/dist/components/data-table-v9/column-filter-kind.d.ts +10 -1
  2. package/dist/components/data-table-v9/column-filter-kind.js +7 -0
  3. package/dist/components/data-table-v9/data-table-head.svelte +230 -230
  4. package/dist/components/data-table-v9/data-table.svelte +154 -154
  5. package/dist/components/data-table-v9/filter-editors/boolean-filter-editor.svelte +45 -45
  6. package/dist/components/data-table-v9/filter-editors/column-filter-editor.svelte +39 -33
  7. package/dist/components/data-table-v9/filter-editors/column-filter-editor.svelte.d.ts +7 -2
  8. package/dist/components/data-table-v9/filter-editors/date-range-filter-editor.svelte +52 -52
  9. package/dist/components/data-table-v9/filter-editors/range-filter-editor.svelte +51 -51
  10. package/dist/components/data-table-v9/filter-editors/select-filter-editor.svelte +59 -59
  11. package/dist/components/data-table-v9/filter-editors/text-filter-editor.svelte +20 -20
  12. package/dist/components/data-table-v9/header/column-header-filter.svelte +66 -66
  13. package/dist/components/data-table-v9/index.d.ts +9 -1
  14. package/dist/components/data-table-v9/index.js +7 -0
  15. package/dist/components/data-table-v9/toolbar/data-table-column-filter.svelte +203 -203
  16. package/dist/components/data-table-v9/types.d.ts +3 -1
  17. package/dist/components/data-table-v9/virtual/data-table-virtualized.svelte +82 -82
  18. package/dist/components/data-table-v9/virtual/index.d.ts +2 -2
  19. package/dist/components/data-table-v9/virtual/index.js +1 -1
  20. package/dist/components/dialog/alert-dialog.svelte +73 -73
  21. package/dist/components/dialog/dialog-root.svelte +45 -45
  22. package/dist/components/drawer/drawer-content.svelte +213 -213
  23. package/dist/components/popover/popover-content.svelte +97 -97
  24. package/dist/components/popover/popover-description.svelte +19 -19
  25. package/dist/components/popover/popover-root.svelte +27 -27
  26. package/dist/components/popover/popover-title.svelte +19 -19
  27. package/dist/icons/PhFunnelFill.svelte +19 -19
  28. package/package.json +1 -1
  29. package/skills/component-usage/references/overlays-and-floating-ui.md +278 -278
  30. package/skills/data-table/SKILL.md +362 -314
  31. package/skills/data-table/references/column-options.md +175 -175
  32. package/skills/data-table/references/table-state-and-reactivity.md +65 -65
@@ -1,203 +1,203 @@
1
- <script lang="ts" generics="T extends RowData">
2
- import type { Column, RowData } from '@tanstack/svelte-table';
3
- import * as Popover from '../../popover';
4
- import * as Tooltip from '../../tooltip';
5
- import * as ScrollArea from '../../scroll-area';
6
- import { getColumnLabel, type DataTableInstance } from '../data-table-utils';
7
- import type { DataTableFeatures } from '../features';
8
- import Badge from '../../badge/badge.svelte';
9
- import { button } from '../../button/button.variants';
10
- import { PhX, PhMagnifyingGlass, PhFunnel } from '../../../icons';
11
- import { ColumnFilterEditing } from '../column-filter-editing.svelte';
12
- import ColumnFilterEditor from '../filter-editors/column-filter-editor.svelte';
13
-
14
- type Props = {
15
- table: DataTableInstance<T>;
16
- /** Text label for the trigger. When omitted, a funnel icon is shown instead. */
17
- triggerLabel?: string;
18
- };
19
-
20
- let { table, triggerLabel }: Props = $props();
21
-
22
- // Popover and tooltip share one trigger element, so both must agree on its id.
23
- const triggerId = $props.id();
24
-
25
- // Pending edits belong to the table: shared with the other filter hosts, and they still
26
- // commit after this popover closes.
27
- const editing = new ColumnFilterEditing({
28
- table: () => table,
29
- isActive: (columnId) => activeFilterIds.includes(columnId)
30
- });
31
-
32
- const columnFilters = $derived.by(() => table.atoms.columnFilters.get());
33
- const columnVisibility = $derived.by(() => table.atoms.columnVisibility.get());
34
- const activeCount = $derived(columnFilters.length);
35
-
36
- // Filters the user has explicitly opened. Kept separate from the table's
37
- // columnFilters so a filter card stays visible after its value is cleared
38
- // (e.g. unchecking the last select option) until removed via the X button.
39
- let manualFilterIds = $state<string[]>([]);
40
- const activeFilterIds: string[] = $derived.by(() => {
41
- const ids = columnFilters.map((f) => f.id);
42
- for (const id of manualFilterIds) {
43
- if (!ids.includes(id)) ids.push(id);
44
- }
45
- return ids;
46
- });
47
- let showColumnPicker = $state(false);
48
- let columnSearchText = $state('');
49
-
50
- const activeColumns = $derived.by(() => {
51
- return activeFilterIds
52
- .map((id) => table.getColumn(id))
53
- .filter((col): col is Column<DataTableFeatures, T, unknown> => col != null);
54
- });
55
-
56
- const availableColumns = $derived.by(() => {
57
- void columnVisibility;
58
- return table
59
- .getAllLeafColumns()
60
- .filter((col) => col.getCanFilter() && !activeFilterIds.includes(col.id))
61
- .filter(
62
- (col) =>
63
- !columnSearchText ||
64
- getColumnLabel(col).toLowerCase().includes(columnSearchText.toLowerCase())
65
- );
66
- });
67
-
68
- function addFilter(column: Column<DataTableFeatures, T, unknown>) {
69
- manualFilterIds = [...manualFilterIds, column.id];
70
- showColumnPicker = false;
71
- columnSearchText = '';
72
- }
73
-
74
- function removeFilter(column: Column<DataTableFeatures, T, unknown>) {
75
- manualFilterIds = manualFilterIds.filter((id) => id !== column.id);
76
- editing.cancel(column.id);
77
- column.setFilterValue(undefined);
78
- }
79
-
80
- function clearFilters() {
81
- editing.cancelAll();
82
- manualFilterIds = [];
83
- showColumnPicker = false;
84
- columnSearchText = '';
85
- table.resetColumnFilters();
86
- }
87
- </script>
88
-
89
- <Popover.Root ids={{ trigger: triggerId }} positioning={{ placement: 'bottom-end' }}>
90
- <Tooltip.Root ids={{ trigger: triggerId }} disabled={!!triggerLabel}>
91
- <Tooltip.Trigger>
92
- {#snippet asChild(tooltipProps)}
93
- <Popover.Trigger
94
- {...tooltipProps()}
95
- aria-label={triggerLabel ? undefined : 'Filters'}
96
- class={button({
97
- variant: 'outline',
98
- size: triggerLabel ? 'default' : 'icon',
99
- class: 'relative'
100
- })}
101
- >
102
- {#if triggerLabel}
103
- {triggerLabel}
104
- {:else}
105
- <PhFunnel />
106
- {/if}
107
- {#if activeCount > 0}
108
- <Badge
109
- variant="solid"
110
- color="primary"
111
- class="absolute top-0 right-0 size-4 translate-x-1/3 -translate-y-1/3 justify-center px-1 text-xs"
112
- >
113
- {activeCount > 99 ? '99+' : activeCount}
114
- </Badge>
115
- {/if}
116
- </Popover.Trigger>
117
- {/snippet}
118
- </Tooltip.Trigger>
119
- <Tooltip.Content>Filters</Tooltip.Content>
120
- </Tooltip.Root>
121
-
122
- <Popover.Content class="flex w-70 flex-col gap-3 p-3" showArrow={false}>
123
- <div class="mr-1 flex items-center justify-between py-2.5">
124
- <Popover.Title class="text-sm font-medium text-ink">Filters</Popover.Title>
125
- {#if activeCount > 0}
126
- <button type="button" onclick={clearFilters} class="text-xs text-primary hover:underline">
127
- Clear all
128
- </button>
129
- {/if}
130
- </div>
131
-
132
- {#if activeColumns.length > 0}
133
- <div class="overflow-hidden border-t border-surface-2">
134
- <ScrollArea.Root>
135
- <ScrollArea.Viewport class="max-h-96">
136
- <ScrollArea.Content class="flex flex-col gap-3">
137
- {#each activeColumns as column (column.id)}
138
- <div class="border border-surface-3 p-3">
139
- <div class="mb-2 flex items-center justify-between">
140
- <span class="text-sm font-medium text-ink">{getColumnLabel(column)}</span>
141
- <button
142
- type="button"
143
- onclick={() => removeFilter(column)}
144
- class="text-ink-dim transition-colors hover:text-ink"
145
- >
146
- <PhX class="size-3.5" />
147
- </button>
148
- </div>
149
-
150
- <ColumnFilterEditor {column} {editing} />
151
- </div>
152
- {/each}
153
- </ScrollArea.Content>
154
- </ScrollArea.Viewport>
155
- <ScrollArea.Scrollbar orientation="vertical">
156
- <ScrollArea.Thumb />
157
- </ScrollArea.Scrollbar>
158
- <ScrollArea.Corner />
159
- </ScrollArea.Root>
160
- </div>
161
- {/if}
162
-
163
- {#if showColumnPicker}
164
- <div class="border-t border-surface-3 p-3">
165
- <div class="relative mb-1">
166
- <PhMagnifyingGlass
167
- class="pointer-events-none absolute top-1/2 left-2.5 size-3.5 -translate-y-1/2 text-ink-dim"
168
- />
169
- <input
170
- type="text"
171
- placeholder="Search columns..."
172
- bind:value={columnSearchText}
173
- class="h-8 w-full rounded border border-border bg-surface-1 pr-3 pl-7 text-sm text-ink outline-none placeholder:text-ink-dim focus:ring-1 focus:ring-ring"
174
- />
175
- </div>
176
- <div class="max-h-48 overflow-y-auto">
177
- {#each availableColumns as column (column.id)}
178
- <button
179
- type="button"
180
- onclick={() => addFilter(column)}
181
- class="w-full rounded px-2 py-1.5 text-left text-sm text-ink hover:bg-surface-2"
182
- >
183
- {getColumnLabel(column)}
184
- </button>
185
- {:else}
186
- <p class="px-2 py-3 text-center text-sm text-ink-dim">No more columns</p>
187
- {/each}
188
- </div>
189
- </div>
190
- {:else}
191
- <div class="border-t border-surface-3">
192
- <button
193
- type="button"
194
- onclick={() => (showColumnPicker = true)}
195
- class="flex w-full items-center gap-2 px-3 py-2.5 text-sm text-ink-dim hover:bg-surface-2 hover:text-ink"
196
- >
197
- <span class="text-base leading-none">+</span>
198
- Add Filter
199
- </button>
200
- </div>
201
- {/if}
202
- </Popover.Content>
203
- </Popover.Root>
1
+ <script lang="ts" generics="T extends RowData">
2
+ import type { Column, RowData } from '@tanstack/svelte-table';
3
+ import * as Popover from '../../popover';
4
+ import * as Tooltip from '../../tooltip';
5
+ import * as ScrollArea from '../../scroll-area';
6
+ import { getColumnLabel, type DataTableInstance } from '../data-table-utils';
7
+ import type { DataTableFeatures } from '../features';
8
+ import Badge from '../../badge/badge.svelte';
9
+ import { button } from '../../button/button.variants';
10
+ import { PhX, PhMagnifyingGlass, PhFunnel } from '../../../icons';
11
+ import { ColumnFilterEditing } from '../column-filter-editing.svelte';
12
+ import ColumnFilterEditor from '../filter-editors/column-filter-editor.svelte';
13
+
14
+ type Props = {
15
+ table: DataTableInstance<T>;
16
+ /** Text label for the trigger. When omitted, a funnel icon is shown instead. */
17
+ triggerLabel?: string;
18
+ };
19
+
20
+ let { table, triggerLabel }: Props = $props();
21
+
22
+ // Popover and tooltip share one trigger element, so both must agree on its id.
23
+ const triggerId = $props.id();
24
+
25
+ // Pending edits belong to the table: shared with the other filter hosts, and they still
26
+ // commit after this popover closes.
27
+ const editing = new ColumnFilterEditing({
28
+ table: () => table,
29
+ isActive: (columnId) => activeFilterIds.includes(columnId)
30
+ });
31
+
32
+ const columnFilters = $derived.by(() => table.atoms.columnFilters.get());
33
+ const columnVisibility = $derived.by(() => table.atoms.columnVisibility.get());
34
+ const activeCount = $derived(columnFilters.length);
35
+
36
+ // Filters the user has explicitly opened. Kept separate from the table's
37
+ // columnFilters so a filter card stays visible after its value is cleared
38
+ // (e.g. unchecking the last select option) until removed via the X button.
39
+ let manualFilterIds = $state<string[]>([]);
40
+ const activeFilterIds: string[] = $derived.by(() => {
41
+ const ids = columnFilters.map((f) => f.id);
42
+ for (const id of manualFilterIds) {
43
+ if (!ids.includes(id)) ids.push(id);
44
+ }
45
+ return ids;
46
+ });
47
+ let showColumnPicker = $state(false);
48
+ let columnSearchText = $state('');
49
+
50
+ const activeColumns = $derived.by(() => {
51
+ return activeFilterIds
52
+ .map((id) => table.getColumn(id))
53
+ .filter((col): col is Column<DataTableFeatures, T, unknown> => col != null);
54
+ });
55
+
56
+ const availableColumns = $derived.by(() => {
57
+ void columnVisibility;
58
+ return table
59
+ .getAllLeafColumns()
60
+ .filter((col) => col.getCanFilter() && !activeFilterIds.includes(col.id))
61
+ .filter(
62
+ (col) =>
63
+ !columnSearchText ||
64
+ getColumnLabel(col).toLowerCase().includes(columnSearchText.toLowerCase())
65
+ );
66
+ });
67
+
68
+ function addFilter(column: Column<DataTableFeatures, T, unknown>) {
69
+ manualFilterIds = [...manualFilterIds, column.id];
70
+ showColumnPicker = false;
71
+ columnSearchText = '';
72
+ }
73
+
74
+ function removeFilter(column: Column<DataTableFeatures, T, unknown>) {
75
+ manualFilterIds = manualFilterIds.filter((id) => id !== column.id);
76
+ editing.cancel(column.id);
77
+ column.setFilterValue(undefined);
78
+ }
79
+
80
+ function clearFilters() {
81
+ editing.cancelAll();
82
+ manualFilterIds = [];
83
+ showColumnPicker = false;
84
+ columnSearchText = '';
85
+ table.resetColumnFilters();
86
+ }
87
+ </script>
88
+
89
+ <Popover.Root ids={{ trigger: triggerId }} positioning={{ placement: 'bottom-end' }}>
90
+ <Tooltip.Root ids={{ trigger: triggerId }} disabled={!!triggerLabel}>
91
+ <Tooltip.Trigger>
92
+ {#snippet asChild(tooltipProps)}
93
+ <Popover.Trigger
94
+ {...tooltipProps()}
95
+ aria-label={triggerLabel ? undefined : 'Filters'}
96
+ class={button({
97
+ variant: 'outline',
98
+ size: triggerLabel ? 'default' : 'icon',
99
+ class: 'relative'
100
+ })}
101
+ >
102
+ {#if triggerLabel}
103
+ {triggerLabel}
104
+ {:else}
105
+ <PhFunnel />
106
+ {/if}
107
+ {#if activeCount > 0}
108
+ <Badge
109
+ variant="solid"
110
+ color="primary"
111
+ class="absolute top-0 right-0 size-4 translate-x-1/3 -translate-y-1/3 justify-center px-1 text-xs"
112
+ >
113
+ {activeCount > 99 ? '99+' : activeCount}
114
+ </Badge>
115
+ {/if}
116
+ </Popover.Trigger>
117
+ {/snippet}
118
+ </Tooltip.Trigger>
119
+ <Tooltip.Content>Filters</Tooltip.Content>
120
+ </Tooltip.Root>
121
+
122
+ <Popover.Content class="flex w-70 flex-col gap-3 p-3" showArrow={false}>
123
+ <div class="mr-1 flex items-center justify-between py-2.5">
124
+ <Popover.Title class="text-sm font-medium text-ink">Filters</Popover.Title>
125
+ {#if activeCount > 0}
126
+ <button type="button" onclick={clearFilters} class="text-xs text-primary hover:underline">
127
+ Clear all
128
+ </button>
129
+ {/if}
130
+ </div>
131
+
132
+ {#if activeColumns.length > 0}
133
+ <div class="overflow-hidden border-t border-surface-2">
134
+ <ScrollArea.Root>
135
+ <ScrollArea.Viewport class="max-h-96">
136
+ <ScrollArea.Content class="flex flex-col gap-3">
137
+ {#each activeColumns as column (column.id)}
138
+ <div class="border border-surface-3 p-3">
139
+ <div class="mb-2 flex items-center justify-between">
140
+ <span class="text-sm font-medium text-ink">{getColumnLabel(column)}</span>
141
+ <button
142
+ type="button"
143
+ onclick={() => removeFilter(column)}
144
+ class="text-ink-dim transition-colors hover:text-ink"
145
+ >
146
+ <PhX class="size-3.5" />
147
+ </button>
148
+ </div>
149
+
150
+ <ColumnFilterEditor {column} {editing} />
151
+ </div>
152
+ {/each}
153
+ </ScrollArea.Content>
154
+ </ScrollArea.Viewport>
155
+ <ScrollArea.Scrollbar orientation="vertical">
156
+ <ScrollArea.Thumb />
157
+ </ScrollArea.Scrollbar>
158
+ <ScrollArea.Corner />
159
+ </ScrollArea.Root>
160
+ </div>
161
+ {/if}
162
+
163
+ {#if showColumnPicker}
164
+ <div class="border-t border-surface-3 p-3">
165
+ <div class="relative mb-1">
166
+ <PhMagnifyingGlass
167
+ class="pointer-events-none absolute top-1/2 left-2.5 size-3.5 -translate-y-1/2 text-ink-dim"
168
+ />
169
+ <input
170
+ type="text"
171
+ placeholder="Search columns..."
172
+ bind:value={columnSearchText}
173
+ class="h-8 w-full rounded border border-border bg-surface-1 pr-3 pl-7 text-sm text-ink outline-none placeholder:text-ink-dim focus:ring-1 focus:ring-ring"
174
+ />
175
+ </div>
176
+ <div class="max-h-48 overflow-y-auto">
177
+ {#each availableColumns as column (column.id)}
178
+ <button
179
+ type="button"
180
+ onclick={() => addFilter(column)}
181
+ class="w-full rounded px-2 py-1.5 text-left text-sm text-ink hover:bg-surface-2"
182
+ >
183
+ {getColumnLabel(column)}
184
+ </button>
185
+ {:else}
186
+ <p class="px-2 py-3 text-center text-sm text-ink-dim">No more columns</p>
187
+ {/each}
188
+ </div>
189
+ </div>
190
+ {:else}
191
+ <div class="border-t border-surface-3">
192
+ <button
193
+ type="button"
194
+ onclick={() => (showColumnPicker = true)}
195
+ class="flex w-full items-center gap-2 px-3 py-2.5 text-sm text-ink-dim hover:bg-surface-2 hover:text-ink"
196
+ >
197
+ <span class="text-base leading-none">+</span>
198
+ Add Filter
199
+ </button>
200
+ </div>
201
+ {/if}
202
+ </Popover.Content>
203
+ </Popover.Root>
@@ -1,4 +1,4 @@
1
- import type { FilterFnOption, RowData } from '@tanstack/svelte-table';
1
+ import type { Column, FilterFnOption, RowData } from '@tanstack/svelte-table';
2
2
  import type { Component, Snippet } from 'svelte';
3
3
  import type { DataTableFeatures } from './features';
4
4
  export type DataTableAlign = 'left' | 'center' | 'right';
@@ -63,6 +63,8 @@ export type DataTableGroupColumn<T extends RowData> = DataTableColumnBase & {
63
63
  formatLocale?: never;
64
64
  };
65
65
  export type DataTableColumn<T extends RowData> = DataTableLeafColumn<T> | DataTableGroupColumn<T>;
66
+ /** A column of a compote data table, as `table.getColumn()` and `getAllLeafColumns()` return it. */
67
+ export type DataTableColumnInstance<T extends RowData> = Column<DataTableFeatures, T, unknown>;
66
68
  export type DataTableColumnMeta = {
67
69
  align?: DataTableAlign;
68
70
  type?: DataTableColumnType;
@@ -1,82 +1,82 @@
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 '../data-table-utils';
6
- import { createTableViewState } from '../table-view-state.svelte';
7
- import DataTableHead from '../data-table-head.svelte';
8
- import DataTableFoot from '../data-table-foot.svelte';
9
- import DataTableVirtualRows from './data-table-virtual-rows.svelte';
10
- import { tableSizeStyle } from '../data-table-utils';
11
-
12
- type Props = Omit<HTMLAttributes<HTMLDivElement>, 'class'> & {
13
- table: DataTableInstance<T>;
14
- caption?: string;
15
- emptyMessage?: string;
16
- class?: ClassValue;
17
- /** Show a filter funnel in the header of every filterable column. */
18
- headerFilters?: boolean;
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
- headerFilters = false,
29
- onRowClick,
30
- onRowDoubleClick,
31
- ...rest
32
- }: Props = $props();
33
-
34
- let scrollContainerRef = $state<HTMLDivElement | undefined>(undefined);
35
-
36
- const view = createTableViewState(() => table);
37
- </script>
38
-
39
- <div
40
- class={cn(
41
- 'flex max-h-full min-h-0 flex-col overflow-hidden rounded-lg border border-surface-3 bg-surface-1',
42
- className
43
- )}
44
- {...rest}
45
- >
46
- {#if view.isColumnResizing}
47
- <div aria-hidden="true" class="fixed inset-0 z-50 cursor-col-resize select-none"></div>
48
- {/if}
49
-
50
- <div class="min-h-0 flex-1 overflow-auto" bind:this={scrollContainerRef}>
51
- <table
52
- class="table-fixed border-separate border-spacing-0 text-sm"
53
- style="display: grid; {tableSizeStyle(table, view.isRowSelectionEnabled, view)}"
54
- >
55
- {#if caption}
56
- <caption class="sr-only">{caption}</caption>
57
- {/if}
58
- <DataTableHead {table} {view} isVirtual {headerFilters} />
59
- {#if scrollContainerRef}
60
- <DataTableVirtualRows
61
- {table}
62
- {view}
63
- scrollContainer={scrollContainerRef}
64
- {emptyMessage}
65
- {onRowClick}
66
- {onRowDoubleClick}
67
- />
68
- {/if}
69
- {#if view.hasFooter}
70
- <DataTableFoot {table} {view} hasGrowColumn={false} isVirtual />
71
- {/if}
72
- </table>
73
- </div>
74
-
75
- <div class="shrink-0 border-t border-surface-3 bg-surface-2 px-3 py-2 text-sm text-ink-dim">
76
- {#if view.isRowSelectionEnabled}
77
- {view.selectedRowCount} of {view.rowModel.rows.length} rows selected
78
- {:else}
79
- {view.rowModel.rows.length} rows
80
- {/if}
81
- </div>
82
- </div>
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 '../data-table-utils';
6
+ import { createTableViewState } from '../table-view-state.svelte';
7
+ import DataTableHead from '../data-table-head.svelte';
8
+ import DataTableFoot from '../data-table-foot.svelte';
9
+ import DataTableVirtualRows from './data-table-virtual-rows.svelte';
10
+ import { tableSizeStyle } from '../data-table-utils';
11
+
12
+ type Props = Omit<HTMLAttributes<HTMLDivElement>, 'class'> & {
13
+ table: DataTableInstance<T>;
14
+ caption?: string;
15
+ emptyMessage?: string;
16
+ class?: ClassValue;
17
+ /** Show a filter funnel in the header of every filterable column. */
18
+ headerFilters?: boolean;
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
+ headerFilters = false,
29
+ onRowClick,
30
+ onRowDoubleClick,
31
+ ...rest
32
+ }: Props = $props();
33
+
34
+ let scrollContainerRef = $state<HTMLDivElement | undefined>(undefined);
35
+
36
+ const view = createTableViewState(() => table);
37
+ </script>
38
+
39
+ <div
40
+ class={cn(
41
+ 'flex max-h-full min-h-0 flex-col overflow-hidden rounded-lg border border-surface-3 bg-surface-1',
42
+ className
43
+ )}
44
+ {...rest}
45
+ >
46
+ {#if view.isColumnResizing}
47
+ <div aria-hidden="true" class="fixed inset-0 z-50 cursor-col-resize select-none"></div>
48
+ {/if}
49
+
50
+ <div class="min-h-0 flex-1 overflow-auto" bind:this={scrollContainerRef}>
51
+ <table
52
+ class="table-fixed border-separate border-spacing-0 text-sm"
53
+ style="display: grid; {tableSizeStyle(table, view.isRowSelectionEnabled, view)}"
54
+ >
55
+ {#if caption}
56
+ <caption class="sr-only">{caption}</caption>
57
+ {/if}
58
+ <DataTableHead {table} {view} isVirtual {headerFilters} />
59
+ {#if scrollContainerRef}
60
+ <DataTableVirtualRows
61
+ {table}
62
+ {view}
63
+ scrollContainer={scrollContainerRef}
64
+ {emptyMessage}
65
+ {onRowClick}
66
+ {onRowDoubleClick}
67
+ />
68
+ {/if}
69
+ {#if view.hasFooter}
70
+ <DataTableFoot {table} {view} hasGrowColumn={false} isVirtual />
71
+ {/if}
72
+ </table>
73
+ </div>
74
+
75
+ <div class="shrink-0 border-t border-surface-3 bg-surface-2 px-3 py-2 text-sm text-ink-dim">
76
+ {#if view.isRowSelectionEnabled}
77
+ {view.selectedRowCount} of {view.rowModel.rows.length} rows selected
78
+ {:else}
79
+ {view.rowModel.rows.length} rows
80
+ {/if}
81
+ </div>
82
+ </div>
@@ -1,3 +1,3 @@
1
1
  export { default as Root } from './data-table-virtualized.svelte';
2
- export { ColumnFilter, ColumnVisibility, FlexRender, Refresh, Search, Title, Toolbar, createDataTableColumnHelper, createTable, renderComponent, renderSnippet } from '../index';
3
- export type { CreateDataTableOptions, DataTableAccessorFnColumn, DataTableAccessorKeyColumn, DataTableAlign, DataTableCellPropsResolver, DataTableCellRenderProps, DataTableColumn, DataTableColumnBase, DataTableColumnOptions, DataTableColumnType, DataTableGroupColumn, DataTableInstance, DataTableLeafColumn, DataTableLeafColumnBase } from '../index';
2
+ export { ColumnFilter, ColumnFilterEditing, ColumnFilterEditor, ColumnVisibility, EMPTY_SELECT_VALUE, FlexRender, Refresh, Search, Title, Toolbar, createDataTableColumnHelper, createTable, filterKindFor, getColumnFilterKind, getColumnLabel, renderComponent, renderSnippet, selectFilterOptions } from '../index';
3
+ export type { ColumnFilterEditingOptions, ColumnFilterKind, CreateDataTableOptions, DataTableAccessorFnColumn, DataTableAccessorKeyColumn, DataTableAlign, DataTableCellPropsResolver, DataTableCellRenderProps, DataTableColumn, DataTableColumnBase, DataTableColumnInstance, DataTableColumnOptions, DataTableColumnType, DataTableGroupColumn, DataTableInstance, DataTableLeafColumn, DataTableLeafColumnBase, FilterableColumn, SelectFilterOption, SelectFilterValue } from '../index';
@@ -1,2 +1,2 @@
1
1
  export { default as Root } from './data-table-virtualized.svelte';
2
- export { ColumnFilter, ColumnVisibility, FlexRender, Refresh, Search, Title, Toolbar, createDataTableColumnHelper, createTable, renderComponent, renderSnippet } from '../index';
2
+ export { ColumnFilter, ColumnFilterEditing, ColumnFilterEditor, ColumnVisibility, EMPTY_SELECT_VALUE, FlexRender, Refresh, Search, Title, Toolbar, createDataTableColumnHelper, createTable, filterKindFor, getColumnFilterKind, getColumnLabel, renderComponent, renderSnippet, selectFilterOptions } from '../index';