@svadmin/ui 0.32.10 → 0.33.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.
|
@@ -3,13 +3,30 @@
|
|
|
3
3
|
import { cn } from '../utils.js';
|
|
4
4
|
import {
|
|
5
5
|
createTable,
|
|
6
|
+
createCoreRowModel,
|
|
7
|
+
column_getCanSort,
|
|
8
|
+
column_getIsSorted,
|
|
9
|
+
column_toggleSorting,
|
|
10
|
+
column_getIsVisible,
|
|
11
|
+
column_toggleVisibility,
|
|
12
|
+
header_getSize,
|
|
13
|
+
table_getRowModel,
|
|
14
|
+
table_getHeaderGroups,
|
|
15
|
+
table_getAllLeafColumns,
|
|
16
|
+
table_getIsAllRowsSelected,
|
|
17
|
+
table_toggleAllRowsSelected,
|
|
18
|
+
row_getIsSelected,
|
|
19
|
+
row_toggleSelected,
|
|
20
|
+
row_getAllVisibleCells,
|
|
21
|
+
row_getIsExpanded,
|
|
22
|
+
row_toggleExpanded,
|
|
23
|
+
cell_getValue,
|
|
6
24
|
type ColumnDef,
|
|
7
25
|
type SortingState,
|
|
8
26
|
type RowSelectionState,
|
|
9
27
|
type ColumnVisibilityState,
|
|
10
28
|
type ExpandedState,
|
|
11
29
|
} from '@tanstack/svelte-table';
|
|
12
|
-
import { createCoreRowModel } from '@tanstack/table-core';
|
|
13
30
|
|
|
14
31
|
import { useList, useDelete, useDeleteMany, getResource, notify } from '@svadmin/core';
|
|
15
32
|
import type { Pagination as PaginationState, Sort, Filter, FieldDefinition } from '@svadmin/core';
|
|
@@ -350,7 +367,7 @@
|
|
|
350
367
|
confirmMessage = t('common.batchDeleteConfirm', { count: ids.length });
|
|
351
368
|
confirmAction = async () => {
|
|
352
369
|
try {
|
|
353
|
-
await deleteManyMutation.mutateAsync({ ids, resource: resourceName
|
|
370
|
+
await deleteManyMutation.mutateAsync({ ids, resource: resourceName });
|
|
354
371
|
notify({ type: 'success', message: t('common.batchDeleteSuccess', { count: ids.length }) });
|
|
355
372
|
} catch {
|
|
356
373
|
notify({ type: 'error', message: t('common.batchDeletePartialFail', { failed: 1, total: ids.length }) });
|
|
@@ -423,10 +440,10 @@
|
|
|
423
440
|
{/snippet}
|
|
424
441
|
</DropdownMenu.Trigger>
|
|
425
442
|
<DropdownMenu.Content align="end" class="w-48">
|
|
426
|
-
{#each tbl
|
|
443
|
+
{#each table_getAllLeafColumns(tbl).filter((c: any) => !c.id.startsWith('_')) as column}
|
|
427
444
|
<DropdownMenu.CheckboxItem
|
|
428
|
-
checked={column
|
|
429
|
-
onCheckedChange={(v) => column
|
|
445
|
+
checked={column_getIsVisible(column)}
|
|
446
|
+
onCheckedChange={(v) => column_toggleVisibility(column, !!v)}
|
|
430
447
|
>
|
|
431
448
|
{visibleFields.find(f => f.key === column.id)?.label ?? column.id}
|
|
432
449
|
</DropdownMenu.CheckboxItem>
|
|
@@ -546,7 +563,7 @@
|
|
|
546
563
|
<div class="hidden md:block">
|
|
547
564
|
<Table.Root>
|
|
548
565
|
<Table.Header>
|
|
549
|
-
{#each tbl
|
|
566
|
+
{#each table_getHeaderGroups(tbl) as headerGroup}
|
|
550
567
|
<DraggableHeader
|
|
551
568
|
columns={headerGroup.headers.map((h: any) => ({ id: h.column.id, header: h }))}
|
|
552
569
|
resourceName={resourceName}
|
|
@@ -557,28 +574,28 @@
|
|
|
557
574
|
<Table.Head
|
|
558
575
|
{...dragProps}
|
|
559
576
|
class={cn("bg-transparent hover:bg-muted/10 border-b border-border/20 uppercase tracking-[0.12em] text-[10px] text-muted-foreground/70 font-semibold py-4", dragProps.class)}
|
|
560
|
-
style={header
|
|
577
|
+
style={header_getSize(header) != null && header_getSize(header) !== 150 ? `width:${header_getSize(header)}px` : undefined}
|
|
561
578
|
>
|
|
562
579
|
{#if header.id === '_select'}
|
|
563
580
|
<Checkbox
|
|
564
|
-
checked={tbl
|
|
565
|
-
onCheckedChange={() => tbl
|
|
581
|
+
checked={table_getIsAllRowsSelected(tbl)}
|
|
582
|
+
onCheckedChange={() => table_toggleAllRowsSelected(tbl)}
|
|
566
583
|
/>
|
|
567
584
|
{:else if header.id === '_expand'}
|
|
568
585
|
<!-- empty -->
|
|
569
586
|
{:else if header.id === '_actions'}
|
|
570
587
|
<span class="text-right block">{t('common.actions')}</span>
|
|
571
|
-
{:else if header.column
|
|
588
|
+
{:else if column_getCanSort(header.column)}
|
|
572
589
|
<Button
|
|
573
590
|
variant="ghost"
|
|
574
591
|
size="sm"
|
|
575
592
|
class="flex items-center gap-1 hover:text-foreground -ml-2 h-auto py-1 px-2 uppercase tracking-wide text-[0.7rem] font-semibold"
|
|
576
|
-
onclick={() => header.column
|
|
593
|
+
onclick={() => column_toggleSorting(header.column)}
|
|
577
594
|
>
|
|
578
595
|
{visibleFields.find(f => f.key === header.id)?.label ?? header.id}
|
|
579
596
|
<span class="text-xs opacity-50">
|
|
580
|
-
{#if header.column
|
|
581
|
-
{:else if header.column
|
|
597
|
+
{#if column_getIsSorted(header.column) === 'asc'}↑
|
|
598
|
+
{:else if column_getIsSorted(header.column) === 'desc'}↓
|
|
582
599
|
{:else}⇅
|
|
583
600
|
{/if}
|
|
584
601
|
</span>
|
|
@@ -592,23 +609,23 @@
|
|
|
592
609
|
{/each}
|
|
593
610
|
</Table.Header>
|
|
594
611
|
<Table.Body>
|
|
595
|
-
{#each tbl
|
|
612
|
+
{#each table_getRowModel(tbl).rows as row}
|
|
596
613
|
{@const record = row.original}
|
|
597
614
|
{@const id = record[primaryKey] as string | number}
|
|
598
615
|
<ContextMenu.Root>
|
|
599
616
|
<ContextMenu.Trigger>
|
|
600
617
|
{#snippet child({ props })}
|
|
601
|
-
<Table.Row {...props} class="transition-all duration-300 border-b border-border/10 {row
|
|
602
|
-
{#each row
|
|
618
|
+
<Table.Row {...props} class="transition-all duration-300 border-b border-border/10 {row_getIsSelected(row) ? 'bg-primary/5' : 'hover:bg-muted/20'}">
|
|
619
|
+
{#each row_getAllVisibleCells(row) as cell}
|
|
603
620
|
<Table.Cell>
|
|
604
621
|
{#if cell.column.id === '_select'}
|
|
605
622
|
<Checkbox
|
|
606
|
-
checked={row
|
|
607
|
-
onCheckedChange={() => row
|
|
623
|
+
checked={row_getIsSelected(row)}
|
|
624
|
+
onCheckedChange={() => row_toggleSelected(row)}
|
|
608
625
|
/>
|
|
609
626
|
{:else if cell.column.id === '_expand'}
|
|
610
|
-
<TooltipButton tooltip={row
|
|
611
|
-
{#if row
|
|
627
|
+
<TooltipButton tooltip={row_getIsExpanded(row) ? t('common.collapse') : t('common.expand')} variant="ghost" size="icon" class="h-7 w-7" onclick={() => row_toggleExpanded(row)}>
|
|
628
|
+
{#if row_getIsExpanded(row)}
|
|
612
629
|
<ChevronUp class="h-4 w-4" />
|
|
613
630
|
{:else}
|
|
614
631
|
<ChevronDown class="h-4 w-4" />
|
|
@@ -634,34 +651,34 @@
|
|
|
634
651
|
{:else}
|
|
635
652
|
{@const field = visibleFields.find(f => f.key === cell.column.id)}
|
|
636
653
|
{#if customColumns && field && customColumns[field.key]}
|
|
637
|
-
{@render customColumns[field.key]({ value: cell
|
|
654
|
+
{@render customColumns[field.key]({ value: cell_getValue(cell), record })}
|
|
638
655
|
{:else if defaultCellRenderer && field}
|
|
639
|
-
{@render defaultCellRenderer({ field, value: cell
|
|
656
|
+
{@render defaultCellRenderer({ field, value: cell_getValue(cell), record })}
|
|
640
657
|
{:else if field?.type === 'boolean'}
|
|
641
|
-
<span class="inline-block h-2 w-2 rounded-full {cell
|
|
642
|
-
{:else if field?.type === 'date' && cell
|
|
643
|
-
{new Date(cell
|
|
644
|
-
{:else if field?.type === 'tags' && Array.isArray(cell
|
|
658
|
+
<span class="inline-block h-2 w-2 rounded-full {cell_getValue(cell) ? 'bg-success' : 'bg-muted-foreground/30'}"></span>
|
|
659
|
+
{:else if field?.type === 'date' && cell_getValue(cell)}
|
|
660
|
+
{new Date(cell_getValue(cell) as string).toLocaleDateString()}
|
|
661
|
+
{:else if field?.type === 'tags' && Array.isArray(cell_getValue(cell))}
|
|
645
662
|
<div class="flex flex-wrap gap-1">
|
|
646
|
-
{#each (cell
|
|
663
|
+
{#each (cell_getValue(cell) as string[]).slice(0, 3) as tag}
|
|
647
664
|
<Badge variant="secondary">{tag}</Badge>
|
|
648
665
|
{/each}
|
|
649
666
|
</div>
|
|
650
667
|
{:else if field?.type === 'select' && field.options}
|
|
651
|
-
{@const opt = field.options.find(o => o.value === cell
|
|
652
|
-
<Badge variant="outline">{opt?.label ?? cell
|
|
668
|
+
{@const opt = field.options.find(o => o.value === cell_getValue(cell))}
|
|
669
|
+
<Badge variant="outline">{opt?.label ?? cell_getValue(cell) ?? '—'}</Badge>
|
|
653
670
|
{:else if canEdit && field && ['text', 'number', 'email', 'url'].includes(field.type)}
|
|
654
671
|
<InlineEdit
|
|
655
672
|
{resourceName}
|
|
656
673
|
recordId={id}
|
|
657
674
|
{field}
|
|
658
|
-
value={cell
|
|
675
|
+
value={cell_getValue(cell)}
|
|
659
676
|
onSave={() => listResult.refetch()}
|
|
660
677
|
/>
|
|
661
678
|
{:else if field?.key === primaryKey}
|
|
662
|
-
<span class="font-mono text-xs">{cell
|
|
679
|
+
<span class="font-mono text-xs">{cell_getValue(cell) ?? '—'}</span>
|
|
663
680
|
{:else}
|
|
664
|
-
{cell
|
|
681
|
+
{cell_getValue(cell) ?? '—'}
|
|
665
682
|
{/if}
|
|
666
683
|
{/if}
|
|
667
684
|
</Table.Cell>
|
|
@@ -689,9 +706,9 @@
|
|
|
689
706
|
{/if}
|
|
690
707
|
</ContextMenu.Content>
|
|
691
708
|
</ContextMenu.Root>
|
|
692
|
-
{#if expandedRowRender && row
|
|
709
|
+
{#if expandedRowRender && row_getIsExpanded(row)}
|
|
693
710
|
<Table.Row class="bg-muted/10 border-b border-border/10 transition-all">
|
|
694
|
-
<Table.Cell colspan={row
|
|
711
|
+
<Table.Cell colspan={row_getAllVisibleCells(row).length}>
|
|
695
712
|
{@render expandedRowRender({ record })}
|
|
696
713
|
</Table.Cell>
|
|
697
714
|
</Table.Row>
|
|
@@ -725,19 +742,19 @@
|
|
|
725
742
|
|
|
726
743
|
<!-- Mobile Card View (visible only on small screens) -->
|
|
727
744
|
<div class="md:hidden space-y-3 p-2">
|
|
728
|
-
{#each tbl
|
|
745
|
+
{#each table_getRowModel(tbl).rows as row}
|
|
729
746
|
{@const record = row.original}
|
|
730
747
|
{@const id = record[primaryKey] as string | number}
|
|
731
748
|
<div
|
|
732
|
-
class="rounded-[20px] shadow-[0_4px_20px_rgb(0,0,0,0.03)] ring-1 ring-border/20 bg-card p-5 transition-all {row
|
|
749
|
+
class="rounded-[20px] shadow-[0_4px_20px_rgb(0,0,0,0.03)] ring-1 ring-border/20 bg-card p-5 transition-all {row_getIsSelected(row) ? 'ring-2 ring-primary/50 bg-primary/5' : ''}"
|
|
733
750
|
>
|
|
734
751
|
<!-- Card header: ID + select + actions -->
|
|
735
752
|
<div class="flex items-center justify-between mb-3">
|
|
736
753
|
<div class="flex items-center gap-2">
|
|
737
754
|
{#if selectable && (canDelete || batchActions)}
|
|
738
755
|
<Checkbox
|
|
739
|
-
checked={row
|
|
740
|
-
onCheckedChange={() => row
|
|
756
|
+
checked={row_getIsSelected(row)}
|
|
757
|
+
onCheckedChange={() => row_toggleSelected(row)}
|
|
741
758
|
/>
|
|
742
759
|
{/if}
|
|
743
760
|
<span class="text-xs font-mono text-muted-foreground">#{id}</span>
|
|
@@ -27,8 +27,9 @@
|
|
|
27
27
|
folder: Folder,
|
|
28
28
|
};
|
|
29
29
|
|
|
30
|
-
function getIcon(name?: string): typeof LayoutDashboard {
|
|
30
|
+
function getIcon(name?: string | any): typeof LayoutDashboard {
|
|
31
31
|
if (!name) return depth === 0 ? Settings : Folder;
|
|
32
|
+
if (typeof name !== 'string') return name; // if it's already a component
|
|
32
33
|
return iconMap[name] ?? Settings;
|
|
33
34
|
}
|
|
34
35
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@svadmin/ui",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.33.1",
|
|
4
4
|
"description": "Pre-built admin UI components — AdminApp, AutoTable, AutoForm, Sidebar, Layout",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"sideEffects": [
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
"./components/*": "./dist/components/*"
|
|
28
28
|
},
|
|
29
29
|
"peerDependencies": {
|
|
30
|
-
"@svadmin/core": "^0.
|
|
30
|
+
"@svadmin/core": "^0.24.0",
|
|
31
31
|
"@tanstack/svelte-query": "^6.0.0",
|
|
32
32
|
"highlight.js": "^11.11.1",
|
|
33
33
|
"isomorphic-dompurify": "^3.7.1",
|
|
@@ -82,9 +82,7 @@
|
|
|
82
82
|
"bugs": {
|
|
83
83
|
"url": "https://github.com/zuohuadong/svadmin/issues"
|
|
84
84
|
},
|
|
85
|
-
"devDependencies": {
|
|
86
|
-
"@tanstack/table-core": "^9.0.0-alpha.32"
|
|
87
|
-
},
|
|
85
|
+
"devDependencies": {},
|
|
88
86
|
"scripts": {
|
|
89
87
|
"build": "svelte-package -i src -o dist"
|
|
90
88
|
}
|