@shotleybuilder/svelte-table-kit 0.4.0 → 0.5.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/README.md +94 -5
- package/dist/TableKit.svelte +60 -17
- package/dist/types.d.ts +1 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -66,6 +66,7 @@ Svelte Table Kit brings Airtable-like functionality to your Svelte applications
|
|
|
66
66
|
**AI-Ready:**
|
|
67
67
|
- 🤖 JSON-schema driven configuration
|
|
68
68
|
- 🧠 AI agents can generate table configs from natural language
|
|
69
|
+
- ⚡ **Reactive config prop** - Update table state dynamically without remounting (v0.5.0+)
|
|
69
70
|
- 📋 Preset configurations for common use cases
|
|
70
71
|
- 🔧 Programmatic table setup and state management
|
|
71
72
|
|
|
@@ -135,9 +136,18 @@ Customize initial table state programmatically:
|
|
|
135
136
|
{data}
|
|
136
137
|
{columns}
|
|
137
138
|
config={{
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
139
|
+
id: 'my-view-v1',
|
|
140
|
+
version: '1.0',
|
|
141
|
+
defaultColumnOrder: ['name', 'role', 'age', 'id'],
|
|
142
|
+
defaultColumnSizing: { name: 200, role: 150 },
|
|
143
|
+
defaultVisibleColumns: ['name', 'role', 'age'],
|
|
144
|
+
defaultFilters: [
|
|
145
|
+
{ id: 'f1', field: 'role', operator: 'equals', value: 'Developer' }
|
|
146
|
+
],
|
|
147
|
+
defaultSorting: [
|
|
148
|
+
{ columnId: 'name', direction: 'asc' }
|
|
149
|
+
],
|
|
150
|
+
filterLogic: 'and'
|
|
141
151
|
}}
|
|
142
152
|
features={{
|
|
143
153
|
columnVisibility: true,
|
|
@@ -148,6 +158,66 @@ Customize initial table state programmatically:
|
|
|
148
158
|
/>
|
|
149
159
|
```
|
|
150
160
|
|
|
161
|
+
### Reactive Configuration (v0.5.0+)
|
|
162
|
+
|
|
163
|
+
**The `config` prop is fully reactive** - update it dynamically to change table state without remounting:
|
|
164
|
+
|
|
165
|
+
```svelte
|
|
166
|
+
<script>
|
|
167
|
+
import { TableKit } from '@shotleybuilder/svelte-table-kit';
|
|
168
|
+
|
|
169
|
+
let tableConfig = $state({
|
|
170
|
+
id: 'query-1',
|
|
171
|
+
version: '1.0',
|
|
172
|
+
defaultFilters: [
|
|
173
|
+
{ id: 'f1', field: 'status', operator: 'equals', value: 'active' }
|
|
174
|
+
]
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
// Update config - table reacts automatically
|
|
178
|
+
function showPendingItems() {
|
|
179
|
+
tableConfig = {
|
|
180
|
+
id: 'query-2', // New ID triggers update
|
|
181
|
+
version: '1.0',
|
|
182
|
+
defaultFilters: [
|
|
183
|
+
{ id: 'f1', field: 'status', operator: 'equals', value: 'pending' }
|
|
184
|
+
]
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
</script>
|
|
188
|
+
|
|
189
|
+
<button on:click={showPendingItems}>Show Pending</button>
|
|
190
|
+
<TableKit {data} {columns} config={tableConfig} persistState={false} />
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
**Perfect for AI-driven tables:**
|
|
194
|
+
|
|
195
|
+
```svelte
|
|
196
|
+
<script>
|
|
197
|
+
let aiConfig = $state(undefined);
|
|
198
|
+
|
|
199
|
+
async function askAI(question) {
|
|
200
|
+
const response = await fetch('/api/nl-query', {
|
|
201
|
+
method: 'POST',
|
|
202
|
+
body: JSON.stringify({ question })
|
|
203
|
+
});
|
|
204
|
+
aiConfig = await response.json(); // Table updates automatically
|
|
205
|
+
}
|
|
206
|
+
</script>
|
|
207
|
+
|
|
208
|
+
<input
|
|
209
|
+
placeholder="Ask a question about the data..."
|
|
210
|
+
on:submit={(e) => askAI(e.target.value)}
|
|
211
|
+
/>
|
|
212
|
+
<TableKit {data} {columns} config={aiConfig} persistState={false} />
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
**Key Points:**
|
|
216
|
+
- Config changes detected by comparing `config.id`
|
|
217
|
+
- Set `persistState={false}` to prevent localStorage conflicts
|
|
218
|
+
- When config is active, localStorage is automatically ignored
|
|
219
|
+
- No `{#key}` blocks needed - updates are smooth and instant
|
|
220
|
+
|
|
151
221
|
### Feature Flags
|
|
152
222
|
|
|
153
223
|
Control which features are enabled:
|
|
@@ -225,10 +295,10 @@ TableKit is headless by default. You can:
|
|
|
225
295
|
|------|------|---------|-------------|
|
|
226
296
|
| `data` | `T[]` | `[]` | Table data array |
|
|
227
297
|
| `columns` | `ColumnDef<T>[]` | `[]` | Column definitions |
|
|
228
|
-
| `config` | `TableConfig` | `undefined` |
|
|
298
|
+
| `config` | `TableConfig` | `undefined` | Reactive table configuration (requires `id` and `version`) |
|
|
229
299
|
| `features` | `TableFeatures` | All enabled | Feature flags |
|
|
230
300
|
| `storageKey` | `string` | `undefined` | LocalStorage key for persistence |
|
|
231
|
-
| `persistState` | `boolean` | `true` | Enable state persistence |
|
|
301
|
+
| `persistState` | `boolean` | `true` | Enable state persistence (auto-disabled when config is active) |
|
|
232
302
|
| `theme` | `'light' \| 'dark' \| 'auto'` | `'light'` | Theme mode |
|
|
233
303
|
| `align` | `'left' \| 'center' \| 'right'` | `'left'` | Column text alignment |
|
|
234
304
|
| `rowHeight` | `'short' \| 'medium' \| 'tall' \| 'extra_tall'` | `'medium'` | Row height preset |
|
|
@@ -237,6 +307,25 @@ TableKit is headless by default. You can:
|
|
|
237
307
|
| `onRowSelect` | `(rows: T[]) => void` | `undefined` | Row selection handler |
|
|
238
308
|
| `onStateChange` | `(state: TableState) => void` | `undefined` | State change handler |
|
|
239
309
|
|
|
310
|
+
### TableConfig Type
|
|
311
|
+
|
|
312
|
+
```typescript
|
|
313
|
+
interface TableConfig {
|
|
314
|
+
id: string; // Required: Unique identifier for change detection
|
|
315
|
+
version: string; // Required: Config version
|
|
316
|
+
defaultColumnOrder?: string[]; // Column IDs in display order
|
|
317
|
+
defaultColumnSizing?: Record<string, number>; // Column widths in pixels
|
|
318
|
+
defaultVisibleColumns?: string[]; // Visible column IDs (others hidden)
|
|
319
|
+
defaultFilters?: FilterCondition[]; // Initial filter conditions
|
|
320
|
+
defaultSorting?: SortConfig[]; // Initial sort configuration
|
|
321
|
+
filterLogic?: 'and' | 'or'; // Filter combination logic
|
|
322
|
+
pagination?: {
|
|
323
|
+
pageSize: number;
|
|
324
|
+
pageSizeOptions?: number[];
|
|
325
|
+
};
|
|
326
|
+
}
|
|
327
|
+
```
|
|
328
|
+
|
|
240
329
|
---
|
|
241
330
|
|
|
242
331
|
## 🎯 Use Cases
|
package/dist/TableKit.svelte
CHANGED
|
@@ -47,32 +47,75 @@ export let onRowClick = void 0;
|
|
|
47
47
|
export let onRowSelect = void 0;
|
|
48
48
|
export let onStateChange = void 0;
|
|
49
49
|
let sorting = writable([]);
|
|
50
|
-
let columnVisibility = writable(
|
|
51
|
-
|
|
52
|
-
);
|
|
53
|
-
let
|
|
54
|
-
persistState && storageKey ? loadColumnSizing(storageKey) : {}
|
|
55
|
-
);
|
|
56
|
-
let columnFilters = writable(
|
|
57
|
-
persistState && storageKey ? loadColumnFilters(storageKey) : []
|
|
58
|
-
);
|
|
59
|
-
let columnOrder = writable(
|
|
60
|
-
persistState && storageKey ? loadColumnOrder(storageKey) : config?.defaultColumnOrder || []
|
|
61
|
-
);
|
|
50
|
+
let columnVisibility = writable({});
|
|
51
|
+
let columnSizing = writable({});
|
|
52
|
+
let columnFilters = writable([]);
|
|
53
|
+
let columnOrder = writable([]);
|
|
62
54
|
let filterConditions = writable([]);
|
|
63
55
|
let filterLogic = writable("and");
|
|
64
56
|
let filterBarExpanded = false;
|
|
57
|
+
let previousConfigId = config?.id;
|
|
58
|
+
let configInitialized = false;
|
|
65
59
|
let grouping = writable([]);
|
|
66
60
|
let expanded = writable(true);
|
|
67
61
|
let groupBarExpanded = false;
|
|
62
|
+
$: {
|
|
63
|
+
const configChanged = config?.id && config.id !== previousConfigId;
|
|
64
|
+
const hasConfig = config !== void 0 && config !== null;
|
|
65
|
+
if (hasConfig && config && (configChanged || !configInitialized)) {
|
|
66
|
+
if (config.defaultColumnOrder && config.defaultColumnOrder.length > 0) {
|
|
67
|
+
columnOrder.set(config.defaultColumnOrder);
|
|
68
|
+
}
|
|
69
|
+
if (config.defaultVisibleColumns && columns.length > 0) {
|
|
70
|
+
const visibilityMap = {};
|
|
71
|
+
columns.forEach((col) => {
|
|
72
|
+
const colId = col.accessorKey || col.id;
|
|
73
|
+
if (config && config.defaultVisibleColumns) {
|
|
74
|
+
visibilityMap[colId] = config.defaultVisibleColumns.includes(colId);
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
columnVisibility.set(visibilityMap);
|
|
78
|
+
}
|
|
79
|
+
if (config.defaultSorting) {
|
|
80
|
+
const tanstackSorting = config.defaultSorting.map((sort) => ({
|
|
81
|
+
id: sort.columnId,
|
|
82
|
+
desc: sort.direction === "desc"
|
|
83
|
+
}));
|
|
84
|
+
sorting.set(tanstackSorting);
|
|
85
|
+
}
|
|
86
|
+
if (config.defaultFilters) {
|
|
87
|
+
filterConditions.set(config.defaultFilters);
|
|
88
|
+
}
|
|
89
|
+
if (config.filterLogic) {
|
|
90
|
+
filterLogic.set(config.filterLogic);
|
|
91
|
+
}
|
|
92
|
+
if (config.defaultColumnSizing) {
|
|
93
|
+
columnSizing.set(config.defaultColumnSizing);
|
|
94
|
+
}
|
|
95
|
+
previousConfigId = config.id;
|
|
96
|
+
configInitialized = true;
|
|
97
|
+
} else if (!hasConfig && persistState && storageKey && !configInitialized) {
|
|
98
|
+
columnOrder.set(loadColumnOrder(storageKey) || []);
|
|
99
|
+
columnVisibility.set(loadColumnVisibility(storageKey) || {});
|
|
100
|
+
columnSizing.set(loadColumnSizing(storageKey) || {});
|
|
101
|
+
columnFilters.set(loadColumnFilters(storageKey) || []);
|
|
102
|
+
configInitialized = true;
|
|
103
|
+
} else if (!hasConfig && !configInitialized) {
|
|
104
|
+
configInitialized = true;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
68
107
|
$: horizontalPadding = columnSpacing === "narrow" ? 0.5 : columnSpacing === "wide" ? 2 : 1;
|
|
69
108
|
$: verticalPadding = rowHeight === "short" ? 0.375 : rowHeight === "tall" ? 1 : rowHeight === "extra_tall" ? 1.5 : 0.75;
|
|
70
109
|
$: filteredData = applyFilters(data, $filterConditions, $filterLogic);
|
|
71
|
-
$:
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
110
|
+
$: {
|
|
111
|
+
const hasActiveConfig = config !== void 0 && config !== null;
|
|
112
|
+
const shouldPersist = persistState && !hasActiveConfig && storageKey && isBrowser;
|
|
113
|
+
if (shouldPersist) {
|
|
114
|
+
saveColumnVisibility(storageKey, $columnVisibility);
|
|
115
|
+
saveColumnSizing(storageKey, $columnSizing);
|
|
116
|
+
saveColumnFilters(storageKey, $columnFilters);
|
|
117
|
+
saveColumnOrder(storageKey, $columnOrder);
|
|
118
|
+
}
|
|
76
119
|
}
|
|
77
120
|
let showColumnPicker = false;
|
|
78
121
|
let columnPickerButton = null;
|
package/dist/types.d.ts
CHANGED
package/package.json
CHANGED