@r2digisolutions/ui 0.27.3 → 0.28.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 (35) hide show
  1. package/dist/components/container/DataTableShell/DataTableShell.svelte +631 -0
  2. package/dist/components/container/DataTableShell/DataTableShell.svelte.d.ts +48 -0
  3. package/dist/components/container/DataTableShell/components/AdvancedFiltersBuilder.svelte +311 -0
  4. package/dist/components/container/DataTableShell/components/AdvancedFiltersBuilder.svelte.d.ts +7 -0
  5. package/dist/components/container/DataTableShell/components/ColumnVisibilityMenu.svelte +112 -0
  6. package/dist/components/container/DataTableShell/components/ColumnVisibilityMenu.svelte.d.ts +8 -0
  7. package/dist/components/container/DataTableShell/components/ContextMenu.svelte +70 -0
  8. package/dist/components/container/DataTableShell/components/ContextMenu.svelte.d.ts +30 -0
  9. package/dist/components/container/DataTableShell/components/DataTableFiltersSidebar.svelte +0 -0
  10. package/dist/components/container/DataTableShell/components/DataTableFiltersSidebar.svelte.d.ts +26 -0
  11. package/dist/components/container/DataTableShell/components/DataTableFooter.svelte +36 -0
  12. package/dist/components/container/DataTableShell/components/DataTableFooter.svelte.d.ts +18 -0
  13. package/dist/components/container/DataTableShell/components/DataTableToolbar.svelte +822 -0
  14. package/dist/components/container/DataTableShell/components/DataTableToolbar.svelte.d.ts +30 -0
  15. package/dist/components/container/DataTableShell/components/Pagination.svelte +117 -0
  16. package/dist/components/container/DataTableShell/components/Pagination.svelte.d.ts +28 -0
  17. package/dist/components/container/DataTableShell/components/Submenu.svelte +109 -0
  18. package/dist/components/container/DataTableShell/components/Submenu.svelte.d.ts +30 -0
  19. package/dist/components/container/DataTableShell/components/Toolbar.svelte +0 -0
  20. package/dist/components/container/DataTableShell/components/Toolbar.svelte.d.ts +26 -0
  21. package/dist/components/container/DataTableShell/core/DataTableController.svelte.d.ts +54 -0
  22. package/dist/components/container/DataTableShell/core/DataTableController.svelte.js +148 -0
  23. package/dist/components/container/DataTableShell/core/DataTableEngine.svelte.d.ts +68 -0
  24. package/dist/components/container/DataTableShell/core/DataTableEngine.svelte.js +319 -0
  25. package/dist/components/container/DataTableShell/core/DataTableInternal.svelte.d.ts +68 -0
  26. package/dist/components/container/DataTableShell/core/DataTableInternal.svelte.js +396 -0
  27. package/dist/components/container/DataTableShell/core/context.d.ts +3 -0
  28. package/dist/components/container/DataTableShell/core/context.js +12 -0
  29. package/dist/components/container/DataTableShell/core/filters-types.d.ts +14 -0
  30. package/dist/components/container/DataTableShell/core/filters-types.js +1 -0
  31. package/dist/components/container/DataTableShell/core/types.d.ts +60 -0
  32. package/dist/components/container/DataTableShell/core/types.js +1 -0
  33. package/dist/components/container/index.d.ts +3 -1
  34. package/dist/components/container/index.js +3 -1
  35. package/package.json +13 -13
