zabi-components 7.0.1 → 8.0.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/README.md +46 -3
- package/THEMING.md +255 -15
- package/dist/atoms/ActionPanel.svelte +12 -7
- package/dist/atoms/ActionPanel.svelte.d.ts +2 -0
- package/dist/atoms/Badge.svelte +93 -56
- package/dist/atoms/Badge.svelte.d.ts +15 -3
- package/dist/atoms/Button.svelte +49 -49
- package/dist/atoms/Button.svelte.d.ts +3 -0
- package/dist/atoms/Card.svelte +31 -28
- package/dist/atoms/Card.svelte.d.ts +5 -2
- package/dist/atoms/CardContent.svelte +10 -2
- package/dist/atoms/CardContent.svelte.d.ts +2 -0
- package/dist/atoms/CardFooter.svelte +10 -2
- package/dist/atoms/CardFooter.svelte.d.ts +2 -0
- package/dist/atoms/CardHeader.svelte +10 -2
- package/dist/atoms/CardHeader.svelte.d.ts +2 -0
- package/dist/atoms/Checkbox.svelte +4 -0
- package/dist/atoms/Checkbox.svelte.d.ts +2 -0
- package/dist/atoms/CodeBlock.svelte +15 -7
- package/dist/atoms/CodeBlock.svelte.d.ts +9 -3
- package/dist/atoms/ColorPicker.svelte +19 -9
- package/dist/atoms/ColorPicker.svelte.d.ts +3 -1
- package/dist/atoms/Container.svelte +2 -3
- package/dist/atoms/Divider.svelte +4 -4
- package/dist/atoms/FeatureCard.svelte +4 -3
- package/dist/atoms/Heading.svelte +56 -27
- package/dist/atoms/Heading.svelte.d.ts +17 -4
- package/dist/atoms/IconButton.svelte +30 -37
- package/dist/atoms/Input.svelte +26 -34
- package/dist/atoms/List.svelte +10 -2
- package/dist/atoms/List.svelte.d.ts +2 -0
- package/dist/atoms/ListItem.svelte +2 -2
- package/dist/atoms/ListItemLeading.svelte +4 -2
- package/dist/atoms/ListItemLeading.svelte.d.ts +1 -1
- package/dist/atoms/OptimizedImage.svelte +11 -2
- package/dist/atoms/OptimizedImage.svelte.d.ts +2 -0
- package/dist/atoms/Progress.svelte +4 -1
- package/dist/atoms/Progress.svelte.d.ts +2 -0
- package/dist/atoms/Radio.svelte +4 -0
- package/dist/atoms/Radio.svelte.d.ts +2 -0
- package/dist/atoms/Select.svelte +65 -67
- package/dist/atoms/Select.svelte.d.ts +4 -0
- package/dist/atoms/SelectionControl.svelte +5 -1
- package/dist/atoms/SelectionControl.svelte.d.ts +2 -0
- package/dist/atoms/Skeleton.svelte +5 -3
- package/dist/atoms/Table.svelte +2 -1
- package/dist/atoms/Text.svelte +34 -5
- package/dist/atoms/Text.svelte.d.ts +7 -1
- package/dist/atoms/Textarea.svelte +7 -6
- package/dist/atoms/ThemeToggle.svelte +17 -14
- package/dist/atoms/ThemeToggle.svelte.d.ts +2 -0
- package/dist/atoms/Toast.svelte +10 -8
- package/dist/atoms/Toggle.svelte +21 -13
- package/dist/atoms/Toggle.svelte.d.ts +7 -0
- package/dist/atoms/Tooltip.svelte +89 -57
- package/dist/atoms/Tooltip.svelte.d.ts +15 -0
- package/dist/components/index.d.ts +3 -1
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/organisms/index.d.ts +1 -0
- package/dist/components/organisms/index.d.ts.map +1 -1
- package/dist/components/util/cn.d.ts +8 -0
- package/dist/components/util/cn.d.ts.map +1 -0
- package/dist/components/util/ssr-safe.d.ts +4 -4
- package/dist/components/util/ssr-safe.d.ts.map +1 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.js +3 -6
- package/dist/molecules/Alert.svelte +43 -64
- package/dist/molecules/Alert.svelte.d.ts +7 -1
- package/dist/molecules/ComponentDemo.svelte +10 -2
- package/dist/molecules/ComponentDemo.svelte.d.ts +2 -0
- package/dist/molecules/ContactForm.svelte +12 -2
- package/dist/molecules/ContactForm.svelte.d.ts +2 -0
- package/dist/molecules/Dropdown.svelte +40 -11
- package/dist/molecules/Dropdown.svelte.d.ts +4 -0
- package/dist/molecules/EmptyState.svelte +2 -1
- package/dist/molecules/Form.svelte +25 -14
- package/dist/molecules/Form.svelte.d.ts +13 -5
- package/dist/molecules/FormField.svelte +2 -1
- package/dist/molecules/Header.svelte +13 -3
- package/dist/molecules/Header.svelte.d.ts +2 -0
- package/dist/molecules/ImageUpload.svelte +54 -15
- package/dist/molecules/ImageUpload.svelte.d.ts +16 -5
- package/dist/molecules/Modal.svelte +110 -31
- package/dist/molecules/Modal.svelte.d.ts +9 -6
- package/dist/molecules/NavigationMenu.svelte +15 -3
- package/dist/molecules/NavigationMenu.svelte.d.ts +4 -0
- package/dist/molecules/NavigationMenuContent.svelte +36 -38
- package/dist/molecules/NavigationMenuContent.svelte.d.ts +2 -0
- package/dist/molecules/NavigationMenuItem.svelte +10 -2
- package/dist/molecules/NavigationMenuItem.svelte.d.ts +2 -0
- package/dist/molecules/NavigationMenuLink.svelte +10 -2
- package/dist/molecules/NavigationMenuLink.svelte.d.ts +2 -0
- package/dist/molecules/NavigationMenuList.svelte +10 -2
- package/dist/molecules/NavigationMenuList.svelte.d.ts +2 -0
- package/dist/molecules/NavigationMenuTrigger.svelte +16 -3
- package/dist/molecules/NavigationMenuTrigger.svelte.d.ts +2 -0
- package/dist/molecules/Page.svelte +8 -2
- package/dist/molecules/Page.svelte.d.ts +2 -0
- package/dist/molecules/PropsTable.svelte +6 -3
- package/dist/molecules/PropsTable.svelte.d.ts +2 -0
- package/dist/molecules/RadioGroup.svelte +5 -1
- package/dist/molecules/RadioGroup.svelte.d.ts +2 -0
- package/dist/molecules/Section.svelte +12 -4
- package/dist/molecules/Section.svelte.d.ts +3 -1
- package/dist/molecules/SidebarBrandHeader.svelte +13 -4
- package/dist/molecules/SidebarBrandHeader.svelte.d.ts +2 -0
- package/dist/molecules/SidebarFooter.svelte +12 -4
- package/dist/molecules/SidebarFooter.svelte.d.ts +2 -0
- package/dist/molecules/SidebarNavSection.svelte +12 -4
- package/dist/molecules/SidebarNavSection.svelte.d.ts +2 -0
- package/dist/molecules/SlideUp.svelte +85 -21
- package/dist/molecules/SlideUp.svelte.d.ts +5 -4
- package/dist/molecules/Tabs.svelte +25 -19
- package/dist/molecules/Tabs.svelte.d.ts +8 -4
- package/dist/molecules/Toaster.svelte +3 -2
- package/dist/molecules/ToasterToast.svelte +41 -10
- package/dist/molecules/ToasterToast.svelte.d.ts +2 -0
- package/dist/organisms/SidebarAccountPanel.svelte +4 -0
- package/dist/organisms/SidebarAccountPanel.svelte.d.ts +2 -0
- package/dist/organisms/SidebarNavigation.svelte +102 -59
- package/dist/organisms/SidebarNavigation.svelte.d.ts +2 -0
- package/dist/organisms/SidebarPanel.svelte +19 -11
- package/dist/organisms/SidebarPanel.svelte.d.ts +2 -0
- package/dist/organisms/SidebarShell.svelte +112 -0
- package/dist/organisms/SidebarShell.svelte.d.ts +52 -0
- package/dist/organisms/TopNavbar.svelte +88 -17
- package/dist/organisms/TopNavbar.svelte.d.ts +2 -0
- package/dist/organisms/index.d.ts +1 -0
- package/dist/organisms/index.js +1 -0
- package/dist/routes/lib/variant-utils.d.ts +26 -0
- package/dist/routes/lib/{variant-utils.ts → variant-utils.js} +15 -46
- package/dist/types/events.js +1 -0
- package/dist/types/index.js +3 -0
- package/dist/util/cn.d.ts +7 -0
- package/dist/util/cn.js +48 -0
- package/dist/util/ssr-safe.d.ts +4 -4
- package/dist/zabi-components-colors.css +3 -437
- package/dist/zabi-components-theme-dark-only.css +223 -103
- package/dist/zabi-components-theme-dark.css +223 -103
- package/dist/zabi-components-theme-only.css +347 -107
- package/dist/zabi-components-theme.css +347 -107
- package/dist/zabi-components.css +953 -843
- package/docs/lucide-icons.md +3 -1
- package/package.json +20 -25
- package/dist/lib/layout-width-tokens.d.ts +0 -17
- package/dist/lib/layout-width-tokens.d.ts.map +0 -1
- package/dist/lib/showcase/component-docs/Button.d.ts +0 -3
- package/dist/lib/showcase/component-docs/Button.d.ts.map +0 -1
- package/dist/lib/showcase/component-docs/Input.d.ts +0 -3
- package/dist/lib/showcase/component-docs/Input.d.ts.map +0 -1
- package/dist/lib/showcase/component-docs/List.d.ts +0 -3
- package/dist/lib/showcase/component-docs/List.d.ts.map +0 -1
- package/dist/lib/showcase/component-docs/Modal.d.ts +0 -3
- package/dist/lib/showcase/component-docs/Modal.d.ts.map +0 -1
- package/dist/lib/showcase/component-docs/Radio.d.ts +0 -3
- package/dist/lib/showcase/component-docs/Radio.d.ts.map +0 -1
- package/dist/lib/showcase/component-docs/SidebarNavigation.d.ts +0 -3
- package/dist/lib/showcase/component-docs/SidebarNavigation.d.ts.map +0 -1
- package/dist/lib/showcase/component-docs/Skeleton.d.ts +0 -3
- package/dist/lib/showcase/component-docs/Skeleton.d.ts.map +0 -1
- package/dist/lib/showcase/component-docs/_shared.d.ts +0 -12
- package/dist/lib/showcase/component-docs/_shared.d.ts.map +0 -1
- package/dist/lib/showcase/component-docs/index.d.ts +0 -4
- package/dist/lib/showcase/component-docs/index.d.ts.map +0 -1
- package/dist/lib/showcase/components-catalog.d.ts +0 -3
- package/dist/lib/showcase/components-catalog.d.ts.map +0 -1
- package/dist/lib/showcase/components-showcase-constants.d.ts +0 -89
- package/dist/lib/showcase/components-showcase-constants.d.ts.map +0 -1
- package/dist/lib/showcase/docs-sidebar-helpers.d.ts +0 -15
- package/dist/lib/showcase/docs-sidebar-helpers.d.ts.map +0 -1
- package/dist/routes/lib/focus-utils.d.ts +0 -12
- package/dist/routes/lib/focus-utils.ts +0 -110
- package/dist/routes/lib/ssr-safe.ts +0 -58
- package/scripts/fix-lucide-svelte-icon-dts.js +0 -35
package/dist/atoms/Button.svelte
CHANGED
|
@@ -2,12 +2,16 @@
|
|
|
2
2
|
import type { Snippet } from "svelte";
|
|
3
3
|
import type { HTMLButtonAttributes } from "svelte/elements";
|
|
4
4
|
import type { ButtonVariant, SizeVariant } from "../types/variants.js";
|
|
5
|
+
import { cn } from "../util/cn.js";
|
|
5
6
|
|
|
6
7
|
type Props = Omit<HTMLButtonAttributes, "class"> & {
|
|
7
8
|
variant?: ButtonVariant;
|
|
8
9
|
size?: SizeVariant;
|
|
9
10
|
loading?: boolean;
|
|
10
11
|
text?: string;
|
|
12
|
+
/** Stretch to the width of the container. */
|
|
13
|
+
fullWidth?: boolean;
|
|
14
|
+
/** @deprecated use `fullWidth` — kept so 7.x call sites keep working. */
|
|
11
15
|
isFullWidth?: boolean;
|
|
12
16
|
class?: string;
|
|
13
17
|
children?: Snippet;
|
|
@@ -20,6 +24,7 @@
|
|
|
20
24
|
loading = false,
|
|
21
25
|
type = "button",
|
|
22
26
|
text = "",
|
|
27
|
+
fullWidth = false,
|
|
23
28
|
isFullWidth = false,
|
|
24
29
|
class: className = "",
|
|
25
30
|
onclick,
|
|
@@ -29,63 +34,58 @@
|
|
|
29
34
|
|
|
30
35
|
const isDisabled = $derived(disabled || loading);
|
|
31
36
|
|
|
37
|
+
/**
|
|
38
|
+
* One height scale, shared with Input, Select and IconButton, so controls
|
|
39
|
+
* of the same size line up in a row. Heights are fixed (h-8 / h-10 / h-12)
|
|
40
|
+
* rather than derived from padding + line-height, which is what let Button
|
|
41
|
+
* and Input drift 14px apart at `lg`.
|
|
42
|
+
*
|
|
43
|
+
* Weight and tracking do NOT change with size: a large button used to drop
|
|
44
|
+
* to font-normal, so the biggest button had the lightest label.
|
|
45
|
+
*/
|
|
32
46
|
const sizeClass = $derived.by(() => {
|
|
33
47
|
if (size === "sm") {
|
|
34
|
-
return {
|
|
35
|
-
padding: "px-4 py-2.5",
|
|
36
|
-
text: "text-sm",
|
|
37
|
-
font: "font-medium",
|
|
38
|
-
leading: "leading-5",
|
|
39
|
-
tracking: "tracking-[0.1px]",
|
|
40
|
-
radius: "rounded-lg",
|
|
41
|
-
gap: "gap-2",
|
|
42
|
-
};
|
|
43
|
-
} else if (size === "lg") {
|
|
44
|
-
return {
|
|
45
|
-
padding: "px-8 py-4",
|
|
46
|
-
text: "text-lg",
|
|
47
|
-
font: "font-normal",
|
|
48
|
-
leading: "leading-8",
|
|
49
|
-
tracking: "tracking-normal",
|
|
50
|
-
radius: "rounded-xl",
|
|
51
|
-
gap: "gap-3",
|
|
52
|
-
};
|
|
53
|
-
} else {
|
|
54
|
-
return {
|
|
55
|
-
padding: "px-5 py-3",
|
|
56
|
-
text: "text-base",
|
|
57
|
-
font: "font-medium",
|
|
58
|
-
leading: "leading-6",
|
|
59
|
-
tracking: "tracking-[0.15px]",
|
|
60
|
-
radius: "rounded-lg",
|
|
61
|
-
gap: "gap-2",
|
|
62
|
-
};
|
|
48
|
+
return { box: "h-8 px-3", text: "text-sm", gap: "gap-2", spinner: "size-3.5" };
|
|
63
49
|
}
|
|
50
|
+
if (size === "lg") {
|
|
51
|
+
return { box: "h-12 px-5", text: "text-base", gap: "gap-2", spinner: "size-4" };
|
|
52
|
+
}
|
|
53
|
+
return { box: "h-10 px-4", text: "text-sm", gap: "gap-2", spinner: "size-4" };
|
|
64
54
|
});
|
|
65
55
|
|
|
56
|
+
/**
|
|
57
|
+
* Disabled is deliberately NOT `opacity-50` over the variant colour — that
|
|
58
|
+
* made a disabled primary lighter and more colourful than an enabled
|
|
59
|
+
* secondary. Every variant falls back to the same neutral disabled pair.
|
|
60
|
+
*/
|
|
61
|
+
const disabledClass =
|
|
62
|
+
"disabled:bg-action-disabled disabled:text-action-disabled-text disabled:border-transparent disabled:no-underline disabled:shadow-none disabled:cursor-not-allowed disabled:active:scale-100";
|
|
63
|
+
|
|
66
64
|
const variantClass = $derived.by(() => {
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
:
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
65
|
+
switch (variant) {
|
|
66
|
+
case "secondary":
|
|
67
|
+
return "bg-action-secondary text-headline hover:bg-action-secondary-hover active:bg-action-secondary-active active:scale-[0.98]";
|
|
68
|
+
case "danger":
|
|
69
|
+
return "bg-action-danger text-action-danger-text hover:bg-action-danger-hover active:bg-action-danger-active active:scale-[0.98] focus-ring--danger";
|
|
70
|
+
case "ghost":
|
|
71
|
+
return "bg-transparent text-headline hover:bg-surface-hover active:bg-surface-active active:scale-[0.98] focus-ring--muted";
|
|
72
|
+
case "outline":
|
|
73
|
+
return "bg-transparent border border-border text-headline hover:bg-surface-hover hover:border-border-medium active:bg-surface-active active:scale-[0.98]";
|
|
74
|
+
case "link":
|
|
75
|
+
// A link variant has to look like a link at rest, not only on
|
|
76
|
+
// hover — otherwise it is indistinguishable from `ghost`.
|
|
77
|
+
return "bg-transparent text-link hover:text-link-hover underline underline-offset-4 decoration-1 hover:decoration-2 px-0 focus-ring--muted";
|
|
78
|
+
case "primary":
|
|
79
|
+
default:
|
|
80
|
+
return "bg-action-primary text-action-primary hover:bg-action-primary-hover active:bg-action-primary-active active:scale-[0.98]";
|
|
81
|
+
}
|
|
80
82
|
});
|
|
81
83
|
|
|
82
84
|
const buttonClasses = $derived.by(() => {
|
|
83
|
-
const
|
|
84
|
-
const
|
|
85
|
-
const
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
return `${baseClasses} ${widthClass} ${sizeStyles.padding} ${sizeStyles.text} ${sizeStyles.font} ${sizeStyles.leading} ${sizeStyles.tracking} ${sizeStyles.radius} ${sizeStyles.gap} ${variantClass} ${className}`.trim();
|
|
85
|
+
const s = sizeClass;
|
|
86
|
+
const layout = fullWidth || isFullWidth ? "flex w-full" : "inline-flex";
|
|
87
|
+
const base = `${layout} focus-ring items-center justify-center rounded-control font-medium whitespace-nowrap transition-colors duration-150 cursor-pointer select-none`;
|
|
88
|
+
return cn(`${base} ${s.box} ${s.text} ${s.gap} ${variantClass} ${disabledClass} ${className}`);
|
|
89
89
|
});
|
|
90
90
|
</script>
|
|
91
91
|
|
|
@@ -99,7 +99,7 @@
|
|
|
99
99
|
>
|
|
100
100
|
{#if loading}
|
|
101
101
|
<span
|
|
102
|
-
class="inline-block
|
|
102
|
+
class="inline-block {sizeClass.spinner} shrink-0 animate-spin rounded-full border-2 border-current border-t-transparent opacity-80"
|
|
103
103
|
aria-hidden="true"
|
|
104
104
|
></span>
|
|
105
105
|
{/if}
|
|
@@ -6,6 +6,9 @@ type Props = Omit<HTMLButtonAttributes, "class"> & {
|
|
|
6
6
|
size?: SizeVariant;
|
|
7
7
|
loading?: boolean;
|
|
8
8
|
text?: string;
|
|
9
|
+
/** Stretch to the width of the container. */
|
|
10
|
+
fullWidth?: boolean;
|
|
11
|
+
/** @deprecated use `fullWidth` — kept so 7.x call sites keep working. */
|
|
9
12
|
isFullWidth?: boolean;
|
|
10
13
|
class?: string;
|
|
11
14
|
children?: Snippet;
|
package/dist/atoms/Card.svelte
CHANGED
|
@@ -1,72 +1,75 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import type { Snippet } from "svelte";
|
|
3
|
+
import type { HTMLAttributes } from "svelte/elements";
|
|
3
4
|
import type { CardVariant, SizeVariant } from "../types/variants.js";
|
|
4
5
|
|
|
5
|
-
|
|
6
|
+
import { cn } from "../util/cn.js";
|
|
7
|
+
type Props = Omit<HTMLAttributes<HTMLDivElement>, "class"> & {
|
|
6
8
|
onclick?: (event: MouseEvent) => void | Promise<void>;
|
|
7
9
|
size?: SizeVariant;
|
|
8
10
|
variant?: CardVariant;
|
|
9
11
|
fullWidth?: boolean;
|
|
12
|
+
class?: string;
|
|
13
|
+
/** @deprecated use `class` — kept so 7.x call sites keep working. */
|
|
10
14
|
className?: string;
|
|
11
15
|
/** Required when `onclick` is set (no visible label). */
|
|
12
16
|
ariaLabel?: string;
|
|
13
17
|
children?: Snippet;
|
|
14
|
-
}
|
|
18
|
+
};
|
|
15
19
|
|
|
16
20
|
let {
|
|
17
21
|
onclick,
|
|
18
22
|
size = "md",
|
|
19
23
|
variant = "default",
|
|
20
24
|
fullWidth = true,
|
|
25
|
+
class: classProp = "",
|
|
21
26
|
className = "",
|
|
22
27
|
ariaLabel,
|
|
23
28
|
children,
|
|
24
29
|
...restProps
|
|
25
30
|
}: Props = $props();
|
|
26
31
|
|
|
32
|
+
/** Size changes the padding. It does NOT change the corner — see
|
|
33
|
+
* `--radius-container`. A large card is a bigger box, not a rounder one. */
|
|
27
34
|
const sizeClass = $derived(
|
|
28
35
|
size === "sm" ? "p-4" : size === "lg" ? "p-8" : "p-6",
|
|
29
36
|
);
|
|
30
37
|
|
|
31
|
-
const radiusClass = $derived(
|
|
32
|
-
size === "sm"
|
|
33
|
-
? "rounded-xl"
|
|
34
|
-
: size === "lg"
|
|
35
|
-
? "rounded-3xl"
|
|
36
|
-
: "rounded-2xl",
|
|
37
|
-
);
|
|
38
|
-
|
|
39
38
|
const variantClasses = $derived(
|
|
40
39
|
variant === "elevated"
|
|
41
|
-
? "bg-card shadow-lg"
|
|
40
|
+
? "bg-card-elevated shadow-lg"
|
|
42
41
|
: variant === "outlined"
|
|
43
|
-
? "bg-card border
|
|
42
|
+
? "bg-card border border-border shadow-none"
|
|
44
43
|
: variant === "flat"
|
|
45
44
|
? "bg-card shadow-none border-none"
|
|
46
45
|
: "bg-card shadow-sm",
|
|
47
46
|
);
|
|
48
47
|
|
|
48
|
+
const interactiveClasses = $derived.by(() => {
|
|
49
|
+
if (!onclick) return "";
|
|
50
|
+
const shared = "cursor-pointer focus-ring";
|
|
51
|
+
switch (variant) {
|
|
52
|
+
case "elevated":
|
|
53
|
+
return `${shared} hover:bg-card-hover`;
|
|
54
|
+
case "outlined":
|
|
55
|
+
return `${shared} hover:border-border-medium hover:bg-card-hover`;
|
|
56
|
+
case "flat":
|
|
57
|
+
return `${shared} hover:bg-card-hover`;
|
|
58
|
+
default:
|
|
59
|
+
return `${shared} hover:shadow-lg hover:bg-card-hover`;
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
|
|
49
63
|
const cardClasses = $derived(
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
"transition-all duration-200",
|
|
64
|
+
cn(
|
|
65
|
+
"rounded-container transition-all duration-150",
|
|
53
66
|
variantClasses,
|
|
54
|
-
|
|
55
|
-
? variant === "elevated"
|
|
56
|
-
? "cursor-pointer hover:shadow-xl hover:bg-card-hover"
|
|
57
|
-
: variant === "outlined"
|
|
58
|
-
? "cursor-pointer hover:border-brand-500 hover:bg-card-hover"
|
|
59
|
-
: variant === "flat"
|
|
60
|
-
? "cursor-pointer hover:bg-card-hover"
|
|
61
|
-
: "cursor-pointer hover:shadow-lg hover:bg-card-hover"
|
|
62
|
-
: "",
|
|
67
|
+
interactiveClasses,
|
|
63
68
|
fullWidth ? "w-full" : "",
|
|
64
69
|
sizeClass,
|
|
70
|
+
classProp,
|
|
65
71
|
className,
|
|
66
|
-
|
|
67
|
-
.filter(Boolean)
|
|
68
|
-
.join(" ")
|
|
69
|
-
.trim(),
|
|
72
|
+
),
|
|
70
73
|
);
|
|
71
74
|
|
|
72
75
|
function handleKeydown(event: KeyboardEvent) {
|
|
@@ -1,15 +1,18 @@
|
|
|
1
1
|
import type { Snippet } from "svelte";
|
|
2
|
+
import type { HTMLAttributes } from "svelte/elements";
|
|
2
3
|
import type { CardVariant, SizeVariant } from "../types/variants.js";
|
|
3
|
-
|
|
4
|
+
type Props = Omit<HTMLAttributes<HTMLDivElement>, "class"> & {
|
|
4
5
|
onclick?: (event: MouseEvent) => void | Promise<void>;
|
|
5
6
|
size?: SizeVariant;
|
|
6
7
|
variant?: CardVariant;
|
|
7
8
|
fullWidth?: boolean;
|
|
9
|
+
class?: string;
|
|
10
|
+
/** @deprecated use `class` — kept so 7.x call sites keep working. */
|
|
8
11
|
className?: string;
|
|
9
12
|
/** Required when `onclick` is set (no visible label). */
|
|
10
13
|
ariaLabel?: string;
|
|
11
14
|
children?: Snippet;
|
|
12
|
-
}
|
|
15
|
+
};
|
|
13
16
|
declare const Card: import("svelte").Component<Props, {}, "">;
|
|
14
17
|
type Card = ReturnType<typeof Card>;
|
|
15
18
|
export default Card;
|
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import type { Snippet } from "svelte";
|
|
3
|
+
import { cn } from "../util/cn.js";
|
|
3
4
|
|
|
4
5
|
interface Props {
|
|
5
6
|
image?: string;
|
|
6
7
|
imageAlt?: string;
|
|
8
|
+
class?: string;
|
|
9
|
+
/** @deprecated use `class`. */
|
|
7
10
|
className?: string;
|
|
8
11
|
children?: Snippet;
|
|
9
12
|
}
|
|
@@ -11,10 +14,15 @@
|
|
|
11
14
|
let {
|
|
12
15
|
image = "",
|
|
13
16
|
imageAlt = "",
|
|
14
|
-
|
|
17
|
+
class: classAttr = "",
|
|
18
|
+
className: legacyClass = "",
|
|
15
19
|
children,
|
|
16
20
|
...restProps
|
|
17
21
|
}: Props = $props();
|
|
22
|
+
|
|
23
|
+
/** `class` is the public prop; `className` is a deprecated alias.
|
|
24
|
+
* Both are merged here so existing call sites keep working. */
|
|
25
|
+
const className = $derived(cn(`${classAttr} ${legacyClass}`));
|
|
18
26
|
</script>
|
|
19
27
|
|
|
20
28
|
<div class={className} {...restProps}>
|
|
@@ -22,7 +30,7 @@
|
|
|
22
30
|
<img
|
|
23
31
|
src={image}
|
|
24
32
|
alt={imageAlt}
|
|
25
|
-
class="w-full h-48 object-cover rounded-
|
|
33
|
+
class="w-full h-48 object-cover rounded-control mb-4"
|
|
26
34
|
/>
|
|
27
35
|
{/if}
|
|
28
36
|
{#if children}
|
|
@@ -1,20 +1,28 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import type { Snippet } from "svelte";
|
|
3
|
+
import { cn } from "../util/cn.js";
|
|
3
4
|
|
|
4
5
|
interface Props {
|
|
6
|
+
class?: string;
|
|
7
|
+
/** @deprecated use `class`. */
|
|
5
8
|
className?: string;
|
|
6
9
|
children?: Snippet;
|
|
7
10
|
}
|
|
8
11
|
|
|
9
12
|
let {
|
|
10
|
-
|
|
13
|
+
class: classAttr = "",
|
|
14
|
+
className: legacyClass = "",
|
|
11
15
|
children,
|
|
12
16
|
...restProps
|
|
13
17
|
}: Props = $props();
|
|
18
|
+
|
|
19
|
+
/** `class` is the public prop; `className` is a deprecated alias.
|
|
20
|
+
* Both are merged here so existing call sites keep working. */
|
|
21
|
+
const className = $derived(cn(`${classAttr} ${legacyClass}`));
|
|
14
22
|
</script>
|
|
15
23
|
|
|
16
24
|
<footer
|
|
17
|
-
class="flex items-center p-6 pt-0
|
|
25
|
+
class={cn("flex items-center p-6 pt-0", className)}
|
|
18
26
|
{...restProps}
|
|
19
27
|
>
|
|
20
28
|
{#if children}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import type { Snippet } from "svelte";
|
|
3
|
+
import { cn } from "../util/cn.js";
|
|
3
4
|
|
|
4
5
|
interface Props {
|
|
5
6
|
title?: string;
|
|
@@ -10,6 +11,8 @@
|
|
|
10
11
|
/** `id` on the description `<p>`. */
|
|
11
12
|
descriptionId?: string;
|
|
12
13
|
level?: 1 | 2 | 3 | 4 | 5 | 6;
|
|
14
|
+
class?: string;
|
|
15
|
+
/** @deprecated use `class`. */
|
|
13
16
|
className?: string;
|
|
14
17
|
children?: Snippet;
|
|
15
18
|
}
|
|
@@ -21,18 +24,23 @@
|
|
|
21
24
|
subtitleId,
|
|
22
25
|
descriptionId,
|
|
23
26
|
level = 3,
|
|
24
|
-
|
|
27
|
+
class: classAttr = "",
|
|
28
|
+
className: legacyClass = "",
|
|
25
29
|
children,
|
|
26
30
|
...restProps
|
|
27
31
|
}: Props = $props();
|
|
28
32
|
|
|
33
|
+
/** `class` is the public prop; `className` is a deprecated alias.
|
|
34
|
+
* Both are merged here so existing call sites keep working. */
|
|
35
|
+
const className = $derived(cn(`${classAttr} ${legacyClass}`));
|
|
36
|
+
|
|
29
37
|
const headingTag = $derived(`h${level}`);
|
|
30
38
|
const headingClasses = $derived(() => {
|
|
31
39
|
return "text-2xl font-semibold leading-none tracking-tight text-headline";
|
|
32
40
|
});
|
|
33
41
|
</script>
|
|
34
42
|
|
|
35
|
-
<header class={`flex flex-col space-y-
|
|
43
|
+
<header class={cn(`flex flex-col space-y-2 pb-4 ${className}`)} {...restProps}>
|
|
36
44
|
{#if title}
|
|
37
45
|
<svelte:element this={headingTag} class={headingClasses()}>
|
|
38
46
|
{title}
|
|
@@ -3,6 +3,8 @@
|
|
|
3
3
|
import type { SelectionControlMarkProps } from "./SelectionControl.svelte";
|
|
4
4
|
|
|
5
5
|
interface Props {
|
|
6
|
+
/** Extra classes for the host element. */
|
|
7
|
+
class?: string;
|
|
6
8
|
id?: string;
|
|
7
9
|
name?: string;
|
|
8
10
|
value?: string;
|
|
@@ -16,6 +18,7 @@
|
|
|
16
18
|
}
|
|
17
19
|
|
|
18
20
|
let {
|
|
21
|
+
class: className = "",
|
|
19
22
|
id,
|
|
20
23
|
value = "",
|
|
21
24
|
name = "",
|
|
@@ -65,5 +68,6 @@
|
|
|
65
68
|
{onChange}
|
|
66
69
|
{onchange}
|
|
67
70
|
{mark}
|
|
71
|
+
class={className}
|
|
68
72
|
{...restProps}
|
|
69
73
|
/>
|
|
@@ -2,11 +2,14 @@
|
|
|
2
2
|
import Check from "@lucide/svelte/icons/check";
|
|
3
3
|
import Copy from "@lucide/svelte/icons/copy";
|
|
4
4
|
import IconButton from "./IconButton.svelte";
|
|
5
|
+
import { cn } from "../util/cn.js";
|
|
5
6
|
|
|
6
7
|
interface Props {
|
|
7
8
|
/** Raw source; escaped unless `trustHtml` (e.g. highlighter HTML). */
|
|
8
9
|
code: string;
|
|
9
10
|
language?: string;
|
|
11
|
+
class?: string;
|
|
12
|
+
/** @deprecated use `class`. */
|
|
10
13
|
className?: string;
|
|
11
14
|
showCopyButton?: boolean;
|
|
12
15
|
/** If true, `{@html code}` — only trusted, sanitized input. */
|
|
@@ -16,11 +19,16 @@
|
|
|
16
19
|
let {
|
|
17
20
|
code,
|
|
18
21
|
language = "svelte",
|
|
19
|
-
|
|
22
|
+
class: classAttr = "",
|
|
23
|
+
className: legacyClass = "",
|
|
20
24
|
showCopyButton = true,
|
|
21
25
|
trustHtml = false,
|
|
22
26
|
...restProps
|
|
23
|
-
} = $props();
|
|
27
|
+
}: Props & Record<string, unknown> = $props();
|
|
28
|
+
|
|
29
|
+
/** `class` is the public prop; `className` is a deprecated alias.
|
|
30
|
+
* Both are merged here so existing call sites keep working. */
|
|
31
|
+
const className = $derived(cn(`${classAttr} ${legacyClass}`));
|
|
24
32
|
|
|
25
33
|
let copied = $state(false);
|
|
26
34
|
|
|
@@ -38,16 +46,16 @@
|
|
|
38
46
|
</script>
|
|
39
47
|
|
|
40
48
|
<div
|
|
41
|
-
class="code-block relative bg-surface-1 border border-border rounded-
|
|
49
|
+
class={cn("code-block relative bg-surface-1 border border-border rounded-control overflow-hidden", className)}
|
|
42
50
|
{...restProps}
|
|
43
51
|
>
|
|
44
52
|
<div
|
|
45
53
|
class="flex items-center justify-between px-4 py-2 bg-surface-2 border-b border-border"
|
|
46
54
|
>
|
|
47
|
-
<div class="flex items-center gap-2">
|
|
48
|
-
<div class="w-3 h-3 rounded-full bg-
|
|
49
|
-
<div class="w-3 h-3 rounded-full bg-
|
|
50
|
-
<div class="w-3 h-3 rounded-full bg-
|
|
55
|
+
<div class="flex items-center gap-2" aria-hidden="true">
|
|
56
|
+
<div class="w-3 h-3 rounded-full bg-error"></div>
|
|
57
|
+
<div class="w-3 h-3 rounded-full bg-warning"></div>
|
|
58
|
+
<div class="w-3 h-3 rounded-full bg-success"></div>
|
|
51
59
|
</div>
|
|
52
60
|
{#if showCopyButton}
|
|
53
61
|
<IconButton
|
|
@@ -1,9 +1,15 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
interface Props {
|
|
2
|
+
/** Raw source; escaped unless `trustHtml` (e.g. highlighter HTML). */
|
|
3
|
+
code: string;
|
|
3
4
|
language?: string;
|
|
5
|
+
class?: string;
|
|
6
|
+
/** @deprecated use `class`. */
|
|
4
7
|
className?: string;
|
|
5
8
|
showCopyButton?: boolean;
|
|
9
|
+
/** If true, `{@html code}` — only trusted, sanitized input. */
|
|
6
10
|
trustHtml?: boolean;
|
|
7
|
-
}
|
|
11
|
+
}
|
|
12
|
+
type $$ComponentProps = Props & Record<string, unknown>;
|
|
13
|
+
declare const CodeBlock: import("svelte").Component<$$ComponentProps, {}, "">;
|
|
8
14
|
type CodeBlock = ReturnType<typeof CodeBlock>;
|
|
9
15
|
export default CodeBlock;
|
|
@@ -3,6 +3,8 @@
|
|
|
3
3
|
import { onMount, onDestroy, tick } from "svelte";
|
|
4
4
|
|
|
5
5
|
interface Props {
|
|
6
|
+
/** Extra classes for the host element. */
|
|
7
|
+
class?: string;
|
|
6
8
|
value?: string;
|
|
7
9
|
label?: string;
|
|
8
10
|
disabled?: boolean;
|
|
@@ -11,7 +13,8 @@
|
|
|
11
13
|
}
|
|
12
14
|
|
|
13
15
|
let {
|
|
14
|
-
|
|
16
|
+
class: className = "",
|
|
17
|
+
value = $bindable(""),
|
|
15
18
|
label = "",
|
|
16
19
|
disabled = false,
|
|
17
20
|
placeholder = "#000000",
|
|
@@ -35,7 +38,14 @@
|
|
|
35
38
|
return hexPattern.test(hex);
|
|
36
39
|
}
|
|
37
40
|
|
|
38
|
-
|
|
41
|
+
/** `#f00` → `#ff0000`; 6-digit input is returned unchanged. */
|
|
42
|
+
function expandHex(hex: string): string {
|
|
43
|
+
if (hex.length !== 4) return hex;
|
|
44
|
+
return `#${hex[1]}${hex[1]}${hex[2]}${hex[2]}${hex[3]}${hex[3]}`;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function hexToHsl(rawHex: string): [number, number, number] {
|
|
48
|
+
const hex = expandHex(rawHex);
|
|
39
49
|
const r = parseInt(hex.slice(1, 3), 16) / 255;
|
|
40
50
|
const g = parseInt(hex.slice(3, 5), 16) / 255;
|
|
41
51
|
const b = parseInt(hex.slice(5, 7), 16) / 255;
|
|
@@ -263,7 +273,7 @@
|
|
|
263
273
|
const pickerIndicatorY = $derived(`${100 - lightness}%`);
|
|
264
274
|
</script>
|
|
265
275
|
|
|
266
|
-
<div {...restProps}>
|
|
276
|
+
<div class={className} {...restProps}>
|
|
267
277
|
<div class="flex items-start gap-2">
|
|
268
278
|
<div class="flex-1">
|
|
269
279
|
<Input
|
|
@@ -283,7 +293,7 @@
|
|
|
283
293
|
type="button"
|
|
284
294
|
onclick={togglePicker}
|
|
285
295
|
{disabled}
|
|
286
|
-
class="focus-ring w-11 h-11 rounded-
|
|
296
|
+
class="focus-ring w-11 h-11 rounded-control border-2 border-card shrink-0 cursor-pointer hover:ring-2 hover:ring-border transition-colors disabled:cursor-not-allowed disabled:opacity-50"
|
|
287
297
|
style="background-color: {displayColor};"
|
|
288
298
|
aria-label="Open color picker"
|
|
289
299
|
aria-expanded={isOpen}
|
|
@@ -292,14 +302,14 @@
|
|
|
292
302
|
{#if isOpen}
|
|
293
303
|
<div
|
|
294
304
|
use:setPickerContainer
|
|
295
|
-
class="absolute top-12 right-0 z-
|
|
305
|
+
class="absolute top-12 right-0 z-popover border border-input-border bg-input rounded-container shadow-lg p-4 w-80"
|
|
296
306
|
role="dialog"
|
|
297
307
|
aria-label="Color picker"
|
|
298
308
|
>
|
|
299
309
|
<div class="space-y-4">
|
|
300
310
|
<div
|
|
301
311
|
use:setColorMapContainer
|
|
302
|
-
class="relative w-full h-48 rounded-
|
|
312
|
+
class="relative w-full h-48 rounded-container overflow-hidden cursor-crosshair"
|
|
303
313
|
onmousedown={(e) => {
|
|
304
314
|
isDragging = true;
|
|
305
315
|
handleColorMapClick(e);
|
|
@@ -314,14 +324,14 @@
|
|
|
314
324
|
class="w-full h-full"
|
|
315
325
|
></canvas>
|
|
316
326
|
<div
|
|
317
|
-
class="absolute w-4 h-4 border-2 border-white rounded-full shadow-
|
|
327
|
+
class="absolute w-4 h-4 border-2 border-white rounded-full shadow-sm pointer-events-none transform -translate-x-1/2 -translate-y-1/2"
|
|
318
328
|
style="left: {pickerIndicatorX}; top: {pickerIndicatorY};"
|
|
319
329
|
></div>
|
|
320
330
|
</div>
|
|
321
331
|
|
|
322
332
|
<div class="space-y-2">
|
|
323
333
|
<div
|
|
324
|
-
class="relative h-6 rounded-
|
|
334
|
+
class="relative h-6 rounded-control overflow-hidden"
|
|
325
335
|
>
|
|
326
336
|
<div
|
|
327
337
|
class="absolute inset-0"
|
|
@@ -337,7 +347,7 @@
|
|
|
337
347
|
aria-label="Hue slider"
|
|
338
348
|
/>
|
|
339
349
|
<div
|
|
340
|
-
class="absolute top-0 bottom-0 w-3 bg-card shadow-
|
|
350
|
+
class="absolute top-0 bottom-0 w-3 bg-card shadow-sm pointer-events-none my-px rounded-full border border-base-950"
|
|
341
351
|
style="left: {(hue / 360) * 100}%;"
|
|
342
352
|
></div>
|
|
343
353
|
</div>
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
interface Props {
|
|
2
|
+
/** Extra classes for the host element. */
|
|
3
|
+
class?: string;
|
|
2
4
|
value?: string;
|
|
3
5
|
label?: string;
|
|
4
6
|
disabled?: boolean;
|
|
5
7
|
placeholder?: string;
|
|
6
8
|
onchange?: (event: Event) => void;
|
|
7
9
|
}
|
|
8
|
-
declare const ColorPicker: import("svelte").Component<Props, {}, "">;
|
|
10
|
+
declare const ColorPicker: import("svelte").Component<Props, {}, "value">;
|
|
9
11
|
type ColorPicker = ReturnType<typeof ColorPicker>;
|
|
10
12
|
export default ColorPicker;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import type { Snippet } from 'svelte';
|
|
3
3
|
|
|
4
|
+
import { cn } from "../util/cn.js";
|
|
4
5
|
type MaxWidth = 'sm' | 'md' | 'lg' | 'xl' | '2xl' | 'full';
|
|
5
6
|
|
|
6
7
|
interface Props {
|
|
@@ -31,9 +32,7 @@
|
|
|
31
32
|
|
|
32
33
|
<svelte:element
|
|
33
34
|
this={Tag}
|
|
34
|
-
class={
|
|
35
|
-
.filter(Boolean)
|
|
36
|
-
.join(' ')}
|
|
35
|
+
class={cn('mx-auto w-full', maxClass[maxWidth], padded ? 'px-4 sm:px-6' : '', className)}
|
|
37
36
|
>
|
|
38
37
|
{#if children}
|
|
39
38
|
{@render children()}
|