compote-ui 0.33.1 → 0.35.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 (39) hide show
  1. package/dist/components/carousel/carousel-item-group.svelte +1 -1
  2. package/dist/components/data-table/column-helper.d.ts +12 -0
  3. package/dist/components/data-table/column-helper.js +36 -0
  4. package/dist/components/data-table/create-table.d.ts +38 -0
  5. package/dist/components/data-table/create-table.js +190 -0
  6. package/dist/components/data-table/data-table-column-filter.svelte +249 -0
  7. package/dist/components/data-table/data-table-column-filter.svelte.d.ts +29 -0
  8. package/dist/components/data-table/data-table-column-visibility.svelte +8 -13
  9. package/dist/components/data-table/data-table-column-visibility.svelte.d.ts +13 -13
  10. package/dist/components/data-table/data-table-title.svelte +2 -2
  11. package/dist/components/data-table/data-table-title.svelte.d.ts +2 -2
  12. package/dist/components/data-table/data-table-toolbar.svelte +28 -5
  13. package/dist/components/data-table/data-table-toolbar.svelte.d.ts +4 -2
  14. package/dist/components/data-table/data-table.svelte +293 -270
  15. package/dist/components/data-table/data-table.svelte.d.ts +19 -16
  16. package/dist/components/data-table/index.d.ts +5 -3
  17. package/dist/components/data-table/index.js +3 -3
  18. package/dist/components/data-table/types.d.ts +50 -0
  19. package/dist/components/data-table/types.js +1 -0
  20. package/dist/components/{data-table → data-table-old}/core/create-table.svelte.js +0 -8
  21. package/dist/components/data-table-old/data-table-column-visibility.svelte +79 -0
  22. package/dist/components/data-table-old/data-table-column-visibility.svelte.d.ts +29 -0
  23. package/dist/components/data-table-old/data-table-title.svelte +16 -0
  24. package/dist/components/data-table-old/data-table-title.svelte.d.ts +10 -0
  25. package/dist/components/data-table-old/data-table-toolbar.svelte +16 -0
  26. package/dist/components/data-table-old/data-table-toolbar.svelte.d.ts +10 -0
  27. package/dist/components/data-table-old/data-table.svelte +342 -0
  28. package/dist/components/data-table-old/data-table.svelte.d.ts +32 -0
  29. package/dist/components/data-table-old/index.d.ts +7 -0
  30. package/dist/components/data-table-old/index.js +7 -0
  31. package/dist/components/scroll-area/scroll-area-viewport.svelte +1 -1
  32. package/package.json +5 -5
  33. /package/dist/components/{data-table → data-table-old}/core/cells.d.ts +0 -0
  34. /package/dist/components/{data-table → data-table-old}/core/cells.js +0 -0
  35. /package/dist/components/{data-table → data-table-old}/core/create-table.svelte.d.ts +0 -0
  36. /package/dist/components/{data-table → data-table-old}/core/index.d.ts +0 -0
  37. /package/dist/components/{data-table → data-table-old}/core/index.js +0 -0
  38. /package/dist/components/{data-table → data-table-old}/data-table-filters.svelte +0 -0
  39. /package/dist/components/{data-table → data-table-old}/data-table-filters.svelte.d.ts +0 -0
@@ -13,7 +13,7 @@
13
13
 
14
14
  <Carousel.ItemGroup
15
15
  class={cn(
16
- 'flex min-w-0 flex-1 overflow-hidden rounded-lg [-ms-overflow-style:none] [scrollbar-width:none] [&::-webkit-scrollbar]:hidden',
16
+ 'flex min-w-0 flex-1 [scrollbar-width:none] overflow-hidden rounded-lg [-ms-overflow-style:none] [&::-webkit-scrollbar]:hidden',
17
17
  className
18
18
  )}
19
19
  {...rest}