@@ -0,0 +1,311 @@
1
+ <script lang="ts">
2
+ import { Plus, Trash2, ChevronDown, ChevronRight } from 'lucide-svelte';
3
+ import type { DataTableController } from '../core/DataTableController.svelte';
4
+ import type {
5
+ Filter,
6
+ FilterOperator,
7
+ LogicOperator,
8
+ QueryGroup,
9
+ QueryStructure,
10
+ TQueryFilter
11
+ } from '../core/types.js';
12
+
13
+ interface Props {
14
+ controller: DataTableController<any>;
15
+ }
16
+
17
+ const { controller }: Props = $props();
18
+
19
+ type LocalRule = {
20
+ id: string;
21
+ kind: 'rule';
22
+ field: string;
23
+ operator: FilterOperator;
24
+ value: string;
25
+ };
26
+
27
+ type LocalGroup = {
28
+ id: string;
29
+ kind: 'group';
30
+ join: LogicOperator;
31
+ children: Array<LocalRule | LocalGroup>;
32
+ expanded: boolean;
33
+ };
34
+
35
+ let enabled = $state(false);
36
+
37
+ let root: LocalGroup = $state({
38
+ id: 'root',
39
+ kind: 'group',
40
+ join: 'AND',
41
+ children: [],
42
+ expanded: true
43
+ });
44
+
45
+ let counter = 1;
46
+
47
+ const columns = $derived(controller.allColumns);
48
+
49
+ function createRule(): LocalRule {
50
+ return {
51
+ id: `r-${counter++}`,
52
+ kind: 'rule',
53
+ field: columns[0]?.id ?? '',
54
+ operator: 'contains',
55
+ value: ''
56
+ };
57
+ }
58
+
59
+ function createGroup(): LocalGroup {
60
+ return {
61
+ id: `g-${counter++}`,
62
+ kind: 'group',
63
+ join: 'AND',
64
+ children: [],
65
+ expanded: true
66
+ };
67
+ }
68
+
69
+ function addRule(group: LocalGroup) {
70
+ group.children = [...group.children, createRule()];
71
+ }
72
+
73
+ function addGroup(group: LocalGroup) {
74
+ group.children = [...group.children, createGroup()];
75
+ }
76
+
77
+ function removeChild(parent: LocalGroup, id: string) {
78
+ parent.children = parent.children.filter((c) => c.id !== id);
79
+ }
80
+
81
+ function toggleExpanded(group: LocalGroup) {
82
+ group.expanded = !group.expanded;
83
+ }
84
+
85
+ function buildFilters(group: LocalGroup): TQueryFilter {
86
+ const out: TQueryFilter = [];
87
+
88
+ for (const child of group.children) {
89
+ if (child.kind === 'rule') {
90
+ if (!child.field) continue;
91
+ const op = child.operator;
92
+ const needsValue = op !== 'is_empty' && op !== 'is_not_empty';
93
+ if (needsValue && !child.value) continue;
94
+
95
+ out.push([child.field, child.operator, child.value] as Filter);
96
+ } else {
97
+ const nested = buildFilters(child);
98
+ if (!nested.length) continue;
99
+
100
+ const g: QueryGroup = {
101
+ type: 'group',
102
+ joinOperation: child.join,
103
+ filters: nested
104
+ };
105
+
106
+ out.push(g);
107
+ }
108
+ }
109
+
110
+ return out;
111
+ }
112
+
113
+ function apply() {
114
+ const filters = buildFilters(root);
115
+
116
+ const query: QueryStructure = {
117
+ useQuery: enabled && filters.length > 0,
118
+ joinOperation: root.join,
119
+ filters
120
+ };
121
+
122
+ controller.setQuery(query);
123
+ }
124
+
125
+ function clear() {
126
+ root = {
127
+ id: 'root',
128
+ kind: 'group',
129
+ join: 'AND',
130
+ children: [],
131
+ expanded: true
132
+ };
133
+ enabled = false;
134
+
135
+ const query: QueryStructure = {
136
+ useQuery: false,
137
+ joinOperation: 'AND',
138
+ filters: []
139
+ };
140
+
141
+ controller.setQuery(query);
142
+ }
143
+ </script>
144
+
145
+ {#snippet Group({ group, parent }: { group: LocalGroup; parent: LocalGroup | null })}
146
+ <div
147
+ class={`rounded-2xl border border-neutral-200/80 bg-white/80 px-3 py-2 text-[11px] text-neutral-800 shadow-sm backdrop-blur-md dark:border-neutral-800/80 dark:bg-neutral-900/85 dark:text-neutral-100 ${
148
+ group.id === 'root' ? '' : 'mt-2 ml-3'
149
+ }`}
150
+ >
151
+ <div class="mb-2 flex items-center justify-between gap-2">
152
+ <div class="flex items-center gap-2">
153
+ <button
154
+ type="button"
155
+ onclick={() => toggleExpanded(group)}
156
+ class="inline-flex h-5 w-5 items-center justify-center rounded-full bg-neutral-100/90 text-neutral-500 hover:bg-neutral-200/90 dark:bg-neutral-800/90 dark:text-neutral-300 dark:hover:bg-neutral-700/90"
157
+ >
158
+ {#if group.expanded}
159
+ <ChevronDown class="h-3 w-3" />
160
+ {:else}
161
+ <ChevronRight class="h-3 w-3" />
162
+ {/if}
163
+ </button>
164
+ <div
165
+ class="flex items-center gap-1 rounded-full bg-neutral-900/95 px-2 py-0.5 text-[10px] font-medium text-neutral-50 dark:bg-neutral-50 dark:text-neutral-900"
166
+ >
167
+ <span>Grupo</span>
168
+ <select
169
+ bind:value={group.join}
170
+ class="ml-1 rounded-full border border-neutral-700/60 bg-neutral-900/95 px-1.5 py-0.5 text-[10px] text-neutral-50 focus:outline-none dark:border-neutral-300/80 dark:bg-neutral-50/95 dark:text-neutral-900"
171
+ >
172
+ <option value="AND">AND</option>
173
+ <option value="OR">OR</option>
174
+ </select>
175
+ </div>
176
+ </div>
177
+
178
+ <div class="flex items-center gap-1">
179
+ <button
180
+ type="button"
181
+ onclick={() => addRule(group)}
182
+ class="inline-flex items-center gap-1 rounded-full bg-neutral-100/95 px-2 py-0.5 text-[10px] text-neutral-700 hover:bg-neutral-200/95 dark:bg-neutral-800/95 dark:text-neutral-100 dark:hover:bg-neutral-700/95"
183
+ >
184
+ <Plus class="h-3 w-3" />
185
+ Condición
186
+ </button>
187
+ <button
188
+ type="button"
189
+ onclick={() => addGroup(group)}
190
+ class="inline-flex items-center gap-1 rounded-full bg-neutral-100/95 px-2 py-0.5 text-[10px] text-neutral-700 hover:bg-neutral-200/95 dark:bg-neutral-800/95 dark:text-neutral-100 dark:hover:bg-neutral-700/95"
191
+ >
192
+ <Plus class="h-3 w-3" />
193
+ Grupo
194
+ </button>
195
+ {#if parent}
196
+ <button
197
+ type="button"
198
+ onclick={() => parent && removeChild(parent, group.id)}
199
+ class="inline-flex h-6 w-6 items-center justify-center rounded-full text-neutral-400 hover:bg-neutral-200/80 hover:text-neutral-800 dark:text-neutral-500 dark:hover:bg-neutral-700/80 dark:hover:text-neutral-100"
200
+ >
201
+ <Trash2 class="h-3 w-3" />
202
+ </button>
203
+ {/if}
204
+ </div>
205
+ </div>
206
+
207
+ {#if group.expanded}
208
+ {#if group.children.length}
209
+ <div class="space-y-1">
210
+ {#each group.children as child (child.id)}
211
+ {#if child.kind === 'rule'}
212
+ <div
213
+ class="grid grid-cols-[minmax(0,1.3fr)_minmax(0,1.2fr)_minmax(0,1.5fr)_auto] items-center gap-1 rounded-2xl bg-neutral-50/95 px-2 py-1.5 dark:bg-neutral-950/80"
214
+ >
215
+ <select
216
+ bind:value={child.field}
217
+ class="w-full rounded-xl border border-neutral-200/80 bg-white/95 px-2 py-0.5 text-[10px] text-neutral-800 focus:outline-none dark:border-neutral-700/80 dark:bg-neutral-900/95 dark:text-neutral-50"
218
+ >
219
+ {#each columns as col}
220
+ <option value={col.id}>{col.label}</option>
221
+ {/each}
222
+ </select>
223
+ <select
224
+ bind:value={child.operator}
225
+ class="w-full rounded-xl border border-neutral-200/80 bg-white/95 px-2 py-0.5 text-[10px] text-neutral-800 focus:outline-none dark:border-neutral-700/80 dark:bg-neutral-900/95 dark:text-neutral-50"
226
+ >
227
+ <option value="contains">contiene</option>
228
+ <option value="equals">igual a</option>
229
+ <option value="not_equals">distinto de</option>
230
+ <option value="greater_than">mayor que</option>
231
+ <option value="less_than">menor que</option>
232
+ <option value="startsWith">empieza por</option>
233
+ <option value="endsWith">termina en</option>
234
+ <option value="is_empty">vacío</option>
235
+ <option value="is_not_empty">no vacío</option>
236
+ <option value="in">en lista</option>
237
+ <option value="not_in">fuera de lista</option>
238
+ <option value="not_contains">no contiene</option>
239
+ </select>
240
+ <input
241
+ type="text"
242
+ bind:value={child.value}
243
+ placeholder="Valor"
244
+ class="w-full rounded-xl border border-neutral-200/80 bg-white/95 px-2 py-0.5 text-[10px] text-neutral-800 placeholder:text-neutral-400 focus:outline-none dark:border-neutral-700/80 dark:bg-neutral-900/95 dark:text-neutral-50 dark:placeholder:text-neutral-500"
245
+ disabled={child.operator === 'is_empty' || child.operator === 'is_not_empty'}
246
+ />
247
+ <button
248
+ type="button"
249
+ onclick={() => removeChild(group, child.id)}
250
+ class="ml-1 inline-flex h-6 w-6 items-center justify-center rounded-full text-neutral-400 hover:bg-neutral-200/80 hover:text-neutral-800 dark:text-neutral-500 dark:hover:bg-neutral-700/80 dark:hover:text-neutral-100"
251
+ >
252
+ <Trash2 class="h-3 w-3" />
253
+ </button>
254
+ </div>
255
+ {:else}
256
+ {@render Group({ group: child as LocalGroup, parent: group })}
257
+ {/if}
258
+ {/each}
259
+ </div>
260
+ {:else}
261
+ <div class="text-[11px] text-neutral-400 dark:text-neutral-500">
262
+ Este grupo aún no tiene condiciones.
263
+ </div>
264
+ {/if}
265
+ {/if}
266
+ </div>
267
+ {/snippet}
268
+
269
+ <div
270
+ class="mt-2 rounded-2xl border border-dashed border-neutral-200/80 bg-gradient-to-br from-neutral-50/95 via-white/95 to-purple-50/80 px-3 py-3 text-[11px] text-neutral-700 shadow-[0_14px_40px_rgba(15,23,42,0.18)] backdrop-blur-xl dark:border-neutral-800/80 dark:bg-gradient-to-br dark:from-neutral-950/95 dark:via-neutral-950/90 dark:to-purple-950/40 dark:text-neutral-200"
271
+ >
272
+ <div class="mb-2 flex items-center justify-between gap-2">
273
+ <div>
274
+ <p class="text-[11px] font-semibold text-neutral-800 dark:text-neutral-100">
275
+ Filtro avanzado
276
+ </p>
277
+ <p class="text-[10px] text-neutral-500 dark:text-neutral-400">
278
+ Combina condiciones con grupos AND/OR. Los filtros simples siguen funcionando aparte.
279
+ </p>
280
+ </div>
281
+ <div class="flex items-center gap-2">
282
+ <label
283
+ class="flex cursor-pointer items-center gap-1 rounded-full bg-neutral-100/90 px-2 py-0.5 text-[10px] text-neutral-700 dark:bg-neutral-800/90 dark:text-neutral-100"
284
+ >
285
+ <input
286
+ type="checkbox"
287
+ bind:checked={enabled}
288
+ class="h-3 w-3 rounded border-neutral-300 bg-neutral-50 text-purple-500 focus:ring-purple-500 dark:border-neutral-600 dark:bg-neutral-900"
289
+ />
290
+ <span>Activar</span>
291
+ </label>
292
+ <button
293
+ type="button"
294
+ onclick={clear}
295
+ class="inline-flex items-center gap-1 rounded-full bg-neutral-100 px-2.5 py-1 text-[10px] text-neutral-700 hover:bg-neutral-200 dark:bg-neutral-900 dark:text-neutral-200 dark:hover:bg-neutral-800"
296
+ >
297
+ <Trash2 class="h-3 w-3" />
298
+ Limpiar
299
+ </button>
300
+ <button
301
+ type="button"
302
+ onclick={apply}
303
+ class="inline-flex items-center gap-1 rounded-full bg-purple-600 px-3 py-1 text-[10px] font-semibold text-white shadow-sm hover:bg-purple-500 dark:bg-purple-500 dark:hover:bg-purple-400"
304
+ >
305
+ Aplicar
306
+ </button>
307
+ </div>
308
+ </div>
309
+
310
+ {@render Group({ group: root, parent: null })}
311
+ </div>
@@ -0,0 +1,7 @@
1
+ import type { DataTableController } from '../core/DataTableController.svelte';
2
+ interface Props {
3
+ controller: DataTableController<any>;
4
+ }
5
+ declare const AdvancedFiltersBuilder: import("svelte").Component<Props, {}, "">;
6
+ type AdvancedFiltersBuilder = ReturnType<typeof AdvancedFiltersBuilder>;
7
+ export default AdvancedFiltersBuilder;
@@ -0,0 +1,112 @@
1
+ <script lang="ts">
2
+ import type { DataTableController } from '../core/DataTableController.svelte';
3
+ import { Eye, EyeOff, RotateCcw } from 'lucide-svelte';
4
+
5
+ interface Props {
6
+ controller: DataTableController<any>;
7
+ onClose?: () => void;
8
+ }
9
+
10
+ const { controller, onClose }: Props = $props();
11
+
12
+ const allColumns = $derived(controller.allColumns);
13
+ const visibleColumns = $derived(controller.visibleColumns);
14
+
15
+ function isVisible(id: string) {
16
+ return visibleColumns.some((c) => c.id === id);
17
+ }
18
+
19
+ function toggleColumn(id: string, visible: boolean) {
20
+ controller.setColumnVisibility(id, visible);
21
+ }
22
+
23
+ function showAll() {
24
+ controller.showAllColumns();
25
+ }
26
+
27
+ function hideAll() {
28
+ controller.hideAllColumns();
29
+ }
30
+
31
+ function resetLayout() {
32
+ controller.resetLayout();
33
+ }
34
+ </script>
35
+
36
+ <div class="space-y-2 text-xs">
37
+ <div class="flex items-center justify-between gap-2 pb-1">
38
+ <p class="text-[11px] font-semibold text-neutral-800 dark:text-neutral-100">
39
+ Columnas visibles
40
+ </p>
41
+ <div class="flex items-center gap-1.5">
42
+ <button
43
+ type="button"
44
+ onclick={showAll}
45
+ class="inline-flex items-center gap-1 rounded-full bg-neutral-100/90 px-2 py-0.5 text-[10px] text-neutral-700 hover:bg-neutral-200/90 dark:bg-neutral-800/90 dark:text-neutral-100 dark:hover:bg-neutral-700/90"
46
+ >
47
+ <Eye class="h-3 w-3" />
48
+ Todas
49
+ </button>
50
+ <button
51
+ type="button"
52
+ onclick={hideAll}
53
+ class="inline-flex items-center gap-1 rounded-full bg-neutral-100/90 px-2 py-0.5 text-[10px] text-neutral-700 hover:bg-neutral-200/90 dark:bg-neutral-800/90 dark:text-neutral-100 dark:hover:bg-neutral-700/90"
54
+ >
55
+ <EyeOff class="h-3 w-3" />
56
+ Ninguna
57
+ </button>
58
+ <button
59
+ type="button"
60
+ onclick={resetLayout}
61
+ class="inline-flex items-center gap-1 rounded-full bg-neutral-900 px-2 py-0.5 text-[10px] text-neutral-50 hover:bg-neutral-800 dark:bg-neutral-50 dark:text-neutral-900 dark:hover:bg-neutral-200"
62
+ >
63
+ <RotateCcw class="h-3 w-3" />
64
+ Reset
65
+ </button>
66
+ </div>
67
+ </div>
68
+
69
+ <div class="max-h-64 space-y-1 overflow-y-auto pr-1">
70
+ {#each allColumns as col}
71
+ <label
72
+ class="flex cursor-pointer items-center justify-between gap-2 rounded-2xl px-2 py-1.5 hover:bg-neutral-100/90 dark:hover:bg-neutral-800/80"
73
+ >
74
+ <div class="flex items-center gap-2">
75
+ <input
76
+ type="checkbox"
77
+ checked={isVisible(col.id)}
78
+ onchange={(e) => toggleColumn(col.id, (e.currentTarget as HTMLInputElement).checked)}
79
+ class="h-3.5 w-3.5 rounded border-neutral-300 bg-neutral-50 text-purple-500 focus:ring-purple-500 dark:border-neutral-600 dark:bg-neutral-900"
80
+ />
81
+ <div class="flex flex-col">
82
+ <span class="text-[11px] text-neutral-800 dark:text-neutral-100">
83
+ {col.label}
84
+ </span>
85
+ <span class="text-[10px] text-neutral-400 dark:text-neutral-500">
86
+ {col.id}
87
+ </span>
88
+ </div>
89
+ </div>
90
+ {#if col.sticky === 'left'}
91
+ <span
92
+ class="rounded-full bg-purple-100/80 px-2 py-0.5 text-[9px] font-semibold text-purple-700 dark:bg-purple-900/50 dark:text-purple-200"
93
+ >
94
+ Sticky
95
+ </span>
96
+ {/if}
97
+ </label>
98
+ {/each}
99
+ </div>
100
+
101
+ {#if onClose}
102
+ <div class="pt-1">
103
+ <button
104
+ type="button"
105
+ onclick={onClose}
106
+ class="w-full rounded-2xl bg-neutral-900 px-2 py-1.5 text-[11px] font-medium text-neutral-50 hover:bg-neutral-800 dark:bg-neutral-50 dark:text-neutral-900 dark:hover:bg-neutral-200"
107
+ >
108
+ Cerrar
109
+ </button>
110
+ </div>
111
+ {/if}
112
+ </div>
@@ -0,0 +1,8 @@
1
+ import type { DataTableController } from '../core/DataTableController.svelte';
2
+ interface Props {
3
+ controller: DataTableController<any>;
4
+ onClose?: () => void;
5
+ }
6
+ declare const ColumnVisibilityMenu: import("svelte").Component<Props, {}, "">;
7
+ type ColumnVisibilityMenu = ReturnType<typeof ColumnVisibilityMenu>;
8
+ export default ColumnVisibilityMenu;
@@ -0,0 +1,70 @@
1
+ <script lang="ts" generics="T">
2
+ import type { AnyAction, RowAction } from '../core/types.js';
3
+ import Submenu from './Submenu.svelte';
4
+
5
+ interface Props<T> {
6
+ actions: RowAction<T>[];
7
+ row: T;
8
+ onClose: () => void;
9
+ }
10
+
11
+ const { actions, row, onClose }: Props<T> = $props();
12
+
13
+ function isHidden(action: AnyAction<T>, r: T) {
14
+ return typeof action.hidden === 'function' ? action.hidden(r) : false;
15
+ }
16
+
17
+ function hasChildren(action: AnyAction<T>) {
18
+ return Array.isArray(action.children) && action.children.length > 0;
19
+ }
20
+
21
+ function handleClick(action: AnyAction<T>) {
22
+ if (action.onClick) {
23
+ action.onClick(row);
24
+ }
25
+ onClose();
26
+ }
27
+ </script>
28
+
29
+ <div
30
+ class="max-h-[320px] min-w-[200px] overflow-auto rounded-2xl bg-gradient-to-br from-neutral-50/98 via-white/98 to-neutral-100/98 p-1 text-xs text-neutral-900 shadow-[0_18px_55px_rgba(15,23,42,0.65)] backdrop-blur-2xl dark:from-neutral-900/98 dark:via-neutral-950/98 dark:to-neutral-950/98 dark:text-neutral-50"
31
+ >
32
+ {#each actions as actionRaw, i}
33
+ {@const action = actionRaw as AnyAction}
34
+ {#if !isHidden(action, row)}
35
+ {@const label = typeof action.label === 'function' ? action.label(row) : action.label}
36
+
37
+ <div class="relative" data-context-host="true">
38
+ <button
39
+ type="button"
40
+ onclick={() => !hasChildren(action) && handleClick(action)}
41
+ class={`group flex w-full items-center justify-between gap-2 rounded-2xl px-2.5 py-1.5 text-[11px] transition-colors ${
42
+ action.danger
43
+ ? 'text-red-600 hover:bg-red-50 dark:text-red-300 dark:hover:bg-red-900/40'
44
+ : 'text-neutral-800 hover:bg-neutral-100/90 dark:text-neutral-100 dark:hover:bg-neutral-800/80'
45
+ }`}
46
+ >
47
+ <div class="flex items-center gap-2">
48
+ {#if action.icon}
49
+ {@const Icon = typeof action.icon === 'function' ? action.icon(row) : action.icon}
50
+ <Icon
51
+ class="h-3.5 w-3.5 text-neutral-400 group-hover:text-neutral-700 dark:text-neutral-500 dark:group-hover:text-neutral-100"
52
+ ></Icon>
53
+ {/if}
54
+ <span class="line-clamp-1 text-left">
55
+ {label}
56
+ </span>
57
+ </div>
58
+
59
+ {#if hasChildren(action)}
60
+ <Submenu {action} {row} {onClose} />
61
+ {/if}
62
+ </button>
63
+ </div>
64
+ {/if}
65
+
66
+ {#if i < actions.length - 1}
67
+ <div class="mx-1 my-0.5 h-px bg-neutral-200/70 dark:bg-neutral-800/70"></div>
68
+ {/if}
69
+ {/each}
70
+ </div>
@@ -0,0 +1,30 @@
1
+ import type { RowAction } from '../core/types.js';
2
+ interface Props<T> {
3
+ actions: RowAction<T>[];
4
+ row: T;
5
+ onClose: () => void;
6
+ }
7
+ declare function $$render<T>(): {
8
+ props: Props<T>;
9
+ exports: {};
10
+ bindings: "";
11
+ slots: {};
12
+ events: {};
13
+ };
14
+ declare class __sveltets_Render<T> {
15
+ props(): ReturnType<typeof $$render<T>>['props'];
16
+ events(): ReturnType<typeof $$render<T>>['events'];
17
+ slots(): ReturnType<typeof $$render<T>>['slots'];
18
+ bindings(): "";
19
+ exports(): {};
20
+ }
21
+ interface $$IsomorphicComponent {
22
+ new <T>(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']>> & {
23
+ $$bindings?: ReturnType<__sveltets_Render<T>['bindings']>;
24
+ } & ReturnType<__sveltets_Render<T>['exports']>;
25
+ <T>(internal: unknown, props: ReturnType<__sveltets_Render<T>['props']> & {}): ReturnType<__sveltets_Render<T>['exports']>;
26
+ z_$$bindings?: ReturnType<__sveltets_Render<any>['bindings']>;
27
+ }
28
+ declare const ContextMenu: $$IsomorphicComponent;
29
+ type ContextMenu<T> = InstanceType<typeof ContextMenu<T>>;
30
+ export default ContextMenu;
@@ -0,0 +1,26 @@
1
+ export default DataTableFiltersSidebar;
2
+ type DataTableFiltersSidebar = SvelteComponent<{
3
+ [x: string]: never;
4
+ }, {
5
+ [evt: string]: CustomEvent<any>;
6
+ }, {}> & {
7
+ $$bindings?: string | undefined;
8
+ };
9
+ declare const DataTableFiltersSidebar: $$__sveltets_2_IsomorphicComponent<{
10
+ [x: string]: never;
11
+ }, {
12
+ [evt: string]: CustomEvent<any>;
13
+ }, {}, {}, string>;
14
+ interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
15
+ new (options: import("svelte").ComponentConstructorOptions<Props>): import("svelte").SvelteComponent<Props, Events, Slots> & {
16
+ $$bindings?: Bindings;
17
+ } & Exports;
18
+ (internal: unknown, props: {
19
+ $$events?: Events;
20
+ $$slots?: Slots;
21
+ }): Exports & {
22
+ $set?: any;
23
+ $on?: any;
24
+ };
25
+ z_$$bindings?: Bindings;
26
+ }
@@ -0,0 +1,36 @@
1
+ <script lang="ts">
2
+ import { useTable } from '../core/context.js';
3
+ import Pagination from './Pagination.svelte';
4
+
5
+ const controller = useTable<any>();
6
+
7
+ function rangeLabel() {
8
+ if (!controller.totalRows) return '';
9
+ const start = (controller.page - 1) * controller.pageSize + 1;
10
+ const end = Math.min(controller.page * controller.pageSize, controller.totalRows);
11
+ return `${start}–${end} de ${controller.totalRows}`;
12
+ }
13
+ </script>
14
+
15
+ <div
16
+ class="flex flex-col gap-2 border-t border-neutral-200/80 bg-neutral-50/70 px-3 py-2 text-[11px] text-neutral-600 backdrop-blur-xl dark:border-neutral-800/80 dark:bg-neutral-950/60 dark:text-neutral-300"
17
+ >
18
+ <div class="flex items-center justify-between gap-2">
19
+ <div class="flex flex-col gap-0.5 sm:flex-row sm:items-center sm:gap-3">
20
+ <span>{rangeLabel()}</span>
21
+ {#if controller.selectedCount}
22
+ <span
23
+ class="rounded-full bg-purple-100/80 px-2 py-0.5 text-[10px] font-medium text-purple-700 dark:bg-purple-900/50 dark:text-purple-200"
24
+ >
25
+ {controller.selectedCount} seleccionadas
26
+ </span>
27
+ {/if}
28
+ </div>
29
+
30
+ <div class="flex items-center gap-3">
31
+ {#if controller.options.mode === 'pagination'}
32
+ <Pagination {controller} />
33
+ {/if}
34
+ </div>
35
+ </div>
36
+ </div>
@@ -0,0 +1,18 @@
1
+ interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
2
+ new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
3
+ $$bindings?: Bindings;
4
+ } & Exports;
5
+ (internal: unknown, props: {
6
+ $$events?: Events;
7
+ $$slots?: Slots;
8
+ }): Exports & {
9
+ $set?: any;
10
+ $on?: any;
11
+ };
12
+ z_$$bindings?: Bindings;
13
+ }
14
+ declare const DataTableFooter: $$__sveltets_2_IsomorphicComponent<Record<string, never>, {
15
+ [evt: string]: CustomEvent<any>;
16
+ }, {}, {}, string>;
17
+ type DataTableFooter = InstanceType<typeof DataTableFooter>;
18
+ export default DataTableFooter;