@runwisp/ui 0.4.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/LICENSE +215 -0
- package/README.md +20 -0
- package/package.json +128 -0
- package/src/app.d.ts +8 -0
- package/src/app.html +12 -0
- package/src/astro/CTABand.astro +32 -0
- package/src/astro/Hero.astro +58 -0
- package/src/astro/SiteFooter.astro +47 -0
- package/src/astro/SiteHeader.astro +46 -0
- package/src/lib/actions/portal.ts +16 -0
- package/src/lib/assets/runwisp-logo.svg +16 -0
- package/src/lib/components/Accordion.svelte +20 -0
- package/src/lib/components/AccordionItem.svelte +74 -0
- package/src/lib/components/Alert.svelte +107 -0
- package/src/lib/components/AlertDialog.svelte +63 -0
- package/src/lib/components/Avatar.svelte +88 -0
- package/src/lib/components/Badge.svelte +131 -0
- package/src/lib/components/Breadcrumb.svelte +58 -0
- package/src/lib/components/Button.svelte +69 -0
- package/src/lib/components/Card.svelte +70 -0
- package/src/lib/components/Checkbox.svelte +90 -0
- package/src/lib/components/CodeBlock.svelte +66 -0
- package/src/lib/components/CronInput.svelte +130 -0
- package/src/lib/components/DataGrid.svelte +368 -0
- package/src/lib/components/Drawer.svelte +156 -0
- package/src/lib/components/Dropdown.svelte +195 -0
- package/src/lib/components/DurationInput.svelte +170 -0
- package/src/lib/components/EmptyState.svelte +46 -0
- package/src/lib/components/ErrorState.svelte +73 -0
- package/src/lib/components/FeatureCard.svelte +35 -0
- package/src/lib/components/FeatureGrid.svelte +37 -0
- package/src/lib/components/FormField.svelte +53 -0
- package/src/lib/components/Heading.svelte +46 -0
- package/src/lib/components/Input.svelte +114 -0
- package/src/lib/components/Kbd.svelte +31 -0
- package/src/lib/components/Link.svelte +56 -0
- package/src/lib/components/LinkButton.svelte +55 -0
- package/src/lib/components/LogConsole.svelte +424 -0
- package/src/lib/components/Logo.svelte +34 -0
- package/src/lib/components/Modal.svelte +138 -0
- package/src/lib/components/PageContainer.svelte +38 -0
- package/src/lib/components/Pagination.svelte +96 -0
- package/src/lib/components/Popover.svelte +130 -0
- package/src/lib/components/Progress.svelte +68 -0
- package/src/lib/components/Prose.svelte +43 -0
- package/src/lib/components/Radio.svelte +82 -0
- package/src/lib/components/RadioGroup.svelte +53 -0
- package/src/lib/components/Select.svelte +454 -0
- package/src/lib/components/Separator.svelte +30 -0
- package/src/lib/components/Skeleton.svelte +75 -0
- package/src/lib/components/Sparkline.svelte +58 -0
- package/src/lib/components/Spinner.svelte +44 -0
- package/src/lib/components/StatusIndicator.svelte +203 -0
- package/src/lib/components/Table.svelte +19 -0
- package/src/lib/components/TableBody.svelte +17 -0
- package/src/lib/components/TableCell.svelte +34 -0
- package/src/lib/components/TableHead.svelte +19 -0
- package/src/lib/components/TableRow.svelte +22 -0
- package/src/lib/components/Tabs.svelte +148 -0
- package/src/lib/components/Text.svelte +57 -0
- package/src/lib/components/Textarea.svelte +81 -0
- package/src/lib/components/ThemeToggle.svelte +47 -0
- package/src/lib/components/TimezoneSelect.svelte +127 -0
- package/src/lib/components/ToastContainer.svelte +84 -0
- package/src/lib/components/Toggle.svelte +84 -0
- package/src/lib/components/Tooltip.svelte +56 -0
- package/src/lib/components/button-styles.ts +51 -0
- package/src/lib/components/dashboard/RunDetailPanel.svelte +252 -0
- package/src/lib/components/dashboard/RunsList.svelte +331 -0
- package/src/lib/components/dashboard/run-helpers.ts +12 -0
- package/src/lib/components/dashboard/status-config.ts +141 -0
- package/src/lib/components/dashboard/types.ts +35 -0
- package/src/lib/index.ts +122 -0
- package/src/lib/log-console/LogCache.svelte.ts +93 -0
- package/src/lib/log-console/LogFetcher.svelte.ts +179 -0
- package/src/lib/log-console/types.ts +24 -0
- package/src/lib/theme-tokens.css +235 -0
- package/src/lib/theme.css +276 -0
- package/src/lib/utils/error.ts +18 -0
- package/src/lib/utils/format.ts +76 -0
- package/src/lib/utils/id.ts +6 -0
- package/src/lib/utils/toast.svelte.ts +87 -0
- package/src/lib/utils/toast.ts +60 -0
- package/src/routes/+layout.svelte +10 -0
- package/src/routes/+page.svelte +5 -0
- package/src/routes/layout.css +3 -0
- package/src/stories/Alert.stories.svelte +64 -0
- package/src/stories/Avatar.stories.svelte +76 -0
- package/src/stories/Badge.stories.svelte +76 -0
- package/src/stories/Breadcrumb.stories.svelte +64 -0
- package/src/stories/Button.stories.svelte +101 -0
- package/src/stories/Card.stories.svelte +106 -0
- package/src/stories/Checkbox.stories.svelte +77 -0
- package/src/stories/DataGrid.stories.svelte +130 -0
- package/src/stories/Dropdown.stories.svelte +81 -0
- package/src/stories/EmptyState.stories.svelte +74 -0
- package/src/stories/Input.stories.svelte +88 -0
- package/src/stories/Logo.stories.svelte +82 -0
- package/src/stories/Modal.stories.svelte +101 -0
- package/src/stories/Progress.stories.svelte +65 -0
- package/src/stories/Select.stories.svelte +158 -0
- package/src/stories/Tabs.stories.svelte +103 -0
- package/src/stories/Textarea.stories.svelte +45 -0
- package/src/stories/Toggle.stories.svelte +74 -0
- package/src/stories/Tooltip.stories.svelte +77 -0
- package/src/stories/Welcome.mdx +241 -0
- package/src/stories/assets/runwisp_c.svg +16 -0
- package/src/svelte-shims.d.ts +18 -0
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
<!-- SPDX-FileCopyrightText: PoppyCake, s.r.o. -->
|
|
2
|
+
<!-- SPDX-License-Identifier: Apache-2.0 -->
|
|
3
|
+
|
|
4
|
+
<script lang="ts">
|
|
5
|
+
import type { Snippet } from "svelte";
|
|
6
|
+
|
|
7
|
+
interface Props {
|
|
8
|
+
columns?: 1 | 2 | 3 | 4;
|
|
9
|
+
gap?: "sm" | "md" | "lg";
|
|
10
|
+
children?: Snippet;
|
|
11
|
+
class?: string;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
let { columns = 3, gap = "md", children, class: className = "" }: Props = $props();
|
|
15
|
+
|
|
16
|
+
const colClasses: Record<1 | 2 | 3 | 4, string> = {
|
|
17
|
+
1: "grid-cols-1",
|
|
18
|
+
2: "grid-cols-1 sm:grid-cols-2",
|
|
19
|
+
3: "grid-cols-1 sm:grid-cols-2 lg:grid-cols-3",
|
|
20
|
+
4: "grid-cols-1 sm:grid-cols-2 lg:grid-cols-4",
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
const gapClasses: Record<"sm" | "md" | "lg", string> = {
|
|
24
|
+
sm: "gap-3",
|
|
25
|
+
md: "gap-4",
|
|
26
|
+
lg: "gap-6",
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
const colClass = $derived(colClasses[columns]);
|
|
30
|
+
const gapClass = $derived(gapClasses[gap]);
|
|
31
|
+
</script>
|
|
32
|
+
|
|
33
|
+
<div class="grid {colClass} {gapClass} {className}">
|
|
34
|
+
{#if children}
|
|
35
|
+
{@render children()}
|
|
36
|
+
{/if}
|
|
37
|
+
</div>
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
<!-- SPDX-FileCopyrightText: PoppyCake, s.r.o. -->
|
|
2
|
+
<!-- SPDX-License-Identifier: Apache-2.0 -->
|
|
3
|
+
|
|
4
|
+
<script lang="ts">
|
|
5
|
+
import type { Snippet } from "svelte";
|
|
6
|
+
|
|
7
|
+
interface Props {
|
|
8
|
+
label?: string;
|
|
9
|
+
hint?: string;
|
|
10
|
+
error?: string;
|
|
11
|
+
description?: string;
|
|
12
|
+
required?: boolean;
|
|
13
|
+
children: Snippet;
|
|
14
|
+
class?: string;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
let {
|
|
18
|
+
label,
|
|
19
|
+
hint,
|
|
20
|
+
error,
|
|
21
|
+
description,
|
|
22
|
+
required = false,
|
|
23
|
+
children,
|
|
24
|
+
class: className = "",
|
|
25
|
+
}: Props = $props();
|
|
26
|
+
|
|
27
|
+
const generatedId = `field-${Math.random().toString(36).slice(2, 10)}`;
|
|
28
|
+
</script>
|
|
29
|
+
|
|
30
|
+
<div class="space-y-1.5 {className}">
|
|
31
|
+
{#if label}
|
|
32
|
+
<label for={generatedId} class="block text-sm font-medium text-on-surface-muted">
|
|
33
|
+
{label}
|
|
34
|
+
{#if required}
|
|
35
|
+
<span class="text-danger-500">*</span>
|
|
36
|
+
{/if}
|
|
37
|
+
</label>
|
|
38
|
+
{/if}
|
|
39
|
+
|
|
40
|
+
{#if description}
|
|
41
|
+
<p class="text-sm text-on-surface-faint">{description}</p>
|
|
42
|
+
{/if}
|
|
43
|
+
|
|
44
|
+
{@render children()}
|
|
45
|
+
|
|
46
|
+
{#if error}
|
|
47
|
+
<p class="animate-in slide-in-from-top-1 fade-in text-sm text-danger-600 duration-200">
|
|
48
|
+
{error}
|
|
49
|
+
</p>
|
|
50
|
+
{:else if hint}
|
|
51
|
+
<p class="text-sm text-on-surface-muted">{hint}</p>
|
|
52
|
+
{/if}
|
|
53
|
+
</div>
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
<!-- SPDX-FileCopyrightText: PoppyCake, s.r.o. -->
|
|
2
|
+
<!-- SPDX-License-Identifier: Apache-2.0 -->
|
|
3
|
+
|
|
4
|
+
<script lang="ts">
|
|
5
|
+
import type { Snippet } from "svelte";
|
|
6
|
+
|
|
7
|
+
type HeadingLevel = 1 | 2 | 3 | 4 | 5 | 6;
|
|
8
|
+
type HeadingSize = "xs" | "sm" | "md" | "lg" | "xl" | "2xl" | "3xl" | "4xl";
|
|
9
|
+
|
|
10
|
+
interface Props {
|
|
11
|
+
level: HeadingLevel;
|
|
12
|
+
size?: HeadingSize;
|
|
13
|
+
children: Snippet;
|
|
14
|
+
class?: string;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
let { level, size, children, class: className = "" }: Props = $props();
|
|
18
|
+
|
|
19
|
+
const defaultSizeMap: Record<HeadingLevel, HeadingSize> = {
|
|
20
|
+
1: "4xl",
|
|
21
|
+
2: "3xl",
|
|
22
|
+
3: "2xl",
|
|
23
|
+
4: "xl",
|
|
24
|
+
5: "lg",
|
|
25
|
+
6: "base" as HeadingSize,
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
const sizeClasses: Record<string, string> = {
|
|
29
|
+
xs: "text-xs font-semibold",
|
|
30
|
+
sm: "text-sm font-semibold",
|
|
31
|
+
base: "text-base font-semibold",
|
|
32
|
+
md: "text-base font-semibold",
|
|
33
|
+
lg: "text-lg font-semibold",
|
|
34
|
+
xl: "text-xl font-bold",
|
|
35
|
+
"2xl": "text-2xl font-bold",
|
|
36
|
+
"3xl": "text-3xl font-bold",
|
|
37
|
+
"4xl": "text-4xl font-bold tracking-tight",
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
const resolvedSize = $derived(size ?? defaultSizeMap[level]);
|
|
41
|
+
const tag = $derived(`h${level}` as const);
|
|
42
|
+
</script>
|
|
43
|
+
|
|
44
|
+
<svelte:element this={tag} class="text-on-surface {sizeClasses[resolvedSize]} {className}">
|
|
45
|
+
{@render children()}
|
|
46
|
+
</svelte:element>
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
<!-- SPDX-FileCopyrightText: PoppyCake, s.r.o. -->
|
|
2
|
+
<!-- SPDX-License-Identifier: Apache-2.0 -->
|
|
3
|
+
|
|
4
|
+
<script lang="ts">
|
|
5
|
+
import type { Snippet } from "svelte";
|
|
6
|
+
import type { HTMLInputAttributes } from "svelte/elements";
|
|
7
|
+
import { CircleAlert } from "@lucide/svelte";
|
|
8
|
+
|
|
9
|
+
type InputSize = "sm" | "md" | "lg";
|
|
10
|
+
|
|
11
|
+
interface Props extends Omit<HTMLInputAttributes, "size"> {
|
|
12
|
+
size?: InputSize;
|
|
13
|
+
label?: string;
|
|
14
|
+
hint?: string;
|
|
15
|
+
error?: string | undefined;
|
|
16
|
+
leadingIcon?: Snippet;
|
|
17
|
+
trailingIcon?: Snippet;
|
|
18
|
+
class?: string;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
let {
|
|
22
|
+
size = "md",
|
|
23
|
+
value = $bindable(),
|
|
24
|
+
id,
|
|
25
|
+
label,
|
|
26
|
+
hint,
|
|
27
|
+
error = $bindable(),
|
|
28
|
+
leadingIcon,
|
|
29
|
+
trailingIcon,
|
|
30
|
+
disabled = false,
|
|
31
|
+
class: className = "",
|
|
32
|
+
oninput,
|
|
33
|
+
...restProps
|
|
34
|
+
}: Props = $props();
|
|
35
|
+
|
|
36
|
+
const generatedId = `input-${Math.random().toString(36).slice(2, 10)}`;
|
|
37
|
+
const inputId = $derived(id ?? generatedId);
|
|
38
|
+
|
|
39
|
+
const sizeClasses: Record<InputSize, string> = {
|
|
40
|
+
sm: "text-sm px-3 py-1.5",
|
|
41
|
+
md: "text-sm px-3.5 py-2",
|
|
42
|
+
lg: "text-base px-4 py-2.5",
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
const inputClasses = `
|
|
46
|
+
w-full rounded-lg border
|
|
47
|
+
bg-surface-raised text-on-surface placeholder:text-on-surface-faint
|
|
48
|
+
focus:outline-none focus:ring-4 focus:ring-ring/10 focus:border-ring
|
|
49
|
+
disabled:bg-surface-sunken disabled:text-on-surface-muted disabled:cursor-not-allowed
|
|
50
|
+
transition-all duration-normal ease-in-out
|
|
51
|
+
`;
|
|
52
|
+
|
|
53
|
+
const normalBorder = "border-outline hover:border-outline-hover shadow-sm";
|
|
54
|
+
const errorBorder = "border-danger-400 focus:border-danger-500 focus:ring-danger-500/20";
|
|
55
|
+
</script>
|
|
56
|
+
|
|
57
|
+
<div class="space-y-1.5 {className}">
|
|
58
|
+
{#if label}
|
|
59
|
+
<label for={inputId} class="block text-sm font-medium text-on-surface-muted">
|
|
60
|
+
{label}
|
|
61
|
+
</label>
|
|
62
|
+
{/if}
|
|
63
|
+
|
|
64
|
+
<div class="group relative">
|
|
65
|
+
{#if leadingIcon}
|
|
66
|
+
<div
|
|
67
|
+
class="pointer-events-none absolute top-1/2 left-3 -translate-y-1/2 text-on-surface-faint transition-colors group-focus-within:text-on-surface-muted"
|
|
68
|
+
>
|
|
69
|
+
{@render leadingIcon()}
|
|
70
|
+
</div>
|
|
71
|
+
{/if}
|
|
72
|
+
|
|
73
|
+
<input
|
|
74
|
+
id={inputId}
|
|
75
|
+
class="
|
|
76
|
+
{inputClasses}
|
|
77
|
+
{sizeClasses[size]}
|
|
78
|
+
{error ? errorBorder : normalBorder}
|
|
79
|
+
{leadingIcon ? 'pl-10' : ''}
|
|
80
|
+
{trailingIcon || error ? 'pr-10' : ''}
|
|
81
|
+
"
|
|
82
|
+
{disabled}
|
|
83
|
+
bind:value
|
|
84
|
+
aria-invalid={error ? "true" : undefined}
|
|
85
|
+
oninput={(e) => {
|
|
86
|
+
if (error) error = undefined;
|
|
87
|
+
oninput?.(e);
|
|
88
|
+
}}
|
|
89
|
+
{...restProps}
|
|
90
|
+
/>
|
|
91
|
+
|
|
92
|
+
{#if error}
|
|
93
|
+
<div
|
|
94
|
+
class="pointer-events-none absolute top-1/2 right-3 -translate-y-1/2 text-danger-500"
|
|
95
|
+
>
|
|
96
|
+
<CircleAlert size={18} />
|
|
97
|
+
</div>
|
|
98
|
+
{:else if trailingIcon}
|
|
99
|
+
<div
|
|
100
|
+
class="pointer-events-none absolute top-1/2 right-3 -translate-y-1/2 text-on-surface-faint transition-colors group-focus-within:text-on-surface-muted"
|
|
101
|
+
>
|
|
102
|
+
{@render trailingIcon()}
|
|
103
|
+
</div>
|
|
104
|
+
{/if}
|
|
105
|
+
</div>
|
|
106
|
+
|
|
107
|
+
{#if error}
|
|
108
|
+
<p class="animate-in slide-in-from-top-1 fade-in text-sm text-danger-600 duration-200">
|
|
109
|
+
{error}
|
|
110
|
+
</p>
|
|
111
|
+
{:else if hint}
|
|
112
|
+
<p class="text-sm text-on-surface-muted">{hint}</p>
|
|
113
|
+
{/if}
|
|
114
|
+
</div>
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
<!-- SPDX-FileCopyrightText: PoppyCake, s.r.o. -->
|
|
2
|
+
<!-- SPDX-License-Identifier: Apache-2.0 -->
|
|
3
|
+
|
|
4
|
+
<script lang="ts">
|
|
5
|
+
interface Props {
|
|
6
|
+
keys: string | string[];
|
|
7
|
+
class?: string;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
let { keys, class: className = "" }: Props = $props();
|
|
11
|
+
|
|
12
|
+
const keyList = $derived(Array.isArray(keys) ? keys : [keys]);
|
|
13
|
+
|
|
14
|
+
const kbdClasses = `
|
|
15
|
+
inline-flex items-center justify-center
|
|
16
|
+
min-w-[1.5em] px-1.5 py-0.5
|
|
17
|
+
text-xs font-mono font-medium
|
|
18
|
+
bg-surface-sunken text-on-surface-muted
|
|
19
|
+
border border-outline rounded-md
|
|
20
|
+
shadow-sm
|
|
21
|
+
`;
|
|
22
|
+
</script>
|
|
23
|
+
|
|
24
|
+
<span class="inline-flex items-center gap-1 {className}">
|
|
25
|
+
{#each keyList as key, i (key)}
|
|
26
|
+
{#if i > 0}
|
|
27
|
+
<span class="text-xs text-on-surface-faint select-none">+</span>
|
|
28
|
+
{/if}
|
|
29
|
+
<kbd class={kbdClasses}>{key}</kbd>
|
|
30
|
+
{/each}
|
|
31
|
+
</span>
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
<!-- SPDX-FileCopyrightText: PoppyCake, s.r.o. -->
|
|
2
|
+
<!-- SPDX-License-Identifier: Apache-2.0 -->
|
|
3
|
+
|
|
4
|
+
<script lang="ts">
|
|
5
|
+
import type { Snippet } from "svelte";
|
|
6
|
+
|
|
7
|
+
type LinkVariant = "default" | "muted" | "primary" | "danger";
|
|
8
|
+
type LinkUnderline = "always" | "hover" | "none";
|
|
9
|
+
|
|
10
|
+
interface Props {
|
|
11
|
+
href: string;
|
|
12
|
+
variant?: LinkVariant;
|
|
13
|
+
external?: boolean;
|
|
14
|
+
underline?: LinkUnderline;
|
|
15
|
+
children: Snippet;
|
|
16
|
+
class?: string;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
let {
|
|
20
|
+
href,
|
|
21
|
+
variant = "default",
|
|
22
|
+
external = false,
|
|
23
|
+
underline = "hover",
|
|
24
|
+
children,
|
|
25
|
+
class: className = "",
|
|
26
|
+
}: Props = $props();
|
|
27
|
+
|
|
28
|
+
const baseClasses = `
|
|
29
|
+
inline-flex items-center gap-1
|
|
30
|
+
transition-colors duration-normal ease-out
|
|
31
|
+
focus-visible:outline-none focus-visible:ring-4 focus-visible:ring-ring/10 focus-visible:border-ring
|
|
32
|
+
rounded-sm
|
|
33
|
+
`;
|
|
34
|
+
|
|
35
|
+
const variantClasses: Record<LinkVariant, string> = {
|
|
36
|
+
default: "text-on-surface hover:text-primary",
|
|
37
|
+
muted: "text-on-surface-muted hover:text-on-surface",
|
|
38
|
+
primary: "text-primary hover:text-primary-hover",
|
|
39
|
+
danger: "text-danger-surface hover:text-danger-hover",
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
const underlineClasses: Record<LinkUnderline, string> = {
|
|
43
|
+
always: "underline underline-offset-2",
|
|
44
|
+
hover: "hover:underline underline-offset-2",
|
|
45
|
+
none: "no-underline",
|
|
46
|
+
};
|
|
47
|
+
</script>
|
|
48
|
+
|
|
49
|
+
<a
|
|
50
|
+
{href}
|
|
51
|
+
class="{baseClasses} {variantClasses[variant]} {underlineClasses[underline]} {className}"
|
|
52
|
+
target={external ? "_blank" : undefined}
|
|
53
|
+
rel={external ? "noopener noreferrer" : undefined}
|
|
54
|
+
>
|
|
55
|
+
{@render children()}
|
|
56
|
+
</a>
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
<!-- SPDX-FileCopyrightText: PoppyCake, s.r.o. -->
|
|
2
|
+
<!-- SPDX-License-Identifier: Apache-2.0 -->
|
|
3
|
+
|
|
4
|
+
<script lang="ts">
|
|
5
|
+
import type { Snippet } from "svelte";
|
|
6
|
+
import type { HTMLAnchorAttributes } from "svelte/elements";
|
|
7
|
+
import {
|
|
8
|
+
BUTTON_BASE,
|
|
9
|
+
BUTTON_SIZES,
|
|
10
|
+
BUTTON_VARIANTS,
|
|
11
|
+
type ButtonSize,
|
|
12
|
+
type ButtonVariant,
|
|
13
|
+
} from "./button-styles.js";
|
|
14
|
+
|
|
15
|
+
interface Props extends HTMLAnchorAttributes {
|
|
16
|
+
variant?: ButtonVariant;
|
|
17
|
+
size?: ButtonSize;
|
|
18
|
+
fullWidth?: boolean;
|
|
19
|
+
icon?: Snippet;
|
|
20
|
+
iconRight?: Snippet;
|
|
21
|
+
children?: Snippet;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
let {
|
|
25
|
+
variant = "primary",
|
|
26
|
+
size = "md",
|
|
27
|
+
fullWidth = false,
|
|
28
|
+
icon,
|
|
29
|
+
iconRight,
|
|
30
|
+
children,
|
|
31
|
+
class: className = "",
|
|
32
|
+
...restProps
|
|
33
|
+
}: Props = $props();
|
|
34
|
+
</script>
|
|
35
|
+
|
|
36
|
+
<a
|
|
37
|
+
class="{BUTTON_BASE} {BUTTON_VARIANTS[variant]} {BUTTON_SIZES[size]} {fullWidth
|
|
38
|
+
? 'w-full'
|
|
39
|
+
: ''} {className}"
|
|
40
|
+
{...restProps}
|
|
41
|
+
>
|
|
42
|
+
{#if icon}
|
|
43
|
+
<span class="shrink-0 transition-transform group-active:scale-95">
|
|
44
|
+
{@render icon()}
|
|
45
|
+
</span>
|
|
46
|
+
{/if}
|
|
47
|
+
{#if children}
|
|
48
|
+
{@render children()}
|
|
49
|
+
{/if}
|
|
50
|
+
{#if iconRight}
|
|
51
|
+
<span class="shrink-0 transition-transform group-active:scale-95">
|
|
52
|
+
{@render iconRight()}
|
|
53
|
+
</span>
|
|
54
|
+
{/if}
|
|
55
|
+
</a>
|