@svadmin/ui 0.55.1 → 0.56.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/DetailDrawer.svelte +37 -26
- package/dist/components/DetailDrawer.svelte.d.ts +5 -4
- package/dist/components/content/WorkspaceActionBar.svelte +27 -2
- package/dist/components/content/WorkspaceActionBar.svelte.d.ts +2 -0
- package/dist/components/content/WorkspaceTabBar.svelte +94 -0
- package/dist/components/content/WorkspaceTabBar.svelte.d.ts +23 -0
- package/dist/components/content/index.d.ts +3 -0
- package/dist/components/content/index.js +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +1 -0
- package/package.json +1 -1
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
import type { Snippet } from
|
|
3
|
-
import type { HTMLAttributes } from
|
|
4
|
-
import { cn, type WithElementRef } from
|
|
5
|
-
import * as Sheet from
|
|
2
|
+
import type { Snippet } from "svelte";
|
|
3
|
+
import type { HTMLAttributes } from "svelte/elements";
|
|
4
|
+
import { cn, type WithElementRef } from "../utils.js";
|
|
5
|
+
import * as Sheet from "./ui/sheet/index.js";
|
|
6
6
|
|
|
7
7
|
type Props = WithElementRef<HTMLAttributes<HTMLDivElement>, HTMLDivElement> & {
|
|
8
8
|
open?: boolean;
|
|
@@ -11,30 +11,32 @@
|
|
|
11
11
|
description?: string;
|
|
12
12
|
descriptionId?: string;
|
|
13
13
|
closeLabel?: string;
|
|
14
|
-
side?:
|
|
14
|
+
side?: "left" | "right";
|
|
15
15
|
width?: string;
|
|
16
16
|
onClose?: () => void;
|
|
17
17
|
children?: Snippet;
|
|
18
18
|
footer?: Snippet;
|
|
19
|
+
extra?: Snippet;
|
|
19
20
|
};
|
|
20
21
|
|
|
21
22
|
let {
|
|
22
23
|
open = $bindable(false),
|
|
23
|
-
title =
|
|
24
|
-
description =
|
|
25
|
-
side =
|
|
26
|
-
width =
|
|
24
|
+
title = "",
|
|
25
|
+
description = "",
|
|
26
|
+
side = "right",
|
|
27
|
+
width = "max-w-md w-full sm:max-w-lg",
|
|
27
28
|
ref = $bindable(null),
|
|
28
29
|
class: className,
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
30
|
+
"aria-label": ariaLabel,
|
|
31
|
+
"aria-labelledby": ariaLabelledby,
|
|
32
|
+
"aria-describedby": ariaDescribedby,
|
|
32
33
|
titleId,
|
|
33
34
|
descriptionId,
|
|
34
|
-
closeLabel =
|
|
35
|
+
closeLabel = "Close",
|
|
35
36
|
onClose,
|
|
36
37
|
children,
|
|
37
38
|
footer,
|
|
39
|
+
extra,
|
|
38
40
|
...restProps
|
|
39
41
|
}: Props = $props();
|
|
40
42
|
|
|
@@ -50,34 +52,43 @@
|
|
|
50
52
|
{side}
|
|
51
53
|
onClose={handleClose}
|
|
52
54
|
{closeLabel}
|
|
53
|
-
class={cn(
|
|
55
|
+
class={cn("gap-0 p-0 overflow-hidden", width, className)}
|
|
54
56
|
role="dialog"
|
|
55
57
|
aria-modal="true"
|
|
56
|
-
aria-label={(ariaLabelledby || titleId) ? ariaLabel : (ariaLabel || title ||
|
|
58
|
+
aria-label={(ariaLabelledby || titleId) ? ariaLabel : (ariaLabel || title || "Details")}
|
|
57
59
|
aria-labelledby={ariaLabelledby || (titleId ? titleId : undefined)}
|
|
58
60
|
aria-describedby={ariaDescribedby || (descriptionId ? descriptionId : undefined)}
|
|
59
61
|
{...restProps}
|
|
60
62
|
>
|
|
61
|
-
<Sheet.Content class="flex h-full flex-col">
|
|
62
|
-
{#if title || description}
|
|
63
|
-
<Sheet.Header>
|
|
64
|
-
|
|
65
|
-
<
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
63
|
+
<Sheet.Content class="flex h-full flex-col gap-0 p-0">
|
|
64
|
+
{#if title || description || extra}
|
|
65
|
+
<Sheet.Header class="flex-shrink-0 border-b border-border px-6 py-4 pr-12">
|
|
66
|
+
<div class="flex items-start justify-between gap-4">
|
|
67
|
+
<div class="flex min-w-0 flex-1 flex-col gap-1.5">
|
|
68
|
+
{#if title}
|
|
69
|
+
<Sheet.Title id={titleId}>{title}</Sheet.Title>
|
|
70
|
+
{/if}
|
|
71
|
+
{#if description}
|
|
72
|
+
<Sheet.Description id={descriptionId}>{description}</Sheet.Description>
|
|
73
|
+
{/if}
|
|
74
|
+
</div>
|
|
75
|
+
{#if extra}
|
|
76
|
+
<div class="flex flex-shrink-0 items-center gap-2">
|
|
77
|
+
{@render extra()}
|
|
78
|
+
</div>
|
|
79
|
+
{/if}
|
|
80
|
+
</div>
|
|
70
81
|
</Sheet.Header>
|
|
71
82
|
{/if}
|
|
72
83
|
|
|
73
|
-
<div class="flex-1 overflow-y-auto
|
|
84
|
+
<div class="flex-1 overflow-y-auto p-6">
|
|
74
85
|
{#if children}
|
|
75
86
|
{@render children()}
|
|
76
87
|
{/if}
|
|
77
88
|
</div>
|
|
78
89
|
|
|
79
90
|
{#if footer}
|
|
80
|
-
<Sheet.Footer>
|
|
91
|
+
<Sheet.Footer class="mt-auto flex-shrink-0 border-t border-border px-6 py-4">
|
|
81
92
|
{@render footer()}
|
|
82
93
|
</Sheet.Footer>
|
|
83
94
|
{/if}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type { Snippet } from
|
|
2
|
-
import type { HTMLAttributes } from
|
|
3
|
-
import { type WithElementRef } from
|
|
1
|
+
import type { Snippet } from "svelte";
|
|
2
|
+
import type { HTMLAttributes } from "svelte/elements";
|
|
3
|
+
import { type WithElementRef } from "../utils.js";
|
|
4
4
|
type Props = WithElementRef<HTMLAttributes<HTMLDivElement>, HTMLDivElement> & {
|
|
5
5
|
open?: boolean;
|
|
6
6
|
title?: string;
|
|
@@ -8,11 +8,12 @@ type Props = WithElementRef<HTMLAttributes<HTMLDivElement>, HTMLDivElement> & {
|
|
|
8
8
|
description?: string;
|
|
9
9
|
descriptionId?: string;
|
|
10
10
|
closeLabel?: string;
|
|
11
|
-
side?:
|
|
11
|
+
side?: "left" | "right";
|
|
12
12
|
width?: string;
|
|
13
13
|
onClose?: () => void;
|
|
14
14
|
children?: Snippet;
|
|
15
15
|
footer?: Snippet;
|
|
16
|
+
extra?: Snippet;
|
|
16
17
|
};
|
|
17
18
|
declare const DetailDrawer: import("svelte").Component<Props, {}, "open" | "ref">;
|
|
18
19
|
type DetailDrawer = ReturnType<typeof DetailDrawer>;
|
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
<script module lang="ts">
|
|
2
|
+
export type WorkspaceActionBarTone = 'default' | 'warning' | 'success' | 'destructive' | 'info';
|
|
3
|
+
</script>
|
|
4
|
+
|
|
1
5
|
<script lang="ts">
|
|
2
6
|
import type { Snippet } from 'svelte';
|
|
3
7
|
import { cn } from '../../utils.js';
|
|
@@ -6,12 +10,29 @@
|
|
|
6
10
|
title: string;
|
|
7
11
|
description?: string;
|
|
8
12
|
status?: string;
|
|
13
|
+
statusTone?: WorkspaceActionBarTone;
|
|
9
14
|
primaryAction: Snippet;
|
|
10
15
|
secondaryActions?: Snippet;
|
|
11
16
|
class?: string;
|
|
12
17
|
}
|
|
13
18
|
|
|
14
|
-
let {
|
|
19
|
+
let {
|
|
20
|
+
title,
|
|
21
|
+
description,
|
|
22
|
+
status,
|
|
23
|
+
statusTone = 'warning',
|
|
24
|
+
primaryAction,
|
|
25
|
+
secondaryActions,
|
|
26
|
+
class: className = '',
|
|
27
|
+
}: Props = $props();
|
|
28
|
+
|
|
29
|
+
const toneClassMap: Record<WorkspaceActionBarTone, string> = {
|
|
30
|
+
default: 'bg-muted text-muted-foreground',
|
|
31
|
+
warning: 'bg-warning/15 text-warning-foreground',
|
|
32
|
+
success: 'bg-success/15 text-success',
|
|
33
|
+
destructive: 'bg-destructive/15 text-destructive',
|
|
34
|
+
info: 'bg-info/15 text-info',
|
|
35
|
+
};
|
|
15
36
|
</script>
|
|
16
37
|
|
|
17
38
|
<section
|
|
@@ -21,7 +42,11 @@
|
|
|
21
42
|
>
|
|
22
43
|
<div class="min-w-0">
|
|
23
44
|
<div class="flex flex-wrap items-center gap-2">
|
|
24
|
-
{#if status}
|
|
45
|
+
{#if status}
|
|
46
|
+
<span class={cn('rounded-sm px-2 py-0.5 text-xs font-medium', toneClassMap[statusTone] || toneClassMap.warning)}>
|
|
47
|
+
{status}
|
|
48
|
+
</span>
|
|
49
|
+
{/if}
|
|
25
50
|
<h2 class="text-sm font-semibold text-foreground">{title}</h2>
|
|
26
51
|
</div>
|
|
27
52
|
{#if description}<p class="mt-1 text-xs leading-5 text-muted-foreground">{description}</p>{/if}
|
|
@@ -1,8 +1,10 @@
|
|
|
1
|
+
export type WorkspaceActionBarTone = 'default' | 'warning' | 'success' | 'destructive' | 'info';
|
|
1
2
|
import type { Snippet } from 'svelte';
|
|
2
3
|
interface Props {
|
|
3
4
|
title: string;
|
|
4
5
|
description?: string;
|
|
5
6
|
status?: string;
|
|
7
|
+
statusTone?: WorkspaceActionBarTone;
|
|
6
8
|
primaryAction: Snippet;
|
|
7
9
|
secondaryActions?: Snippet;
|
|
8
10
|
class?: string;
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
<script module lang="ts">
|
|
2
|
+
import type { Component } from 'svelte';
|
|
3
|
+
|
|
4
|
+
export interface WorkspaceTabItem {
|
|
5
|
+
id: string;
|
|
6
|
+
label: string;
|
|
7
|
+
icon?: Component<{ class?: string; 'aria-hidden'?: string | boolean }>;
|
|
8
|
+
badge?: string | number;
|
|
9
|
+
disabled?: boolean;
|
|
10
|
+
description?: string;
|
|
11
|
+
}
|
|
12
|
+
</script>
|
|
13
|
+
|
|
14
|
+
<script lang="ts">
|
|
15
|
+
import { cn } from '../../utils.js';
|
|
16
|
+
|
|
17
|
+
interface Props {
|
|
18
|
+
items: WorkspaceTabItem[];
|
|
19
|
+
activeId: string;
|
|
20
|
+
onselect?: (item: WorkspaceTabItem) => void;
|
|
21
|
+
variant?: 'segmented' | 'pill' | 'underline';
|
|
22
|
+
ariaLabel?: string;
|
|
23
|
+
class?: string;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
let {
|
|
27
|
+
items,
|
|
28
|
+
activeId,
|
|
29
|
+
onselect,
|
|
30
|
+
variant = 'segmented',
|
|
31
|
+
ariaLabel = 'Workspace tabs',
|
|
32
|
+
class: className = '',
|
|
33
|
+
}: Props = $props();
|
|
34
|
+
</script>
|
|
35
|
+
|
|
36
|
+
<nav
|
|
37
|
+
aria-label={ariaLabel}
|
|
38
|
+
class={cn(
|
|
39
|
+
'flex items-center gap-1 overflow-x-auto',
|
|
40
|
+
variant === 'segmented' && 'rounded-lg border border-border bg-muted/40 p-1',
|
|
41
|
+
variant === 'pill' && 'gap-1.5 p-0.5',
|
|
42
|
+
variant === 'underline' && 'gap-2 border-b border-border',
|
|
43
|
+
className,
|
|
44
|
+
)}
|
|
45
|
+
data-svadmin-workspace-tab-bar
|
|
46
|
+
data-variant={variant}
|
|
47
|
+
>
|
|
48
|
+
{#each items as item (item.id)}
|
|
49
|
+
{@const Icon = item.icon}
|
|
50
|
+
{@const isActive = item.id === activeId}
|
|
51
|
+
<button
|
|
52
|
+
type="button"
|
|
53
|
+
disabled={item.disabled}
|
|
54
|
+
class={cn(
|
|
55
|
+
'inline-flex items-center gap-2 rounded-md px-3 py-1.5 text-xs font-medium transition-colors outline-none focus-visible:ring-2 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50',
|
|
56
|
+
variant === 'segmented' && [
|
|
57
|
+
isActive
|
|
58
|
+
? 'bg-background text-foreground shadow-sm font-semibold'
|
|
59
|
+
: 'text-muted-foreground hover:bg-background/50 hover:text-foreground',
|
|
60
|
+
],
|
|
61
|
+
variant === 'pill' && [
|
|
62
|
+
isActive
|
|
63
|
+
? 'bg-primary text-primary-foreground font-semibold'
|
|
64
|
+
: 'bg-muted/50 text-muted-foreground hover:bg-muted hover:text-foreground',
|
|
65
|
+
],
|
|
66
|
+
variant === 'underline' && [
|
|
67
|
+
'rounded-none border-b-2 px-3 py-2',
|
|
68
|
+
isActive
|
|
69
|
+
? 'border-primary text-primary font-semibold'
|
|
70
|
+
: 'border-transparent text-muted-foreground hover:border-border hover:text-foreground',
|
|
71
|
+
],
|
|
72
|
+
)}
|
|
73
|
+
aria-current={isActive ? 'page' : undefined}
|
|
74
|
+
onclick={() => onselect?.(item)}
|
|
75
|
+
>
|
|
76
|
+
{#if Icon}
|
|
77
|
+
<Icon class="size-4 shrink-0" aria-hidden="true" />
|
|
78
|
+
{/if}
|
|
79
|
+
<span>{item.label}</span>
|
|
80
|
+
{#if item.badge !== undefined && item.badge !== ''}
|
|
81
|
+
<span
|
|
82
|
+
class={cn(
|
|
83
|
+
'inline-flex items-center justify-center rounded-full px-1.5 py-0.5 text-[0.6875rem] font-bold leading-none tabular-nums',
|
|
84
|
+
isActive
|
|
85
|
+
? (variant === 'pill' ? 'bg-primary-foreground/20 text-primary-foreground' : 'bg-primary/10 text-primary')
|
|
86
|
+
: 'bg-muted text-muted-foreground',
|
|
87
|
+
)}
|
|
88
|
+
>
|
|
89
|
+
{item.badge}
|
|
90
|
+
</span>
|
|
91
|
+
{/if}
|
|
92
|
+
</button>
|
|
93
|
+
{/each}
|
|
94
|
+
</nav>
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { Component } from 'svelte';
|
|
2
|
+
export interface WorkspaceTabItem {
|
|
3
|
+
id: string;
|
|
4
|
+
label: string;
|
|
5
|
+
icon?: Component<{
|
|
6
|
+
class?: string;
|
|
7
|
+
'aria-hidden'?: string | boolean;
|
|
8
|
+
}>;
|
|
9
|
+
badge?: string | number;
|
|
10
|
+
disabled?: boolean;
|
|
11
|
+
description?: string;
|
|
12
|
+
}
|
|
13
|
+
interface Props {
|
|
14
|
+
items: WorkspaceTabItem[];
|
|
15
|
+
activeId: string;
|
|
16
|
+
onselect?: (item: WorkspaceTabItem) => void;
|
|
17
|
+
variant?: 'segmented' | 'pill' | 'underline';
|
|
18
|
+
ariaLabel?: string;
|
|
19
|
+
class?: string;
|
|
20
|
+
}
|
|
21
|
+
declare const WorkspaceTabBar: Component<Props, {}, "">;
|
|
22
|
+
type WorkspaceTabBar = ReturnType<typeof WorkspaceTabBar>;
|
|
23
|
+
export default WorkspaceTabBar;
|
|
@@ -5,6 +5,9 @@ export { default as PageToolbar } from './PageToolbar.svelte';
|
|
|
5
5
|
export { default as WorkspaceLayout } from './WorkspaceLayout.svelte';
|
|
6
6
|
export { default as WorkspaceStageStepper } from './WorkspaceStageStepper.svelte';
|
|
7
7
|
export { default as WorkspaceActionBar } from './WorkspaceActionBar.svelte';
|
|
8
|
+
export type { WorkspaceActionBarTone } from './WorkspaceActionBar.svelte';
|
|
9
|
+
export { default as WorkspaceTabBar } from './WorkspaceTabBar.svelte';
|
|
10
|
+
export type { WorkspaceTabItem } from './WorkspaceTabBar.svelte';
|
|
8
11
|
export { default as WorkspaceInspector } from './WorkspaceInspector.svelte';
|
|
9
12
|
export { default as WorkspaceSplitPane } from './WorkspaceSplitPane.svelte';
|
|
10
13
|
export { default as SettingsGroup } from './SettingsGroup.svelte';
|
|
@@ -5,6 +5,7 @@ export { default as PageToolbar } from './PageToolbar.svelte';
|
|
|
5
5
|
export { default as WorkspaceLayout } from './WorkspaceLayout.svelte';
|
|
6
6
|
export { default as WorkspaceStageStepper } from './WorkspaceStageStepper.svelte';
|
|
7
7
|
export { default as WorkspaceActionBar } from './WorkspaceActionBar.svelte';
|
|
8
|
+
export { default as WorkspaceTabBar } from './WorkspaceTabBar.svelte';
|
|
8
9
|
export { default as WorkspaceInspector } from './WorkspaceInspector.svelte';
|
|
9
10
|
export { default as WorkspaceSplitPane } from './WorkspaceSplitPane.svelte';
|
|
10
11
|
export { default as SettingsGroup } from './SettingsGroup.svelte';
|
package/dist/index.d.ts
CHANGED
|
@@ -170,6 +170,9 @@ export { default as WorkspaceLayout } from './components/content/WorkspaceLayout
|
|
|
170
170
|
export { default as WorkspaceStageStepper } from './components/content/WorkspaceStageStepper.svelte';
|
|
171
171
|
export type { WorkspaceStage, WorkspaceStageStatus } from './components/content/WorkspaceStageStepper.svelte';
|
|
172
172
|
export { default as WorkspaceActionBar } from './components/content/WorkspaceActionBar.svelte';
|
|
173
|
+
export type { WorkspaceActionBarTone } from './components/content/WorkspaceActionBar.svelte';
|
|
174
|
+
export { default as WorkspaceTabBar } from './components/content/WorkspaceTabBar.svelte';
|
|
175
|
+
export type { WorkspaceTabItem } from './components/content/WorkspaceTabBar.svelte';
|
|
173
176
|
export { default as WorkspaceInspector } from './components/content/WorkspaceInspector.svelte';
|
|
174
177
|
export { default as WorkspaceSplitPane } from './components/content/WorkspaceSplitPane.svelte';
|
|
175
178
|
export { default as SettingsGroup } from './components/content/SettingsGroup.svelte';
|
package/dist/index.js
CHANGED
|
@@ -184,6 +184,7 @@ export { default as PageToolbar } from './components/content/PageToolbar.svelte'
|
|
|
184
184
|
export { default as WorkspaceLayout } from './components/content/WorkspaceLayout.svelte';
|
|
185
185
|
export { default as WorkspaceStageStepper } from './components/content/WorkspaceStageStepper.svelte';
|
|
186
186
|
export { default as WorkspaceActionBar } from './components/content/WorkspaceActionBar.svelte';
|
|
187
|
+
export { default as WorkspaceTabBar } from './components/content/WorkspaceTabBar.svelte';
|
|
187
188
|
export { default as WorkspaceInspector } from './components/content/WorkspaceInspector.svelte';
|
|
188
189
|
export { default as WorkspaceSplitPane } from './components/content/WorkspaceSplitPane.svelte';
|
|
189
190
|
export { default as SettingsGroup } from './components/content/SettingsGroup.svelte';
|