@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.
- package/dist/components/container/DataTableShell/DataTableShell.svelte +631 -0
- package/dist/components/container/DataTableShell/DataTableShell.svelte.d.ts +48 -0
- package/dist/components/container/DataTableShell/components/AdvancedFiltersBuilder.svelte +311 -0
- package/dist/components/container/DataTableShell/components/AdvancedFiltersBuilder.svelte.d.ts +7 -0
- package/dist/components/container/DataTableShell/components/ColumnVisibilityMenu.svelte +112 -0
- package/dist/components/container/DataTableShell/components/ColumnVisibilityMenu.svelte.d.ts +8 -0
- package/dist/components/container/DataTableShell/components/ContextMenu.svelte +70 -0
- package/dist/components/container/DataTableShell/components/ContextMenu.svelte.d.ts +30 -0
- package/dist/components/container/DataTableShell/components/DataTableFiltersSidebar.svelte +0 -0
- package/dist/components/container/DataTableShell/components/DataTableFiltersSidebar.svelte.d.ts +26 -0
- package/dist/components/container/DataTableShell/components/DataTableFooter.svelte +36 -0
- package/dist/components/container/DataTableShell/components/DataTableFooter.svelte.d.ts +18 -0
- package/dist/components/container/DataTableShell/components/DataTableToolbar.svelte +822 -0
- package/dist/components/container/DataTableShell/components/DataTableToolbar.svelte.d.ts +30 -0
- package/dist/components/container/DataTableShell/components/Pagination.svelte +117 -0
- package/dist/components/container/DataTableShell/components/Pagination.svelte.d.ts +28 -0
- package/dist/components/container/DataTableShell/components/Submenu.svelte +109 -0
- package/dist/components/container/DataTableShell/components/Submenu.svelte.d.ts +30 -0
- package/dist/components/container/DataTableShell/components/Toolbar.svelte +0 -0
- package/dist/components/container/DataTableShell/components/Toolbar.svelte.d.ts +26 -0
- package/dist/components/container/DataTableShell/core/DataTableController.svelte.d.ts +54 -0
- package/dist/components/container/DataTableShell/core/DataTableController.svelte.js +148 -0
- package/dist/components/container/DataTableShell/core/DataTableEngine.svelte.d.ts +68 -0
- package/dist/components/container/DataTableShell/core/DataTableEngine.svelte.js +319 -0
- package/dist/components/container/DataTableShell/core/DataTableInternal.svelte.d.ts +68 -0
- package/dist/components/container/DataTableShell/core/DataTableInternal.svelte.js +396 -0
- package/dist/components/container/DataTableShell/core/context.d.ts +3 -0
- package/dist/components/container/DataTableShell/core/context.js +12 -0
- package/dist/components/container/DataTableShell/core/filters-types.d.ts +14 -0
- package/dist/components/container/DataTableShell/core/filters-types.js +1 -0
- package/dist/components/container/DataTableShell/core/types.d.ts +60 -0
- package/dist/components/container/DataTableShell/core/types.js +1 -0
- package/dist/components/container/index.d.ts +3 -1
- package/dist/components/container/index.js +3 -1
- 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>
|
package/dist/components/container/DataTableShell/components/AdvancedFiltersBuilder.svelte.d.ts
ADDED
|
@@ -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;
|
|
File without changes
|
package/dist/components/container/DataTableShell/components/DataTableFiltersSidebar.svelte.d.ts
ADDED
|
@@ -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;
|