zabi-components 6.0.0 → 7.0.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.
- package/README.md +137 -1473
- package/dist/atoms/ActionPanel.svelte +116 -0
- package/dist/atoms/ActionPanel.svelte.d.ts +19 -0
- package/dist/atoms/Badge.svelte +1 -1
- package/dist/atoms/Badge.svelte.d.ts +1 -1
- package/dist/atoms/Button.svelte +38 -21
- package/dist/atoms/Button.svelte.d.ts +6 -6
- package/dist/atoms/Card.svelte +12 -3
- package/dist/atoms/Card.svelte.d.ts +2 -2
- package/dist/atoms/CardHeader.svelte +8 -4
- package/dist/atoms/CardHeader.svelte.d.ts +4 -2
- package/dist/atoms/Checkbox.svelte +50 -76
- package/dist/atoms/Checkbox.svelte.d.ts +7 -2
- package/dist/atoms/CodeBlock.svelte +20 -34
- package/dist/atoms/CodeBlock.svelte.d.ts +1 -0
- package/dist/atoms/ColorPicker.svelte +2 -6
- package/dist/atoms/Container.svelte +41 -0
- package/dist/atoms/Container.svelte.d.ts +12 -0
- package/dist/atoms/Divider.svelte +68 -0
- package/dist/atoms/Divider.svelte.d.ts +13 -0
- package/dist/atoms/FeatureCard.svelte +35 -50
- package/dist/atoms/FeatureCard.svelte.d.ts +9 -4
- package/dist/atoms/IconButton.svelte +36 -29
- package/dist/atoms/IconButton.svelte.d.ts +7 -13
- package/dist/atoms/Input.svelte +58 -26
- package/dist/atoms/Input.svelte.d.ts +6 -1
- package/dist/atoms/List.svelte +2 -7
- package/dist/atoms/List.svelte.d.ts +1 -6
- package/dist/atoms/ListItem.svelte +54 -65
- package/dist/atoms/ListItem.svelte.d.ts +7 -13
- package/dist/atoms/ListItemLeading.svelte +19 -0
- package/dist/atoms/ListItemLeading.svelte.d.ts +9 -0
- package/dist/atoms/Progress.svelte +1 -1
- package/dist/atoms/Radio.svelte +51 -0
- package/dist/atoms/Radio.svelte.d.ts +14 -0
- package/dist/atoms/Select.svelte +23 -30
- package/dist/atoms/Select.svelte.d.ts +0 -10
- package/dist/atoms/SelectionControl.svelte +98 -0
- package/dist/atoms/SelectionControl.svelte.d.ts +26 -0
- package/dist/atoms/Skeleton.svelte +39 -15
- package/dist/atoms/Skeleton.svelte.d.ts +7 -3
- package/dist/atoms/Table.svelte +27 -0
- package/dist/atoms/Table.svelte.d.ts +10 -0
- package/dist/atoms/Text.svelte +46 -0
- package/dist/atoms/Text.svelte.d.ts +13 -0
- package/dist/atoms/Textarea.svelte +74 -53
- package/dist/atoms/Textarea.svelte.d.ts +6 -2
- package/dist/atoms/ThemeToggle.svelte +35 -24
- package/dist/atoms/ThemeToggle.svelte.d.ts +1 -0
- package/dist/atoms/Toast.svelte +55 -31
- package/dist/atoms/Toast.svelte.d.ts +4 -1
- package/dist/atoms/Toggle.svelte +37 -22
- package/dist/atoms/Toggle.svelte.d.ts +2 -1
- package/dist/atoms/Tooltip.svelte +97 -14
- package/dist/atoms/Tooltip.svelte.d.ts +6 -5
- package/dist/atoms/index.d.ts +6 -0
- package/dist/atoms/index.js +6 -0
- package/dist/atoms/selection-control.styles.d.ts +25 -0
- package/dist/atoms/selection-control.styles.js +30 -0
- package/dist/components/atoms/index.d.ts +6 -0
- package/dist/components/atoms/index.d.ts.map +1 -1
- package/dist/components/atoms/selection-control.styles.d.ts +26 -0
- package/dist/components/atoms/selection-control.styles.d.ts.map +1 -0
- package/dist/components/index.d.ts +41 -5
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/molecules/index.d.ts +10 -0
- package/dist/components/molecules/index.d.ts.map +1 -1
- package/dist/components/molecules/navigation-menu-context.d.ts +11 -0
- package/dist/components/molecules/navigation-menu-context.d.ts.map +1 -1
- package/dist/components/molecules/toast-store.d.ts +39 -0
- package/dist/components/molecules/toast-store.d.ts.map +1 -0
- package/dist/components/organisms/index.d.ts +2 -1
- package/dist/components/organisms/index.d.ts.map +1 -1
- package/dist/components/types/page.types.d.ts +69 -0
- package/dist/components/types/page.types.d.ts.map +1 -0
- package/dist/components/types/page.types.js +1 -0
- package/dist/components/types/variants.d.ts +64 -0
- package/dist/components/types/variants.d.ts.map +1 -0
- package/dist/components/types/variants.js +44 -0
- package/dist/components/util/fixed-sidebar-flyout.d.ts +23 -0
- package/dist/components/util/fixed-sidebar-flyout.d.ts.map +1 -0
- package/dist/components/util/focus-utils.d.ts +12 -0
- package/dist/components/util/focus-utils.d.ts.map +1 -0
- package/dist/components/util/ssr-safe.d.ts +17 -0
- package/dist/components/util/ssr-safe.d.ts.map +1 -0
- package/dist/index.d.ts +41 -5
- package/dist/index.js +44 -8
- package/dist/lib/layout-width-tokens.d.ts +17 -0
- package/dist/lib/layout-width-tokens.d.ts.map +1 -0
- package/dist/lib/showcase/component-docs/Button.d.ts +3 -0
- package/dist/lib/showcase/component-docs/Button.d.ts.map +1 -0
- package/dist/lib/showcase/component-docs/Input.d.ts +3 -0
- package/dist/lib/showcase/component-docs/Input.d.ts.map +1 -0
- package/dist/lib/showcase/component-docs/List.d.ts +3 -0
- package/dist/lib/showcase/component-docs/List.d.ts.map +1 -0
- package/dist/lib/showcase/component-docs/Modal.d.ts +3 -0
- package/dist/lib/showcase/component-docs/Modal.d.ts.map +1 -0
- package/dist/lib/showcase/component-docs/Radio.d.ts +3 -0
- package/dist/lib/showcase/component-docs/Radio.d.ts.map +1 -0
- package/dist/lib/showcase/component-docs/SidebarNavigation.d.ts +3 -0
- package/dist/lib/showcase/component-docs/SidebarNavigation.d.ts.map +1 -0
- package/dist/lib/showcase/component-docs/Skeleton.d.ts +3 -0
- package/dist/lib/showcase/component-docs/Skeleton.d.ts.map +1 -0
- package/dist/lib/showcase/component-docs/_shared.d.ts +12 -0
- package/dist/lib/showcase/component-docs/_shared.d.ts.map +1 -0
- package/dist/lib/showcase/component-docs/index.d.ts +4 -0
- package/dist/lib/showcase/component-docs/index.d.ts.map +1 -0
- package/dist/lib/showcase/components-catalog.d.ts.map +1 -1
- package/dist/lib/showcase/components-showcase-constants.d.ts +26 -0
- package/dist/lib/showcase/components-showcase-constants.d.ts.map +1 -1
- package/dist/molecules/Alert.svelte +50 -23
- package/dist/molecules/Alert.svelte.d.ts +1 -1
- package/dist/molecules/ComponentDemo.svelte +2 -2
- package/dist/molecules/ContactForm.svelte +1 -1
- package/dist/molecules/Dropdown.svelte +99 -109
- package/dist/molecules/Dropdown.svelte.d.ts +12 -6
- package/dist/molecules/EmptyState.svelte +44 -0
- package/dist/molecules/EmptyState.svelte.d.ts +11 -0
- package/dist/molecules/FormField.svelte +89 -0
- package/dist/molecules/FormField.svelte.d.ts +23 -0
- package/dist/molecules/Header.svelte +41 -0
- package/dist/molecules/Header.svelte.d.ts +10 -0
- package/dist/molecules/Modal.svelte +37 -24
- package/dist/molecules/Modal.svelte.d.ts +4 -2
- package/dist/molecules/NavigationMenu.svelte +16 -0
- package/dist/molecules/NavigationMenu.svelte.d.ts +2 -0
- package/dist/molecules/NavigationMenuContent.svelte +9 -1
- package/dist/molecules/NavigationMenuLink.svelte +1 -1
- package/dist/molecules/NavigationMenuTrigger.svelte +9 -1
- package/dist/molecules/Page.svelte +16 -0
- package/dist/molecules/Page.svelte.d.ts +8 -0
- package/dist/molecules/PropsTable.svelte +61 -0
- package/dist/molecules/PropsTable.svelte.d.ts +8 -0
- package/dist/molecules/RadioGroup.svelte +197 -0
- package/dist/molecules/RadioGroup.svelte.d.ts +20 -0
- package/dist/molecules/Section.svelte +2 -11
- package/dist/molecules/Section.svelte.d.ts +2 -11
- package/dist/molecules/SidebarBrandHeader.svelte +68 -0
- package/dist/molecules/SidebarBrandHeader.svelte.d.ts +10 -0
- package/dist/molecules/SidebarFooter.svelte +119 -0
- package/dist/molecules/SidebarFooter.svelte.d.ts +23 -0
- package/dist/molecules/SidebarNavSection.svelte +49 -0
- package/dist/molecules/SidebarNavSection.svelte.d.ts +14 -0
- package/dist/molecules/SlideUp.svelte +19 -14
- package/dist/molecules/SlideUp.svelte.d.ts +1 -1
- package/dist/molecules/Tabs.svelte +4 -9
- package/dist/molecules/Toaster.svelte +21 -0
- package/dist/molecules/Toaster.svelte.d.ts +6 -0
- package/dist/molecules/ToasterToast.svelte +217 -0
- package/dist/molecules/ToasterToast.svelte.d.ts +7 -0
- package/dist/molecules/index.d.ts +10 -0
- package/dist/molecules/index.js +10 -0
- package/dist/molecules/navigation-menu-context.d.ts +11 -0
- package/dist/molecules/navigation-menu-context.js +18 -0
- package/dist/molecules/toast-store.d.ts +38 -0
- package/dist/molecules/toast-store.js +34 -0
- package/dist/organisms/SidebarAccountPanel.svelte +118 -0
- package/dist/organisms/SidebarAccountPanel.svelte.d.ts +20 -0
- package/dist/organisms/SidebarNavigation.svelte +267 -237
- package/dist/organisms/SidebarNavigation.svelte.d.ts +21 -5
- package/dist/organisms/SidebarPanel.svelte +54 -22
- package/dist/organisms/SidebarPanel.svelte.d.ts +3 -0
- package/dist/organisms/{Navbar.svelte → TopNavbar.svelte} +22 -17
- package/dist/organisms/TopNavbar.svelte.d.ts +35 -0
- package/dist/organisms/index.d.ts +2 -1
- package/dist/organisms/index.js +2 -1
- package/dist/routes/lib/focus-utils.d.ts +7 -18
- package/dist/routes/lib/focus-utils.ts +32 -34
- package/dist/routes/lib/ssr-safe.ts +5 -4
- package/dist/routes/lib/variant-utils.ts +48 -39
- package/dist/types/components.d.ts +187 -0
- package/dist/types/components.d.ts.map +1 -0
- package/dist/types/events.d.ts +200 -0
- package/dist/types/events.d.ts.map +1 -0
- package/dist/types/index.d.ts +171 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/page.types.d.ts +2 -31
- package/dist/types/page.types.d.ts.map +1 -1
- package/dist/types/page.types.js +1 -0
- package/dist/types/page.types.ts +79 -0
- package/dist/types/variants.d.ts +3 -0
- package/dist/types/variants.d.ts.map +1 -0
- package/dist/types/variants.js +1 -0
- package/dist/types/variants.ts +5 -6
- package/dist/util/fixed-sidebar-flyout.d.ts +22 -0
- package/dist/util/fixed-sidebar-flyout.js +148 -0
- package/dist/util/focus-utils.d.ts +11 -0
- package/dist/util/focus-utils.js +94 -0
- package/dist/util/ssr-safe.d.ts +16 -0
- package/dist/util/ssr-safe.js +48 -0
- package/dist/zabi-components-colors.css +128 -115
- package/dist/zabi-components-theme-dark-only.css +77 -72
- package/dist/zabi-components-theme-dark.css +77 -72
- package/dist/zabi-components-theme-only.css +51 -43
- package/dist/zabi-components-theme.css +51 -43
- package/dist/zabi-components.css +952 -249
- package/docs/lucide-icons.md +24 -0
- package/package.json +22 -9
- package/scripts/fix-lucide-svelte-icon-dts.js +35 -0
- package/dist/organisms/Navbar.svelte.d.ts +0 -41
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import Badge from "./Badge.svelte";
|
|
3
|
+
import type { ExtendedSemanticVariant } from "../types/variants.js";
|
|
4
|
+
|
|
5
|
+
interface Props {
|
|
6
|
+
title: string;
|
|
7
|
+
description: string;
|
|
8
|
+
href?: string;
|
|
9
|
+
onclick?: (event: MouseEvent) => void | Promise<void>;
|
|
10
|
+
disabled?: boolean;
|
|
11
|
+
loading?: boolean;
|
|
12
|
+
badgeText?: string;
|
|
13
|
+
badgeVariant?: ExtendedSemanticVariant;
|
|
14
|
+
/** Overrides the default accessible name for the clickable region. */
|
|
15
|
+
ariaLabel?: string;
|
|
16
|
+
className?: string;
|
|
17
|
+
target?: HTMLAnchorElement["target"];
|
|
18
|
+
rel?: string;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
let {
|
|
22
|
+
title,
|
|
23
|
+
description,
|
|
24
|
+
href,
|
|
25
|
+
onclick,
|
|
26
|
+
disabled = false,
|
|
27
|
+
loading = false,
|
|
28
|
+
badgeText,
|
|
29
|
+
badgeVariant = "neutral",
|
|
30
|
+
ariaLabel,
|
|
31
|
+
className = "",
|
|
32
|
+
target,
|
|
33
|
+
rel,
|
|
34
|
+
...restProps
|
|
35
|
+
}: Props = $props();
|
|
36
|
+
|
|
37
|
+
const isDisabled = $derived(disabled || loading);
|
|
38
|
+
|
|
39
|
+
const computedAriaLabel = $derived(
|
|
40
|
+
ariaLabel ?? (href ? `Open ${title}` : title),
|
|
41
|
+
);
|
|
42
|
+
|
|
43
|
+
const baseClasses =
|
|
44
|
+
"group focus-ring focus-ring--muted block rounded-2xl border border-base-200 bg-base-0 p-6 text-left transition-all duration-200 hover:border-headline/30 hover:bg-base-50 active:scale-[0.99] active:bg-base-100";
|
|
45
|
+
|
|
46
|
+
const disabledClasses =
|
|
47
|
+
"opacity-50 cursor-not-allowed pointer-events-none hover:border-base-200 hover:bg-base-0 active:scale-100";
|
|
48
|
+
|
|
49
|
+
const panelClasses = $derived(
|
|
50
|
+
[baseClasses, isDisabled ? disabledClasses : "", className]
|
|
51
|
+
.filter(Boolean)
|
|
52
|
+
.join(" ")
|
|
53
|
+
.trim(),
|
|
54
|
+
);
|
|
55
|
+
|
|
56
|
+
function handleKeydown(event: KeyboardEvent) {
|
|
57
|
+
if (isDisabled) return;
|
|
58
|
+
if (!href && onclick && (event.key === "Enter" || event.key === " ")) {
|
|
59
|
+
event.preventDefault();
|
|
60
|
+
onclick(event as unknown as MouseEvent);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
</script>
|
|
64
|
+
|
|
65
|
+
{#snippet body()}
|
|
66
|
+
<div class="flex items-start justify-between gap-4">
|
|
67
|
+
<div class="min-w-0">
|
|
68
|
+
<h3
|
|
69
|
+
class="truncate text-lg font-semibold text-headline transition-colors group-hover:text-headline/90"
|
|
70
|
+
>
|
|
71
|
+
{title}
|
|
72
|
+
</h3>
|
|
73
|
+
<p class="mt-3 line-clamp-2 text-description">{description}</p>
|
|
74
|
+
</div>
|
|
75
|
+
<div class="flex shrink-0 items-center gap-3">
|
|
76
|
+
{#if badgeText}
|
|
77
|
+
<Badge variant={badgeVariant} text={badgeText} />
|
|
78
|
+
{/if}
|
|
79
|
+
{#if loading}
|
|
80
|
+
<span
|
|
81
|
+
class="inline-block size-5 shrink-0 animate-spin rounded-full border-2 border-description border-t-transparent opacity-70"
|
|
82
|
+
aria-hidden="true"
|
|
83
|
+
></span>
|
|
84
|
+
{/if}
|
|
85
|
+
</div>
|
|
86
|
+
</div>
|
|
87
|
+
{/snippet}
|
|
88
|
+
|
|
89
|
+
{#if href}
|
|
90
|
+
<a
|
|
91
|
+
class={panelClasses}
|
|
92
|
+
href={isDisabled ? undefined : href}
|
|
93
|
+
aria-label={computedAriaLabel}
|
|
94
|
+
aria-disabled={isDisabled ? "true" : undefined}
|
|
95
|
+
aria-busy={loading ? "true" : undefined}
|
|
96
|
+
tabindex={isDisabled ? -1 : undefined}
|
|
97
|
+
target={target}
|
|
98
|
+
rel={rel}
|
|
99
|
+
{...restProps}
|
|
100
|
+
>
|
|
101
|
+
{@render body()}
|
|
102
|
+
</a>
|
|
103
|
+
{:else}
|
|
104
|
+
<button
|
|
105
|
+
type="button"
|
|
106
|
+
class={panelClasses}
|
|
107
|
+
aria-label={computedAriaLabel}
|
|
108
|
+
aria-busy={loading ? "true" : undefined}
|
|
109
|
+
disabled={isDisabled}
|
|
110
|
+
onclick={onclick}
|
|
111
|
+
onkeydown={handleKeydown}
|
|
112
|
+
{...restProps}
|
|
113
|
+
>
|
|
114
|
+
{@render body()}
|
|
115
|
+
</button>
|
|
116
|
+
{/if}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { ExtendedSemanticVariant } from "../types/variants.js";
|
|
2
|
+
interface Props {
|
|
3
|
+
title: string;
|
|
4
|
+
description: string;
|
|
5
|
+
href?: string;
|
|
6
|
+
onclick?: (event: MouseEvent) => void | Promise<void>;
|
|
7
|
+
disabled?: boolean;
|
|
8
|
+
loading?: boolean;
|
|
9
|
+
badgeText?: string;
|
|
10
|
+
badgeVariant?: ExtendedSemanticVariant;
|
|
11
|
+
/** Overrides the default accessible name for the clickable region. */
|
|
12
|
+
ariaLabel?: string;
|
|
13
|
+
className?: string;
|
|
14
|
+
target?: HTMLAnchorElement["target"];
|
|
15
|
+
rel?: string;
|
|
16
|
+
}
|
|
17
|
+
declare const ActionPanel: import("svelte").Component<Props, {}, "">;
|
|
18
|
+
type ActionPanel = ReturnType<typeof ActionPanel>;
|
|
19
|
+
export default ActionPanel;
|
package/dist/atoms/Badge.svelte
CHANGED
package/dist/atoms/Button.svelte
CHANGED
|
@@ -1,31 +1,35 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import type { Snippet } from "svelte";
|
|
3
|
-
import type {
|
|
3
|
+
import type { HTMLButtonAttributes } from "svelte/elements";
|
|
4
|
+
import type { ButtonVariant, SizeVariant } from "../types/variants.js";
|
|
4
5
|
|
|
5
|
-
|
|
6
|
+
type Props = Omit<HTMLButtonAttributes, "class"> & {
|
|
6
7
|
variant?: ButtonVariant;
|
|
7
8
|
size?: SizeVariant;
|
|
8
|
-
|
|
9
|
-
type?: "button" | "submit" | "reset";
|
|
9
|
+
loading?: boolean;
|
|
10
10
|
text?: string;
|
|
11
11
|
isFullWidth?: boolean;
|
|
12
|
-
|
|
12
|
+
class?: string;
|
|
13
13
|
children?: Snippet;
|
|
14
|
-
}
|
|
14
|
+
};
|
|
15
15
|
|
|
16
16
|
let {
|
|
17
17
|
variant = "primary",
|
|
18
18
|
size = "md",
|
|
19
19
|
disabled = false,
|
|
20
|
+
loading = false,
|
|
20
21
|
type = "button",
|
|
21
22
|
text = "",
|
|
22
23
|
isFullWidth = false,
|
|
24
|
+
class: className = "",
|
|
23
25
|
onclick,
|
|
24
26
|
children,
|
|
25
27
|
...restProps
|
|
26
28
|
}: Props = $props();
|
|
27
29
|
|
|
28
|
-
const
|
|
30
|
+
const isDisabled = $derived(disabled || loading);
|
|
31
|
+
|
|
32
|
+
const sizeClass = $derived.by(() => {
|
|
29
33
|
if (size === "sm") {
|
|
30
34
|
return {
|
|
31
35
|
padding: "px-4 py-2.5",
|
|
@@ -59,33 +63,46 @@
|
|
|
59
63
|
}
|
|
60
64
|
});
|
|
61
65
|
|
|
62
|
-
const variantClass = $derived(() => {
|
|
66
|
+
const variantClass = $derived.by(() => {
|
|
63
67
|
return variant === "primary"
|
|
64
|
-
? "bg-action-primary text-action-primary hover:bg-action-primary-hover active:bg-action-primary-active
|
|
68
|
+
? "bg-action-primary text-action-primary hover:bg-action-primary-hover active:bg-action-primary-active active:scale-[0.98]"
|
|
65
69
|
: variant === "secondary"
|
|
66
|
-
? "bg-action-secondary text-headline hover:bg-action-secondary-hover active:bg-action-secondary-active
|
|
70
|
+
? "bg-action-secondary text-headline hover:bg-action-secondary-hover active:bg-action-secondary-active active:scale-[0.98]"
|
|
67
71
|
: variant === "danger"
|
|
68
|
-
? "bg-action-danger text-inverse hover:bg-action-danger-hover active:bg-action-danger-active
|
|
72
|
+
? "bg-action-danger text-inverse hover:bg-action-danger-hover active:bg-action-danger-active active:scale-[0.98] focus-ring--danger"
|
|
69
73
|
: variant === "ghost"
|
|
70
|
-
? "bg-transparent text-headline hover:bg-base-100 active:bg-base-200
|
|
71
|
-
|
|
72
|
-
|
|
74
|
+
? "bg-transparent text-headline hover:bg-base-100 active:bg-base-200 active:scale-[0.98] focus-ring--muted disabled:text-disabled"
|
|
75
|
+
: variant === "outline"
|
|
76
|
+
? "bg-transparent border border-border text-headline hover:bg-action-secondary hover:border-border-medium hover:text-action-primary active:bg-action-primary-active active:text-action-primary active:scale-[0.98] disabled:border-disabled disabled:text-disabled"
|
|
73
77
|
: variant === "link"
|
|
74
|
-
? "text-brand-700 active:text-brand-700 underline-offset-4 hover:underline
|
|
75
|
-
: "bg-action-primary text-action-primary hover:bg-action-primary-hover active:bg-action-primary-active
|
|
78
|
+
? "text-brand-700 active:text-brand-700 underline-offset-4 hover:underline disabled:text-disabled disabled:no-underline"
|
|
79
|
+
: "bg-action-primary text-action-primary hover:bg-action-primary-hover active:bg-action-primary-active active:scale-[0.98]";
|
|
76
80
|
});
|
|
77
81
|
|
|
78
|
-
const buttonClasses = $derived(() => {
|
|
79
|
-
const sizeStyles = sizeClass
|
|
82
|
+
const buttonClasses = $derived.by(() => {
|
|
83
|
+
const sizeStyles = sizeClass;
|
|
80
84
|
const flexClass = isFullWidth ? "flex" : "inline-flex";
|
|
81
85
|
const widthClass = isFullWidth ? "w-full" : "";
|
|
82
|
-
const baseClasses = `${flexClass} items-center justify-center transition-all duration-200 cursor-pointer disabled:opacity-50 disabled:cursor-not-allowed
|
|
86
|
+
const baseClasses = `${flexClass} focus-ring items-center justify-center transition-all duration-200 cursor-pointer disabled:opacity-50 disabled:cursor-not-allowed disabled:active:scale-100`;
|
|
83
87
|
|
|
84
|
-
return `${baseClasses} ${widthClass} ${sizeStyles.padding} ${sizeStyles.text} ${sizeStyles.font} ${sizeStyles.leading} ${sizeStyles.tracking} ${sizeStyles.radius} ${sizeStyles.gap} ${variantClass
|
|
88
|
+
return `${baseClasses} ${widthClass} ${sizeStyles.padding} ${sizeStyles.text} ${sizeStyles.font} ${sizeStyles.leading} ${sizeStyles.tracking} ${sizeStyles.radius} ${sizeStyles.gap} ${variantClass} ${className}`.trim();
|
|
85
89
|
});
|
|
86
90
|
</script>
|
|
87
91
|
|
|
88
|
-
<button
|
|
92
|
+
<button
|
|
93
|
+
{type}
|
|
94
|
+
class={buttonClasses}
|
|
95
|
+
disabled={isDisabled}
|
|
96
|
+
aria-busy={loading ? "true" : undefined}
|
|
97
|
+
{onclick}
|
|
98
|
+
{...restProps}
|
|
99
|
+
>
|
|
100
|
+
{#if loading}
|
|
101
|
+
<span
|
|
102
|
+
class="inline-block size-4 shrink-0 animate-spin rounded-full border-2 border-current border-t-transparent opacity-80"
|
|
103
|
+
aria-hidden="true"
|
|
104
|
+
></span>
|
|
105
|
+
{/if}
|
|
89
106
|
{#if text}
|
|
90
107
|
{text}
|
|
91
108
|
{:else if children}
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import type { Snippet } from "svelte";
|
|
2
|
-
import type {
|
|
3
|
-
|
|
2
|
+
import type { HTMLButtonAttributes } from "svelte/elements";
|
|
3
|
+
import type { ButtonVariant, SizeVariant } from "../types/variants.js";
|
|
4
|
+
type Props = Omit<HTMLButtonAttributes, "class"> & {
|
|
4
5
|
variant?: ButtonVariant;
|
|
5
6
|
size?: SizeVariant;
|
|
6
|
-
|
|
7
|
-
type?: "button" | "submit" | "reset";
|
|
7
|
+
loading?: boolean;
|
|
8
8
|
text?: string;
|
|
9
9
|
isFullWidth?: boolean;
|
|
10
|
-
|
|
10
|
+
class?: string;
|
|
11
11
|
children?: Snippet;
|
|
12
|
-
}
|
|
12
|
+
};
|
|
13
13
|
declare const Button: import("svelte").Component<Props, {}, "">;
|
|
14
14
|
type Button = ReturnType<typeof Button>;
|
|
15
15
|
export default Button;
|
package/dist/atoms/Card.svelte
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import type { Snippet } from "svelte";
|
|
3
|
-
import type { CardVariant, SizeVariant } from "
|
|
3
|
+
import type { CardVariant, SizeVariant } from "../types/variants.js";
|
|
4
4
|
|
|
5
5
|
interface Props {
|
|
6
6
|
onclick?: (event: MouseEvent) => void | Promise<void>;
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
variant?: CardVariant;
|
|
9
9
|
fullWidth?: boolean;
|
|
10
10
|
className?: string;
|
|
11
|
-
/** Required when
|
|
11
|
+
/** Required when `onclick` is set (no visible label). */
|
|
12
12
|
ariaLabel?: string;
|
|
13
13
|
children?: Snippet;
|
|
14
14
|
}
|
|
@@ -28,6 +28,14 @@
|
|
|
28
28
|
size === "sm" ? "p-4" : size === "lg" ? "p-8" : "p-6",
|
|
29
29
|
);
|
|
30
30
|
|
|
31
|
+
const radiusClass = $derived(
|
|
32
|
+
size === "sm"
|
|
33
|
+
? "rounded-xl"
|
|
34
|
+
: size === "lg"
|
|
35
|
+
? "rounded-3xl"
|
|
36
|
+
: "rounded-2xl",
|
|
37
|
+
);
|
|
38
|
+
|
|
31
39
|
const variantClasses = $derived(
|
|
32
40
|
variant === "elevated"
|
|
33
41
|
? "bg-card shadow-lg"
|
|
@@ -40,7 +48,8 @@
|
|
|
40
48
|
|
|
41
49
|
const cardClasses = $derived(
|
|
42
50
|
[
|
|
43
|
-
|
|
51
|
+
radiusClass,
|
|
52
|
+
"transition-all duration-200",
|
|
44
53
|
variantClasses,
|
|
45
54
|
onclick
|
|
46
55
|
? variant === "elevated"
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import type { Snippet } from "svelte";
|
|
2
|
-
import type { CardVariant, SizeVariant } from "
|
|
2
|
+
import type { CardVariant, SizeVariant } from "../types/variants.js";
|
|
3
3
|
interface Props {
|
|
4
4
|
onclick?: (event: MouseEvent) => void | Promise<void>;
|
|
5
5
|
size?: SizeVariant;
|
|
6
6
|
variant?: CardVariant;
|
|
7
7
|
fullWidth?: boolean;
|
|
8
8
|
className?: string;
|
|
9
|
-
/** Required when
|
|
9
|
+
/** Required when `onclick` is set (no visible label). */
|
|
10
10
|
ariaLabel?: string;
|
|
11
11
|
children?: Snippet;
|
|
12
12
|
}
|
|
@@ -3,10 +3,12 @@
|
|
|
3
3
|
|
|
4
4
|
interface Props {
|
|
5
5
|
title?: string;
|
|
6
|
-
/** Short secondary text displayed directly under the title */
|
|
7
6
|
subtitle?: string;
|
|
8
|
-
/** Longer supporting text displayed below the subtitle */
|
|
9
7
|
description?: string;
|
|
8
|
+
/** `id` on the subtitle `<p>` (e.g. `aria-describedby` on the title). */
|
|
9
|
+
subtitleId?: string;
|
|
10
|
+
/** `id` on the description `<p>`. */
|
|
11
|
+
descriptionId?: string;
|
|
10
12
|
level?: 1 | 2 | 3 | 4 | 5 | 6;
|
|
11
13
|
className?: string;
|
|
12
14
|
children?: Snippet;
|
|
@@ -16,6 +18,8 @@
|
|
|
16
18
|
title = "",
|
|
17
19
|
subtitle = "",
|
|
18
20
|
description = "",
|
|
21
|
+
subtitleId,
|
|
22
|
+
descriptionId,
|
|
19
23
|
level = 3,
|
|
20
24
|
className = "",
|
|
21
25
|
children,
|
|
@@ -38,12 +42,12 @@
|
|
|
38
42
|
{@render children()}
|
|
39
43
|
{/if}
|
|
40
44
|
{#if subtitle}
|
|
41
|
-
<p class="text-sm text-description">
|
|
45
|
+
<p id={subtitleId} class="text-sm text-description">
|
|
42
46
|
{subtitle}
|
|
43
47
|
</p>
|
|
44
48
|
{/if}
|
|
45
49
|
{#if description}
|
|
46
|
-
<p class="text-sm text-description">
|
|
50
|
+
<p id={descriptionId} class="text-sm text-description">
|
|
47
51
|
{description}
|
|
48
52
|
</p>
|
|
49
53
|
{/if}
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import type { Snippet } from "svelte";
|
|
2
2
|
interface Props {
|
|
3
3
|
title?: string;
|
|
4
|
-
/** Short secondary text displayed directly under the title */
|
|
5
4
|
subtitle?: string;
|
|
6
|
-
/** Longer supporting text displayed below the subtitle */
|
|
7
5
|
description?: string;
|
|
6
|
+
/** `id` on the subtitle `<p>` (e.g. `aria-describedby` on the title). */
|
|
7
|
+
subtitleId?: string;
|
|
8
|
+
/** `id` on the description `<p>`. */
|
|
9
|
+
descriptionId?: string;
|
|
8
10
|
level?: 1 | 2 | 3 | 4 | 5 | 6;
|
|
9
11
|
className?: string;
|
|
10
12
|
children?: Snippet;
|
|
@@ -1,95 +1,69 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
import
|
|
2
|
+
import SelectionControl from "./SelectionControl.svelte";
|
|
3
|
+
import type { SelectionControlMarkProps } from "./SelectionControl.svelte";
|
|
3
4
|
|
|
4
5
|
interface Props {
|
|
5
|
-
|
|
6
|
+
id?: string;
|
|
6
7
|
name?: string;
|
|
8
|
+
value?: string;
|
|
7
9
|
disabled?: boolean;
|
|
10
|
+
loading?: boolean;
|
|
8
11
|
label?: string;
|
|
12
|
+
defaultChecked?: boolean;
|
|
13
|
+
checked?: boolean;
|
|
14
|
+
onChange?: (event: Event) => void;
|
|
9
15
|
onchange?: (event: Event) => void;
|
|
10
16
|
}
|
|
11
17
|
|
|
12
18
|
let {
|
|
13
|
-
|
|
19
|
+
id,
|
|
20
|
+
value = "",
|
|
14
21
|
name = "",
|
|
15
22
|
disabled = false,
|
|
23
|
+
loading = false,
|
|
16
24
|
label = "",
|
|
25
|
+
defaultChecked = false,
|
|
26
|
+
checked = $bindable(defaultChecked),
|
|
27
|
+
onChange,
|
|
17
28
|
onchange,
|
|
18
29
|
...restProps
|
|
19
30
|
}: Props = $props();
|
|
20
|
-
|
|
21
|
-
const checkboxId = generateId("checkbox");
|
|
22
|
-
|
|
23
|
-
const checkboxContainerClasses = $derived(() => {
|
|
24
|
-
const baseClasses =
|
|
25
|
-
"relative inline-flex items-center justify-center w-5 h-5 rounded transition-all duration-200";
|
|
26
|
-
|
|
27
|
-
if (disabled) {
|
|
28
|
-
return `${baseClasses} opacity-50 cursor-not-allowed`;
|
|
29
|
-
}
|
|
30
|
-
return `${baseClasses} cursor-pointer`;
|
|
31
|
-
});
|
|
32
|
-
|
|
33
|
-
const checkboxBoxClasses = $derived(() => {
|
|
34
|
-
if (checked) {
|
|
35
|
-
return disabled
|
|
36
|
-
? "border-0 opacity-50 bg-brand-500"
|
|
37
|
-
: "border-0 bg-brand-500";
|
|
38
|
-
}
|
|
39
|
-
return disabled
|
|
40
|
-
? "border-2 border-base-400 bg-transparent"
|
|
41
|
-
: "border-2 border-base-400 bg-transparent";
|
|
42
|
-
});
|
|
43
|
-
|
|
44
|
-
function handleChange(event: Event) {
|
|
45
|
-
if (disabled) return;
|
|
46
|
-
const target = event.target as HTMLInputElement;
|
|
47
|
-
checked = target.checked;
|
|
48
|
-
if (onchange) {
|
|
49
|
-
onchange(event);
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
31
|
</script>
|
|
53
32
|
|
|
54
|
-
|
|
55
|
-
<
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
33
|
+
{#snippet mark(props: SelectionControlMarkProps)}
|
|
34
|
+
<span
|
|
35
|
+
class="pointer-events-none absolute inline-block size-3 shrink-0 animate-spin rounded-full border-2 border-brand-500 border-t-transparent z-10 opacity-0 group-has-[aria-busy=true]/control:opacity-100 group-has-checked/control:border-base-50"
|
|
36
|
+
aria-hidden="true"
|
|
37
|
+
></span>
|
|
38
|
+
<svg
|
|
39
|
+
class="absolute w-3 h-3 text-base-50 pointer-events-none z-10 opacity-0 group-has-checked/control:opacity-100"
|
|
40
|
+
fill="none"
|
|
41
|
+
stroke="currentColor"
|
|
42
|
+
viewBox="0 0 24 24"
|
|
43
|
+
aria-hidden="true"
|
|
60
44
|
>
|
|
61
|
-
<
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
</svg>
|
|
87
|
-
{/if}
|
|
88
|
-
</div>
|
|
89
|
-
{#if label}
|
|
90
|
-
<span class="text-sm font-medium text-label">
|
|
91
|
-
{label}
|
|
92
|
-
</span>
|
|
93
|
-
{/if}
|
|
94
|
-
</label>
|
|
95
|
-
</div>
|
|
45
|
+
<path
|
|
46
|
+
stroke-linecap="round"
|
|
47
|
+
stroke-linejoin="round"
|
|
48
|
+
stroke-width="2.5"
|
|
49
|
+
d="M5 13l4 4L19 7"
|
|
50
|
+
/>
|
|
51
|
+
</svg>
|
|
52
|
+
{/snippet}
|
|
53
|
+
|
|
54
|
+
<SelectionControl
|
|
55
|
+
type="checkbox"
|
|
56
|
+
shape="square"
|
|
57
|
+
{id}
|
|
58
|
+
{name}
|
|
59
|
+
{value}
|
|
60
|
+
{label}
|
|
61
|
+
{disabled}
|
|
62
|
+
{loading}
|
|
63
|
+
bind:checked
|
|
64
|
+
{defaultChecked}
|
|
65
|
+
{onChange}
|
|
66
|
+
{onchange}
|
|
67
|
+
{mark}
|
|
68
|
+
{...restProps}
|
|
69
|
+
/>
|
|
@@ -1,10 +1,15 @@
|
|
|
1
1
|
interface Props {
|
|
2
|
-
|
|
2
|
+
id?: string;
|
|
3
3
|
name?: string;
|
|
4
|
+
value?: string;
|
|
4
5
|
disabled?: boolean;
|
|
6
|
+
loading?: boolean;
|
|
5
7
|
label?: string;
|
|
8
|
+
defaultChecked?: boolean;
|
|
9
|
+
checked?: boolean;
|
|
10
|
+
onChange?: (event: Event) => void;
|
|
6
11
|
onchange?: (event: Event) => void;
|
|
7
12
|
}
|
|
8
|
-
declare const Checkbox: import("svelte").Component<Props, {}, "">;
|
|
13
|
+
declare const Checkbox: import("svelte").Component<Props, {}, "checked">;
|
|
9
14
|
type Checkbox = ReturnType<typeof Checkbox>;
|
|
10
15
|
export default Checkbox;
|
|
@@ -1,9 +1,16 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
+
import Check from "@lucide/svelte/icons/check";
|
|
3
|
+
import Copy from "@lucide/svelte/icons/copy";
|
|
4
|
+
import IconButton from "./IconButton.svelte";
|
|
5
|
+
|
|
2
6
|
interface Props {
|
|
7
|
+
/** Raw source; escaped unless `trustHtml` (e.g. highlighter HTML). */
|
|
3
8
|
code: string;
|
|
4
9
|
language?: string;
|
|
5
10
|
className?: string;
|
|
6
11
|
showCopyButton?: boolean;
|
|
12
|
+
/** If true, `{@html code}` — only trusted, sanitized input. */
|
|
13
|
+
trustHtml?: boolean;
|
|
7
14
|
}
|
|
8
15
|
|
|
9
16
|
let {
|
|
@@ -11,6 +18,7 @@
|
|
|
11
18
|
language = "svelte",
|
|
12
19
|
className = "",
|
|
13
20
|
showCopyButton = true,
|
|
21
|
+
trustHtml = false,
|
|
14
22
|
...restProps
|
|
15
23
|
} = $props();
|
|
16
24
|
|
|
@@ -30,11 +38,11 @@
|
|
|
30
38
|
</script>
|
|
31
39
|
|
|
32
40
|
<div
|
|
33
|
-
class="code-block relative bg-
|
|
41
|
+
class="code-block relative bg-surface-1 border border-border rounded-lg overflow-hidden {className}"
|
|
34
42
|
{...restProps}
|
|
35
43
|
>
|
|
36
44
|
<div
|
|
37
|
-
class="flex items-center justify-between px-4 py-2 bg-
|
|
45
|
+
class="flex items-center justify-between px-4 py-2 bg-surface-2 border-b border-border"
|
|
38
46
|
>
|
|
39
47
|
<div class="flex items-center gap-2">
|
|
40
48
|
<div class="w-3 h-3 rounded-full bg-red-500"></div>
|
|
@@ -42,46 +50,24 @@
|
|
|
42
50
|
<div class="w-3 h-3 rounded-full bg-green-500"></div>
|
|
43
51
|
</div>
|
|
44
52
|
{#if showCopyButton}
|
|
45
|
-
<
|
|
53
|
+
<IconButton
|
|
54
|
+
variant="ghost"
|
|
55
|
+
size="sm"
|
|
56
|
+
label={copied ? "Code copied to clipboard" : "Copy code to clipboard"}
|
|
46
57
|
onclick={copyToClipboard}
|
|
47
|
-
class="flex cursor-pointer items-center gap-2 rounded px-3 py-1 text-xs text-base-300 transition-colors duration-200 hover:bg-base-700 hover:text-white"
|
|
48
|
-
aria-label="Copy code to clipboard"
|
|
49
58
|
>
|
|
50
59
|
{#if copied}
|
|
51
|
-
<
|
|
52
|
-
class="w-4 h-4"
|
|
53
|
-
fill="currentColor"
|
|
54
|
-
viewBox="0 0 20 20"
|
|
55
|
-
>
|
|
56
|
-
<path
|
|
57
|
-
fill-rule="evenodd"
|
|
58
|
-
d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z"
|
|
59
|
-
clip-rule="evenodd"
|
|
60
|
-
/>
|
|
61
|
-
</svg>
|
|
62
|
-
Copied!
|
|
60
|
+
<Check size={16} class="shrink-0" aria-hidden="true" />
|
|
63
61
|
{:else}
|
|
64
|
-
<
|
|
65
|
-
class="w-4 h-4"
|
|
66
|
-
fill="none"
|
|
67
|
-
stroke="currentColor"
|
|
68
|
-
viewBox="0 0 24 24"
|
|
69
|
-
>
|
|
70
|
-
<path
|
|
71
|
-
stroke-linecap="round"
|
|
72
|
-
stroke-linejoin="round"
|
|
73
|
-
stroke-width="2"
|
|
74
|
-
d="M8 16H6a2 2 0 01-2-2V6a2 2 0 012-2h8a2 2 0 012 2v2m-6 12h8a2 2 0 002-2v-8a2 2 0 00-2-2h-8a2 2 0 00-2 2v8a2 2 0 002 2z"
|
|
75
|
-
/>
|
|
76
|
-
</svg>
|
|
77
|
-
Copy
|
|
62
|
+
<Copy size={16} class="shrink-0" aria-hidden="true" />
|
|
78
63
|
{/if}
|
|
79
|
-
</
|
|
64
|
+
</IconButton>
|
|
80
65
|
{/if}
|
|
81
66
|
</div>
|
|
82
67
|
|
|
83
|
-
<pre class="p-4 overflow-x-auto text-sm text-base-
|
|
84
|
-
class="language-{language}"
|
|
68
|
+
<pre class="p-4 overflow-x-auto text-sm text-base-900 leading-relaxed"><code
|
|
69
|
+
class="language-{language}"
|
|
70
|
+
>{#if trustHtml}{@html code}{:else}{code}{/if}</code
|
|
85
71
|
></pre>
|
|
86
72
|
</div>
|
|
87
73
|
|