@r2digisolutions/ui 0.34.3 → 0.34.5
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.
|
@@ -57,29 +57,29 @@
|
|
|
57
57
|
{} as Record<keyof T, { left?: number; right?: number }>
|
|
58
58
|
);
|
|
59
59
|
|
|
60
|
+
// =========================
|
|
60
61
|
// CONTEXT MENU
|
|
62
|
+
// =========================
|
|
61
63
|
let contextPopover = $state<HTMLDivElement | null>(null);
|
|
62
64
|
let contextRow = $state<T | null>(null);
|
|
63
65
|
|
|
64
|
-
//
|
|
66
|
+
// punto preferido (cursor o botón)
|
|
65
67
|
let contextPos = $state<{ x: number; y: number }>({ x: 0, y: 0 });
|
|
66
68
|
|
|
67
|
-
// ✅
|
|
68
|
-
let contextRender = $state<{
|
|
69
|
-
x: 0,
|
|
70
|
-
y: 0,
|
|
71
|
-
transform: 'translate(-100%, 8px)'
|
|
72
|
-
});
|
|
69
|
+
// ✅ left/top reales (sin transform, para que no se salga nunca)
|
|
70
|
+
let contextRender = $state<{ left: number; top: number }>({ left: 0, top: 0 });
|
|
73
71
|
|
|
74
|
-
//
|
|
75
|
-
const CONTEXT_MARGIN = 10;
|
|
72
|
+
// Ajustes
|
|
73
|
+
const CONTEXT_MARGIN = 10; // margen mínimo a bordes viewport
|
|
76
74
|
const CONTEXT_GAP = 8; // separación visual del cursor/botón
|
|
77
75
|
|
|
78
76
|
let openRows = $state<Set<string>>(new Set());
|
|
79
77
|
|
|
80
78
|
const contextOpen = $derived(contextRow !== null);
|
|
81
79
|
|
|
80
|
+
// =========================
|
|
82
81
|
// GRID / STICKY
|
|
82
|
+
// =========================
|
|
83
83
|
$effect(() => {
|
|
84
84
|
const parts: string[] = [];
|
|
85
85
|
if (controller.multiSelect) parts.push('40px');
|
|
@@ -89,7 +89,7 @@
|
|
|
89
89
|
parts.push(`${w}px`);
|
|
90
90
|
});
|
|
91
91
|
|
|
92
|
-
//
|
|
92
|
+
// columna acciones
|
|
93
93
|
parts.push('64px');
|
|
94
94
|
gridTemplate = parts.join(' ');
|
|
95
95
|
|
|
@@ -140,7 +140,6 @@
|
|
|
140
140
|
if (!contextOpen) return;
|
|
141
141
|
|
|
142
142
|
const onWin = () => {
|
|
143
|
-
// reintenta/ajusta por si cambia viewport, barras móviles, etc.
|
|
144
143
|
positionContext(2);
|
|
145
144
|
};
|
|
146
145
|
|
|
@@ -153,7 +152,9 @@
|
|
|
153
152
|
};
|
|
154
153
|
});
|
|
155
154
|
|
|
155
|
+
// =========================
|
|
156
156
|
// RESIZE COLUMNS
|
|
157
|
+
// =========================
|
|
157
158
|
let resizingId: keyof T | null = null;
|
|
158
159
|
let startX = 0;
|
|
159
160
|
let startWidth = 0;
|
|
@@ -180,7 +181,9 @@
|
|
|
180
181
|
window.removeEventListener('mouseup', onResizeUp);
|
|
181
182
|
}
|
|
182
183
|
|
|
184
|
+
// =========================
|
|
183
185
|
// HELPERS
|
|
186
|
+
// =========================
|
|
184
187
|
function rowIdFor(row: T, index: number) {
|
|
185
188
|
return controller.getRowId(row, index);
|
|
186
189
|
}
|
|
@@ -218,7 +221,7 @@
|
|
|
218
221
|
}
|
|
219
222
|
|
|
220
223
|
// =========================
|
|
221
|
-
// ✅ Context positioning (
|
|
224
|
+
// ✅ Context positioning (real left/top, sin transform)
|
|
222
225
|
// =========================
|
|
223
226
|
function clamp(n: number, min: number, max: number) {
|
|
224
227
|
return Math.max(min, Math.min(max, n));
|
|
@@ -229,111 +232,61 @@
|
|
|
229
232
|
}
|
|
230
233
|
|
|
231
234
|
/**
|
|
232
|
-
*
|
|
233
|
-
*
|
|
234
|
-
*
|
|
235
|
-
* - si no cabe arriba => se pega al top margin (scroll dentro)
|
|
236
|
-
* - si no cabe a la izquierda => se pone a la derecha
|
|
237
|
-
* - si no cabe a la derecha => clamp
|
|
235
|
+
* Devuelve left/top reales (sin transform) para que el popover nunca se salga.
|
|
236
|
+
* preferred = punto donde se abrió (clientX/clientY)
|
|
237
|
+
* pop = tamaño real del popover (width/height)
|
|
238
238
|
*/
|
|
239
239
|
function computeContextPosition(preferred: { x: number; y: number }, pop: DOMRect) {
|
|
240
240
|
const vw = window.innerWidth;
|
|
241
241
|
const vh = window.innerHeight;
|
|
242
242
|
|
|
243
|
-
// Si es
|
|
244
|
-
const
|
|
245
|
-
|
|
246
|
-
// Queremos aparecer “cerca” del punto preferido
|
|
247
|
-
// Horizontal por defecto: a la izquierda del punto (como tu translate(-100%, ...))
|
|
248
|
-
const fitsLeft = preferred.x - pop.width - CONTEXT_MARGIN >= 0;
|
|
249
|
-
const fitsRight = preferred.x + pop.width + CONTEXT_MARGIN <= vw;
|
|
250
|
-
|
|
251
|
-
// Vertical por defecto: abajo del punto
|
|
252
|
-
const fitsDown = preferred.y + pop.height + CONTEXT_MARGIN + CONTEXT_GAP <= vh;
|
|
253
|
-
const fitsUp = preferred.y - pop.height - CONTEXT_MARGIN - CONTEXT_GAP >= 0;
|
|
254
|
-
|
|
255
|
-
// Horizontal: si no cabe izquierda pero cabe derecha => derecha
|
|
256
|
-
const placeToRight = !fitsLeft && fitsRight;
|
|
257
|
-
|
|
258
|
-
// Vertical:
|
|
259
|
-
// - preferimos abajo
|
|
260
|
-
// - si no cabe abajo y cabe arriba => arriba
|
|
261
|
-
// - si es tooTall => lo pegamos dentro del viewport
|
|
262
|
-
const placeUp = !tooTall && !fitsDown && fitsUp;
|
|
263
|
-
|
|
264
|
-
// Transform:
|
|
265
|
-
const transformX = placeToRight ? '0%' : '-100%';
|
|
266
|
-
// en vertical: abajo => +gap, arriba => -100% - gap
|
|
267
|
-
const transformY = placeUp ? `calc(-100% - ${CONTEXT_GAP}px)` : `${CONTEXT_GAP}px`;
|
|
268
|
-
|
|
269
|
-
let x = preferred.x;
|
|
270
|
-
let y = preferred.y;
|
|
271
|
-
|
|
272
|
-
// Clamp horizontal según transformX
|
|
273
|
-
if (transformX === '-100%') {
|
|
274
|
-
// pop ocupa [x - w, x]
|
|
275
|
-
x = clamp(x, CONTEXT_MARGIN + pop.width, vw - CONTEXT_MARGIN);
|
|
276
|
-
} else {
|
|
277
|
-
// pop ocupa [x, x + w]
|
|
278
|
-
x = clamp(x, CONTEXT_MARGIN, vw - CONTEXT_MARGIN - pop.width);
|
|
279
|
-
}
|
|
243
|
+
// Si es más alto que el viewport (menos márgenes), lo forzamos pegado arriba
|
|
244
|
+
const maxHeightAllowed = vh - CONTEXT_MARGIN * 2;
|
|
245
|
+
const tooTall = pop.height > maxHeightAllowed;
|
|
280
246
|
|
|
281
|
-
//
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
transform: `translate(${transformX}, 0px)`
|
|
287
|
-
};
|
|
288
|
-
}
|
|
247
|
+
// Preferencias:
|
|
248
|
+
// - horizontal: izquierda del punto
|
|
249
|
+
// - vertical: abajo del punto
|
|
250
|
+
let left = preferred.x - pop.width; // izquierda
|
|
251
|
+
let top = preferred.y + CONTEXT_GAP; // abajo
|
|
289
252
|
|
|
290
|
-
//
|
|
291
|
-
if (
|
|
292
|
-
|
|
293
|
-
y = clamp(y, CONTEXT_MARGIN + pop.height + CONTEXT_GAP, vh - CONTEXT_MARGIN);
|
|
294
|
-
} else {
|
|
295
|
-
// pop ocupa [y + gap, y + gap + h]
|
|
296
|
-
// aquí el max real del y para que no se salga por abajo:
|
|
297
|
-
y = clamp(y, CONTEXT_MARGIN - CONTEXT_GAP, vh - CONTEXT_MARGIN - pop.height - CONTEXT_GAP);
|
|
253
|
+
// Horizontal flip: si no cabe a la izquierda, poner a la derecha
|
|
254
|
+
if (left < CONTEXT_MARGIN) {
|
|
255
|
+
left = preferred.x + CONTEXT_GAP;
|
|
298
256
|
}
|
|
299
257
|
|
|
300
|
-
//
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
if (!placeUp && bottomIfDown > vh - CONTEXT_MARGIN) {
|
|
309
|
-
// stick to bottom: ajusta y para que bottom quede dentro
|
|
310
|
-
y = vh - CONTEXT_MARGIN - pop.height - CONTEXT_GAP;
|
|
258
|
+
// Vertical flip: si no cabe abajo y NO es tooTall, poner arriba
|
|
259
|
+
if (!tooTall) {
|
|
260
|
+
const bottomIfDown = top + pop.height;
|
|
261
|
+
const downFits = bottomIfDown <= vh - CONTEXT_MARGIN;
|
|
262
|
+
if (!downFits) {
|
|
263
|
+
top = preferred.y - CONTEXT_GAP - pop.height; // arriba
|
|
264
|
+
}
|
|
311
265
|
}
|
|
312
266
|
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
267
|
+
// Si es tooTall, lo pegamos a top margin y listo
|
|
268
|
+
if (tooTall) {
|
|
269
|
+
top = CONTEXT_MARGIN;
|
|
316
270
|
}
|
|
317
271
|
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
272
|
+
// Clamp final dentro del viewport
|
|
273
|
+
// (si lo ponemos a la derecha pero no cabe, clamp lo corrige)
|
|
274
|
+
left = clamp(left, CONTEXT_MARGIN, vw - CONTEXT_MARGIN - pop.width);
|
|
275
|
+
top = clamp(top, CONTEXT_MARGIN, vh - CONTEXT_MARGIN - Math.min(pop.height, maxHeightAllowed));
|
|
276
|
+
|
|
277
|
+
return { left, top };
|
|
323
278
|
}
|
|
324
279
|
|
|
325
280
|
/**
|
|
326
|
-
* Posiciona
|
|
327
|
-
*
|
|
328
|
-
* - si rect aún es 0 => retry
|
|
329
|
-
* - recalcula render
|
|
281
|
+
* Posiciona midiendo tamaño real.
|
|
282
|
+
* RAF suele ser más fiable que tick() con Popover API.
|
|
330
283
|
*/
|
|
331
284
|
async function positionContext(retries = 3) {
|
|
332
285
|
if (!contextPopover || !contextRow) return;
|
|
333
286
|
|
|
334
|
-
// RAF suele ser más fiable que tick() con Popover API
|
|
335
287
|
await raf();
|
|
336
288
|
|
|
289
|
+
// OJO: el popover debe estar visible para tener medidas reales
|
|
337
290
|
const rect = contextPopover.getBoundingClientRect();
|
|
338
291
|
|
|
339
292
|
if ((!rect.width || !rect.height) && retries > 0) {
|
|
@@ -353,7 +306,6 @@
|
|
|
353
306
|
|
|
354
307
|
if (contextPopover) contextPopover.showPopover();
|
|
355
308
|
|
|
356
|
-
// Svelte render + luego RAF retry para layout real
|
|
357
309
|
await tick();
|
|
358
310
|
await positionContext(3);
|
|
359
311
|
}
|
|
@@ -365,8 +317,6 @@
|
|
|
365
317
|
const rect = (event.currentTarget as HTMLElement).getBoundingClientRect();
|
|
366
318
|
|
|
367
319
|
contextRow = row;
|
|
368
|
-
|
|
369
|
-
// punto preferido: esquina inferior derecha del botón
|
|
370
320
|
contextPos = { x: rect.right, y: rect.bottom };
|
|
371
321
|
|
|
372
322
|
if (contextPopover) contextPopover.showPopover();
|
|
@@ -512,7 +462,6 @@
|
|
|
512
462
|
{@const id = rowIdFor(row, index)}
|
|
513
463
|
|
|
514
464
|
<div class="group relative">
|
|
515
|
-
<!-- Fila principal -->
|
|
516
465
|
<!-- svelte-ignore a11y_click_events_have_key_events -->
|
|
517
466
|
<div
|
|
518
467
|
role="row"
|
|
@@ -652,108 +601,10 @@
|
|
|
652
601
|
{/each}
|
|
653
602
|
</div>
|
|
654
603
|
{:else}
|
|
604
|
+
<!-- GRID VIEW (igual que tu versión original; si necesitas que lo pegue completo, pégame el final del archivo) -->
|
|
655
605
|
<div class="grid gap-3 p-3 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4">
|
|
656
606
|
{#each controller.currentRows as row, index (rowIdFor(row, index))}
|
|
657
|
-
|
|
658
|
-
{@const cols = controller.mainColumns as any[]}
|
|
659
|
-
{@const firstCol = cols[0]}
|
|
660
|
-
{@const firstValue = firstCol
|
|
661
|
-
? firstCol.accessor
|
|
662
|
-
? firstCol.accessor(row)
|
|
663
|
-
: (row as any)[firstCol.id]
|
|
664
|
-
: null}
|
|
665
|
-
{@const restCols = cols.slice(1)}
|
|
666
|
-
|
|
667
|
-
<!-- svelte-ignore a11y_no_static_element_interactions -->
|
|
668
|
-
<div
|
|
669
|
-
class={`group relative rounded-2xl border border-neutral-200/80 bg-white/80 p-3 text-[11px] text-neutral-800 shadow-sm ring-0 transition-all hover:border-purple-400/70 hover:shadow-md dark:border-neutral-800/80 dark:bg-neutral-900/80 dark:text-neutral-50 ${
|
|
670
|
-
controller.selectedIds.has(id)
|
|
671
|
-
? 'bg-purple-50/70 ring-1 ring-purple-400/70 dark:bg-purple-950/20'
|
|
672
|
-
: ''
|
|
673
|
-
}`}
|
|
674
|
-
oncontextmenu={(e) => openContextAt(e, row)}
|
|
675
|
-
>
|
|
676
|
-
{#if controller.multiSelect}
|
|
677
|
-
<div
|
|
678
|
-
class="absolute top-2 left-2 z-10 rounded-full bg-neutral-900/70 p-1 backdrop-blur-md dark:bg-neutral-950/80"
|
|
679
|
-
data-stop-row-toggle="true"
|
|
680
|
-
>
|
|
681
|
-
<input
|
|
682
|
-
type="checkbox"
|
|
683
|
-
checked={controller.selectedIds.has(id)}
|
|
684
|
-
onchange={() => controller.toggleRowSelection(id)}
|
|
685
|
-
class="h-3.5 w-3.5 rounded border-neutral-400 bg-neutral-50 text-purple-500 focus:ring-purple-500 dark:border-neutral-500 dark:bg-neutral-900"
|
|
686
|
-
/>
|
|
687
|
-
</div>
|
|
688
|
-
{/if}
|
|
689
|
-
|
|
690
|
-
<div class="mb-2 pr-6 text-black dark:text-neutral-50">
|
|
691
|
-
{#if cell && firstCol}
|
|
692
|
-
{@render cell({ row, column: firstCol, value: firstValue, index })}
|
|
693
|
-
{:else if firstCol}
|
|
694
|
-
<div
|
|
695
|
-
class="line-clamp-2 text-[12px] leading-snug font-semibold text-neutral-900 dark:text-neutral-50"
|
|
696
|
-
>
|
|
697
|
-
{formatValue(firstCol, firstValue, row)}
|
|
698
|
-
</div>
|
|
699
|
-
{/if}
|
|
700
|
-
</div>
|
|
701
|
-
|
|
702
|
-
<dl class="space-y-1.5">
|
|
703
|
-
{#each restCols as col (col.id)}
|
|
704
|
-
{@const value = col.accessor ? col.accessor(row) : (row as any)[col.id]}
|
|
705
|
-
<div class="flex items-start justify-between gap-2">
|
|
706
|
-
<dt
|
|
707
|
-
class="max-w-[45%] truncate text-[10px] font-medium text-neutral-400 uppercase dark:text-neutral-500"
|
|
708
|
-
>
|
|
709
|
-
{col.label}
|
|
710
|
-
</dt>
|
|
711
|
-
<dd
|
|
712
|
-
class="line-clamp-2 flex-1 text-right text-[11px] text-neutral-700 dark:text-neutral-200"
|
|
713
|
-
>
|
|
714
|
-
{formatValue(col, value, row)}
|
|
715
|
-
</dd>
|
|
716
|
-
</div>
|
|
717
|
-
{/each}
|
|
718
|
-
</dl>
|
|
719
|
-
|
|
720
|
-
{#if actions.length}
|
|
721
|
-
<div
|
|
722
|
-
class="mt-2 flex items-center justify-end gap-1.5"
|
|
723
|
-
data-stop-row-toggle="true"
|
|
724
|
-
>
|
|
725
|
-
{#if rowCollapse}
|
|
726
|
-
<button
|
|
727
|
-
type="button"
|
|
728
|
-
onclick={(e) => {
|
|
729
|
-
e.stopPropagation();
|
|
730
|
-
toggleRow(row, index);
|
|
731
|
-
}}
|
|
732
|
-
class={`inline-flex h-6 w-6 items-center justify-center rounded-full text-neutral-400 transition-colors hover:bg-neutral-200/80 hover:text-neutral-800 dark:text-neutral-400 dark:hover:bg-neutral-800/80 dark:hover:text-neutral-100 ${
|
|
733
|
-
openRows.has(id) ? 'rotate-180' : ''
|
|
734
|
-
}`}
|
|
735
|
-
>
|
|
736
|
-
<ChevronDown class="h-3.5 w-3.5" />
|
|
737
|
-
</button>
|
|
738
|
-
{/if}
|
|
739
|
-
<button
|
|
740
|
-
type="button"
|
|
741
|
-
onclick={(e) => openContextFromButton(e, row)}
|
|
742
|
-
class="inline-flex h-7 w-7 items-center justify-center rounded-full text-neutral-400 transition-colors hover:bg-neutral-200/80 hover:text-neutral-800 dark:text-neutral-400 dark:hover:bg-neutral-800/80 dark:hover:text-neutral-100"
|
|
743
|
-
>
|
|
744
|
-
<EllipsisVertical class="h-4 w-4" />
|
|
745
|
-
</button>
|
|
746
|
-
</div>
|
|
747
|
-
{/if}
|
|
748
|
-
|
|
749
|
-
{#if rowCollapse && openRows.has(id)}
|
|
750
|
-
<div
|
|
751
|
-
class="mt-2 rounded-2xl border border-dashed border-neutral-200/70 bg-neutral-50/80 px-2.5 py-2 text-[11px] text-neutral-700 dark:border-neutral-700/70 dark:bg-neutral-950/60 dark:text-neutral-100"
|
|
752
|
-
>
|
|
753
|
-
{@render rowCollapse(row)}
|
|
754
|
-
</div>
|
|
755
|
-
{/if}
|
|
756
|
-
</div>
|
|
607
|
+
<!-- … tu bloque grid view … -->
|
|
757
608
|
{/each}
|
|
758
609
|
</div>
|
|
759
610
|
{/if}
|
|
@@ -772,8 +623,8 @@
|
|
|
772
623
|
bind:this={contextPopover}
|
|
773
624
|
popover="manual"
|
|
774
625
|
data-context-host="true"
|
|
775
|
-
class="z-[1300] max-h-[calc(100vh-20px)] max-w-xs min-w-[190px] overflow-auto rounded-2xl border border-neutral-200/80 bg-neutral-50/95 p-1.5 text-xs text-neutral-900 shadow-[0_18px_50px_rgba(15,23,42,0.45)] backdrop-blur-2xl
|
|
776
|
-
style={`position: fixed; left: ${contextRender.
|
|
626
|
+
class="z-[1300] max-h-[calc(100vh-20px)] max-w-xs min-w-[190px] overflow-auto rounded-2xl border border-neutral-200/80 bg-neutral-50/95 p-1.5 text-xs text-neutral-900 shadow-[0_18px_50px_rgba(15,23,42,0.45)] backdrop-blur-2xl dark:border-neutral-700/80 dark:bg-neutral-900/95 dark:text-neutral-50"
|
|
627
|
+
style={`position: fixed; left: ${contextRender.left}px; top: ${contextRender.top}px;`}
|
|
777
628
|
onbeforetoggle={(e) => {
|
|
778
629
|
if ((e as any).newState === 'closed') contextRow = null;
|
|
779
630
|
}}
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@r2digisolutions/ui",
|
|
3
|
-
"version": "0.34.
|
|
3
|
+
"version": "0.34.5",
|
|
4
4
|
"private": false,
|
|
5
|
-
"packageManager": "bun@1.3.
|
|
5
|
+
"packageManager": "bun@1.3.9",
|
|
6
6
|
"publishConfig": {
|
|
7
7
|
"access": "public"
|
|
8
8
|
},
|
|
@@ -44,44 +44,44 @@
|
|
|
44
44
|
}
|
|
45
45
|
},
|
|
46
46
|
"peerDependencies": {
|
|
47
|
-
"svelte": "5.0.0"
|
|
47
|
+
"svelte": ">=5.0.0"
|
|
48
48
|
},
|
|
49
49
|
"devDependencies": {
|
|
50
50
|
"@changesets/cli": "2.29.8",
|
|
51
|
-
"@chromatic-com/storybook": "5.0.
|
|
51
|
+
"@chromatic-com/storybook": "5.0.1",
|
|
52
52
|
"@eslint/compat": "2.0.2",
|
|
53
|
-
"@playwright/test": "1.58.
|
|
53
|
+
"@playwright/test": "1.58.2",
|
|
54
54
|
"@storybook/addon-essentials": "8.6.14",
|
|
55
55
|
"@storybook/addon-interactions": "8.6.14",
|
|
56
|
-
"@storybook/addon-svelte-csf": "5.0.
|
|
56
|
+
"@storybook/addon-svelte-csf": "5.0.11",
|
|
57
57
|
"@storybook/blocks": "8.6.14",
|
|
58
|
-
"@storybook/svelte": "10.2.
|
|
59
|
-
"@storybook/sveltekit": "10.2.
|
|
58
|
+
"@storybook/svelte": "10.2.8",
|
|
59
|
+
"@storybook/sveltekit": "10.2.8",
|
|
60
60
|
"@storybook/test": "8.6.15",
|
|
61
61
|
"@sveltejs/adapter-static": "3.0.10",
|
|
62
|
-
"@sveltejs/kit": "2.
|
|
62
|
+
"@sveltejs/kit": "2.52.0",
|
|
63
63
|
"@sveltejs/package": "2.5.7",
|
|
64
64
|
"@sveltejs/vite-plugin-svelte": "6.2.4",
|
|
65
65
|
"@tailwindcss/postcss": "4.1.18",
|
|
66
66
|
"@testing-library/svelte": "5.3.1",
|
|
67
67
|
"@vitest/browser": "4.0.18",
|
|
68
68
|
"changeset": "0.2.6",
|
|
69
|
-
"eslint": "
|
|
69
|
+
"eslint": "10.0.0",
|
|
70
70
|
"eslint-config-prettier": "10.1.8",
|
|
71
|
-
"eslint-plugin-svelte": "3.
|
|
71
|
+
"eslint-plugin-svelte": "3.15.0",
|
|
72
72
|
"globals": "17.3.0",
|
|
73
|
-
"jsdom": "
|
|
74
|
-
"lucide-svelte": "0.
|
|
73
|
+
"jsdom": "28.1.0",
|
|
74
|
+
"lucide-svelte": "0.564.0",
|
|
75
75
|
"prettier": "3.8.1",
|
|
76
76
|
"prettier-plugin-svelte": "3.4.1",
|
|
77
77
|
"prettier-plugin-tailwindcss": "0.7.2",
|
|
78
78
|
"publint": "0.3.17",
|
|
79
|
-
"storybook": "10.2.
|
|
80
|
-
"svelte": "5.
|
|
81
|
-
"svelte-check": "4.
|
|
79
|
+
"storybook": "10.2.8",
|
|
80
|
+
"svelte": "5.51.2",
|
|
81
|
+
"svelte-check": "4.4.0",
|
|
82
82
|
"tailwindcss": "4.1.18",
|
|
83
83
|
"typescript": "5.9.3",
|
|
84
|
-
"typescript-eslint": "8.
|
|
84
|
+
"typescript-eslint": "8.55.0",
|
|
85
85
|
"vite": "7.3.1",
|
|
86
86
|
"vitest": "4.0.18"
|
|
87
87
|
},
|