@beeblock/svelar-datatable 0.1.7 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +347 -154
- package/dist/SvelarDatatablePlugin.d.ts +57 -2
- package/dist/index.js +7 -7
- package/dist/plugin.js +1 -1
- package/dist/server/DataTableService.d.ts +21 -0
- package/dist/server/index.js +1 -1
- package/dist/state/ServerDataTableStore.d.ts +2 -0
- package/dist/types.d.ts +2 -0
- package/package.json +82 -76
- package/src/state/ServerDataTableStore.ts +14 -0
- package/src/types.ts +2 -0
- package/src/ui/DataTable.svelte +8 -4
- package/src/ui/DataTableBody.svelte +3 -1
- package/src/ui/DataTableBubbleEditor.svelte +4 -1
- package/src/ui/DataTableButtons.svelte +12 -6
- package/src/ui/DataTableCell.svelte +3 -1
- package/src/ui/DataTableColumnToggle.svelte +2 -1
- package/src/ui/DataTableEditor.svelte +3 -1
- package/src/ui/DataTableEditorField.svelte +3 -1
- package/src/ui/DataTableEditorForm.svelte +1 -1
- package/src/ui/DataTableFooter.svelte +3 -1
- package/src/ui/DataTableHead.svelte +3 -1
- package/src/ui/DataTableModalEditor.svelte +4 -1
- package/src/ui/DataTablePagination.svelte +3 -1
- package/src/ui/DataTableRow.svelte +22 -3
- package/src/ui/DataTableSearch.svelte +3 -1
- package/src/ui/DataTableToolbar.svelte +3 -1
package/README.md
CHANGED
|
@@ -1,154 +1,347 @@
|
|
|
1
|
-
# @beeblock/svelar-datatable
|
|
2
|
-
|
|
3
|
-
Full-featured DataTable plugin for [Svelar](https://svelar.dev) / SvelteKit 2 with Svelte 5.
|
|
4
|
-
|
|
5
|
-
## Features
|
|
6
|
-
|
|
7
|
-
- **Sorting** — single-click or multi-sort (Shift+click)
|
|
8
|
-
- **Searching** — global search with debounce
|
|
9
|
-
- **Pagination** — configurable per-page options, page navigation
|
|
10
|
-
- **Selection** — single, multi, range (Shift+click), select all
|
|
11
|
-
- **Column management** — visibility toggle, reorder, resize
|
|
12
|
-
- **Editing** — four modes: modal, bubble (popover), inline (double-click), excel (spreadsheet)
|
|
13
|
-
- **Export** — CSV, clipboard, print (Excel/PDF with optional deps)
|
|
14
|
-
- **Virtual scroll** — render 10,000+ rows with only visible DOM nodes
|
|
15
|
-
- **Row grouping** — group rows by any column value
|
|
16
|
-
- **Per-column filters** — programmatic column-level filtering
|
|
17
|
-
- **Custom cells** — Svelte 5 snippets for full cell rendering control
|
|
18
|
-
- **Row customization** — `rowClass`, `rowId` function, expandable detail rows
|
|
19
|
-
- **Server-side** — jQuery DataTables wire protocol compatible, GET or POST
|
|
20
|
-
- **State persistence** — save sort/filter/page/column state to localStorage
|
|
21
|
-
- **Tailwind CSS** — `classNames` prop for pure Tailwind customization of every element
|
|
22
|
-
- **CSS variables** — 12+ CSS custom properties for quick theming
|
|
23
|
-
- **Footer aggregation** — per-column footer with custom functions
|
|
24
|
-
- **Responsive** — horizontal scroll for small screens
|
|
25
|
-
|
|
26
|
-
## Installation
|
|
27
|
-
|
|
28
|
-
```bash
|
|
29
|
-
# Install and publish route stubs
|
|
30
|
-
npx svelar plugin:install @beeblock/svelar-datatable
|
|
31
|
-
|
|
32
|
-
# Or manual install
|
|
33
|
-
npm install @beeblock/svelar-datatable
|
|
34
|
-
npx svelar plugin:publish @beeblock/svelar-datatable
|
|
35
|
-
```
|
|
36
|
-
|
|
37
|
-
Peer dependencies: `@beeblock/svelar >= 0.
|
|
38
|
-
|
|
39
|
-
## Quick Start
|
|
40
|
-
|
|
41
|
-
```svelte
|
|
42
|
-
<script lang="ts">
|
|
43
|
-
import { DataTable } from '@beeblock/svelar-datatable/ui';
|
|
44
|
-
import type { ColumnDef } from '@beeblock/svelar-datatable';
|
|
45
|
-
|
|
46
|
-
const columns: ColumnDef[] = [
|
|
47
|
-
{ key: 'id', header: 'ID', type: 'number', sortable: true },
|
|
48
|
-
{ key: 'name', header: 'Name', sortable: true, searchable: true },
|
|
49
|
-
{ key: 'email', header: 'Email', sortable: true, searchable: true },
|
|
50
|
-
];
|
|
51
|
-
|
|
52
|
-
const data = [
|
|
53
|
-
{ id: 1, name: 'Alice', email: 'alice@example.com' },
|
|
54
|
-
{ id: 2, name: 'Bob', email: 'bob@example.com' },
|
|
55
|
-
];
|
|
56
|
-
</script>
|
|
57
|
-
|
|
58
|
-
<DataTable {data} {columns} sortable searchable paginate perPage={10} />
|
|
59
|
-
```
|
|
60
|
-
|
|
61
|
-
## Server-Side
|
|
62
|
-
|
|
63
|
-
```svelte
|
|
64
|
-
<!-- Frontend -->
|
|
65
|
-
<DataTable
|
|
66
|
-
serverUrl="/api/datatable/users"
|
|
67
|
-
columns={columns}
|
|
68
|
-
sortable
|
|
69
|
-
searchable
|
|
70
|
-
paginate
|
|
71
|
-
perPage={25}
|
|
72
|
-
/>
|
|
73
|
-
```
|
|
74
|
-
|
|
75
|
-
```ts
|
|
76
|
-
// src/routes/api/datatable/users/+server.ts
|
|
77
|
-
import { DataTableController } from '@beeblock/svelar-datatable/server';
|
|
78
|
-
import { User } from '$lib/models/User';
|
|
79
|
-
|
|
80
|
-
const dt = new DataTableController(User);
|
|
81
|
-
export const GET = dt.handle();
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
1
|
+
# @beeblock/svelar-datatable
|
|
2
|
+
|
|
3
|
+
Full-featured DataTable plugin for [Svelar](https://svelar.dev) / SvelteKit 2 with Svelte 5.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **Sorting** — single-click or multi-sort (Shift+click)
|
|
8
|
+
- **Searching** — global search with debounce
|
|
9
|
+
- **Pagination** — configurable per-page options, page navigation
|
|
10
|
+
- **Selection** — single, multi, range (Shift+click), select all
|
|
11
|
+
- **Column management** — visibility toggle, reorder, resize
|
|
12
|
+
- **Editing** — four modes: modal, bubble (popover), inline (double-click), excel (spreadsheet)
|
|
13
|
+
- **Export** — CSV, clipboard, print (Excel/PDF with optional deps)
|
|
14
|
+
- **Virtual scroll** — render 10,000+ rows with only visible DOM nodes
|
|
15
|
+
- **Row grouping** — group rows by any column value
|
|
16
|
+
- **Per-column filters** — programmatic column-level filtering
|
|
17
|
+
- **Custom cells** — Svelte 5 snippets for full cell rendering control
|
|
18
|
+
- **Row customization** — `rowClass`, `rowId` function, expandable detail rows
|
|
19
|
+
- **Server-side** — jQuery DataTables wire protocol compatible, GET or POST
|
|
20
|
+
- **State persistence** — save sort/filter/page/column state to localStorage
|
|
21
|
+
- **Tailwind CSS** — `classNames` prop for pure Tailwind customization of every element
|
|
22
|
+
- **CSS variables** — 12+ CSS custom properties for quick theming
|
|
23
|
+
- **Footer aggregation** — per-column footer with custom functions
|
|
24
|
+
- **Responsive** — horizontal scroll for small screens
|
|
25
|
+
|
|
26
|
+
## Installation
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
# Install and publish route stubs
|
|
30
|
+
npx svelar plugin:install @beeblock/svelar-datatable
|
|
31
|
+
|
|
32
|
+
# Or manual install
|
|
33
|
+
npm install @beeblock/svelar-datatable
|
|
34
|
+
npx svelar plugin:publish @beeblock/svelar-datatable
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Peer dependencies: `@beeblock/svelar >= 0.6.7`, `svelte ^5.0.0`. `exceljs` is an optional peer dependency used only for Excel export.
|
|
38
|
+
|
|
39
|
+
## Quick Start
|
|
40
|
+
|
|
41
|
+
```svelte
|
|
42
|
+
<script lang="ts">
|
|
43
|
+
import { DataTable } from '@beeblock/svelar-datatable/ui';
|
|
44
|
+
import type { ColumnDef } from '@beeblock/svelar-datatable';
|
|
45
|
+
|
|
46
|
+
const columns: ColumnDef[] = [
|
|
47
|
+
{ key: 'id', header: 'ID', type: 'number', sortable: true },
|
|
48
|
+
{ key: 'name', header: 'Name', sortable: true, searchable: true },
|
|
49
|
+
{ key: 'email', header: 'Email', sortable: true, searchable: true },
|
|
50
|
+
];
|
|
51
|
+
|
|
52
|
+
const data = [
|
|
53
|
+
{ id: 1, name: 'Alice', email: 'alice@example.com' },
|
|
54
|
+
{ id: 2, name: 'Bob', email: 'bob@example.com' },
|
|
55
|
+
];
|
|
56
|
+
</script>
|
|
57
|
+
|
|
58
|
+
<DataTable {data} {columns} sortable searchable paginate perPage={10} />
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## Server-Side
|
|
62
|
+
|
|
63
|
+
```svelte
|
|
64
|
+
<!-- Frontend -->
|
|
65
|
+
<DataTable
|
|
66
|
+
serverUrl="/api/datatable/users"
|
|
67
|
+
columns={columns}
|
|
68
|
+
sortable
|
|
69
|
+
searchable
|
|
70
|
+
paginate
|
|
71
|
+
perPage={25}
|
|
72
|
+
/>
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
```ts
|
|
76
|
+
// src/routes/api/datatable/users/+server.ts
|
|
77
|
+
import { DataTableController } from '@beeblock/svelar-datatable/server';
|
|
78
|
+
import { User } from '$lib/modules/auth/domain/models/User.js';
|
|
79
|
+
|
|
80
|
+
const dt = new DataTableController(User);
|
|
81
|
+
export const GET = dt.handle('query');
|
|
82
|
+
export const POST = dt.handle('query');
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
The server controller handles pagination, sorting, searching, and filtering — compatible with the jQuery DataTables wire protocol.
|
|
86
|
+
|
|
87
|
+
Server search is case-insensitive on PostgreSQL (`ILIKE`) and uses the database driver's normal `LIKE` behavior on SQLite/MySQL.
|
|
88
|
+
|
|
89
|
+
### Server Filters
|
|
90
|
+
|
|
91
|
+
Use `serverParams` on the component for custom server filters. GET requests send these as `filters[name]` query params; POST requests include them in `customFilters`.
|
|
92
|
+
|
|
93
|
+
```svelte
|
|
94
|
+
<script lang="ts">
|
|
95
|
+
let priority = $state('');
|
|
96
|
+
|
|
97
|
+
function serverParams() {
|
|
98
|
+
return priority ? { priority } : {};
|
|
99
|
+
}
|
|
100
|
+
</script>
|
|
101
|
+
|
|
102
|
+
<DataTable
|
|
103
|
+
serverUrl="/api/datatable/cards"
|
|
104
|
+
columns={columns}
|
|
105
|
+
serverParams={serverParams}
|
|
106
|
+
searchable
|
|
107
|
+
sortable
|
|
108
|
+
/>
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
Register matching filters on the server:
|
|
112
|
+
|
|
113
|
+
```ts
|
|
114
|
+
import { DataTableController } from '@beeblock/svelar-datatable/server';
|
|
115
|
+
import { Card } from '$lib/modules/boards/domain/models/Card.js';
|
|
116
|
+
|
|
117
|
+
const dt = new DataTableController(Card, {
|
|
118
|
+
searchable: ['title', 'description', 'priority'],
|
|
119
|
+
orderable: ['title', 'priority', 'updated_at'],
|
|
120
|
+
filters: {
|
|
121
|
+
priority: (query, value) => query.where('priority', value),
|
|
122
|
+
},
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
export const GET = dt.handle('query');
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
### Meilisearch
|
|
129
|
+
|
|
130
|
+
When a model uses Svelar's `Searchable` mixin, global server search can use Meilisearch:
|
|
131
|
+
|
|
132
|
+
```ts
|
|
133
|
+
const dt = new DataTableController(Card, {
|
|
134
|
+
searchDriver: 'auto',
|
|
135
|
+
filters: {
|
|
136
|
+
priority: (query, value) => query.where('priority', value),
|
|
137
|
+
},
|
|
138
|
+
meilisearchFilter: (filters) => {
|
|
139
|
+
if (!filters.priority) return undefined;
|
|
140
|
+
return `priority = "${String(filters.priority).replaceAll('"', '\\"')}"`;
|
|
141
|
+
},
|
|
142
|
+
});
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
`searchDriver: 'auto'` is the default. It tries Meilisearch for global search when the model exposes `search()`, then falls back to database search if Meilisearch is not configured. Use `searchDriver: 'database'` to force SQL search, or `searchDriver: 'meilisearch'` to fail instead of falling back.
|
|
146
|
+
|
|
147
|
+
Meilisearch mode returns the indexed document fields from `model.search()`. Keep the datatable columns in the model's searchable/displayed attributes, and mark filtered/sorted attributes in Meilisearch index settings.
|
|
148
|
+
|
|
149
|
+
## Extending and Customizing
|
|
150
|
+
|
|
151
|
+
The plugin is meant to stay a reusable table black box, but it exposes extension points instead of forcing app-specific forks.
|
|
152
|
+
|
|
153
|
+
### Frontend Extension Points
|
|
154
|
+
|
|
155
|
+
- `customCell` snippet for custom badges, links, menus, previews, or composed app UI.
|
|
156
|
+
- `buttons` for export buttons and custom actions that receive selected rows and all rows.
|
|
157
|
+
- `classNames` for Tailwind/shadcn styling without editing plugin CSS.
|
|
158
|
+
- `bind:storeRef` for page-level controls such as external filters, refresh buttons, selected-row panels, or programmatic column visibility.
|
|
159
|
+
- `editorField` and `editorMode` for inline, modal, bubble, or Excel-style editing.
|
|
160
|
+
|
|
161
|
+
```svelte
|
|
162
|
+
<script lang="ts">
|
|
163
|
+
import { DataTable } from '@beeblock/svelar-datatable/ui';
|
|
164
|
+
import type { ButtonDef, ColumnDef } from '@beeblock/svelar-datatable';
|
|
165
|
+
|
|
166
|
+
const columns: ColumnDef[] = [
|
|
167
|
+
{ key: 'title', header: 'Title' },
|
|
168
|
+
{ key: 'priority', header: 'Priority', type: 'custom' },
|
|
169
|
+
{ key: 'actions', header: 'Actions', type: 'custom', sortable: false, searchable: false },
|
|
170
|
+
];
|
|
171
|
+
|
|
172
|
+
const buttons: ButtonDef[] = [
|
|
173
|
+
{
|
|
174
|
+
key: 'archive',
|
|
175
|
+
label: 'Archive selected',
|
|
176
|
+
disabled: (rows) => rows.length === 0,
|
|
177
|
+
action: (rows) => archiveCards(rows),
|
|
178
|
+
},
|
|
179
|
+
];
|
|
180
|
+
</script>
|
|
181
|
+
|
|
182
|
+
{#snippet customCell({ row, column, value })}
|
|
183
|
+
{#if column.key === 'priority'}
|
|
184
|
+
<span class="rounded border px-2 py-0.5 text-xs">{value}</span>
|
|
185
|
+
{:else if column.key === 'actions'}
|
|
186
|
+
<button type="button" onclick={() => openCard(row)}>Open</button>
|
|
187
|
+
{:else}
|
|
188
|
+
{value}
|
|
189
|
+
{/if}
|
|
190
|
+
{/snippet}
|
|
191
|
+
|
|
192
|
+
<DataTable {columns} data={cards} {buttons} {customCell} selectable="multi" />
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
### Server Extension Points
|
|
196
|
+
|
|
197
|
+
- `filters` on `DataTableController` or `DataTableService.addFilter()` for app-specific server filters.
|
|
198
|
+
- `baseQuery` for tenant/team/user scoping.
|
|
199
|
+
- `scopes` for named reusable query constraints.
|
|
200
|
+
- `computedColumns` for derived SQL columns.
|
|
201
|
+
- `searchDriver`, `meilisearchFilter`, and `meilisearchSort` for Searchable/Meilisearch-backed server search.
|
|
202
|
+
|
|
203
|
+
```ts
|
|
204
|
+
const dt = new DataTableController(Card, {
|
|
205
|
+
baseQuery: (query) => query.where('board_id', board.id),
|
|
206
|
+
searchable: ['title', 'description', 'priority'],
|
|
207
|
+
orderable: ['title', 'priority', 'position', 'updated_at'],
|
|
208
|
+
filters: {
|
|
209
|
+
priority: (query, value) => query.where('priority', value),
|
|
210
|
+
completed: (query, value) => query.where('completed', value === 'true'),
|
|
211
|
+
},
|
|
212
|
+
searchDriver: 'auto',
|
|
213
|
+
meilisearchFilter: (filters) => {
|
|
214
|
+
const clauses = [];
|
|
215
|
+
if (filters.priority) clauses.push(`priority = "${filters.priority}"`);
|
|
216
|
+
if (filters.completed) clauses.push(`completed = ${filters.completed === 'true'}`);
|
|
217
|
+
return clauses.length ? clauses.join(' AND ') : undefined;
|
|
218
|
+
},
|
|
219
|
+
});
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
## Plugin Contract
|
|
223
|
+
|
|
224
|
+
The package exposes the required Svelar plugin entry at `@beeblock/svelar-datatable/plugin`.
|
|
225
|
+
|
|
226
|
+
```ts
|
|
227
|
+
import DatatablePlugin from '@beeblock/svelar-datatable/plugin';
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
The plugin publishes a route stub to `src/routes/api/datatable/+server.ts` and registers default config under the `datatable` config key.
|
|
231
|
+
|
|
232
|
+
## Editing
|
|
233
|
+
|
|
234
|
+
Four editor modes, configured via `editorMode`:
|
|
235
|
+
|
|
236
|
+
```svelte
|
|
237
|
+
<!-- Modal editor -->
|
|
238
|
+
<DataTable editorMode="modal" editorFields={fields} onEdit={save} onCreate={create} />
|
|
239
|
+
|
|
240
|
+
<!-- Bubble (popover anchored to row) -->
|
|
241
|
+
<DataTable editorMode="bubble" editorFields={fields} onEdit={save} />
|
|
242
|
+
|
|
243
|
+
<!-- Inline (double-click a cell) -->
|
|
244
|
+
<DataTable editorMode="inline" onCellEdit={saveCellEdit} />
|
|
245
|
+
|
|
246
|
+
<!-- Excel (spreadsheet navigation) -->
|
|
247
|
+
<DataTable editorMode="excel" onCellEdit={saveCellEdit} />
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
Server-side Excel editing should still go through normal Svelar backend layers. Wire `onCellEdit` to a PATCH route that validates with a FormRequest, creates a DTO, runs an action/service, and returns a resource response. Throw from `onCellEdit` when the API rejects the update so the table can keep the old value.
|
|
251
|
+
|
|
252
|
+
```svelte
|
|
253
|
+
<script lang="ts">
|
|
254
|
+
import { apiFetchJson } from '@beeblock/svelar/http';
|
|
255
|
+
import type { ButtonDef, ExportFormat } from '@beeblock/svelar-datatable';
|
|
256
|
+
|
|
257
|
+
async function saveCell(row, columnKey, newValue) {
|
|
258
|
+
const response = await apiFetchJson(`/api/datatable/cards/${row.public_id}`, {
|
|
259
|
+
method: 'PATCH',
|
|
260
|
+
body: JSON.stringify({ column: columnKey, value: newValue }),
|
|
261
|
+
});
|
|
262
|
+
|
|
263
|
+
if (!response.ok) {
|
|
264
|
+
throw new Error(response.error?.message ?? 'Failed to update row');
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
const buttons: (ButtonDef | ExportFormat)[] = [
|
|
269
|
+
'csv',
|
|
270
|
+
{
|
|
271
|
+
key: 'mark-urgent',
|
|
272
|
+
label: 'Mark urgent',
|
|
273
|
+
disabled: (rows) => rows.length === 0,
|
|
274
|
+
action: (rows) => Promise.all(rows.map((row) => saveCell(row, 'priority', 'urgent'))),
|
|
275
|
+
},
|
|
276
|
+
];
|
|
277
|
+
</script>
|
|
278
|
+
|
|
279
|
+
<DataTable
|
|
280
|
+
serverUrl="/api/datatable/cards"
|
|
281
|
+
{columns}
|
|
282
|
+
selectable="multi"
|
|
283
|
+
editorMode="excel"
|
|
284
|
+
onCellEdit={saveCell}
|
|
285
|
+
{buttons}
|
|
286
|
+
/>
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
## Tailwind Customization
|
|
290
|
+
|
|
291
|
+
Style every element with Tailwind utility classes via the `classNames` prop:
|
|
292
|
+
|
|
293
|
+
```svelte
|
|
294
|
+
<DataTable
|
|
295
|
+
{data}
|
|
296
|
+
{columns}
|
|
297
|
+
striped={false}
|
|
298
|
+
hover={false}
|
|
299
|
+
classNames={{
|
|
300
|
+
container: '!bg-slate-900 !border-slate-800',
|
|
301
|
+
thead: '!bg-slate-950',
|
|
302
|
+
th: '!bg-slate-950 !text-slate-400 !tracking-widest',
|
|
303
|
+
tr: 'hover:!bg-slate-800',
|
|
304
|
+
td: '!text-slate-300 !border-b-slate-800',
|
|
305
|
+
pagination: '!border-t-slate-800 !text-slate-400 !bg-slate-900',
|
|
306
|
+
pageButton: '!bg-slate-800 !text-slate-400 !border-slate-700',
|
|
307
|
+
searchInput: '!bg-slate-800 !text-slate-200 !border-slate-700',
|
|
308
|
+
}}
|
|
309
|
+
/>
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
All 39 keys from `DataTableClassNames` are wired: `container`, `toolbar`, `toolbarLeft`, `toolbarRight`, `searchInput`, `thead`, `th`, `tbody`, `tr`, `trSelected`, `trEven`, `td`, `tfoot`, `tf`, `pagination`, `paginationInfo`, `paginationControls`, `pageButton`, `pageButtonActive`, `perPageSelect`, `btn`, `btnCreate`, `btnEdit`, `btnDelete`, `editorModal`, `editorBackdrop`, `editorField`, `editorInput`, `editorLabel`, `loading`, `empty`, `error`.
|
|
313
|
+
|
|
314
|
+
## Imports
|
|
315
|
+
|
|
316
|
+
```ts
|
|
317
|
+
// UI component (Svelte source — not compiled)
|
|
318
|
+
import { DataTable } from '@beeblock/svelar-datatable/ui';
|
|
319
|
+
|
|
320
|
+
// Types
|
|
321
|
+
import type {
|
|
322
|
+
ColumnDef, EditorFieldDef, ButtonDef, DataTableClassNames,
|
|
323
|
+
DataTableConfig, DataTableState, ExportFormat,
|
|
324
|
+
} from '@beeblock/svelar-datatable';
|
|
325
|
+
|
|
326
|
+
// Stores
|
|
327
|
+
import { DataTableStore, ServerDataTableStore } from '@beeblock/svelar-datatable';
|
|
328
|
+
|
|
329
|
+
// Server controller (API routes)
|
|
330
|
+
import { DataTableController, DataTableService } from '@beeblock/svelar-datatable/server';
|
|
331
|
+
```
|
|
332
|
+
|
|
333
|
+
## Documentation
|
|
334
|
+
|
|
335
|
+
Full documentation with all props, callbacks, store API, and examples: [svelar.dev/docs/datatable](https://svelar.dev/docs/datatable)
|
|
336
|
+
|
|
337
|
+
## Local Validation
|
|
338
|
+
|
|
339
|
+
```bash
|
|
340
|
+
npm run lint
|
|
341
|
+
npm run test
|
|
342
|
+
npm run build
|
|
343
|
+
```
|
|
344
|
+
|
|
345
|
+
## License
|
|
346
|
+
|
|
347
|
+
MIT
|
|
@@ -1,17 +1,72 @@
|
|
|
1
1
|
import { Plugin } from '@beeblock/svelar/plugins';
|
|
2
2
|
import type { DataTableConfig } from './types.js';
|
|
3
|
+
import type { Container } from '@beeblock/svelar/container';
|
|
3
4
|
interface DatatablePluginConfig {
|
|
4
5
|
prefix?: string;
|
|
5
6
|
defaults?: Partial<DataTableConfig>;
|
|
6
7
|
}
|
|
8
|
+
export declare const SVELAR_DATATABLE_PACKAGE: string;
|
|
9
|
+
export declare const SVELAR_DATATABLE_VERSION: string;
|
|
7
10
|
export declare class SvelarDatatablePlugin extends Plugin {
|
|
8
|
-
readonly name
|
|
9
|
-
readonly version
|
|
11
|
+
readonly name: string;
|
|
12
|
+
readonly version: string;
|
|
10
13
|
readonly description = "Full-featured DataTable plugin for Svelar \u2014 sorting, searching, pagination, inline editing, export, and server-side processing";
|
|
11
14
|
private _config;
|
|
12
15
|
constructor(config?: DatatablePluginConfig);
|
|
13
16
|
get datatableConfig(): DatatablePluginConfig;
|
|
14
17
|
static defaults(): Partial<DataTableConfig>;
|
|
18
|
+
config(): {
|
|
19
|
+
key: string;
|
|
20
|
+
defaults: {
|
|
21
|
+
prefix: string | undefined;
|
|
22
|
+
defaults: {
|
|
23
|
+
data?: any[] | undefined;
|
|
24
|
+
serverUrl?: string;
|
|
25
|
+
serverMethod?: "GET" | "POST";
|
|
26
|
+
serverParams?: Record<string, any> | (() => Record<string, any>);
|
|
27
|
+
csrfCookieName?: string;
|
|
28
|
+
csrfHeaderName?: string;
|
|
29
|
+
columns?: import("./types.js").ColumnDef<any>[] | undefined;
|
|
30
|
+
sortable?: boolean;
|
|
31
|
+
searchable?: boolean;
|
|
32
|
+
paginate?: boolean;
|
|
33
|
+
selectable?: import("./types.js").SelectionMode;
|
|
34
|
+
perPage?: number;
|
|
35
|
+
perPageOptions?: number[];
|
|
36
|
+
searchDebounceMs?: number;
|
|
37
|
+
stateSaveKey?: string;
|
|
38
|
+
rowId?: string | ((row: any) => string | number) | undefined;
|
|
39
|
+
rowClass?: string | ((row: any, index: number) => string) | undefined;
|
|
40
|
+
buttons?: (import("./types.js").ButtonDef | import("./types.js").ExportFormat)[];
|
|
41
|
+
editorMode?: import("./types.js").EditorMode;
|
|
42
|
+
editorFields?: import("./types.js").EditorFieldDef[];
|
|
43
|
+
onSort?: (sort: import("./types.js").SortState[]) => void;
|
|
44
|
+
onFilter?: (filters: import("./types.js").FilterState[]) => void;
|
|
45
|
+
onPageChange?: (page: number, perPage: number) => void;
|
|
46
|
+
onSelect?: ((selectedRows: any[]) => void) | undefined;
|
|
47
|
+
onRowClick?: ((row: any, event: MouseEvent) => void) | undefined;
|
|
48
|
+
onEdit?: ((row: any, data: Record<string, any>) => void | Promise<void>) | undefined;
|
|
49
|
+
onCellEdit?: ((row: any, columnKey: string, newValue: any, oldValue: any) => void | Promise<void>) | undefined;
|
|
50
|
+
onCreate?: (data: Record<string, any>) => void | Promise<void>;
|
|
51
|
+
onDelete?: ((rows: any[]) => void | Promise<void>) | undefined;
|
|
52
|
+
virtualScroll?: boolean;
|
|
53
|
+
virtualRowHeight?: number;
|
|
54
|
+
responsive?: boolean;
|
|
55
|
+
groupBy?: string;
|
|
56
|
+
expandable?: boolean;
|
|
57
|
+
emptyText?: string;
|
|
58
|
+
loadingText?: string;
|
|
59
|
+
className?: string;
|
|
60
|
+
compact?: boolean;
|
|
61
|
+
striped?: boolean;
|
|
62
|
+
hover?: boolean;
|
|
63
|
+
bordered?: boolean;
|
|
64
|
+
classNames?: import("./types.js").DataTableClassNames;
|
|
65
|
+
unstyled?: boolean;
|
|
66
|
+
};
|
|
67
|
+
};
|
|
68
|
+
};
|
|
69
|
+
register(app: Container): Promise<void>;
|
|
15
70
|
publishables(): {
|
|
16
71
|
routes: {
|
|
17
72
|
source: string;
|