runeforge 0.0.55 → 0.0.57

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 (61) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +1355 -1342
  3. package/dist/components/Avatar.svelte +31 -31
  4. package/dist/components/IconRenderer.svelte +73 -22
  5. package/dist/components/IconRenderer.svelte.d.ts +2 -0
  6. package/dist/components/Modal.svelte +75 -75
  7. package/dist/components/common/Header.svelte +40 -40
  8. package/dist/components/crud/EmbeddedField.svelte +175 -175
  9. package/dist/components/crud/Field.svelte +469 -376
  10. package/dist/components/crud/GenericCRUD.svelte +426 -426
  11. package/dist/components/crud/SearchInput.svelte +53 -53
  12. package/dist/components/crud/columns/Avatar.svelte +15 -15
  13. package/dist/components/crud/columns/Icon.svelte +8 -8
  14. package/dist/components/crud/views/Create.svelte +232 -232
  15. package/dist/components/crud/views/Read.svelte +124 -124
  16. package/dist/components/crud/views/Update.svelte +208 -208
  17. package/dist/components/crud/views/list/List.svelte +291 -291
  18. package/dist/components/crud/views/list/Modals.svelte +56 -56
  19. package/dist/components/crud/views/list/Table.svelte +176 -176
  20. package/dist/components/crud/views/list/Toolbar.svelte +341 -341
  21. package/dist/components/form/Button.svelte +27 -27
  22. package/dist/components/form/Label.svelte +37 -37
  23. package/dist/components/form/MultiSelect.svelte +248 -248
  24. package/dist/components/form/PasswordInput.svelte +68 -68
  25. package/dist/components/form/Required.svelte +1 -1
  26. package/dist/components/form/Select.svelte +209 -209
  27. package/dist/components/form/Tree.svelte +62 -62
  28. package/dist/components/form/TreeNode.svelte +66 -66
  29. package/dist/components/navigation/Breadcrumbs.svelte +111 -111
  30. package/dist/components/table/ColumnFilter.svelte +168 -168
  31. package/dist/components/table/PaginatedTable.svelte +536 -536
  32. package/dist/components/table/Paginator.svelte +113 -113
  33. package/dist/components/table/SortHeader.svelte +43 -43
  34. package/dist/components/table/TableBody.svelte +150 -150
  35. package/dist/components/table/TableHeader.svelte +88 -88
  36. package/dist/i18n/en.js +1 -0
  37. package/dist/i18n/es.js +1 -0
  38. package/dist/i18n/types.d.ts +1 -0
  39. package/dist/icons/context.d.ts +5 -0
  40. package/dist/icons/context.js +10 -0
  41. package/dist/icons/defaults/Clear.svelte +6 -6
  42. package/dist/icons/defaults/Create.svelte +6 -6
  43. package/dist/icons/defaults/Delete.svelte +6 -6
  44. package/dist/icons/defaults/Download.svelte +7 -7
  45. package/dist/icons/defaults/Edit.svelte +7 -7
  46. package/dist/icons/defaults/Filter.svelte +6 -6
  47. package/dist/icons/defaults/FilterActive.svelte +6 -6
  48. package/dist/icons/defaults/Folder.svelte +6 -6
  49. package/dist/icons/defaults/Grip.svelte +7 -7
  50. package/dist/icons/defaults/Home.svelte +6 -6
  51. package/dist/icons/defaults/PasswordHide.svelte +9 -9
  52. package/dist/icons/defaults/PasswordShow.svelte +7 -7
  53. package/dist/icons/defaults/SortAsc.svelte +6 -6
  54. package/dist/icons/defaults/SortDesc.svelte +6 -6
  55. package/dist/icons/defaults/SortNone.svelte +6 -6
  56. package/dist/icons/defaults/View.svelte +7 -7
  57. package/dist/icons/sets/bootstrap.js +1 -4
  58. package/dist/icons/types.d.ts +0 -1
  59. package/dist/index.d.ts +1 -1
  60. package/dist/index.js +1 -1
  61. package/package.json +1 -1
