@r2digisolutions/ui 0.26.12 → 0.27.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/container/DataTable/DataTable.svelte +134 -77
- package/dist/components/container/DataTable/DataTable.svelte.d.ts +6 -6
- package/dist/components/container/DataTable/core/DataTableManager.svelte.js +84 -33
- package/dist/components/container/DataTable/core/types.d.ts +47 -4
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/stores/FormStatus.svelte.d.ts +61 -0
- package/dist/stores/FormStatus.svelte.js +45 -0
- package/package.json +17 -17
|
@@ -44,6 +44,7 @@
|
|
|
44
44
|
filterFields
|
|
45
45
|
}: Props<T> = $props();
|
|
46
46
|
|
|
47
|
+
// Layout constants
|
|
47
48
|
const CHECK_W = 64;
|
|
48
49
|
const ACTION_W = 56;
|
|
49
50
|
const EXPAND_W = 40;
|
|
@@ -60,18 +61,21 @@
|
|
|
60
61
|
density === 'compact' ? 'py-2' : density === 'comfortable' ? 'py-4' : 'py-3'
|
|
61
62
|
);
|
|
62
63
|
|
|
63
|
-
|
|
64
|
+
// Importante: dejamos que el propio manager se encargue de la carga
|
|
65
|
+
// vía su efecto interno en el constructor. No hacemos `await manager.load()` aquí.
|
|
64
66
|
|
|
67
|
+
// Ajustar ancho reservado para checkbox / expand / actions
|
|
65
68
|
$effect(() => {
|
|
66
69
|
const hasActions = !!rowActions;
|
|
67
70
|
const reserved =
|
|
68
71
|
CHECK_W +
|
|
69
72
|
(expandIconPosition === 'end' && !hasActions ? EXPAND_W : 0) +
|
|
70
73
|
(hasActions ? ACTION_W : 0);
|
|
74
|
+
|
|
71
75
|
manager.setReservedWidth(reserved);
|
|
72
76
|
});
|
|
73
77
|
|
|
74
|
-
// Reflow ancho
|
|
78
|
+
// Reflow ancho por ResizeObserver
|
|
75
79
|
$effect(() => {
|
|
76
80
|
if (!container) return;
|
|
77
81
|
const ro = new ResizeObserver((entries) => {
|
|
@@ -82,29 +86,42 @@
|
|
|
82
86
|
return () => ro.disconnect();
|
|
83
87
|
});
|
|
84
88
|
|
|
85
|
-
// Medir DOM
|
|
89
|
+
// Medir DOM para calcular anchos de columnas
|
|
86
90
|
const SAMPLE_ROWS = 10;
|
|
91
|
+
|
|
87
92
|
async function measureColumns() {
|
|
88
93
|
await tick();
|
|
89
94
|
if (!container) return;
|
|
95
|
+
|
|
90
96
|
const widths: Record<string, number> = {};
|
|
97
|
+
|
|
91
98
|
for (const c of manager.columns) {
|
|
92
99
|
const head = container.querySelector(`[data-dt-head="${c.id}"]`) as HTMLElement | null;
|
|
100
|
+
|
|
93
101
|
let maxW = head ? head.offsetWidth : 0;
|
|
102
|
+
|
|
94
103
|
const cells = Array.from(
|
|
95
104
|
container.querySelectorAll(`[data-dt-cell="1"][data-col-id="${c.id}"]`)
|
|
96
105
|
).slice(0, SAMPLE_ROWS) as HTMLElement[];
|
|
97
|
-
|
|
106
|
+
|
|
107
|
+
for (const el of cells) {
|
|
108
|
+
maxW = Math.max(maxW, el.offsetWidth);
|
|
109
|
+
}
|
|
110
|
+
|
|
98
111
|
if (c.minWidth != null) maxW = Math.max(maxW, c.minWidth);
|
|
99
112
|
if (c.width != null) maxW = Math.max(maxW, c.width);
|
|
113
|
+
|
|
100
114
|
widths[c.id] = Math.ceil(maxW + 16);
|
|
101
115
|
}
|
|
116
|
+
|
|
102
117
|
manager.setMeasuredWidths(widths);
|
|
118
|
+
|
|
103
119
|
const rect = container.getBoundingClientRect();
|
|
104
120
|
manager.reflowForWidth(Math.floor(rect.width));
|
|
105
121
|
measuring = false;
|
|
106
122
|
}
|
|
107
123
|
|
|
124
|
+
// Lanzar medición cuando ya haya datos cargados
|
|
108
125
|
$effect(() => {
|
|
109
126
|
if (!manager.state.ready) return;
|
|
110
127
|
measuring = true;
|
|
@@ -124,8 +141,10 @@
|
|
|
124
141
|
) {
|
|
125
142
|
e.preventDefault();
|
|
126
143
|
const columnIndex = columnId ? manager.state.visibleColumns.indexOf(columnId) : null;
|
|
127
|
-
|
|
144
|
+
|
|
145
|
+
// Reset del menú para evitar glitches de posición
|
|
128
146
|
rightMenu = { open: false, x: 0, y: 0 };
|
|
147
|
+
|
|
129
148
|
tick().then(() => {
|
|
130
149
|
rightMenu = { open: true, x: e.clientX, y: e.clientY };
|
|
131
150
|
rightClickContext = {
|
|
@@ -144,12 +163,10 @@
|
|
|
144
163
|
return manager.state.items.filter((r) => ids.has(rowId(r)));
|
|
145
164
|
}
|
|
146
165
|
|
|
147
|
-
const selectedRowsItems = $derived.by(() =>
|
|
148
|
-
return selectedRows();
|
|
149
|
-
});
|
|
166
|
+
const selectedRowsItems = $derived.by(() => selectedRows());
|
|
150
167
|
|
|
151
|
-
function colTrack(cId: string,
|
|
152
|
-
if (
|
|
168
|
+
function colTrack(cId: string, isMeasuring: boolean) {
|
|
169
|
+
if (isMeasuring) return 'max-content';
|
|
153
170
|
const c = manager.getColumn(cId);
|
|
154
171
|
const w = manager.measured[cId] ?? c.width ?? c.minWidth ?? 160;
|
|
155
172
|
return `${Math.max(40, Math.ceil(Number(w)))}px`;
|
|
@@ -167,42 +184,64 @@
|
|
|
167
184
|
const colsForRender = $derived(
|
|
168
185
|
measuring ? manager.columns.map((c) => c.id) : manager.state.visibleColumns
|
|
169
186
|
);
|
|
187
|
+
|
|
170
188
|
const endExtras = $derived(
|
|
171
189
|
expandIconPosition === 'end' && !rowActions && manager.state.hiddenColumns.length > 0
|
|
172
190
|
);
|
|
191
|
+
|
|
192
|
+
const allSelected = $derived.by(() => {
|
|
193
|
+
const items = manager.state.items;
|
|
194
|
+
if (items.length === 0) return false;
|
|
195
|
+
return items.every((r) => manager.state.selected.has(rowId(r)));
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
const hasHiddenColumns = $derived.by(() => manager.state.hiddenColumns.length > 0);
|
|
173
199
|
</script>
|
|
174
200
|
|
|
175
|
-
<div class={`space-y-3 ${measuring ? 'overflow-x-hidden' : ''}`}
|
|
201
|
+
<div bind:this={container} class={`space-y-3 ${measuring ? 'overflow-x-hidden' : ''}`}>
|
|
202
|
+
<!-- Toolbar filtros / acciones -->
|
|
176
203
|
<div class="flex flex-wrap items-center justify-between gap-3">
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
204
|
+
<div class="flex flex-wrap items-center gap-2">
|
|
205
|
+
{@render filters?.()}
|
|
206
|
+
{#if filterFields && filterFields.length}
|
|
207
|
+
<FilterPanel
|
|
208
|
+
fields={filterFields}
|
|
209
|
+
values={filterValues}
|
|
210
|
+
onapply={(defs) => manager.setFilters(defs)}
|
|
211
|
+
onclear={() => manager.clearFilters()}
|
|
212
|
+
/>
|
|
213
|
+
{/if}
|
|
214
|
+
</div>
|
|
215
|
+
|
|
216
|
+
<div class="flex items-center gap-2">
|
|
217
|
+
{#if showColumnToggle}
|
|
218
|
+
<ColumnVisibilityToggle
|
|
219
|
+
columns={manager.columns}
|
|
220
|
+
visible={manager.state.visibleColumns}
|
|
221
|
+
onToggle={(id, show) => manager.setColumnVisibility(id, show)}
|
|
222
|
+
/>
|
|
223
|
+
{/if}
|
|
224
|
+
</div>
|
|
193
225
|
</div>
|
|
194
226
|
|
|
195
|
-
|
|
227
|
+
<!-- Tabla -->
|
|
228
|
+
<div
|
|
229
|
+
class="rounded-2xl border border-neutral-200/80 bg-white/70 shadow-sm shadow-black/5 backdrop-blur-sm
|
|
230
|
+
dark:border-neutral-800/80 dark:bg-neutral-950/80"
|
|
231
|
+
>
|
|
196
232
|
<!-- HEADER -->
|
|
197
233
|
<div
|
|
198
|
-
class={`grid items-center border-b border-
|
|
234
|
+
class={`grid items-center border-b border-neutral-200/80 text-xs font-semibold tracking-wide text-neutral-500
|
|
235
|
+
uppercase dark:border-neutral-800/80 dark:text-neutral-400
|
|
236
|
+
${stickyHeader ? 'sticky top-0 z-10 bg-white/90 backdrop-blur-md dark:bg-neutral-950/90' : ''}`}
|
|
199
237
|
style={`grid-template-columns:${headerTemplateCols(colsForRender, endExtras)};`}
|
|
200
238
|
>
|
|
201
|
-
|
|
239
|
+
<!-- checkbox global -->
|
|
240
|
+
<div class="flex h-11 items-center px-3">
|
|
202
241
|
<input
|
|
203
242
|
type="checkbox"
|
|
204
|
-
|
|
205
|
-
|
|
243
|
+
class="h-4 w-4 rounded border-neutral-300 text-neutral-800 shadow-sm focus-visible:ring-2 focus-visible:ring-neutral-500 focus-visible:outline-none dark:border-neutral-700 dark:bg-neutral-900"
|
|
244
|
+
checked={allSelected}
|
|
206
245
|
onclick={(e) =>
|
|
207
246
|
(e.currentTarget as HTMLInputElement).checked
|
|
208
247
|
? manager.selectAllCurrentPage(rowId)
|
|
@@ -210,23 +249,21 @@
|
|
|
210
249
|
/>
|
|
211
250
|
</div>
|
|
212
251
|
|
|
252
|
+
<!-- headers -->
|
|
213
253
|
{#each colsForRender as cid}
|
|
254
|
+
{@const col = manager.getColumn(cid)}
|
|
214
255
|
<div
|
|
215
256
|
data-dt-head={cid}
|
|
216
|
-
class="flex h-
|
|
217
|
-
class:cursor-pointer={
|
|
218
|
-
onclick={() => headerClick(
|
|
257
|
+
class="flex h-11 items-center px-3 select-none"
|
|
258
|
+
class:cursor-pointer={col.sortable}
|
|
259
|
+
onclick={() => headerClick(col)}
|
|
219
260
|
oncontextmenu={(e) => onCellContext(e, null, cid, null)}
|
|
220
261
|
>
|
|
221
|
-
<div class="truncate">
|
|
222
|
-
{
|
|
223
|
-
{#if manager.state.sortBy === cid}
|
|
224
|
-
<span class="
|
|
225
|
-
{manager.state.sortDir === 'asc'
|
|
226
|
-
? '▲'
|
|
227
|
-
: manager.state.sortDir === 'desc'
|
|
228
|
-
? '▼'
|
|
229
|
-
: ''}
|
|
262
|
+
<div class="flex items-center gap-1 truncate">
|
|
263
|
+
<span>{col.header}</span>
|
|
264
|
+
{#if manager.state.sortBy === cid && manager.state.sortDir}
|
|
265
|
+
<span class="text-[10px] opacity-70">
|
|
266
|
+
{manager.state.sortDir === 'asc' ? '▲' : '▼'}
|
|
230
267
|
</span>
|
|
231
268
|
{/if}
|
|
232
269
|
</div>
|
|
@@ -234,48 +271,57 @@
|
|
|
234
271
|
{/each}
|
|
235
272
|
|
|
236
273
|
{#if rowActions}
|
|
237
|
-
<div class="h-
|
|
274
|
+
<div class="h-11 px-3"></div>
|
|
238
275
|
{:else if endExtras}
|
|
239
|
-
<div class="h-
|
|
276
|
+
<div class="h-11 px-3"></div>
|
|
240
277
|
{/if}
|
|
241
278
|
</div>
|
|
242
279
|
|
|
243
280
|
<!-- BODY -->
|
|
244
281
|
<div>
|
|
245
282
|
{#if manager.state.loading}
|
|
246
|
-
<div class="p-6 text-center
|
|
283
|
+
<div class="p-6 text-center text-sm text-neutral-500 dark:text-neutral-400">Cargando…</div>
|
|
247
284
|
{:else if manager.state.error}
|
|
248
|
-
<div class="p-6 text-center text-red-600">
|
|
285
|
+
<div class="p-6 text-center text-sm text-red-600 dark:text-red-400">
|
|
286
|
+
{manager.state.error}
|
|
287
|
+
</div>
|
|
249
288
|
{:else if manager.state.items.length === 0}
|
|
250
|
-
<div class="p-6 text-center
|
|
289
|
+
<div class="p-6 text-center text-sm text-neutral-500 dark:text-neutral-400">
|
|
290
|
+
Sin resultados
|
|
291
|
+
</div>
|
|
251
292
|
{:else}
|
|
252
293
|
{#each manager.state.items as row, i (rowId(row))}
|
|
253
294
|
<!-- ROW -->
|
|
254
295
|
<div
|
|
255
|
-
class={`grid items-
|
|
296
|
+
class={`grid items-stretch border-b border-neutral-100/60 last:border-b-0
|
|
297
|
+
dark:border-neutral-900 ${sizeRow}
|
|
298
|
+
transition-colors hover:bg-neutral-50/80 dark:hover:bg-neutral-900/60`}
|
|
256
299
|
style={`grid-template-columns:${headerTemplateCols(colsForRender, endExtras)};`}
|
|
257
300
|
>
|
|
258
|
-
<!-- col 0: check + expand -->
|
|
301
|
+
<!-- col 0: check + expand (start) -->
|
|
259
302
|
<div class="px-3 py-2">
|
|
260
303
|
<div class="flex items-center gap-2">
|
|
261
304
|
<input
|
|
262
305
|
type="checkbox"
|
|
306
|
+
class="h-4 w-4 rounded border-neutral-300 text-neutral-800 shadow-sm focus-visible:ring-2 focus-visible:ring-neutral-500 focus-visible:outline-none dark:border-neutral-700 dark:bg-neutral-900"
|
|
263
307
|
checked={manager.state.selected.has(rowId(row))}
|
|
264
308
|
onclick={() => manager.toggleSelect(rowId(row))}
|
|
265
309
|
oncontextmenu={(e) => onCellContext(e, row, '_check', i)}
|
|
266
310
|
/>
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
311
|
+
|
|
312
|
+
{#if hasHiddenColumns && expandIconPosition === 'start'}
|
|
313
|
+
<button
|
|
314
|
+
type="button"
|
|
315
|
+
class="inline-flex h-7 w-7 items-center justify-center rounded-lg border border-transparent text-neutral-500 hover:bg-neutral-100 dark:text-neutral-400 dark:hover:bg-neutral-800"
|
|
316
|
+
title={manager.isExpanded(rowId(row)) ? 'Ocultar detalles' : 'Ver detalles'}
|
|
317
|
+
onclick={() => manager.toggleExpand(rowId(row))}
|
|
318
|
+
>
|
|
319
|
+
{#if manager.isExpanded(rowId(row))}
|
|
320
|
+
<ChevronDown class="h-4 w-4" />
|
|
321
|
+
{:else}
|
|
322
|
+
<ChevronRight class="h-4 w-4" />
|
|
323
|
+
{/if}
|
|
324
|
+
</button>
|
|
279
325
|
{/if}
|
|
280
326
|
</div>
|
|
281
327
|
</div>
|
|
@@ -284,13 +330,12 @@
|
|
|
284
330
|
{#each colsForRender as cid}
|
|
285
331
|
{@const col = manager.getColumn(cid)}
|
|
286
332
|
<div
|
|
287
|
-
onkeydown={(e) => console.log('KEYDOWN', e)}
|
|
288
|
-
tabindex="0"
|
|
289
|
-
role="button"
|
|
290
333
|
data-dt-cell="1"
|
|
291
334
|
data-col-id={cid}
|
|
292
335
|
data-row-index={i}
|
|
293
|
-
|
|
336
|
+
tabindex="0"
|
|
337
|
+
role="button"
|
|
338
|
+
class="flex h-full w-full items-center px-3 text-sm text-neutral-800 outline-none focus-visible:ring-2 focus-visible:ring-neutral-500/70 dark:text-neutral-100"
|
|
294
339
|
onclick={() => onRowClick?.(row)}
|
|
295
340
|
oncontextmenu={(e) => onCellContext(e, row, cid, i)}
|
|
296
341
|
>
|
|
@@ -306,15 +351,18 @@
|
|
|
306
351
|
{#if rowActions}
|
|
307
352
|
<div class="px-3 text-right">
|
|
308
353
|
<div class="inline-flex items-center gap-2">
|
|
309
|
-
{#if expandIconPosition === 'end' &&
|
|
354
|
+
{#if expandIconPosition === 'end' && hasHiddenColumns}
|
|
310
355
|
<button
|
|
311
|
-
|
|
356
|
+
type="button"
|
|
357
|
+
class="inline-flex h-7 w-7 items-center justify-center rounded-lg border border-transparent text-neutral-500 hover:bg-neutral-100 dark:text-neutral-400 dark:hover:bg-neutral-800"
|
|
312
358
|
title={manager.isExpanded(rowId(row)) ? 'Ocultar detalles' : 'Ver detalles'}
|
|
313
359
|
onclick={() => manager.toggleExpand(rowId(row))}
|
|
314
360
|
>
|
|
315
|
-
{#if manager.isExpanded(rowId(row))}
|
|
316
|
-
|
|
317
|
-
|
|
361
|
+
{#if manager.isExpanded(rowId(row))}
|
|
362
|
+
<ChevronDown class="h-4 w-4" />
|
|
363
|
+
{:else}
|
|
364
|
+
<ChevronRight class="h-4 w-4" />
|
|
365
|
+
{/if}
|
|
318
366
|
</button>
|
|
319
367
|
{/if}
|
|
320
368
|
{@render rowActions(row)}
|
|
@@ -323,7 +371,8 @@
|
|
|
323
371
|
{:else if endExtras}
|
|
324
372
|
<div class="px-3 text-right">
|
|
325
373
|
<button
|
|
326
|
-
|
|
374
|
+
type="button"
|
|
375
|
+
class="inline-flex h-7 w-7 items-center justify-center rounded-lg border border-transparent text-neutral-500 hover:bg-neutral-100 dark:text-neutral-400 dark:hover:bg-neutral-800"
|
|
327
376
|
title={manager.isExpanded(rowId(row)) ? 'Ocultar detalles' : 'Ver detalles'}
|
|
328
377
|
onclick={() => manager.toggleExpand(rowId(row))}
|
|
329
378
|
>
|
|
@@ -337,17 +386,23 @@
|
|
|
337
386
|
{/if}
|
|
338
387
|
|
|
339
388
|
{#if manager.isExpanded(rowId(row))}
|
|
340
|
-
|
|
389
|
+
<!-- Detalles colapsados en modo "cards" -->
|
|
390
|
+
<div class="col-span-full bg-neutral-50/60 px-3 pt-1 pb-3 dark:bg-neutral-950/60">
|
|
341
391
|
<div class="grid gap-3 sm:grid-cols-2 md:grid-cols-3">
|
|
342
392
|
{#each manager.state.hiddenColumns as hid}
|
|
343
393
|
{#key hid}
|
|
344
394
|
{@const col = manager.columns.find((cc) => cc.id === hid)}
|
|
345
395
|
{#if col}
|
|
346
|
-
<div
|
|
347
|
-
|
|
396
|
+
<div
|
|
397
|
+
class="rounded-xl border border-neutral-200/70 bg-white/70 p-3 text-sm
|
|
398
|
+
dark:border-neutral-800/70 dark:bg-neutral-900/70"
|
|
399
|
+
>
|
|
400
|
+
<div
|
|
401
|
+
class="mb-1 text-[11px] font-medium tracking-wide text-neutral-500 uppercase dark:text-neutral-400"
|
|
402
|
+
>
|
|
348
403
|
{col.responsiveLabel ?? col.header}
|
|
349
404
|
</div>
|
|
350
|
-
<div class="text-sm">
|
|
405
|
+
<div class="text-sm text-neutral-800 dark:text-neutral-100">
|
|
351
406
|
{#if col.renderCollapsed}
|
|
352
407
|
{@render col.renderCollapsed(row)}
|
|
353
408
|
{:else if col.renderCell}
|
|
@@ -369,6 +424,7 @@
|
|
|
369
424
|
</div>
|
|
370
425
|
</div>
|
|
371
426
|
|
|
427
|
+
<!-- Paginación -->
|
|
372
428
|
<Pagination
|
|
373
429
|
page={manager.state.page}
|
|
374
430
|
perPage={manager.state.perPage}
|
|
@@ -378,6 +434,7 @@
|
|
|
378
434
|
onperpage={(n) => manager.setPerPage(n)}
|
|
379
435
|
/>
|
|
380
436
|
|
|
437
|
+
<!-- Context menu -->
|
|
381
438
|
<ContextMenu
|
|
382
439
|
bind:open={rightMenu.open}
|
|
383
440
|
x={rightMenu.x}
|
|
@@ -16,21 +16,21 @@ interface Props<T> {
|
|
|
16
16
|
}
|
|
17
17
|
declare function $$render<T extends {
|
|
18
18
|
id?: any;
|
|
19
|
-
}>():
|
|
19
|
+
}>(): {
|
|
20
20
|
props: Props<T>;
|
|
21
21
|
exports: {};
|
|
22
22
|
bindings: "";
|
|
23
23
|
slots: {};
|
|
24
24
|
events: {};
|
|
25
|
-
}
|
|
25
|
+
};
|
|
26
26
|
declare class __sveltets_Render<T extends {
|
|
27
27
|
id?: any;
|
|
28
28
|
}> {
|
|
29
|
-
props():
|
|
30
|
-
events():
|
|
31
|
-
slots():
|
|
29
|
+
props(): ReturnType<typeof $$render<T>>['props'];
|
|
30
|
+
events(): ReturnType<typeof $$render<T>>['events'];
|
|
31
|
+
slots(): ReturnType<typeof $$render<T>>['slots'];
|
|
32
32
|
bindings(): "";
|
|
33
|
-
exports():
|
|
33
|
+
exports(): {};
|
|
34
34
|
}
|
|
35
35
|
interface $$IsomorphicComponent {
|
|
36
36
|
new <T extends {
|
|
@@ -8,7 +8,7 @@ export class DataTableManager {
|
|
|
8
8
|
multiSelect: true,
|
|
9
9
|
columns: [],
|
|
10
10
|
loadMode: 'local',
|
|
11
|
-
data: []
|
|
11
|
+
data: []
|
|
12
12
|
});
|
|
13
13
|
state = $state({
|
|
14
14
|
ready: false,
|
|
@@ -34,18 +34,19 @@ export class DataTableManager {
|
|
|
34
34
|
constructor(options) {
|
|
35
35
|
const opts = options();
|
|
36
36
|
const columns = normalize(opts.columns);
|
|
37
|
-
this.options =
|
|
37
|
+
this.options = {
|
|
38
38
|
...opts,
|
|
39
39
|
columns
|
|
40
|
-
}
|
|
41
|
-
this.state =
|
|
40
|
+
};
|
|
41
|
+
this.state = {
|
|
42
42
|
...this.state,
|
|
43
43
|
perPage: this.options.perPage,
|
|
44
44
|
sortBy: opts.initialSortBy ?? null,
|
|
45
45
|
sortDir: opts.initialSortDir ?? null,
|
|
46
46
|
filters: opts.initialFilters ?? [],
|
|
47
|
-
visibleColumns: columns.map((c) => c.id)
|
|
48
|
-
}
|
|
47
|
+
visibleColumns: columns.map((c) => c.id)
|
|
48
|
+
};
|
|
49
|
+
// Sincroniza con cambios en options() (columnas, fetcher, etc.)
|
|
49
50
|
$effect(() => {
|
|
50
51
|
const new_options = options();
|
|
51
52
|
untrack(() => {
|
|
@@ -54,6 +55,7 @@ export class DataTableManager {
|
|
|
54
55
|
...new_options,
|
|
55
56
|
columns
|
|
56
57
|
};
|
|
58
|
+
// Lógica: si cambian opciones, recargamos data con los nuevos ajustes
|
|
57
59
|
this.load();
|
|
58
60
|
});
|
|
59
61
|
});
|
|
@@ -62,10 +64,21 @@ export class DataTableManager {
|
|
|
62
64
|
this.measured = map;
|
|
63
65
|
this.reflow();
|
|
64
66
|
}
|
|
65
|
-
get columns() {
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
67
|
+
get columns() {
|
|
68
|
+
return this.options.columns;
|
|
69
|
+
}
|
|
70
|
+
getColumn(id) {
|
|
71
|
+
return this.columns.find((c) => c.id === id);
|
|
72
|
+
}
|
|
73
|
+
isExpanded(id) {
|
|
74
|
+
return this.expanded.has(id);
|
|
75
|
+
}
|
|
76
|
+
toggleExpand(id) {
|
|
77
|
+
if (this.isExpanded(id))
|
|
78
|
+
this.expanded.delete(id);
|
|
79
|
+
else
|
|
80
|
+
this.expanded.add(id);
|
|
81
|
+
}
|
|
69
82
|
setColumnVisibility(id, show) {
|
|
70
83
|
if (show) {
|
|
71
84
|
this.forcedVisible.add(id);
|
|
@@ -101,20 +114,20 @@ export class DataTableManager {
|
|
|
101
114
|
// columnas que siempre se ocultan en móvil, aunque quepan
|
|
102
115
|
const mustHide = new Set();
|
|
103
116
|
if (available < 640) {
|
|
104
|
-
for (const c of cols)
|
|
117
|
+
for (const c of cols) {
|
|
105
118
|
if (c.hideOnMobile)
|
|
106
119
|
mustHide.add(c.id);
|
|
120
|
+
}
|
|
107
121
|
}
|
|
108
122
|
// empezamos conservando el orden original
|
|
109
123
|
let visible = origOrder.filter((id) => !mustHide.has(id));
|
|
110
124
|
const totalNeed = () => visible.reduce((sum, id) => sum + needOf(id), 0);
|
|
125
|
+
// Caso: no caben todas → ocultamos por prioridad
|
|
111
126
|
if (totalNeed() > available) {
|
|
112
|
-
// hay que ocultar: orden de descarte por prioridad (más alta => se quita antes)
|
|
113
|
-
// empate: quitamos antes las columnas que están más a la derecha (idx más alto)
|
|
114
127
|
const dropOrder = cols
|
|
115
128
|
.map((c, idx) => ({ id: c.id, pr: c.priority ?? 999, idx }))
|
|
116
129
|
.filter((x) => !mustHide.has(x.id))
|
|
117
|
-
.sort((a, b) =>
|
|
130
|
+
.sort((a, b) => b.pr - a.pr || b.idx - a.idx);
|
|
118
131
|
const hidden = new Set([...mustHide]);
|
|
119
132
|
for (const d of dropOrder) {
|
|
120
133
|
if (totalNeed() <= available)
|
|
@@ -125,7 +138,6 @@ export class DataTableManager {
|
|
|
125
138
|
hidden.add(d.id);
|
|
126
139
|
}
|
|
127
140
|
}
|
|
128
|
-
// overrides manuales
|
|
129
141
|
const visSet = new Set(visible);
|
|
130
142
|
for (const id of this.forcedHidden)
|
|
131
143
|
visSet.delete(id);
|
|
@@ -136,7 +148,7 @@ export class DataTableManager {
|
|
|
136
148
|
const finalHidden = origOrder.filter((id) => !finalVisible.includes(id));
|
|
137
149
|
return { visible: finalVisible, hidden: finalHidden };
|
|
138
150
|
}
|
|
139
|
-
//
|
|
151
|
+
// Caso: caben todas → respetamos orden original + overrides manuales
|
|
140
152
|
const visSet = new Set(visible);
|
|
141
153
|
for (const id of this.forcedHidden)
|
|
142
154
|
visSet.delete(id);
|
|
@@ -164,46 +176,79 @@ export class DataTableManager {
|
|
|
164
176
|
this.state.visibleColumns = plan.visible;
|
|
165
177
|
this.state.hiddenColumns = plan.hidden;
|
|
166
178
|
}
|
|
167
|
-
// NUEVO: para usar desde el ResizeObserver
|
|
168
179
|
reflowForWidth(width) {
|
|
169
180
|
this.lastWidth = width;
|
|
170
181
|
const base = this.visibilityPlan(width);
|
|
171
182
|
this.applyVisibility(this.mergeWithOverrides(base));
|
|
172
183
|
}
|
|
173
|
-
// NUEVO: reflow con el último ancho conocido (o infinito si no hay)
|
|
174
184
|
reflow() {
|
|
175
185
|
const width = this.lastWidth ?? Number.POSITIVE_INFINITY;
|
|
176
186
|
const base = this.visibilityPlan(width);
|
|
177
187
|
this.applyVisibility(this.mergeWithOverrides(base));
|
|
178
188
|
}
|
|
179
|
-
// Selección / paginación / sort / filtros
|
|
180
|
-
setPerPage(n) {
|
|
181
|
-
|
|
189
|
+
// Selección / paginación / sort / filtros
|
|
190
|
+
setPerPage(n) {
|
|
191
|
+
this.state.perPage = n;
|
|
192
|
+
this.state.page = 1;
|
|
193
|
+
return this.load();
|
|
194
|
+
}
|
|
195
|
+
setPage(p) {
|
|
196
|
+
this.state.page = p;
|
|
197
|
+
return this.load();
|
|
198
|
+
}
|
|
182
199
|
setSort(id) {
|
|
183
200
|
if (this.state.sortBy !== id) {
|
|
184
201
|
this.state.sortBy = id;
|
|
185
202
|
this.state.sortDir = 'asc';
|
|
186
203
|
}
|
|
187
204
|
else {
|
|
188
|
-
this.state.sortDir =
|
|
205
|
+
this.state.sortDir =
|
|
206
|
+
this.state.sortDir === 'asc'
|
|
207
|
+
? 'desc'
|
|
208
|
+
: this.state.sortDir === 'desc'
|
|
209
|
+
? null
|
|
210
|
+
: 'asc';
|
|
189
211
|
}
|
|
190
212
|
this.state.page = 1;
|
|
191
213
|
return this.load();
|
|
192
214
|
}
|
|
193
|
-
setFilters(filters) {
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
215
|
+
setFilters(filters) {
|
|
216
|
+
this.state.filters = filters;
|
|
217
|
+
this.state.page = 1;
|
|
218
|
+
return this.load();
|
|
219
|
+
}
|
|
220
|
+
clearFilters() {
|
|
221
|
+
this.state.filters = [];
|
|
222
|
+
this.state.page = 1;
|
|
223
|
+
return this.load();
|
|
224
|
+
}
|
|
225
|
+
toggleSelect(rowId) {
|
|
226
|
+
const s = this.state.selected;
|
|
227
|
+
if (s.has(rowId))
|
|
228
|
+
s.delete(rowId);
|
|
229
|
+
else
|
|
230
|
+
s.add(rowId);
|
|
231
|
+
}
|
|
232
|
+
clearSelection() {
|
|
233
|
+
this.state.selected.clear();
|
|
234
|
+
}
|
|
235
|
+
selectAllCurrentPage(getId = (r) => r.id) {
|
|
236
|
+
this.state.items.forEach((r) => this.state.selected.add(getId(r)));
|
|
237
|
+
}
|
|
238
|
+
// --------- CARGA DE DATOS ---------
|
|
198
239
|
async load() {
|
|
199
240
|
const { loadMode } = this.options;
|
|
200
241
|
this.state.loading = true;
|
|
201
242
|
this.state.error = undefined;
|
|
202
243
|
try {
|
|
203
|
-
if (loadMode === 'local')
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
244
|
+
if (loadMode === 'local') {
|
|
245
|
+
await this.loadLocal();
|
|
246
|
+
}
|
|
247
|
+
else {
|
|
248
|
+
await this.loadRemote();
|
|
249
|
+
}
|
|
250
|
+
// Después de tener items, recalculamos visibilidad de columnas
|
|
251
|
+
this.reflow();
|
|
207
252
|
}
|
|
208
253
|
catch (e) {
|
|
209
254
|
this.state.error = e?.message ?? 'Error al cargar';
|
|
@@ -212,7 +257,6 @@ export class DataTableManager {
|
|
|
212
257
|
this.state.loading = false;
|
|
213
258
|
this.state.ready = true;
|
|
214
259
|
}
|
|
215
|
-
this.reflow(); // asegura visibilidad coherente tras cargar
|
|
216
260
|
}
|
|
217
261
|
async loadRemote() {
|
|
218
262
|
const { fetcher } = this.options;
|
|
@@ -234,13 +278,19 @@ export class DataTableManager {
|
|
|
234
278
|
async loadLocal() {
|
|
235
279
|
const data = this.options.data ?? [];
|
|
236
280
|
let rows = [...data];
|
|
281
|
+
// Filtros locales
|
|
237
282
|
for (const f of this.state.filters) {
|
|
238
283
|
const col = f.columnId ? this.getColumn(f.columnId) : undefined;
|
|
239
284
|
rows = rows.filter((r) => {
|
|
240
|
-
const value = col
|
|
285
|
+
const value = col
|
|
286
|
+
? col.accessor
|
|
287
|
+
? col.accessor(r)
|
|
288
|
+
: r[col.id]
|
|
289
|
+
: r;
|
|
241
290
|
return applyFilterOp(value, f.op, f.value);
|
|
242
291
|
});
|
|
243
292
|
}
|
|
293
|
+
// Orden
|
|
244
294
|
if (this.state.sortBy && this.state.sortDir) {
|
|
245
295
|
const col = this.getColumn(this.state.sortBy);
|
|
246
296
|
rows.sort((a, b) => {
|
|
@@ -250,6 +300,7 @@ export class DataTableManager {
|
|
|
250
300
|
return this.state.sortDir === 'asc' ? cmp : -cmp;
|
|
251
301
|
});
|
|
252
302
|
}
|
|
303
|
+
// Paginación
|
|
253
304
|
const start = (this.state.page - 1) * this.state.perPage;
|
|
254
305
|
const end = start + this.state.perPage;
|
|
255
306
|
this.state.total = rows.length;
|
|
@@ -4,43 +4,74 @@ export type TDataTableColumnKey<T> = Extract<keyof T, string>;
|
|
|
4
4
|
export type TDataTableAccessor<T, R = any> = (row: T) => R;
|
|
5
5
|
export type TDataTableColumnType = 'text' | 'number' | 'currency' | 'date' | 'datetime' | 'boolean' | 'badge' | 'link' | 'code';
|
|
6
6
|
type TDataTableBaseColumn<T> = {
|
|
7
|
+
/** Título mostrado en el header */
|
|
7
8
|
header: string;
|
|
9
|
+
/** Ancho fijo en px (si lo quieres forzar) */
|
|
8
10
|
width?: number;
|
|
11
|
+
/** Ancho mínimo en px (usado también como fallback para auto-medición) */
|
|
9
12
|
minWidth?: number;
|
|
13
|
+
/** Prioridad para ocultar en responsive (más alto = se oculta antes) */
|
|
10
14
|
priority?: number;
|
|
15
|
+
/** Alineación del contenido de la celda */
|
|
11
16
|
align?: 'left' | 'center' | 'right';
|
|
17
|
+
/** Si la columna es ordenable */
|
|
12
18
|
sortable?: boolean;
|
|
19
|
+
/** Forzar ocultar en mobile, incluso si cabe */
|
|
13
20
|
hideOnMobile?: boolean;
|
|
21
|
+
/** Label a usar cuando la columna se muestra en el panel colapsado (expand) */
|
|
14
22
|
responsiveLabel?: string;
|
|
23
|
+
/** Clases extra para esta columna (celdas) */
|
|
15
24
|
class?: string;
|
|
25
|
+
/** Tipo semántico de columna (para Cell: formateo, badge, boolean, etc.) */
|
|
16
26
|
type?: TDataTableColumnType;
|
|
27
|
+
/** Opciones de Intl para number/date según el type */
|
|
17
28
|
format?: Intl.NumberFormatOptions | Intl.DateTimeFormatOptions;
|
|
29
|
+
/** Labels personalizados para boolean true/false */
|
|
18
30
|
trueLabel?: string;
|
|
19
31
|
falseLabel?: string;
|
|
20
32
|
};
|
|
21
33
|
/** Columna ligada a una key existente de T (autocomplete de keys) */
|
|
22
34
|
export type TDataTableKeyColumn<T, K extends TDataTableColumnKey<T> = TDataTableColumnKey<T>> = TDataTableBaseColumn<T> & {
|
|
35
|
+
/** ID de la columna, atado a una key real de T */
|
|
23
36
|
id: K;
|
|
37
|
+
/** Accessor opcional, si quieres derivar el valor a partir de la key */
|
|
24
38
|
accessor?: (row: T) => T[K];
|
|
39
|
+
/** Render personalizado para la celda en vista normal */
|
|
25
40
|
renderCell?: (row: T) => any;
|
|
41
|
+
/** Render personalizado para la celda en vista colapsada (expand) */
|
|
26
42
|
renderCollapsed?: (row: T) => any;
|
|
27
43
|
};
|
|
28
|
-
/** Columna virtual (id libre),
|
|
44
|
+
/** Columna virtual (id libre), pensada para valores derivados o acciones */
|
|
29
45
|
export type TDataTableVirtualColumn<T> = TDataTableBaseColumn<T> & {
|
|
46
|
+
/** ID de la columna, no está restringido a keyof T */
|
|
30
47
|
id: string;
|
|
48
|
+
/** Accessor requerido: cómo obtener el valor a mostrar en esta columna */
|
|
31
49
|
accessor: TDataTableAccessor<T>;
|
|
50
|
+
/** Render personalizado para la celda en vista normal */
|
|
32
51
|
renderCell?: (row: T) => any;
|
|
52
|
+
/** Render personalizado para la celda en vista colapsada (expand) */
|
|
33
53
|
renderCollapsed?: (row: T) => any;
|
|
34
54
|
};
|
|
35
|
-
|
|
55
|
+
/**
|
|
56
|
+
* Definición de columna: puede ser una columna ligada a una key real de T
|
|
57
|
+
* o una columna virtual con accessor obligatorio.
|
|
58
|
+
*/
|
|
59
|
+
export type TDataTableColumnDef<T> = TDataTableKeyColumn<T> | TDataTableVirtualColumn<T>;
|
|
36
60
|
export type TDataTableFilterOp = 'equals' | 'not_equals' | 'contains' | 'starts_with' | 'ends_with' | 'gt' | 'lt' | 'gte' | 'lte' | 'in' | 'not_in' | 'is_empty' | 'is_not_empty';
|
|
37
61
|
export type TDataTableFilterDef<T> = {
|
|
62
|
+
/** ID interno del filtro (para guardarlo, etc.) */
|
|
38
63
|
id: string;
|
|
64
|
+
/** Label visible del filtro (UI) */
|
|
39
65
|
label: string;
|
|
40
|
-
|
|
66
|
+
/**
|
|
67
|
+
* ID de columna a la que aplica el filtro.
|
|
68
|
+
* Puede ser una key de T o una columna virtual (string).
|
|
69
|
+
*/
|
|
70
|
+
columnId?: TDataTableColumnKey<T> | string;
|
|
41
71
|
op: TDataTableFilterOp;
|
|
42
72
|
value?: any;
|
|
43
|
-
|
|
73
|
+
/** Metadata auxiliar para la UI del filtro (select options, etc.) */
|
|
74
|
+
meta?: Record<string, unknown>;
|
|
44
75
|
};
|
|
45
76
|
export type TDataTableFetchResult<T> = {
|
|
46
77
|
items: T[];
|
|
@@ -57,17 +88,29 @@ export type TDataTableFetchParams = {
|
|
|
57
88
|
};
|
|
58
89
|
export type TDataTableLoadMode = 'local' | 'remote' | 'cursor';
|
|
59
90
|
export type TDataTableTableOptions<T> = {
|
|
91
|
+
/** ID lógico de la tabla (por si quieres guardar preferencias de usuario, etc.) */
|
|
60
92
|
id?: string;
|
|
93
|
+
/** Definición de columnas */
|
|
61
94
|
columns: TDataTableColumnDef<T>[];
|
|
95
|
+
/** Modo de carga de datos: local / remoto / cursor */
|
|
62
96
|
loadMode: TDataTableLoadMode;
|
|
97
|
+
/** Datos en memoria para loadMode = 'local' */
|
|
63
98
|
data?: T[];
|
|
99
|
+
/** Función fetcher para loadMode = 'remote' | 'cursor' */
|
|
64
100
|
fetcher?: (params: TDataTableFetchParams) => Promise<TDataTableFetchResult<T>>;
|
|
101
|
+
/** Tamaño de página por defecto */
|
|
65
102
|
perPage?: number;
|
|
103
|
+
/** Opciones disponibles de tamaño de página */
|
|
66
104
|
perPageOptions?: number[];
|
|
105
|
+
/** Permitir selección múltiple */
|
|
67
106
|
multiSelect?: boolean;
|
|
107
|
+
/** Mantener selección al cambiar de página */
|
|
68
108
|
keepSelectionOnPageChange?: boolean;
|
|
109
|
+
/** Sort inicial (id de columna) */
|
|
69
110
|
initialSortBy?: string | null;
|
|
111
|
+
/** Dirección de sort inicial */
|
|
70
112
|
initialSortDir?: TDataTableSortDir;
|
|
113
|
+
/** Filtros iniciales */
|
|
71
114
|
initialFilters?: TDataTableFilterDef<T>[];
|
|
72
115
|
};
|
|
73
116
|
export type TDataTableTableState<T> = {
|
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
type BuiltinFormTypes = 'delete' | 'duplicate' | 'change_status' | 'preview' | 'download' | 'create' | 'update' | 'error';
|
|
2
|
+
type ActionKeys<P extends Record<string, any>> = keyof P | BuiltinFormTypes;
|
|
3
|
+
type Payloads<P extends Record<string, any>> = {
|
|
4
|
+
[K in ActionKeys<P>]: K extends keyof P ? P[K] : unknown;
|
|
5
|
+
};
|
|
6
|
+
export interface IFormStatusStore<P extends Record<string, any> = {}> {
|
|
7
|
+
open<K extends ActionKeys<P>>(...args: Payloads<P>[K] extends void ? [type: K] : [type: K, data: Payloads<P>[K]]): void;
|
|
8
|
+
close(): void;
|
|
9
|
+
readonly type: ActionKeys<P> | null;
|
|
10
|
+
readonly data: Payloads<P>[ActionKeys<P>] | null;
|
|
11
|
+
readonly isOpen: boolean;
|
|
12
|
+
is<K extends ActionKeys<P>>(type: K): this is {
|
|
13
|
+
type: K;
|
|
14
|
+
data: Payloads<P>[K];
|
|
15
|
+
};
|
|
16
|
+
isSome<K extends ActionKeys<P>>(type: K[]): this is {
|
|
17
|
+
type: K;
|
|
18
|
+
data: Payloads<P>[K];
|
|
19
|
+
};
|
|
20
|
+
isNone<K extends ActionKeys<P>>(type: K[]): this is {
|
|
21
|
+
type: K;
|
|
22
|
+
data: Payloads<P>[K];
|
|
23
|
+
};
|
|
24
|
+
match<R>(handlers: Partial<{
|
|
25
|
+
[K in ActionKeys<P>]: (data: Payloads<P>[K]) => R;
|
|
26
|
+
}> & {
|
|
27
|
+
_: () => R;
|
|
28
|
+
}): R;
|
|
29
|
+
get<K extends keyof P>(type: K): P[K] | undefined;
|
|
30
|
+
expect<K extends keyof P>(type: K, msg?: string): P[K];
|
|
31
|
+
select<K extends keyof P, R>(type: K, map: (data: P[K]) => R, fallback?: R): R | undefined;
|
|
32
|
+
}
|
|
33
|
+
export declare class StoreFormStatus<P extends Record<string, any> = {}> implements IFormStatusStore<P> {
|
|
34
|
+
#private;
|
|
35
|
+
open<K extends ActionKeys<P>>(...args: Payloads<P>[K] extends void ? [type: K] : [type: K, data: Payloads<P>[K]]): void;
|
|
36
|
+
close: () => void;
|
|
37
|
+
get type(): ActionKeys<P> | null;
|
|
38
|
+
get data(): Payloads<P>[ActionKeys<P>] | null;
|
|
39
|
+
get isOpen(): boolean;
|
|
40
|
+
is<K extends ActionKeys<P>>(type: K): this is {
|
|
41
|
+
type: K;
|
|
42
|
+
data: Payloads<P>[K];
|
|
43
|
+
};
|
|
44
|
+
isSome<K extends ActionKeys<P>>(type: K[]): this is {
|
|
45
|
+
type: K;
|
|
46
|
+
data: Payloads<P>[K];
|
|
47
|
+
};
|
|
48
|
+
isNone<K extends ActionKeys<P>>(type: K[]): this is {
|
|
49
|
+
type: K;
|
|
50
|
+
data: Payloads<P>[K];
|
|
51
|
+
};
|
|
52
|
+
match<R>(handlers: Partial<{
|
|
53
|
+
[K in ActionKeys<P>]: (data: Payloads<P>[K]) => R;
|
|
54
|
+
}> & {
|
|
55
|
+
_: () => R;
|
|
56
|
+
}): R;
|
|
57
|
+
get<K extends keyof P>(type: K): P[K] | undefined;
|
|
58
|
+
expect<K extends keyof P>(type: K, msg?: string): P[K];
|
|
59
|
+
select<K extends keyof P, R>(type: K, map: (data: P[K]) => R, fallback?: R): R | undefined;
|
|
60
|
+
}
|
|
61
|
+
export {};
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
export class StoreFormStatus {
|
|
2
|
+
#type = $state(null);
|
|
3
|
+
#data = $state(null);
|
|
4
|
+
open(...args) {
|
|
5
|
+
const [type, maybeData] = args;
|
|
6
|
+
this.#type = type;
|
|
7
|
+
this.#data = (maybeData ?? null);
|
|
8
|
+
}
|
|
9
|
+
close = () => {
|
|
10
|
+
this.#type = null;
|
|
11
|
+
this.#data = null;
|
|
12
|
+
};
|
|
13
|
+
get type() { return this.#type; }
|
|
14
|
+
get data() { return this.#data; }
|
|
15
|
+
get isOpen() { return this.#type !== null; }
|
|
16
|
+
is(type) {
|
|
17
|
+
return this.#type === type;
|
|
18
|
+
}
|
|
19
|
+
isSome(type) {
|
|
20
|
+
return this.#type !== null && type.includes(this.#type);
|
|
21
|
+
}
|
|
22
|
+
isNone(type) {
|
|
23
|
+
return this.#type === null || !type.includes(this.#type);
|
|
24
|
+
}
|
|
25
|
+
match(handlers) {
|
|
26
|
+
if (!this.isOpen || this.#type === null)
|
|
27
|
+
return handlers._();
|
|
28
|
+
const fn = handlers[this.#type];
|
|
29
|
+
return fn ? fn(this.#data) : handlers._();
|
|
30
|
+
}
|
|
31
|
+
get(type) {
|
|
32
|
+
return this.#type === type
|
|
33
|
+
? (this.#data ?? undefined)
|
|
34
|
+
: undefined;
|
|
35
|
+
}
|
|
36
|
+
expect(type, msg = `Expected state '${String(type)}'`) {
|
|
37
|
+
const value = this.get(type);
|
|
38
|
+
if (value === undefined)
|
|
39
|
+
throw new Error(msg);
|
|
40
|
+
return value;
|
|
41
|
+
}
|
|
42
|
+
select(type, map, fallback) {
|
|
43
|
+
return this.#type === type ? map(this.#data) : fallback;
|
|
44
|
+
}
|
|
45
|
+
}
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@r2digisolutions/ui",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.27.1",
|
|
4
4
|
"private": false,
|
|
5
|
-
"packageManager": "bun@1.3.
|
|
5
|
+
"packageManager": "bun@1.3.3",
|
|
6
6
|
"publishConfig": {
|
|
7
7
|
"access": "public"
|
|
8
8
|
},
|
|
@@ -48,42 +48,42 @@
|
|
|
48
48
|
},
|
|
49
49
|
"devDependencies": {
|
|
50
50
|
"@changesets/cli": "2.29.7",
|
|
51
|
-
"@chromatic-com/storybook": "4.1.
|
|
52
|
-
"@eslint/compat": "
|
|
51
|
+
"@chromatic-com/storybook": "4.1.3",
|
|
52
|
+
"@eslint/compat": "2.0.0",
|
|
53
53
|
"@playwright/test": "1.56.1",
|
|
54
54
|
"@storybook/addon-essentials": "8.6.14",
|
|
55
55
|
"@storybook/addon-interactions": "8.6.14",
|
|
56
56
|
"@storybook/addon-svelte-csf": "5.0.10",
|
|
57
57
|
"@storybook/blocks": "8.6.14",
|
|
58
|
-
"@storybook/svelte": "10.0.
|
|
59
|
-
"@storybook/sveltekit": "10.0.
|
|
58
|
+
"@storybook/svelte": "10.0.8",
|
|
59
|
+
"@storybook/sveltekit": "10.0.8",
|
|
60
60
|
"@storybook/test": "8.6.14",
|
|
61
61
|
"@sveltejs/adapter-static": "3.0.10",
|
|
62
|
-
"@sveltejs/kit": "2.
|
|
63
|
-
"@sveltejs/package": "2.5.
|
|
62
|
+
"@sveltejs/kit": "2.49.0",
|
|
63
|
+
"@sveltejs/package": "2.5.6",
|
|
64
64
|
"@sveltejs/vite-plugin-svelte": "6.2.1",
|
|
65
65
|
"@tailwindcss/postcss": "4.1.17",
|
|
66
|
-
"@testing-library/svelte": "5.2.
|
|
67
|
-
"@vitest/browser": "4.0.
|
|
66
|
+
"@testing-library/svelte": "5.2.9",
|
|
67
|
+
"@vitest/browser": "4.0.13",
|
|
68
68
|
"changeset": "0.2.6",
|
|
69
69
|
"eslint": "9.39.1",
|
|
70
70
|
"eslint-config-prettier": "10.1.8",
|
|
71
71
|
"eslint-plugin-svelte": "3.13.0",
|
|
72
72
|
"globals": "16.5.0",
|
|
73
|
-
"jsdom": "27.
|
|
74
|
-
"lucide-svelte": "0.
|
|
73
|
+
"jsdom": "27.2.0",
|
|
74
|
+
"lucide-svelte": "0.554.0",
|
|
75
75
|
"prettier": "3.6.2",
|
|
76
76
|
"prettier-plugin-svelte": "3.4.0",
|
|
77
77
|
"prettier-plugin-tailwindcss": "0.7.1",
|
|
78
78
|
"publint": "0.3.15",
|
|
79
|
-
"storybook": "10.0.
|
|
80
|
-
"svelte": "5.43.
|
|
79
|
+
"storybook": "10.0.8",
|
|
80
|
+
"svelte": "5.43.14",
|
|
81
81
|
"svelte-check": "4.3.4",
|
|
82
82
|
"tailwindcss": "4.1.17",
|
|
83
83
|
"typescript": "5.9.3",
|
|
84
|
-
"typescript-eslint": "8.
|
|
85
|
-
"vite": "7.2.
|
|
86
|
-
"vitest": "4.0.
|
|
84
|
+
"typescript-eslint": "8.47.0",
|
|
85
|
+
"vite": "7.2.4",
|
|
86
|
+
"vitest": "4.0.13"
|
|
87
87
|
},
|
|
88
88
|
"dependencies": {
|
|
89
89
|
"@tailwindcss/container-queries": "0.1.1",
|