@@ -0,0 +1,12 @@
1
+ import type { RowData } from '@tanstack/svelte-table';
2
+ import type { DataTableAccessorFnColumn, DataTableAccessorKeyColumn, DataTableColumn, DataTableGroupColumn } from './types';
3
+ type AccessorKeyColumnOptions<T extends RowData> = Omit<DataTableAccessorKeyColumn<T>, 'accessorKey' | 'accessorFn' | 'columns'>;
4
+ type AccessorFnColumnOptions<T extends RowData> = Omit<DataTableAccessorFnColumn<T>, 'accessorFn' | 'accessorKey' | 'columns'>;
5
+ type GroupColumnOptions<T extends RowData> = Omit<DataTableGroupColumn<T>, 'columns' | 'accessorKey' | 'accessorFn' | 'cell' | 'cellComponent' | 'cellProps' | 'cellSnippet' | 'type' | 'formatOptions' | 'formatLocale'>;
6
+ export declare function createDataTableColumnHelper<T extends RowData>(): {
7
+ accessor<K extends Extract<keyof T, string>>(accessorKey: K, options: AccessorKeyColumnOptions<T>): DataTableAccessorKeyColumn<T>;
8
+ accessorFn(accessorFn: (row: T) => unknown, options: AccessorFnColumnOptions<T>): DataTableAccessorFnColumn<T>;
9
+ group(header: string, columns: DataTableColumn<T>[], options?: Omit<GroupColumnOptions<T>, "header">): DataTableGroupColumn<T>;
10
+ columns(columns: DataTableColumn<T>[]): DataTableColumn<T>[];
11
+ };
12
+ export {};
@@ -0,0 +1,36 @@
1
+ function urlDefaults(options) {
2
+ if (options.type !== 'url')
3
+ return options;
4
+ return {
5
+ align: 'center',
6
+ enableSorting: false,
7
+ size: 60,
8
+ ...options
9
+ };
10
+ }
11
+ export function createDataTableColumnHelper() {
12
+ return {
13
+ accessor(accessorKey, options) {
14
+ return {
15
+ ...urlDefaults(options),
16
+ accessorKey
17
+ };
18
+ },
19
+ accessorFn(accessorFn, options) {
20
+ return {
21
+ ...urlDefaults(options),
22
+ accessorFn
23
+ };
24
+ },
25
+ group(header, columns, options = {}) {
26
+ return {
27
+ ...options,
28
+ header,
29
+ columns
30
+ };
31
+ },
32
+ columns(columns) {
33
+ return columns;
34
+ }
35
+ };
36
+ }
@@ -0,0 +1,38 @@
1
+ import { type ColumnFiltersState, type ColumnResizeMode, type Row, type RowData, type RowSelectionState, type SortingState, type SvelteTable, type TableState } from '@tanstack/svelte-table';
2
+ import type { DataTableColumn, DataTableLeafColumn } from './types';
3
+ declare const dataTableFeatures: {
4
+ columnVisibilityFeature: import("@tanstack/table-core").TableFeature<import("@tanstack/table-core").ColumnVisibilityFeatureConstructors<import("@tanstack/table-core").TableFeatures, RowData>>;
5
+ columnSizingFeature: import("@tanstack/table-core").TableFeature<import("@tanstack/table-core").ColumnSizingFeatureConstructors<import("@tanstack/table-core").TableFeatures, RowData>>;
6
+ columnResizingFeature: import("@tanstack/table-core").TableFeature<import("@tanstack/table-core").ColumnResizingFeatureConstructors<import("@tanstack/table-core").TableFeatures, RowData>>;
7
+ columnFilteringFeature: import("@tanstack/table-core").TableFeature<import("@tanstack/table-core").ColumnFilteringFeatureConstructors<import("@tanstack/table-core").TableFeatures, RowData>>;
8
+ columnFacetingFeature: import("@tanstack/table-core").TableFeature<import("@tanstack/table-core").ColumnFacetingFeatureConstructors<import("@tanstack/table-core").TableFeatures, RowData>>;
9
+ rowSelectionFeature: import("@tanstack/table-core").TableFeature<import("@tanstack/table-core").RowSelectionFeatureConstructors<import("@tanstack/table-core").TableFeatures, RowData>>;
10
+ rowSortingFeature: import("@tanstack/table-core").TableFeature<import("@tanstack/table-core").RowSortingFeatureConstructors<import("@tanstack/table-core").TableFeatures, RowData>>;
11
+ };
12
+ export type DataTableFeatures = typeof dataTableFeatures;
13
+ export type DataTableSelectedState = Pick<TableState<DataTableFeatures>, 'columnVisibility' | 'columnSizing' | 'columnResizing' | 'rowSelection' | 'sorting' | 'columnFilters'>;
14
+ export type DataTableInstance<T extends RowData> = SvelteTable<DataTableFeatures, T, DataTableSelectedState>;
15
+ export type CreateDataTableOptions<T extends RowData> = {
16
+ data: T[];
17
+ columns: DataTableColumn<T>[];
18
+ columnResizeMode?: ColumnResizeMode;
19
+ initialSorting?: SortingState;
20
+ initialRowSelection?: RowSelectionState;
21
+ initialColumnFilters?: ColumnFiltersState;
22
+ getRowId?: (row: T, index: number, parent?: Row<DataTableFeatures, T>) => string;
23
+ enableRowSelection?: boolean | ((row: Row<DataTableFeatures, T>) => boolean);
24
+ enableMultiRowSelection?: boolean | ((row: Row<DataTableFeatures, T>) => boolean);
25
+ enableSorting?: boolean;
26
+ debugTable?: boolean;
27
+ };
28
+ export declare function createTable<T extends RowData>(options: CreateDataTableOptions<T>): SvelteTable<{
29
+ columnVisibilityFeature: import("@tanstack/table-core").TableFeature<import("@tanstack/table-core").ColumnVisibilityFeatureConstructors<import("@tanstack/table-core").TableFeatures, RowData>>;
30
+ columnSizingFeature: import("@tanstack/table-core").TableFeature<import("@tanstack/table-core").ColumnSizingFeatureConstructors<import("@tanstack/table-core").TableFeatures, RowData>>;
31
+ columnResizingFeature: import("@tanstack/table-core").TableFeature<import("@tanstack/table-core").ColumnResizingFeatureConstructors<import("@tanstack/table-core").TableFeatures, RowData>>;
32
+ columnFilteringFeature: import("@tanstack/table-core").TableFeature<import("@tanstack/table-core").ColumnFilteringFeatureConstructors<import("@tanstack/table-core").TableFeatures, RowData>>;
33
+ columnFacetingFeature: import("@tanstack/table-core").TableFeature<import("@tanstack/table-core").ColumnFacetingFeatureConstructors<import("@tanstack/table-core").TableFeatures, RowData>>;
34
+ rowSelectionFeature: import("@tanstack/table-core").TableFeature<import("@tanstack/table-core").RowSelectionFeatureConstructors<import("@tanstack/table-core").TableFeatures, RowData>>;
35
+ rowSortingFeature: import("@tanstack/table-core").TableFeature<import("@tanstack/table-core").RowSortingFeatureConstructors<import("@tanstack/table-core").TableFeatures, RowData>>;
36
+ }, T, DataTableSelectedState>;
37
+ export declare function getColumnId<T extends RowData>(column: DataTableLeafColumn<T>): string;
38
+ export {};
@@ -0,0 +1,190 @@
1
+ import { columnVisibilityFeature, columnResizingFeature, columnSizingFeature, columnFilteringFeature, columnFacetingFeature, createSortedRowModel, createFilteredRowModel, createFacetedRowModel, createFacetedMinMaxValues, createFacetedUniqueValues, createTable as createTanStackTable, filterFns, renderComponent, renderSnippet, rowSelectionFeature, rowSortingFeature, sortFns, tableFeatures } from '@tanstack/svelte-table';
2
+ import { useLocaleContext } from '@ark-ui/svelte/locale';
3
+ const dataTableFeatures = tableFeatures({
4
+ columnVisibilityFeature,
5
+ columnSizingFeature,
6
+ columnResizingFeature,
7
+ columnFilteringFeature,
8
+ columnFacetingFeature,
9
+ rowSelectionFeature,
10
+ rowSortingFeature
11
+ });
12
+ function oneOfFilterFn(row, columnId, filterValue) {
13
+ return filterValue.includes(String(row.getValue(columnId)));
14
+ }
15
+ oneOfFilterFn.autoRemove = (val) => !Array.isArray(val) || val.length === 0;
16
+ export function createTable(options) {
17
+ const localeCtx = useLocaleContext();
18
+ return createTanStackTable({
19
+ _features: dataTableFeatures,
20
+ _rowModels: {
21
+ sortedRowModel: createSortedRowModel(sortFns),
22
+ filteredRowModel: createFilteredRowModel({ ...filterFns, oneOf: oneOfFilterFn }),
23
+ facetedRowModel: createFacetedRowModel(),
24
+ facetedMinMaxValues: createFacetedMinMaxValues(),
25
+ facetedUniqueValues: createFacetedUniqueValues()
26
+ },
27
+ columnResizeMode: options.columnResizeMode,
28
+ getRowId: options.getRowId,
29
+ enableRowSelection: options.enableRowSelection ?? false,
30
+ enableMultiRowSelection: options.enableMultiRowSelection,
31
+ enableSorting: options.enableSorting,
32
+ debugTable: options.debugTable,
33
+ get data() {
34
+ return options.data;
35
+ },
36
+ get columns() {
37
+ return createColumns(options.columns, localeCtx);
38
+ },
39
+ initialState: {
40
+ columnVisibility: createColumnVisibility(options.columns),
41
+ columnSizing: createColumnSizing(options.columns),
42
+ rowSelection: options.initialRowSelection ?? {},
43
+ sorting: options.initialSorting ?? [],
44
+ columnFilters: options.initialColumnFilters ?? []
45
+ }
46
+ }, (state) => ({
47
+ columnVisibility: state.columnVisibility,
48
+ columnSizing: state.columnSizing,
49
+ columnResizing: state.columnResizing,
50
+ rowSelection: state.rowSelection,
51
+ sorting: state.sorting,
52
+ columnFilters: state.columnFilters
53
+ }));
54
+ }
55
+ function createColumnVisibility(columns) {
56
+ return getLeafColumns(columns).reduce((visibility, column) => {
57
+ visibility[getColumnId(column)] = true;
58
+ return visibility;
59
+ }, {});
60
+ }
61
+ function createColumnSizing(columns) {
62
+ return getLeafColumns(columns).reduce((sizes, column) => {
63
+ if (typeof column.size === 'number') {
64
+ sizes[getColumnId(column)] = column.size;
65
+ }
66
+ return sizes;
67
+ }, {});
68
+ }
69
+ function createColumns(columns, localeCtx) {
70
+ return columns.map((column) => {
71
+ if (isGroupColumn(column)) {
72
+ return {
73
+ id: getGroupColumnId(column),
74
+ header: column.header,
75
+ columns: createColumns(column.columns, localeCtx),
76
+ meta: {
77
+ align: column.align
78
+ }
79
+ };
80
+ }
81
+ const columnId = getColumnId(column);
82
+ const derivedFilterFn = column.filterFn ?? getFilterFnForType(column.type);
83
+ const columnDef = {
84
+ id: columnId,
85
+ header: column.header,
86
+ size: column.size,
87
+ minSize: column.minSize,
88
+ maxSize: column.maxSize,
89
+ enableResizing: column.enableResizing,
90
+ enableHiding: getColumnEnableHiding(column, columnId),
91
+ enableSorting: column.enableSorting,
92
+ enableColumnFilter: column.enableColumnFilter,
93
+ sortDescFirst: column.sortDescFirst,
94
+ ...(derivedFilterFn !== undefined ? { filterFn: derivedFilterFn } : {}),
95
+ meta: {
96
+ align: column.align,
97
+ type: column.type,
98
+ formatOptions: column.formatOptions,
99
+ formatLocale: column.formatLocale
100
+ }
101
+ };
102
+ if (typeof column.accessorFn === 'function') {
103
+ return {
104
+ ...columnDef,
105
+ accessorFn: column.accessorFn,
106
+ cell: (context) => formatCellValue(column, context.getValue(), context.row.original, localeCtx)
107
+ };
108
+ }
109
+ return {
110
+ ...columnDef,
111
+ accessorKey: column.accessorKey,
112
+ cell: (context) => formatCellValue(column, context.getValue(), context.row.original, localeCtx)
113
+ };
114
+ });
115
+ }
116
+ function isGroupColumn(column) {
117
+ return Array.isArray(column.columns);
118
+ }
119
+ function getLeafColumns(columns) {
120
+ return columns.flatMap((column) => isGroupColumn(column) ? getLeafColumns(column.columns) : column);
121
+ }
122
+ function getGroupColumnId(column) {
123
+ return column.id ?? column.header;
124
+ }
125
+ function getColumnEnableHiding(column, columnId) {
126
+ if (column.enableHiding !== undefined)
127
+ return column.enableHiding;
128
+ if (columnId === 'id')
129
+ return false;
130
+ return undefined;
131
+ }
132
+ export function getColumnId(column) {
133
+ if (column.id !== undefined)
134
+ return column.id;
135
+ if ('accessorKey' in column && column.accessorKey !== undefined)
136
+ return column.accessorKey;
137
+ throw new Error('DataTableColumn with accessorFn requires an id.');
138
+ }
139
+ const TYPE_FORMAT_DEFAULTS = {
140
+ currency: { style: 'currency', currency: 'USD' },
141
+ percent: { style: 'percent' },
142
+ number: {}
143
+ };
144
+ function getFilterFnForType(type) {
145
+ switch (type) {
146
+ case 'number':
147
+ case 'currency':
148
+ case 'percent':
149
+ return 'inNumberRange';
150
+ case 'boolean':
151
+ return 'equals';
152
+ case 'select':
153
+ return 'oneOf';
154
+ default:
155
+ return undefined;
156
+ }
157
+ }
158
+ function applyTypeFormat(column, value, localeCtx) {
159
+ if (value === null || value === undefined || value === '')
160
+ return undefined;
161
+ const defaults = column.type ? TYPE_FORMAT_DEFAULTS[column.type] : undefined;
162
+ if (defaults !== undefined) {
163
+ const locale = column.formatLocale ?? localeCtx().locale;
164
+ return new Intl.NumberFormat(locale, {
165
+ ...defaults,
166
+ ...column.formatOptions
167
+ }).format(Number(value));
168
+ }
169
+ if (column.type === 'boolean')
170
+ return value ? 'Yes' : 'No';
171
+ return value;
172
+ }
173
+ function formatCellValue(column, value, row, localeCtx) {
174
+ if (column.cellComponent) {
175
+ return renderComponent(column.cellComponent, getCellComponentProps(column, value, row));
176
+ }
177
+ if (column.cellSnippet) {
178
+ return renderSnippet(column.cellSnippet, { value, row });
179
+ }
180
+ const rendered = column.cell
181
+ ? column.cell(value, row)
182
+ : applyTypeFormat(column, value, localeCtx);
183
+ if (rendered === null || rendered === undefined || rendered === '') {
184
+ return '-';
185
+ }
186
+ return String(rendered);
187
+ }
188
+ function getCellComponentProps(column, value, row) {
189
+ return column.cellProps ? column.cellProps(value, row) : { value, row };
190
+ }
@@ -0,0 +1,249 @@
1
+ <script lang="ts" generics="T extends RowData">
2
+ import { onDestroy } from 'svelte';
3
+ import type { CellData, Column, RowData } from '@tanstack/svelte-table';
4
+ import * as Popover from '../popover';
5
+ import * as ScrollArea from '../scroll-area';
6
+ import Checkbox from '../checkbox/checkbox.svelte';
7
+ import { cn } from 'tailwind-variants';
8
+ import type { DataTableFeatures, DataTableInstance } from './create-table';
9
+ import NumberInput from '../number-input/number-input.svelte';
10
+ import * as Field from '../field';
11
+
12
+ type Props = {
13
+ table: DataTableInstance<T>;
14
+ triggerLabel?: string;
15
+ };
16
+
17
+ let { table, triggerLabel = 'Filters' }: Props = $props();
18
+
19
+ let localText: Record<string, string> = $state({});
20
+ let localNumMin: Record<string, number> = $state({});
21
+ let localNumMax: Record<string, number> = $state({});
22
+ const timers: Record<string, ReturnType<typeof setTimeout>> = {};
23
+
24
+ const columnFilters = $derived(table.store.state.columnFilters);
25
+ const activeCount = $derived(columnFilters.length);
26
+ const filterableColumns = $derived(table.getAllLeafColumns().filter((col) => col.getCanFilter()));
27
+
28
+ onDestroy(() => {
29
+ Object.values(timers).forEach(clearTimeout);
30
+ });
31
+
32
+ function getColumnType(column: Column<DataTableFeatures, T, CellData>): string | undefined {
33
+ return (column.columnDef.meta as Record<string, unknown> | undefined)?.type as
34
+ | string
35
+ | undefined;
36
+ }
37
+
38
+ function getColumnLabel(column: Column<DataTableFeatures, T, CellData>): string {
39
+ return typeof column.columnDef.header === 'string' ? column.columnDef.header : column.id;
40
+ }
41
+
42
+ function clearFilters() {
43
+ Object.values(timers).forEach(clearTimeout);
44
+ for (const key of Object.keys(timers)) delete timers[key];
45
+ localText = {};
46
+ localNumMin = {};
47
+ localNumMax = {};
48
+ table.resetColumnFilters();
49
+ }
50
+
51
+ function handleTextInput(column: Column<DataTableFeatures, T, CellData>, value: string) {
52
+ localText[column.id] = value;
53
+ clearTimeout(timers[column.id]);
54
+ timers[column.id] = setTimeout(() => {
55
+ column.setFilterValue(value || undefined);
56
+ }, 300);
57
+ }
58
+
59
+ function handleNumericInput(
60
+ column: Column<DataTableFeatures, T, CellData>,
61
+ which: 'min' | 'max',
62
+ value: number | null
63
+ ) {
64
+ if (value === null) {
65
+ if (which === 'min') delete localNumMin[column.id];
66
+ else delete localNumMax[column.id];
67
+ } else {
68
+ if (which === 'min') localNumMin[column.id] = value;
69
+ else localNumMax[column.id] = value;
70
+ }
71
+ clearTimeout(timers[`${column.id}_${which}`]);
72
+ timers[`${column.id}_${which}`] = setTimeout(() => {
73
+ const min = localNumMin[column.id];
74
+ const max = localNumMax[column.id];
75
+ column.setFilterValue(min === undefined && max === undefined ? undefined : [min, max]);
76
+ }, 300);
77
+ }
78
+
79
+ function getSelectValues(column: Column<DataTableFeatures, T, CellData>): string[] {
80
+ return (column.getFilterValue() as string[] | undefined) ?? [];
81
+ }
82
+
83
+ function handleSelectChange(
84
+ column: Column<DataTableFeatures, T, CellData>,
85
+ value: string,
86
+ checked: boolean
87
+ ) {
88
+ const current = getSelectValues(column);
89
+ const next = checked ? [...current, value] : current.filter((v) => v !== value);
90
+ column.setFilterValue(next.length ? next : undefined);
91
+ }
92
+
93
+ function getFacetedValues(column: Column<DataTableFeatures, T, CellData>): string[] {
94
+ return Array.from(column.getFacetedUniqueValues().keys()).map(String).sort();
95
+ }
96
+
97
+ function getFacetedMinMax(
98
+ column: Column<DataTableFeatures, T, CellData>
99
+ ): [number | undefined, number | undefined] {
100
+ const vals = column.getFacetedMinMaxValues();
101
+ return vals ? [vals[0] as number, vals[1] as number] : [undefined, undefined];
102
+ }
103
+
104
+ function getColumnFormatOptions(
105
+ column: Column<DataTableFeatures, T, CellData>
106
+ ): Intl.NumberFormatOptions | undefined {
107
+ return (column.columnDef.meta as Record<string, unknown> | undefined)?.formatOptions as
108
+ | Intl.NumberFormatOptions
109
+ | undefined;
110
+ }
111
+ </script>
112
+
113
+ <Popover.Root positioning={{ placement: 'bottom-end' }}>
114
+ <Popover.Trigger
115
+ class="flex h-9 cursor-pointer items-center rounded-md border border-surface-3 bg-surface-1 px-3 text-sm font-medium text-ink shadow-sm outline-none hover:bg-surface-2 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ring"
116
+ >
117
+ {triggerLabel}{#if activeCount > 0}
118
+ ({activeCount}){/if}
119
+ </Popover.Trigger>
120
+
121
+ <Popover.Content class="w-72 px-0" showArrow={false}>
122
+ <div class="mb-2 flex items-center justify-between px-4">
123
+ <span class="text-sm font-medium text-ink">Filters</span>
124
+ {#if activeCount > 0}
125
+ <button type="button" onclick={clearFilters} class="text-xs text-primary hover:underline">
126
+ Clear all
127
+ </button>
128
+ {/if}
129
+ </div>
130
+ <div class="mb-2 border-b border-surface-3"></div>
131
+
132
+ <ScrollArea.Root class="h-80">
133
+ <ScrollArea.Viewport>
134
+ <ScrollArea.Content>
135
+ {#each filterableColumns as column (column.id)}
136
+ <div class="mb-3">
137
+ <p class="mb-1 text-xs font-medium text-ink">{getColumnLabel(column)}</p>
138
+
139
+ {#if getColumnType(column) === 'number' || getColumnType(column) === 'currency' || getColumnType(column) === 'percent'}
140
+ {@const [facetMin, facetMax] = getFacetedMinMax(column)}
141
+ {@const colFormatOptions = getColumnFormatOptions(column)}
142
+ <div class="flex gap-1.5">
143
+ <div class="min-w-0 flex-1">
144
+ <p class="mb-1 text-xs text-ink-dim">From</p>
145
+ <NumberInput
146
+ value={localNumMin[column.id] ?? facetMin ?? null}
147
+ min={facetMin}
148
+ max={facetMax}
149
+ formatOptions={colFormatOptions}
150
+ onValueChange={({ valueAsNumber }) =>
151
+ handleNumericInput(
152
+ column,
153
+ 'min',
154
+ isNaN(valueAsNumber) ? null : valueAsNumber
155
+ )}
156
+ />
157
+ </div>
158
+ <div class="min-w-0 flex-1">
159
+ <p class="mb-1 text-xs text-ink-dim">To</p>
160
+ <NumberInput
161
+ value={localNumMax[column.id] ?? facetMax ?? null}
162
+ min={facetMin}
163
+ max={facetMax}
164
+ formatOptions={colFormatOptions}
165
+ onValueChange={({ valueAsNumber }) =>
166
+ handleNumericInput(
167
+ column,
168
+ 'max',
169
+ isNaN(valueAsNumber) ? null : valueAsNumber
170
+ )}
171
+ />
172
+ </div>
173
+ </div>
174
+ {:else if getColumnType(column) === 'boolean'}
175
+ {@const boolFilter = column.getFilterValue() as boolean | undefined}
176
+ <div class="flex overflow-hidden rounded border border-border text-xs">
177
+ <button
178
+ type="button"
179
+ onclick={() => column.setFilterValue(undefined)}
180
+ class={cn(
181
+ 'flex-1 px-2 py-1',
182
+ boolFilter === undefined
183
+ ? 'bg-surface-3 font-medium text-ink'
184
+ : 'text-ink-dim hover:bg-surface-2'
185
+ )}
186
+ >
187
+ All
188
+ </button>
189
+ <button
190
+ type="button"
191
+ onclick={() => column.setFilterValue(boolFilter === true ? undefined : true)}
192
+ class={cn(
193
+ 'flex-1 border-x border-border px-2 py-1',
194
+ boolFilter === true
195
+ ? 'bg-surface-3 font-medium text-ink'
196
+ : 'text-ink-dim hover:bg-surface-2'
197
+ )}
198
+ >
199
+ Yes
200
+ </button>
201
+ <button
202
+ type="button"
203
+ onclick={() => column.setFilterValue(boolFilter === false ? undefined : false)}
204
+ class={cn(
205
+ 'flex-1 px-2 py-1',
206
+ boolFilter === false
207
+ ? 'bg-surface-3 font-medium text-ink'
208
+ : 'text-ink-dim hover:bg-surface-2'
209
+ )}
210
+ >
211
+ No
212
+ </button>
213
+ </div>
214
+ {:else if getColumnType(column) === 'select'}
215
+ {@const options = getFacetedValues(column)}
216
+ {@const selected = getSelectValues(column)}
217
+ <div class="flex flex-col gap-0.5">
218
+ {#each options as option (option)}
219
+ <Checkbox
220
+ size="sm"
221
+ label={option}
222
+ class="min-h-7 rounded-sm px-2 hover:bg-surface-2"
223
+ checked={selected.includes(option)}
224
+ onCheckedChange={({ checked }) =>
225
+ handleSelectChange(column, option, checked === true)}
226
+ />
227
+ {/each}
228
+ </div>
229
+ {:else}
230
+ <Field.Root>
231
+ <Field.Input
232
+ placeholder="Search..."
233
+ value={localText[column.id] ?? ''}
234
+ oninput={(e: Event) =>
235
+ handleTextInput(column, (e.currentTarget as HTMLInputElement).value)}
236
+ />
237
+ </Field.Root>
238
+ {/if}
239
+ </div>
240
+ {/each}
241
+ </ScrollArea.Content>
242
+ </ScrollArea.Viewport>
243
+ <ScrollArea.Scrollbar orientation="vertical">
244
+ <ScrollArea.Thumb />
245
+ </ScrollArea.Scrollbar>
246
+ <ScrollArea.Corner />
247
+ </ScrollArea.Root>
248
+ </Popover.Content>
249
+ </Popover.Root>
@@ -0,0 +1,29 @@
1
+ import type { RowData } from '@tanstack/svelte-table';
2
+ import type { DataTableInstance } from './create-table';
3
+ declare function $$render<T extends RowData>(): {
4
+ props: {
5
+ table: DataTableInstance<T>;
6
+ triggerLabel?: string;
7
+ };
8
+ exports: {};
9
+ bindings: "";
10
+ slots: {};
11
+ events: {};
12
+ };
13
+ declare class __sveltets_Render<T extends RowData> {
14
+ props(): ReturnType<typeof $$render<T>>['props'];
15
+ events(): ReturnType<typeof $$render<T>>['events'];
16
+ slots(): ReturnType<typeof $$render<T>>['slots'];
17
+ bindings(): "";
18
+ exports(): {};
19
+ }
20
+ interface $$IsomorphicComponent {
21
+ new <T extends RowData>(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']>> & {
22
+ $$bindings?: ReturnType<__sveltets_Render<T>['bindings']>;
23
+ } & ReturnType<__sveltets_Render<T>['exports']>;
24
+ <T extends RowData>(internal: unknown, props: ReturnType<__sveltets_Render<T>['props']> & {}): ReturnType<__sveltets_Render<T>['exports']>;
25
+ z_$$bindings?: ReturnType<__sveltets_Render<any>['bindings']>;
26
+ }
27
+ declare const DataTableColumnFilter: $$IsomorphicComponent;
28
+ type DataTableColumnFilter<T extends RowData> = InstanceType<typeof DataTableColumnFilter<T>>;
29
+ export default DataTableColumnFilter;
@@ -1,20 +1,18 @@
1
- <script lang="ts" generics="TData extends RowData, TSelected = object">
1
+ <script lang="ts" generics="T extends RowData">
2
+ import type { CellData, Column, RowData } from '@tanstack/svelte-table';
2
3
  import * as Popover from '../popover';
3
4
  import * as ScrollArea from '../scroll-area';
4
5
  import Checkbox from '../checkbox/checkbox.svelte';
5
- import type { Column, RowData } from '@tanstack/svelte-table';
6
- import type { DataTable, DataTableFeatures, DataTableSelectedState } from './core';
6
+ import type { DataTableFeatures, DataTableInstance } from './create-table';
7
7
 
8
8
  type Props = {
9
- table: DataTable<TData, TSelected>;
9
+ table: DataTableInstance<T>;
10
10
  triggerLabel?: string;
11
11
  };
12
12
 
13
13
  let { table, triggerLabel = 'Columns' }: Props = $props();
14
14
 
15
- const columnVisibility = $derived(
16
- (table.state as unknown as DataTableSelectedState).columnVisibility
17
- );
15
+ const columnVisibility = $derived(table.store.state.columnVisibility);
18
16
  const allColumnsVisible = $derived(table.getIsAllColumnsVisible());
19
17
  const someColumnsVisible = $derived(
20
18
  table.getAllLeafColumns().some((column) => column.getCanHide() && column.getIsVisible())
@@ -23,15 +21,12 @@
23
21
  allColumnsVisible ? true : someColumnsVisible ? 'indeterminate' : false
24
22
  );
25
23
 
26
- function getColumnLabel(column: Column<DataTableFeatures, TData, unknown>) {
24
+ function getColumnLabel(column: Column<DataTableFeatures, T, CellData>) {
27
25
  return typeof column.columnDef.header === 'string' ? column.columnDef.header : column.id;
28
26
  }
29
27
 
30
- function getColumnIsVisible(
31
- column: Column<DataTableFeatures, TData, unknown>,
32
- visibilityState: unknown
33
- ) {
34
- void visibilityState;
28
+ function getColumnIsVisible(column: Column<DataTableFeatures, T, CellData>, state: unknown) {
29
+ void state;
35
30
  return column.getIsVisible();
36
31
  }
37
32
  </script>
@@ -1,8 +1,8 @@
1
1
  import type { RowData } from '@tanstack/svelte-table';
2
- import type { DataTable } from './core';
3
- declare function $$render<TData extends RowData, TSelected = object>(): {
2
+ import type { DataTableInstance } from './create-table';
3
+ declare function $$render<T extends RowData>(): {
4
4
  props: {
5
- table: DataTable<TData, TSelected>;
5
+ table: DataTableInstance<T>;
6
6
  triggerLabel?: string;
7
7
  };
8
8
  exports: {};
@@ -10,20 +10,20 @@ declare function $$render<TData extends RowData, TSelected = object>(): {
10
10
  slots: {};
11
11
  events: {};
12
12
  };
13
- declare class __sveltets_Render<TData extends RowData, TSelected = object> {
14
- props(): ReturnType<typeof $$render<TData, TSelected>>['props'];
15
- events(): ReturnType<typeof $$render<TData, TSelected>>['events'];
16
- slots(): ReturnType<typeof $$render<TData, TSelected>>['slots'];
13
+ declare class __sveltets_Render<T extends RowData> {
14
+ props(): ReturnType<typeof $$render<T>>['props'];
15
+ events(): ReturnType<typeof $$render<T>>['events'];
16
+ slots(): ReturnType<typeof $$render<T>>['slots'];
17
17
  bindings(): "";
18
18
  exports(): {};
19
19
  }
20
20
  interface $$IsomorphicComponent {
21
- new <TData extends RowData, TSelected = object>(options: import('svelte').ComponentConstructorOptions<ReturnType<__sveltets_Render<TData, TSelected>['props']>>): import('svelte').SvelteComponent<ReturnType<__sveltets_Render<TData, TSelected>['props']>, ReturnType<__sveltets_Render<TData, TSelected>['events']>, ReturnType<__sveltets_Render<TData, TSelected>['slots']>> & {
22
- $$bindings?: ReturnType<__sveltets_Render<TData, TSelected>['bindings']>;
23
- } & ReturnType<__sveltets_Render<TData, TSelected>['exports']>;
24
- <TData extends RowData, TSelected = object>(internal: unknown, props: ReturnType<__sveltets_Render<TData, TSelected>['props']> & {}): ReturnType<__sveltets_Render<TData, TSelected>['exports']>;
25
- z_$$bindings?: ReturnType<__sveltets_Render<any, any>['bindings']>;
21
+ new <T extends RowData>(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']>> & {
22
+ $$bindings?: ReturnType<__sveltets_Render<T>['bindings']>;
23
+ } & ReturnType<__sveltets_Render<T>['exports']>;
24
+ <T extends RowData>(internal: unknown, props: ReturnType<__sveltets_Render<T>['props']> & {}): ReturnType<__sveltets_Render<T>['exports']>;
25
+ z_$$bindings?: ReturnType<__sveltets_Render<any>['bindings']>;
26
26
  }
27
27
  declare const DataTableColumnVisibility: $$IsomorphicComponent;
28
- type DataTableColumnVisibility<TData extends RowData, TSelected = object> = InstanceType<typeof DataTableColumnVisibility<TData, TSelected>>;
28
+ type DataTableColumnVisibility<T extends RowData> = InstanceType<typeof DataTableColumnVisibility<T>>;
29
29
  export default DataTableColumnVisibility;
@@ -1,7 +1,7 @@
1
1
  <script lang="ts">
2
- import { cn, type ClassValue } from 'tailwind-variants';
3
- import type { HTMLAttributes } from 'svelte/elements';
4
2
  import type { Snippet } from 'svelte';
3
+ import type { HTMLAttributes } from 'svelte/elements';
4
+ import { cn, type ClassValue } from 'tailwind-variants';
5
5
 
6
6
  type Props = Omit<HTMLAttributes<HTMLHeadingElement>, 'class'> & {
7
7
  class?: ClassValue;