@@ -1,291 +1,291 @@
1
- <script lang="ts" generics="T extends object = Record<string, unknown>">
2
- import { SvelteSet } from 'svelte/reactivity';
3
- import { invalidateAll } from '$app/navigation';
4
- import Toolbar from './Toolbar.svelte';
5
- import Table from './Table.svelte';
6
- import Modals from './Modals.svelte';
7
- import { computeReorderChanges } from '../../utils/reorder.js';
8
- import type {
9
- ActionConfiguration,
10
- ColumnDefinition,
11
- CustomAction,
12
- CustomBulkAction,
13
- ListActions,
14
- ListConfig,
15
- ViewBasedCustomBulkAction
16
- } from '../../../../types/crud.js';
17
- import type {
18
- FilterSnapshot,
19
- ServerPagination,
20
- SortDirection,
21
- TableQuery
22
- } from '../../../../types/table.js';
23
- import { getStrings } from '../../../../i18n/context.js';
24
-
25
- const strings = getStrings();
26
-
27
- function isViewBasedBulkAction<U extends object>(
28
- action: CustomBulkAction<U>
29
- ): action is ViewBasedCustomBulkAction<U> {
30
- return action.kind === 'view';
31
- }
32
-
33
- let {
34
- data = [] as T[],
35
- labelOne = '',
36
- labelMany = '',
37
- icon,
38
- pageSize = 10,
39
- idKey = '_id',
40
- creation = {} as ActionConfiguration<T>,
41
- update = {} as ActionConfiguration<T>,
42
- read = {} as ActionConfiguration<T>,
43
- deletion = {} as ActionConfiguration<T>,
44
- actions = {} as ListActions<T>,
45
- config = {} as ListConfig<T>,
46
- columns = [] as ColumnDefinition<T>[],
47
- pagination = undefined as ServerPagination | undefined,
48
- initialSort = undefined as { column: string; direction: SortDirection } | undefined,
49
- initialFilters = undefined as Partial<FilterSnapshot> | undefined,
50
- onPaginationChange = undefined as ((query: TableQuery) => void) | undefined,
51
- onCreate,
52
- onEdit,
53
- onView,
54
- onAction,
55
- onBulkAction
56
- }: {
57
- data?: T[];
58
- labelOne?: string;
59
- labelMany?: string;
60
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
61
- icon?: any;
62
- pageSize?: number;
63
- idKey?: string;
64
- creation?: ActionConfiguration<T>;
65
- update?: ActionConfiguration<T>;
66
- read?: ActionConfiguration<T>;
67
- deletion?: ActionConfiguration<T>;
68
- actions?: ListActions<T>;
69
- config?: ListConfig<T>;
70
- columns?: ColumnDefinition<T>[];
71
- pagination?: ServerPagination;
72
- initialSort?: { column: string; direction: SortDirection };
73
- initialFilters?: Partial<FilterSnapshot>;
74
- onPaginationChange?: (query: TableQuery) => void;
75
- onCreate?: () => void;
76
- onEdit?: (item: T) => void;
77
- onView?: (item: T) => void;
78
- onAction?: (action: CustomAction<T>, item: T) => void;
79
- onBulkAction?: (action: ViewBasedCustomBulkAction<T>, items: T[]) => void;
80
- } = $props();
81
-
82
- const customActions = $derived(actions.custom ?? []);
83
- const bulkActions = $derived(actions.bulk ?? []);
84
- const searchConfig = $derived(config.search);
85
- const exportConfig = $derived(config.export);
86
- const reorderConfig = $derived(config.reorder);
87
-
88
- const allowRead = $derived(read.enabled ?? true);
89
- const allowUpdate = $derived(update.enabled ?? true);
90
- const allowDelete = $derived(deletion.enabled ?? true);
91
- const allowCreate = $derived(creation.enabled ?? true);
92
- const deleteLabel = $derived(deletion.label ?? strings.delete);
93
- const updateLabel = $derived(update.label ?? strings.edit);
94
- const readLabel = $derived(read.label ?? strings.view);
95
- const allowSelection = $derived(
96
- allowDelete || bulkActions.some((action) => !isViewBasedBulkAction(action))
97
- );
98
-
99
- // SvelteSet is already reactive on its own; passing it through Table's
100
- // (and PaginatedTable's) own `bind:selected` makes svelte-check's
101
- // non_reactive_update warning fire here too — a false positive, per the
102
- // same reasoning as the "intentional one-time hydration" notes elsewhere
103
- // in this codebase.
104
- let selected = new SvelteSet<number>();
105
- let pendingDeletion = $state<T[] | null>(null);
106
- let pendingBulkAction = $state<{ action: CustomBulkAction<T>; items: T[] } | null>(null);
107
- const selectedItems = $derived([...selected].map((i) => data[i]));
108
-
109
- let visibleRows = $state<T[]>([]);
110
- let exportQuery = $state<TableQuery | undefined>(undefined);
111
-
112
- // `selected` holds indices into `data`; if `data` is swapped for a different
113
- // slice (page/sort/filter change in server mode) stale indices could point
114
- // at unrelated rows, so clear on any data reference change.
115
- let lastData: T[] | undefined;
116
- $effect(() => {
117
- if (data !== lastData) {
118
- selected.clear();
119
- lastData = data;
120
- }
121
- });
122
-
123
- async function runEndpointAction(
124
- endpoint: string,
125
- items: T[],
126
- extraFields?: (item: T) => Record<string, string>
127
- ) {
128
- await Promise.all(
129
- items.map((item) => {
130
- const fd = new FormData();
131
- fd.set('id', String((item as Record<string, unknown>)[idKey] ?? ''));
132
- for (const [k, v] of Object.entries(extraFields?.(item) ?? {})) fd.set(k, v);
133
- return fetch(endpoint, { method: 'POST', body: fd });
134
- })
135
- );
136
- await invalidateAll();
137
- }
138
-
139
- /** One POST for every row that moved, instead of `runEndpointAction`'s one
140
- * request per row — a drag that shifts N rows only settles once (on
141
- * release), but N rows changing means N *parallel* requests fire at that
142
- * moment, which reads a lot like "one per row crossed" from the network
143
- * tab. FormData field `changes` carries a JSON array of `{id, value}`
144
- * pairs, one per row whose `attribute` changed. */
145
- async function runBatchEndpointAction(endpoint: string, items: T[], attribute: keyof T & string) {
146
- const fd = new FormData();
147
- fd.set(
148
- 'changes',
149
- JSON.stringify(
150
- items.map((item) => ({
151
- id: String((item as Record<string, unknown>)[idKey] ?? ''),
152
- value: (item as Record<string, unknown>)[attribute]
153
- }))
154
- )
155
- );
156
- await fetch(endpoint, { method: 'POST', body: fd });
157
- await invalidateAll();
158
- }
159
-
160
- async function runDeletion(items: T[]) {
161
- if (deletion.endpoint) {
162
- await runEndpointAction(deletion.endpoint, items);
163
- } else {
164
- await deletion.callback?.(items);
165
- }
166
- }
167
-
168
- function requestDeletion(items: T[]) {
169
- if (deletion.confirm) {
170
- pendingDeletion = items;
171
- } else {
172
- runDeletion(items);
173
- }
174
- }
175
-
176
- function handleDeleteSelected() {
177
- const items = [...selected].map((i) => data[i]);
178
- selected.clear();
179
- requestDeletion(items);
180
- }
181
-
182
- async function confirmDeletion() {
183
- if (pendingDeletion) {
184
- await runDeletion(pendingDeletion);
185
- pendingDeletion = null;
186
- }
187
- }
188
-
189
- async function runBulkAction(action: CustomBulkAction<T>, items: T[]) {
190
- if (isViewBasedBulkAction(action)) return;
191
- await runEndpointAction(action.endpoint, items);
192
- }
193
-
194
- function requestBulkAction(action: CustomBulkAction<T>, items: T[]) {
195
- if (!isViewBasedBulkAction(action) && action.confirm) {
196
- pendingBulkAction = { action, items };
197
- } else {
198
- runBulkAction(action, items);
199
- }
200
- }
201
-
202
- function handleBulkAction(action: CustomBulkAction<T>) {
203
- const items = selectedItems;
204
- if (isViewBasedBulkAction(action)) {
205
- onBulkAction?.(action, items);
206
- return;
207
- }
208
- selected.clear();
209
- requestBulkAction(action, items);
210
- }
211
-
212
- async function confirmBulkAction() {
213
- if (pendingBulkAction) {
214
- await runBulkAction(pendingBulkAction.action, pendingBulkAction.items);
215
- pendingBulkAction = null;
216
- }
217
- }
218
-
219
- async function handleReorder(rows: T[]) {
220
- const cfg = reorderConfig;
221
- if (!cfg) return;
222
- const changed = computeReorderChanges(rows, cfg.attribute);
223
- if (changed.length === 0) return;
224
- if (cfg.endpoint) {
225
- await runBatchEndpointAction(cfg.endpoint, changed, cfg.attribute);
226
- } else {
227
- await cfg.callback?.(changed);
228
- }
229
- }
230
- </script>
231
-
232
- <div class="flex flex-col gap-6">
233
- <Toolbar
234
- {labelOne}
235
- {labelMany}
236
- {icon}
237
- {creation}
238
- {allowCreate}
239
- {allowDelete}
240
- {deleteLabel}
241
- search={searchConfig}
242
- {exportConfig}
243
- {bulkActions}
244
- {columns}
245
- {pagination}
246
- {visibleRows}
247
- {exportQuery}
248
- selectedCount={selected.size}
249
- {selectedItems}
250
- {onCreate}
251
- onDeleteSelected={handleDeleteSelected}
252
- onBulkAction={handleBulkAction}
253
- />
254
-
255
- <Table
256
- {data}
257
- {columns}
258
- {pageSize}
259
- selectable={allowSelection}
260
- bind:selected
261
- {pagination}
262
- {initialSort}
263
- {initialFilters}
264
- {onPaginationChange}
265
- bind:visibleRows
266
- bind:query={exportQuery}
267
- {customActions}
268
- {allowRead}
269
- {allowUpdate}
270
- {allowDelete}
271
- {readLabel}
272
- {updateLabel}
273
- {deleteLabel}
274
- reorder={reorderConfig}
275
- {onView}
276
- {onEdit}
277
- {onAction}
278
- onRequestDeletion={(item) => requestDeletion([item])}
279
- onReorder={handleReorder}
280
- />
281
- </div>
282
-
283
- <Modals
284
- {deleteLabel}
285
- {pendingDeletion}
286
- {pendingBulkAction}
287
- onCancelDeletion={() => (pendingDeletion = null)}
288
- onConfirmDeletion={confirmDeletion}
289
- onCancelBulkAction={() => (pendingBulkAction = null)}
290
- onConfirmBulkAction={confirmBulkAction}
291
- />
1
+ <script lang="ts" generics="T extends object = Record<string, unknown>">
2
+ import { SvelteSet } from 'svelte/reactivity';
3
+ import { invalidateAll } from '$app/navigation';
4
+ import Toolbar from './Toolbar.svelte';
5
+ import Table from './Table.svelte';
6
+ import Modals from './Modals.svelte';
7
+ import { computeReorderChanges } from '../../utils/reorder.js';
8
+ import type {
9
+ ActionConfiguration,
10
+ ColumnDefinition,
11
+ CustomAction,
12
+ CustomBulkAction,
13
+ ListActions,
14
+ ListConfig,
15
+ ViewBasedCustomBulkAction
16
+ } from '../../../../types/crud.js';
17
+ import type {
18
+ FilterSnapshot,
19
+ ServerPagination,
20
+ SortDirection,
21
+ TableQuery
22
+ } from '../../../../types/table.js';
23
+ import { getStrings } from '../../../../i18n/context.js';
24
+
25
+ const strings = getStrings();
26
+
27
+ function isViewBasedBulkAction<U extends object>(
28
+ action: CustomBulkAction<U>
29
+ ): action is ViewBasedCustomBulkAction<U> {
30
+ return action.kind === 'view';
31
+ }
32
+
33
+ let {
34
+ data = [] as T[],
35
+ labelOne = '',
36
+ labelMany = '',
37
+ icon,
38
+ pageSize = 10,
39
+ idKey = '_id',
40
+ creation = {} as ActionConfiguration<T>,
41
+ update = {} as ActionConfiguration<T>,
42
+ read = {} as ActionConfiguration<T>,
43
+ deletion = {} as ActionConfiguration<T>,
44
+ actions = {} as ListActions<T>,
45
+ config = {} as ListConfig<T>,
46
+ columns = [] as ColumnDefinition<T>[],
47
+ pagination = undefined as ServerPagination | undefined,
48
+ initialSort = undefined as { column: string; direction: SortDirection } | undefined,
49
+ initialFilters = undefined as Partial<FilterSnapshot> | undefined,
50
+ onPaginationChange = undefined as ((query: TableQuery) => void) | undefined,
51
+ onCreate,
52
+ onEdit,
53
+ onView,
54
+ onAction,
55
+ onBulkAction
56
+ }: {
57
+ data?: T[];
58
+ labelOne?: string;
59
+ labelMany?: string;
60
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
61
+ icon?: any;
62
+ pageSize?: number;
63
+ idKey?: string;
64
+ creation?: ActionConfiguration<T>;
65
+ update?: ActionConfiguration<T>;
66
+ read?: ActionConfiguration<T>;
67
+ deletion?: ActionConfiguration<T>;
68
+ actions?: ListActions<T>;
69
+ config?: ListConfig<T>;
70
+ columns?: ColumnDefinition<T>[];
71
+ pagination?: ServerPagination;
72
+ initialSort?: { column: string; direction: SortDirection };
73
+ initialFilters?: Partial<FilterSnapshot>;
74
+ onPaginationChange?: (query: TableQuery) => void;
75
+ onCreate?: () => void;
76
+ onEdit?: (item: T) => void;
77
+ onView?: (item: T) => void;
78
+ onAction?: (action: CustomAction<T>, item: T) => void;
79
+ onBulkAction?: (action: ViewBasedCustomBulkAction<T>, items: T[]) => void;
80
+ } = $props();
81
+
82
+ const customActions = $derived(actions.custom ?? []);
83
+ const bulkActions = $derived(actions.bulk ?? []);
84
+ const searchConfig = $derived(config.search);
85
+ const exportConfig = $derived(config.export);
86
+ const reorderConfig = $derived(config.reorder);
87
+
88
+ const allowRead = $derived(read.enabled ?? true);
89
+ const allowUpdate = $derived(update.enabled ?? true);
90
+ const allowDelete = $derived(deletion.enabled ?? true);
91
+ const allowCreate = $derived(creation.enabled ?? true);
92
+ const deleteLabel = $derived(deletion.label ?? strings.delete);
93
+ const updateLabel = $derived(update.label ?? strings.edit);
94
+ const readLabel = $derived(read.label ?? strings.view);
95
+ const allowSelection = $derived(
96
+ allowDelete || bulkActions.some((action) => !isViewBasedBulkAction(action))
97
+ );
98
+
99
+ // SvelteSet is already reactive on its own; passing it through Table's
100
+ // (and PaginatedTable's) own `bind:selected` makes svelte-check's
101
+ // non_reactive_update warning fire here too — a false positive, per the
102
+ // same reasoning as the "intentional one-time hydration" notes elsewhere
103
+ // in this codebase.
104
+ let selected = new SvelteSet<number>();
105
+ let pendingDeletion = $state<T[] | null>(null);
106
+ let pendingBulkAction = $state<{ action: CustomBulkAction<T>; items: T[] } | null>(null);
107
+ const selectedItems = $derived([...selected].map((i) => data[i]));
108
+
109
+ let visibleRows = $state<T[]>([]);
110
+ let exportQuery = $state<TableQuery | undefined>(undefined);
111
+
112
+ // `selected` holds indices into `data`; if `data` is swapped for a different
113
+ // slice (page/sort/filter change in server mode) stale indices could point
114
+ // at unrelated rows, so clear on any data reference change.
115
+ let lastData: T[] | undefined;
116
+ $effect(() => {
117
+ if (data !== lastData) {
118
+ selected.clear();
119
+ lastData = data;
120
+ }
121
+ });
122
+
123
+ async function runEndpointAction(
124
+ endpoint: string,
125
+ items: T[],
126
+ extraFields?: (item: T) => Record<string, string>
127
+ ) {
128
+ await Promise.all(
129
+ items.map((item) => {
130
+ const fd = new FormData();
131
+ fd.set('id', String((item as Record<string, unknown>)[idKey] ?? ''));
132
+ for (const [k, v] of Object.entries(extraFields?.(item) ?? {})) fd.set(k, v);
133
+ return fetch(endpoint, { method: 'POST', body: fd });
134
+ })
135
+ );
136
+ await invalidateAll();
137
+ }
138
+
139
+ /** One POST for every row that moved, instead of `runEndpointAction`'s one
140
+ * request per row — a drag that shifts N rows only settles once (on
141
+ * release), but N rows changing means N *parallel* requests fire at that
142
+ * moment, which reads a lot like "one per row crossed" from the network
143
+ * tab. FormData field `changes` carries a JSON array of `{id, value}`
144
+ * pairs, one per row whose `attribute` changed. */
145
+ async function runBatchEndpointAction(endpoint: string, items: T[], attribute: keyof T & string) {
146
+ const fd = new FormData();
147
+ fd.set(
148
+ 'changes',
149
+ JSON.stringify(
150
+ items.map((item) => ({
151
+ id: String((item as Record<string, unknown>)[idKey] ?? ''),
152
+ value: (item as Record<string, unknown>)[attribute]
153
+ }))
154
+ )
155
+ );
156
+ await fetch(endpoint, { method: 'POST', body: fd });
157
+ await invalidateAll();
158
+ }
159
+
160
+ async function runDeletion(items: T[]) {
161
+ if (deletion.endpoint) {
162
+ await runEndpointAction(deletion.endpoint, items);
163
+ } else {
164
+ await deletion.callback?.(items);
165
+ }
166
+ }
167
+
168
+ function requestDeletion(items: T[]) {
169
+ if (deletion.confirm) {
170
+ pendingDeletion = items;
171
+ } else {
172
+ runDeletion(items);
173
+ }
174
+ }
175
+
176
+ function handleDeleteSelected() {
177
+ const items = [...selected].map((i) => data[i]);
178
+ selected.clear();
179
+ requestDeletion(items);
180
+ }
181
+
182
+ async function confirmDeletion() {
183
+ if (pendingDeletion) {
184
+ await runDeletion(pendingDeletion);
185
+ pendingDeletion = null;
186
+ }
187
+ }
188
+
189
+ async function runBulkAction(action: CustomBulkAction<T>, items: T[]) {
190
+ if (isViewBasedBulkAction(action)) return;
191
+ await runEndpointAction(action.endpoint, items);
192
+ }
193
+
194
+ function requestBulkAction(action: CustomBulkAction<T>, items: T[]) {
195
+ if (!isViewBasedBulkAction(action) && action.confirm) {
196
+ pendingBulkAction = { action, items };
197
+ } else {
198
+ runBulkAction(action, items);
199
+ }
200
+ }
201
+
202
+ function handleBulkAction(action: CustomBulkAction<T>) {
203
+ const items = selectedItems;
204
+ if (isViewBasedBulkAction(action)) {
205
+ onBulkAction?.(action, items);
206
+ return;
207
+ }
208
+ selected.clear();
209
+ requestBulkAction(action, items);
210
+ }
211
+
212
+ async function confirmBulkAction() {
213
+ if (pendingBulkAction) {
214
+ await runBulkAction(pendingBulkAction.action, pendingBulkAction.items);
215
+ pendingBulkAction = null;
216
+ }
217
+ }
218
+
219
+ async function handleReorder(rows: T[]) {
220
+ const cfg = reorderConfig;
221
+ if (!cfg) return;
222
+ const changed = computeReorderChanges(rows, cfg.attribute);
223
+ if (changed.length === 0) return;
224
+ if (cfg.endpoint) {
225
+ await runBatchEndpointAction(cfg.endpoint, changed, cfg.attribute);
226
+ } else {
227
+ await cfg.callback?.(changed);
228
+ }
229
+ }
230
+ </script>
231
+
232
+ <div class="flex flex-col gap-6">
233
+ <Toolbar
234
+ {labelOne}
235
+ {labelMany}
236
+ {icon}
237
+ {creation}
238
+ {allowCreate}
239
+ {allowDelete}
240
+ {deleteLabel}
241
+ search={searchConfig}
242
+ {exportConfig}
243
+ {bulkActions}
244
+ {columns}
245
+ {pagination}
246
+ {visibleRows}
247
+ {exportQuery}
248
+ selectedCount={selected.size}
249
+ {selectedItems}
250
+ {onCreate}
251
+ onDeleteSelected={handleDeleteSelected}
252
+ onBulkAction={handleBulkAction}
253
+ />
254
+
255
+ <Table
256
+ {data}
257
+ {columns}
258
+ {pageSize}
259
+ selectable={allowSelection}
260
+ bind:selected
261
+ {pagination}
262
+ {initialSort}
263
+ {initialFilters}
264
+ {onPaginationChange}
265
+ bind:visibleRows
266
+ bind:query={exportQuery}
267
+ {customActions}
268
+ {allowRead}
269
+ {allowUpdate}
270
+ {allowDelete}
271
+ {readLabel}
272
+ {updateLabel}
273
+ {deleteLabel}
274
+ reorder={reorderConfig}
275
+ {onView}
276
+ {onEdit}
277
+ {onAction}
278
+ onRequestDeletion={(item) => requestDeletion([item])}
279
+ onReorder={handleReorder}
280
+ />
281
+ </div>
282
+
283
+ <Modals
284
+ {deleteLabel}
285
+ {pendingDeletion}
286
+ {pendingBulkAction}
287
+ onCancelDeletion={() => (pendingDeletion = null)}
288
+ onConfirmDeletion={confirmDeletion}
289
+ onCancelBulkAction={() => (pendingBulkAction = null)}
290
+ onConfirmBulkAction={confirmBulkAction}
291
+ />