@svadmin/ui 0.20.0 → 0.20.2
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/package.json +1 -1
- package/src/components/AuditLogViewer.svelte +5 -5
- package/src/components/AutoForm.svelte +3 -3
- package/src/components/AutoTable.svelte +4 -3
- package/src/components/DraggableGrid.svelte +5 -3
- package/src/components/PermissionMatrix.svelte +8 -8
- package/src/components/SettingsPage.svelte +1 -1
- package/src/components/ShowPage.svelte +8 -8
- package/src/components/TaskQueueDrawer.svelte +8 -6
- package/src/components/TenantSwitcher.svelte +10 -8
- package/src/index.ts +1 -2
package/package.json
CHANGED
|
@@ -103,7 +103,7 @@
|
|
|
103
103
|
</div>
|
|
104
104
|
|
|
105
105
|
<!-- Table -->
|
|
106
|
-
<div class="flex-1 border rounded-lg bg-card overflow-hidden">
|
|
106
|
+
<div class="flex-1 shadow-sm ring-1 ring-border/10 rounded-lg bg-card overflow-hidden">
|
|
107
107
|
{#if loading}
|
|
108
108
|
<div class="flex items-center justify-center h-48 text-muted-foreground">
|
|
109
109
|
<Loader2 class="h-5 w-5 animate-spin mr-2" />
|
|
@@ -124,7 +124,7 @@
|
|
|
124
124
|
</Table.Header>
|
|
125
125
|
<Table.Body>
|
|
126
126
|
{#each filteredLogs as log}
|
|
127
|
-
<Table.Row class="hover:bg-muted/
|
|
127
|
+
<Table.Row class="border-0 even:bg-muted/20 hover:bg-muted/40 transition-colors">
|
|
128
128
|
<Table.Cell class="text-xs text-muted-foreground font-mono">
|
|
129
129
|
{formatDate(log.createdAt)}
|
|
130
130
|
</Table.Cell>
|
|
@@ -188,7 +188,7 @@
|
|
|
188
188
|
<!-- svelte-ignore a11y_click_events_have_key_events -->
|
|
189
189
|
<div class="bg-card shadow-2xl w-full max-w-2xl h-full flex flex-col animate-in slide-in-from-right duration-300" onclick={(e) => e.stopPropagation()}>
|
|
190
190
|
<!-- Drawer Header -->
|
|
191
|
-
<div class="p-6
|
|
191
|
+
<div class="p-6 shadow-[0_1px_0_rgba(0,0,0,0.05)] dark:shadow-[0_1px_0_rgba(255,255,255,0.05)] flex items-center justify-between bg-muted/30">
|
|
192
192
|
<div>
|
|
193
193
|
<h2 class="text-lg font-bold text-foreground flex items-center gap-2">
|
|
194
194
|
<FileSearch class="h-5 w-5 text-primary" />
|
|
@@ -202,7 +202,7 @@
|
|
|
202
202
|
</div>
|
|
203
203
|
|
|
204
204
|
<!-- Meta Tags -->
|
|
205
|
-
<div class="px-6 py-3
|
|
205
|
+
<div class="px-6 py-3 shadow-[0_1px_0_rgba(0,0,0,0.05)] dark:shadow-[0_1px_0_rgba(255,255,255,0.05)] flex items-center gap-2 flex-wrap">
|
|
206
206
|
<Badge variant="outline">{drawerLog.action}</Badge>
|
|
207
207
|
{#if drawerLog.resource}
|
|
208
208
|
<Badge variant="secondary">{drawerLog.resource}</Badge>
|
|
@@ -218,7 +218,7 @@
|
|
|
218
218
|
</div>
|
|
219
219
|
|
|
220
220
|
<!-- Footer -->
|
|
221
|
-
<div class="p-4
|
|
221
|
+
<div class="p-4 shadow-[0_-1px_0_rgba(0,0,0,0.05)] dark:shadow-[0_-1px_0_rgba(255,255,255,0.05)] bg-muted/20 text-right text-[11px] text-muted-foreground font-medium">
|
|
222
222
|
System audit snapshot · Read-only
|
|
223
223
|
</div>
|
|
224
224
|
</div>
|
|
@@ -139,7 +139,7 @@
|
|
|
139
139
|
|
|
140
140
|
{#if form.loading}
|
|
141
141
|
<div class="max-w-3xl space-y-6">
|
|
142
|
-
<div class="rounded-lg border p-6 space-y-5">
|
|
142
|
+
<div class="rounded-lg shadow-sm ring-1 ring-border/10 p-6 space-y-5">
|
|
143
143
|
{#each Array(4) as _}
|
|
144
144
|
<div class="space-y-2">
|
|
145
145
|
<Skeleton class="h-4 w-24" />
|
|
@@ -159,7 +159,7 @@
|
|
|
159
159
|
|
|
160
160
|
{#if hasGroups}
|
|
161
161
|
{#each groups as group}
|
|
162
|
-
<Card.Root>
|
|
162
|
+
<Card.Root class="border-border/40 shadow-sm">
|
|
163
163
|
{#if group.name}
|
|
164
164
|
<Card.Header>
|
|
165
165
|
<Card.Title class="text-lg">{group.name}</Card.Title>
|
|
@@ -186,7 +186,7 @@
|
|
|
186
186
|
</Card.Root>
|
|
187
187
|
{/each}
|
|
188
188
|
{:else}
|
|
189
|
-
<Card.Root>
|
|
189
|
+
<Card.Root class="border-border/40 shadow-sm">
|
|
190
190
|
<Card.Content class="space-y-5 px-4 sm:px-6 pb-4 sm:pb-6 pt-0">
|
|
191
191
|
{#each formFields as field (field.key)}
|
|
192
192
|
<div class:border-destructive={!!form.errors[field.key]}>
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import { untrack } from 'svelte';
|
|
3
|
+
import { cn } from '../utils.js';
|
|
3
4
|
import {
|
|
4
5
|
createTable,
|
|
5
6
|
getCoreRowModel,
|
|
@@ -446,7 +447,7 @@
|
|
|
446
447
|
{/if}
|
|
447
448
|
|
|
448
449
|
<!-- Table (TanStack-powered) -->
|
|
449
|
-
<div class="rounded-lg bg-card shadow-sm overflow-hidden" role="region" aria-label="{resource.label} {t('common.list')}">
|
|
450
|
+
<div class="rounded-lg bg-card shadow-sm ring-1 ring-border/10 overflow-hidden" role="region" aria-label="{resource.label} {t('common.list')}">
|
|
450
451
|
{#if query.isLoading}
|
|
451
452
|
<div class="p-4 space-y-3">
|
|
452
453
|
<div class="flex gap-4 mb-2">
|
|
@@ -524,7 +525,7 @@
|
|
|
524
525
|
<ContextMenu.Root>
|
|
525
526
|
<ContextMenu.Trigger>
|
|
526
527
|
{#snippet child({ props })}
|
|
527
|
-
<Table.Row {...props} class="transition-colors {row.getIsSelected() ? 'bg-accent' : ''}">
|
|
528
|
+
<Table.Row {...props} class="transition-colors border-0 even:bg-muted/20 {row.getIsSelected() ? 'bg-accent/50' : 'hover:bg-muted/40'}">
|
|
528
529
|
{#each row.getVisibleCells() as cell}
|
|
529
530
|
<Table.Cell>
|
|
530
531
|
{#if cell.column.id === '_select'}
|
|
@@ -653,7 +654,7 @@
|
|
|
653
654
|
{@const record = row.original}
|
|
654
655
|
{@const id = record[primaryKey] as string | number}
|
|
655
656
|
<div
|
|
656
|
-
class="rounded-xl border bg-card p-4
|
|
657
|
+
class="rounded-xl shadow-sm ring-1 ring-border/10 bg-card p-4 transition-colors {row.getIsSelected() ? 'ring-2 ring-primary bg-accent/30' : ''}"
|
|
657
658
|
>
|
|
658
659
|
<!-- Card header: ID + select + actions -->
|
|
659
660
|
<div class="flex items-center justify-between mb-3">
|
|
@@ -1,10 +1,12 @@
|
|
|
1
|
-
<script
|
|
2
|
-
import type { Snippet } from 'svelte';
|
|
3
|
-
|
|
1
|
+
<script context="module">
|
|
4
2
|
export interface GridModule {
|
|
5
3
|
id: string;
|
|
6
4
|
[key: string]: unknown;
|
|
7
5
|
}
|
|
6
|
+
</script>
|
|
7
|
+
|
|
8
|
+
<script lang="ts">
|
|
9
|
+
import type { Snippet } from 'svelte';
|
|
8
10
|
|
|
9
11
|
let {
|
|
10
12
|
modules = $bindable<GridModule[]>([]),
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
<script
|
|
1
|
+
<script context="module">
|
|
2
2
|
export type RoleInfo = { code: string; name: string; [key: string]: any };
|
|
3
3
|
export type ResourceInfo = { code: string; name: string; section?: string; [key: string]: any };
|
|
4
4
|
export type ActionInfo = { code: string; name: string; [key: string]: any };
|
|
@@ -128,12 +128,12 @@
|
|
|
128
128
|
|
|
129
129
|
<!-- Table Area -->
|
|
130
130
|
<div class="flex-1 overflow-auto p-4">
|
|
131
|
-
<table class="min-w-full
|
|
131
|
+
<table class="min-w-full rounded-lg overflow-hidden shadow-sm ring-1 ring-border/10">
|
|
132
132
|
<thead class="bg-muted/50">
|
|
133
133
|
<tr>
|
|
134
|
-
<th scope="col" class="py-3 pr-3 pl-4 text-left text-sm font-semibold text-foreground
|
|
134
|
+
<th scope="col" class="py-3 pr-3 pl-4 text-left text-sm font-semibold text-foreground w-48">模块域与资源点</th>
|
|
135
135
|
{#each actions as action}
|
|
136
|
-
<th scope="col" class="px-2 py-3 text-center text-sm font-semibold text-foreground
|
|
136
|
+
<th scope="col" class="px-2 py-3 text-center text-sm font-semibold text-foreground">
|
|
137
137
|
<div class="flex flex-col items-center">
|
|
138
138
|
<span>{action.name}</span>
|
|
139
139
|
<span class="text-[10px] text-muted-foreground font-mono">{action.code}</span>
|
|
@@ -142,7 +142,7 @@
|
|
|
142
142
|
{/each}
|
|
143
143
|
</tr>
|
|
144
144
|
</thead>
|
|
145
|
-
<tbody class="
|
|
145
|
+
<tbody class="bg-card">
|
|
146
146
|
{#if resources.length === 0}
|
|
147
147
|
<tr>
|
|
148
148
|
<td colspan={actions.length + 1} class="py-10 text-center text-muted-foreground">暂无可用资源</td>
|
|
@@ -156,8 +156,8 @@
|
|
|
156
156
|
</tr>
|
|
157
157
|
{/if}
|
|
158
158
|
|
|
159
|
-
<tr class="hover:bg-muted/50 transition-colors">
|
|
160
|
-
<td class="whitespace-nowrap py-3 pl-4 pr-3 text-sm
|
|
159
|
+
<tr class="even:bg-muted/30 hover:bg-muted/50 transition-colors">
|
|
160
|
+
<td class="whitespace-nowrap py-3 pl-4 pr-3 text-sm">
|
|
161
161
|
<div class="font-medium text-foreground">{resource.name}</div>
|
|
162
162
|
<div class="text-xs text-muted-foreground font-mono">{resource.code}</div>
|
|
163
163
|
</td>
|
|
@@ -165,7 +165,7 @@
|
|
|
165
165
|
<!-- Action Checkboxes -->
|
|
166
166
|
{#each actions as action}
|
|
167
167
|
{@const granted = selectedRole ? isGranted(selectedRole, resource.code, action.code) : false}
|
|
168
|
-
<td class="whitespace-nowrap px-3 py-3 text-center
|
|
168
|
+
<td class="whitespace-nowrap px-3 py-3 text-center">
|
|
169
169
|
<div class="flex items-center justify-center">
|
|
170
170
|
<button
|
|
171
171
|
disabled={loading || !selectedRole}
|
|
@@ -47,7 +47,7 @@
|
|
|
47
47
|
|
|
48
48
|
<div class="flex flex-col lg:flex-row gap-0 min-h-full">
|
|
49
49
|
<!-- Left sidebar navigation -->
|
|
50
|
-
<nav class="w-full lg:w-56 shrink-0
|
|
50
|
+
<nav class="w-full lg:w-56 shrink-0 bg-muted/10 shadow-[inset_0_-1px_0_rgba(0,0,0,0.05)] lg:shadow-[inset_-1px_0_0_rgba(0,0,0,0.05)] dark:shadow-[inset_-1px_0_0_rgba(255,255,255,0.05)]">
|
|
51
51
|
<!-- Mobile: horizontal scroll tabs -->
|
|
52
52
|
<div class="flex lg:hidden overflow-x-auto px-4 py-2 gap-1">
|
|
53
53
|
{#each sections as section}
|
|
@@ -36,10 +36,10 @@
|
|
|
36
36
|
</PageHeader>
|
|
37
37
|
|
|
38
38
|
{#if query.query.isLoading}
|
|
39
|
-
<Card.Root>
|
|
40
|
-
<Card.Content class="
|
|
41
|
-
{#each showFields.slice(0, 6) as _}
|
|
42
|
-
<div class="flex flex-col sm:flex-row px-4 sm:px-6 py-3 sm:py-4">
|
|
39
|
+
<Card.Root class="overflow-hidden border-border/40 shadow-sm">
|
|
40
|
+
<Card.Content class="p-0">
|
|
41
|
+
{#each showFields.slice(0, 6) as _, i}
|
|
42
|
+
<div class="flex flex-col sm:flex-row px-4 sm:px-6 py-3 sm:py-4 {i % 2 === 1 ? 'bg-muted/20' : ''}">
|
|
43
43
|
<Skeleton class="h-4 w-1/2 sm:w-1/4" />
|
|
44
44
|
<Skeleton class="h-4 w-3/4 sm:w-2/5 mt-1 sm:mt-0 sm:ml-auto" />
|
|
45
45
|
</div>
|
|
@@ -47,12 +47,12 @@
|
|
|
47
47
|
</Card.Content>
|
|
48
48
|
</Card.Root>
|
|
49
49
|
{:else if query.query.data?.data}
|
|
50
|
-
<Card.Root>
|
|
51
|
-
<Card.Content class="
|
|
52
|
-
{#each showFields as field}
|
|
50
|
+
<Card.Root class="overflow-hidden border-border/40 shadow-sm">
|
|
51
|
+
<Card.Content class="p-0">
|
|
52
|
+
{#each showFields as field, i}
|
|
53
53
|
{@const value = (query.query.data!.data as Record<string, unknown>)[field.key]}
|
|
54
54
|
{@const DisplayComponent = getDisplayComponent(field.type)}
|
|
55
|
-
<div class="flex flex-col sm:flex-row px-4 sm:px-6 py-3 sm:py-4">
|
|
55
|
+
<div class="flex flex-col sm:flex-row px-4 sm:px-6 py-3 sm:py-4 {i % 2 === 1 ? 'bg-muted/20' : ''}">
|
|
56
56
|
<div class="sm:w-1/3 text-xs sm:text-sm font-medium text-muted-foreground mb-1 sm:mb-0">{field.label}</div>
|
|
57
57
|
<div class="sm:w-2/3 text-sm text-foreground">
|
|
58
58
|
{#if DisplayComponent && value != null}
|
|
@@ -1,9 +1,4 @@
|
|
|
1
|
-
<script
|
|
2
|
-
import type { Snippet } from 'svelte';
|
|
3
|
-
import { Loader2, CheckCircle2, XCircle, Clock, Download, X, ListTodo } from 'lucide-svelte';
|
|
4
|
-
import { Button } from './ui/button/index.js';
|
|
5
|
-
import { Badge } from './ui/badge/index.js';
|
|
6
|
-
|
|
1
|
+
<script context="module">
|
|
7
2
|
export type TaskStatus = 'pending' | 'running' | 'completed' | 'failed';
|
|
8
3
|
|
|
9
4
|
export interface BackgroundTask {
|
|
@@ -16,6 +11,13 @@
|
|
|
16
11
|
downloadUrl?: string;
|
|
17
12
|
[key: string]: unknown;
|
|
18
13
|
}
|
|
14
|
+
</script>
|
|
15
|
+
|
|
16
|
+
<script lang="ts">
|
|
17
|
+
import type { Snippet } from 'svelte';
|
|
18
|
+
import { Loader2, CheckCircle2, XCircle, Clock, Download, X, ListTodo } from 'lucide-svelte';
|
|
19
|
+
import { Button } from './ui/button/index.js';
|
|
20
|
+
import { Badge } from './ui/badge/index.js';
|
|
19
21
|
|
|
20
22
|
let {
|
|
21
23
|
open = $bindable(false),
|
|
@@ -1,15 +1,17 @@
|
|
|
1
|
-
<script
|
|
2
|
-
import type { Snippet } from 'svelte';
|
|
3
|
-
import { ChevronsUpDown, Building2, Check } from 'lucide-svelte';
|
|
4
|
-
import { Button } from './ui/button/index.js';
|
|
5
|
-
import * as DropdownMenu from './ui/dropdown-menu/index.js';
|
|
6
|
-
|
|
1
|
+
<script context="module">
|
|
7
2
|
export interface Tenant {
|
|
8
3
|
id: string;
|
|
9
4
|
name: string;
|
|
10
5
|
logo?: string;
|
|
11
6
|
[key: string]: unknown;
|
|
12
7
|
}
|
|
8
|
+
</script>
|
|
9
|
+
|
|
10
|
+
<script lang="ts">
|
|
11
|
+
import type { Snippet } from 'svelte';
|
|
12
|
+
import { ChevronsUpDown, Building2, Check } from 'lucide-svelte';
|
|
13
|
+
import { Button } from './ui/button/index.js';
|
|
14
|
+
import * as DropdownMenu from './ui/dropdown-menu/index.js';
|
|
13
15
|
|
|
14
16
|
let {
|
|
15
17
|
tenants = [],
|
|
@@ -59,14 +61,14 @@
|
|
|
59
61
|
</button>
|
|
60
62
|
{/snippet}
|
|
61
63
|
</DropdownMenu.Trigger>
|
|
62
|
-
<DropdownMenu.Content class="w-56"
|
|
64
|
+
<DropdownMenu.Content class="w-56">
|
|
63
65
|
{#if headerSnippet}
|
|
64
66
|
<div class="px-2 py-1.5">
|
|
65
67
|
{@render headerSnippet()}
|
|
66
68
|
</div>
|
|
67
69
|
<DropdownMenu.Separator />
|
|
68
70
|
{/if}
|
|
69
|
-
<
|
|
71
|
+
<div class="px-2 py-1.5 text-xs text-muted-foreground">Workspaces</div>
|
|
70
72
|
{#each tenants as tenant}
|
|
71
73
|
<DropdownMenu.Item
|
|
72
74
|
class="flex items-center gap-3 cursor-pointer"
|
package/src/index.ts
CHANGED
|
@@ -93,8 +93,7 @@ export { default as RelationField } from './components/fields/RelationField.svel
|
|
|
93
93
|
export { default as JsonField } from './components/fields/JsonField.svelte';
|
|
94
94
|
export { default as RichTextField } from './components/fields/RichTextField.svelte';
|
|
95
95
|
|
|
96
|
-
// Rich text editor (requires @svadmin/editor)
|
|
97
|
-
export { Editor as RichTextEditor } from '@svadmin/editor';
|
|
96
|
+
// Rich text editor (requires @svadmin/editor) as a direct import in consumer app
|
|
98
97
|
|
|
99
98
|
// CRUD Buttons
|
|
100
99
|
export {
|