zabi-components 6.0.0 → 7.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 +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 +35 -16
- package/dist/atoms/Button.svelte.d.ts +3 -1
- 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 +33 -24
- package/dist/atoms/IconButton.svelte.d.ts +4 -8
- 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 +90 -11
- 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 +14 -1
- package/dist/zabi-components-theme-dark-only.css +5 -0
- package/dist/zabi-components-theme-dark.css +5 -0
- package/dist/zabi-components-theme-only.css +9 -1
- package/dist/zabi-components-theme.css +9 -1
- package/dist/zabi-components.css +877 -192
- package/package.json +19 -7
- package/dist/organisms/Navbar.svelte.d.ts +0 -41
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
let colorMap: HTMLCanvasElement | undefined;
|
|
26
26
|
let colorMapContainer: HTMLDivElement | undefined;
|
|
27
27
|
|
|
28
|
-
// HSL
|
|
28
|
+
// Working color in HSL (h: 0–360; s, l: 0–100).
|
|
29
29
|
let hue = $state(0);
|
|
30
30
|
let saturation = $state(100);
|
|
31
31
|
let lightness = $state(50);
|
|
@@ -156,7 +156,6 @@
|
|
|
156
156
|
const width = colorMap.width;
|
|
157
157
|
const height = colorMap.height;
|
|
158
158
|
|
|
159
|
-
// Draw saturation/lightness gradient
|
|
160
159
|
for (let x = 0; x < width; x++) {
|
|
161
160
|
for (let y = 0; y < height; y++) {
|
|
162
161
|
const s = (x / width) * 100;
|
|
@@ -284,7 +283,7 @@
|
|
|
284
283
|
type="button"
|
|
285
284
|
onclick={togglePicker}
|
|
286
285
|
{disabled}
|
|
287
|
-
class="w-11 h-11 rounded-lg border-2 border-card shrink-0 cursor-pointer hover:ring-2 hover:ring-
|
|
286
|
+
class="focus-ring w-11 h-11 rounded-lg border-2 border-card shrink-0 cursor-pointer hover:ring-2 hover:ring-border transition-colors disabled:cursor-not-allowed disabled:opacity-50"
|
|
288
287
|
style="background-color: {displayColor};"
|
|
289
288
|
aria-label="Open color picker"
|
|
290
289
|
aria-expanded={isOpen}
|
|
@@ -298,7 +297,6 @@
|
|
|
298
297
|
aria-label="Color picker"
|
|
299
298
|
>
|
|
300
299
|
<div class="space-y-4">
|
|
301
|
-
<!-- Color Map -->
|
|
302
300
|
<div
|
|
303
301
|
use:setColorMapContainer
|
|
304
302
|
class="relative w-full h-48 rounded-xl overflow-hidden cursor-crosshair"
|
|
@@ -315,14 +313,12 @@
|
|
|
315
313
|
height={192}
|
|
316
314
|
class="w-full h-full"
|
|
317
315
|
></canvas>
|
|
318
|
-
<!-- Color indicator -->
|
|
319
316
|
<div
|
|
320
317
|
class="absolute w-4 h-4 border-2 border-white rounded-full shadow-lg pointer-events-none transform -translate-x-1/2 -translate-y-1/2"
|
|
321
318
|
style="left: {pickerIndicatorX}; top: {pickerIndicatorY};"
|
|
322
319
|
></div>
|
|
323
320
|
</div>
|
|
324
321
|
|
|
325
|
-
<!-- Hue Slider -->
|
|
326
322
|
<div class="space-y-2">
|
|
327
323
|
<div
|
|
328
324
|
class="relative h-6 rounded-lg overflow-hidden"
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { Snippet } from 'svelte';
|
|
3
|
+
|
|
4
|
+
type MaxWidth = 'sm' | 'md' | 'lg' | 'xl' | '2xl' | 'full';
|
|
5
|
+
|
|
6
|
+
interface Props {
|
|
7
|
+
as?: 'div' | 'section' | 'main' | 'article';
|
|
8
|
+
maxWidth?: MaxWidth;
|
|
9
|
+
padded?: boolean;
|
|
10
|
+
class?: string;
|
|
11
|
+
children?: Snippet;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
let {
|
|
15
|
+
as: Tag = 'div',
|
|
16
|
+
maxWidth = 'xl',
|
|
17
|
+
padded = true,
|
|
18
|
+
class: className = '',
|
|
19
|
+
children,
|
|
20
|
+
}: Props = $props();
|
|
21
|
+
|
|
22
|
+
const maxClass: Record<MaxWidth, string> = {
|
|
23
|
+
sm: 'max-w-screen-sm',
|
|
24
|
+
md: 'max-w-screen-md',
|
|
25
|
+
lg: 'max-w-screen-lg',
|
|
26
|
+
xl: 'max-w-screen-xl',
|
|
27
|
+
'2xl': 'max-w-screen-2xl',
|
|
28
|
+
full: 'max-w-full',
|
|
29
|
+
};
|
|
30
|
+
</script>
|
|
31
|
+
|
|
32
|
+
<svelte:element
|
|
33
|
+
this={Tag}
|
|
34
|
+
class={['mx-auto w-full', maxClass[maxWidth], padded ? 'px-4 sm:px-6' : '', className]
|
|
35
|
+
.filter(Boolean)
|
|
36
|
+
.join(' ')}
|
|
37
|
+
>
|
|
38
|
+
{#if children}
|
|
39
|
+
{@render children()}
|
|
40
|
+
{/if}
|
|
41
|
+
</svelte:element>
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { Snippet } from 'svelte';
|
|
2
|
+
type MaxWidth = 'sm' | 'md' | 'lg' | 'xl' | '2xl' | 'full';
|
|
3
|
+
interface Props {
|
|
4
|
+
as?: 'div' | 'section' | 'main' | 'article';
|
|
5
|
+
maxWidth?: MaxWidth;
|
|
6
|
+
padded?: boolean;
|
|
7
|
+
class?: string;
|
|
8
|
+
children?: Snippet;
|
|
9
|
+
}
|
|
10
|
+
declare const Container: import("svelte").Component<Props, {}, "">;
|
|
11
|
+
type Container = ReturnType<typeof Container>;
|
|
12
|
+
export default Container;
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
type Orientation = 'horizontal' | 'vertical';
|
|
3
|
+
|
|
4
|
+
interface Props {
|
|
5
|
+
orientation?: Orientation;
|
|
6
|
+
label?: string;
|
|
7
|
+
inset?: boolean;
|
|
8
|
+
class?: string;
|
|
9
|
+
labelClass?: string;
|
|
10
|
+
/** Decorative: omit `role="separator"` so SR does not announce a split. */
|
|
11
|
+
decorative?: boolean;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
let {
|
|
15
|
+
orientation = 'horizontal',
|
|
16
|
+
label,
|
|
17
|
+
inset = false,
|
|
18
|
+
class: className = '',
|
|
19
|
+
labelClass = '',
|
|
20
|
+
decorative = true,
|
|
21
|
+
}: Props = $props();
|
|
22
|
+
|
|
23
|
+
const isVertical = $derived(orientation === 'vertical');
|
|
24
|
+
|
|
25
|
+
const lineClasses = $derived(
|
|
26
|
+
[
|
|
27
|
+
'bg-border',
|
|
28
|
+
isVertical ? 'h-full w-px flex-1' : 'h-px w-full flex-1',
|
|
29
|
+
inset ? (isVertical ? 'my-2' : 'mx-2') : undefined,
|
|
30
|
+
]
|
|
31
|
+
.filter(Boolean)
|
|
32
|
+
.join(' '),
|
|
33
|
+
);
|
|
34
|
+
</script>
|
|
35
|
+
|
|
36
|
+
<div
|
|
37
|
+
class={[
|
|
38
|
+
'flex items-center text-description',
|
|
39
|
+
isVertical ? 'h-full min-h-[1rem] flex-col' : 'w-full flex-row',
|
|
40
|
+
className,
|
|
41
|
+
]
|
|
42
|
+
.filter(Boolean)
|
|
43
|
+
.join(' ')}
|
|
44
|
+
>
|
|
45
|
+
<div
|
|
46
|
+
aria-hidden={decorative ? 'true' : undefined}
|
|
47
|
+
role={decorative ? 'presentation' : 'separator'}
|
|
48
|
+
aria-orientation={decorative ? undefined : orientation}
|
|
49
|
+
class={lineClasses}
|
|
50
|
+
></div>
|
|
51
|
+
|
|
52
|
+
{#if label}
|
|
53
|
+
<span
|
|
54
|
+
class={['shrink-0 px-3 text-xs font-medium text-description', labelClass]
|
|
55
|
+
.filter(Boolean)
|
|
56
|
+
.join(' ')}
|
|
57
|
+
>
|
|
58
|
+
{label}
|
|
59
|
+
</span>
|
|
60
|
+
|
|
61
|
+
<div
|
|
62
|
+
aria-hidden={decorative ? 'true' : undefined}
|
|
63
|
+
role={decorative ? 'presentation' : 'separator'}
|
|
64
|
+
aria-orientation={decorative ? undefined : orientation}
|
|
65
|
+
class={lineClasses}
|
|
66
|
+
></div>
|
|
67
|
+
{/if}
|
|
68
|
+
</div>
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
type Orientation = 'horizontal' | 'vertical';
|
|
2
|
+
interface Props {
|
|
3
|
+
orientation?: Orientation;
|
|
4
|
+
label?: string;
|
|
5
|
+
inset?: boolean;
|
|
6
|
+
class?: string;
|
|
7
|
+
labelClass?: string;
|
|
8
|
+
/** Decorative: omit `role="separator"` so SR does not announce a split. */
|
|
9
|
+
decorative?: boolean;
|
|
10
|
+
}
|
|
11
|
+
declare const Divider: import("svelte").Component<Props, {}, "">;
|
|
12
|
+
type Divider = ReturnType<typeof Divider>;
|
|
13
|
+
export default Divider;
|
|
@@ -1,64 +1,49 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
import {
|
|
2
|
+
import type { Component, Snippet } from "svelte";
|
|
3
3
|
|
|
4
4
|
interface Props {
|
|
5
|
-
icon?: string;
|
|
6
5
|
title: string;
|
|
7
|
-
description
|
|
8
|
-
|
|
6
|
+
description?: string;
|
|
7
|
+
icon?: Component<{ size?: number; class?: string }>;
|
|
8
|
+
children?: Snippet;
|
|
9
|
+
class?: string;
|
|
9
10
|
}
|
|
10
11
|
|
|
11
12
|
let {
|
|
12
|
-
icon = "✨",
|
|
13
13
|
title,
|
|
14
14
|
description,
|
|
15
|
-
|
|
16
|
-
|
|
15
|
+
icon: Icon,
|
|
16
|
+
children,
|
|
17
|
+
class: className = "",
|
|
17
18
|
}: Props = $props();
|
|
18
|
-
|
|
19
|
-
let mounted = $state(false);
|
|
20
|
-
|
|
21
|
-
onMount(() => {
|
|
22
|
-
mounted = true;
|
|
23
|
-
});
|
|
24
19
|
</script>
|
|
25
20
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
21
|
+
<article
|
|
22
|
+
class="flex flex-col gap-3 p-6 rounded-2xl bg-surface-1 border border-base-200 transition-colors duration-200 hover:border-base-300 {className}"
|
|
23
|
+
>
|
|
24
|
+
{#if Icon}
|
|
25
|
+
<span
|
|
26
|
+
class="inline-flex items-center justify-center w-10 h-10 rounded-lg bg-brand-50 text-brand-600"
|
|
27
|
+
aria-hidden="true"
|
|
28
|
+
>
|
|
29
|
+
<Icon size={20} />
|
|
30
|
+
</span>
|
|
31
|
+
{/if}
|
|
32
|
+
|
|
33
|
+
<div class="flex flex-col gap-1.5">
|
|
34
|
+
<h3 class="text-base font-semibold leading-snug text-headline">
|
|
35
|
+
{title}
|
|
36
|
+
</h3>
|
|
37
|
+
{#if description}
|
|
38
|
+
<p class="text-sm leading-relaxed text-description">
|
|
39
|
+
{description}
|
|
40
|
+
</p>
|
|
41
|
+
{/if}
|
|
44
42
|
</div>
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
class="
|
|
48
|
-
|
|
49
|
-
>
|
|
50
|
-
<div class="flex items-start gap-4">
|
|
51
|
-
<div class="shrink-0 text-2xl" aria-hidden="true">
|
|
52
|
-
{icon}
|
|
53
|
-
</div>
|
|
54
|
-
<div class="flex-1 min-w-0">
|
|
55
|
-
<h3 class="text-lg font-semibold text-headline mb-2">
|
|
56
|
-
{title}
|
|
57
|
-
</h3>
|
|
58
|
-
<p class="text-description leading-relaxed">
|
|
59
|
-
{description}
|
|
60
|
-
</p>
|
|
61
|
-
</div>
|
|
43
|
+
|
|
44
|
+
{#if children}
|
|
45
|
+
<div class="mt-2">
|
|
46
|
+
{@render children()}
|
|
62
47
|
</div>
|
|
63
|
-
|
|
64
|
-
|
|
48
|
+
{/if}
|
|
49
|
+
</article>
|
|
@@ -1,9 +1,14 @@
|
|
|
1
|
+
import type { Component, Snippet } from "svelte";
|
|
1
2
|
interface Props {
|
|
2
|
-
icon?: string;
|
|
3
3
|
title: string;
|
|
4
|
-
description
|
|
5
|
-
|
|
4
|
+
description?: string;
|
|
5
|
+
icon?: Component<{
|
|
6
|
+
size?: number;
|
|
7
|
+
class?: string;
|
|
8
|
+
}>;
|
|
9
|
+
children?: Snippet;
|
|
10
|
+
class?: string;
|
|
6
11
|
}
|
|
7
|
-
declare const FeatureCard:
|
|
12
|
+
declare const FeatureCard: Component<Props, {}, "">;
|
|
8
13
|
type FeatureCard = ReturnType<typeof FeatureCard>;
|
|
9
14
|
export default FeatureCard;
|
|
@@ -1,21 +1,17 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import type { Snippet } from "svelte";
|
|
3
|
-
import type { ButtonVariant, SizeVariant } from "
|
|
3
|
+
import type { ButtonVariant, SizeVariant } from "../types/variants.js";
|
|
4
4
|
|
|
5
5
|
interface Props {
|
|
6
|
-
/** Visual style variant. */
|
|
7
6
|
variant?: ButtonVariant;
|
|
8
|
-
/** Size variant controlling padding and radius. */
|
|
9
7
|
size?: SizeVariant;
|
|
10
|
-
/** Whether the button is disabled. */
|
|
11
8
|
disabled?: boolean;
|
|
12
|
-
|
|
9
|
+
loading?: boolean;
|
|
13
10
|
type?: "button" | "submit" | "reset";
|
|
14
|
-
/**
|
|
11
|
+
/** Required for icon-only usage (no visible text). */
|
|
15
12
|
label?: string;
|
|
16
|
-
|
|
13
|
+
class?: string;
|
|
17
14
|
onclick?: (event: MouseEvent) => void;
|
|
18
|
-
/** Icon content. */
|
|
19
15
|
children?: Snippet;
|
|
20
16
|
}
|
|
21
17
|
|
|
@@ -23,66 +19,79 @@
|
|
|
23
19
|
variant = "primary",
|
|
24
20
|
size = "md",
|
|
25
21
|
disabled = false,
|
|
22
|
+
loading = false,
|
|
26
23
|
type = "button",
|
|
27
24
|
label = "",
|
|
25
|
+
class: className = "",
|
|
28
26
|
onclick,
|
|
29
27
|
children,
|
|
30
28
|
...restProps
|
|
31
29
|
}: Props = $props();
|
|
32
30
|
|
|
33
|
-
const
|
|
31
|
+
const isDisabled = $derived(disabled || loading);
|
|
32
|
+
|
|
33
|
+
const sizeClass = $derived.by(() => {
|
|
34
34
|
if (size === "sm") {
|
|
35
35
|
return {
|
|
36
36
|
padding: "p-2",
|
|
37
37
|
radius: "rounded-md",
|
|
38
|
+
spinner: "size-4",
|
|
38
39
|
};
|
|
39
40
|
} else if (size === "lg") {
|
|
40
41
|
return {
|
|
41
42
|
padding: "p-3",
|
|
42
43
|
radius: "rounded-xl",
|
|
44
|
+
spinner: "size-6",
|
|
43
45
|
};
|
|
44
46
|
} else {
|
|
45
47
|
return {
|
|
46
48
|
padding: "p-2.5",
|
|
47
49
|
radius: "rounded-lg",
|
|
50
|
+
spinner: "size-5",
|
|
48
51
|
};
|
|
49
52
|
}
|
|
50
53
|
});
|
|
51
54
|
|
|
52
|
-
const variantClass = $derived(() => {
|
|
55
|
+
const variantClass = $derived.by(() => {
|
|
53
56
|
return variant === "primary"
|
|
54
|
-
? "bg-action-primary text-action-primary hover:bg-action-primary-hover active:bg-action-primary-active
|
|
57
|
+
? "bg-action-primary text-action-primary hover:bg-action-primary-hover active:bg-action-primary-active active:scale-[0.98]"
|
|
55
58
|
: variant === "secondary"
|
|
56
|
-
? "bg-action-secondary text-headline hover:bg-action-secondary-hover active:bg-action-secondary-active
|
|
59
|
+
? "bg-action-secondary text-headline hover:bg-action-secondary-hover active:bg-action-secondary-active active:scale-[0.98]"
|
|
57
60
|
: variant === "danger"
|
|
58
|
-
? "bg-action-danger text-inverse hover:bg-action-danger-hover active:bg-action-danger-active
|
|
61
|
+
? "bg-action-danger text-inverse hover:bg-action-danger-hover active:bg-action-danger-active active:scale-[0.98] focus-ring--danger"
|
|
59
62
|
: variant === "ghost"
|
|
60
|
-
? "bg-transparent text-headline hover:bg-base-100 active:bg-base-200
|
|
63
|
+
? "bg-transparent text-headline hover:bg-base-100 active:bg-base-200 active:scale-[0.98] focus-ring--muted disabled:text-disabled"
|
|
61
64
|
: variant === "outline"
|
|
62
|
-
? "bg-transparent border-2 border-action-primary text-headline hover:bg-action-secondary hover:text-action-primary active:bg-action-primary-active active:text-action-primary
|
|
65
|
+
? "bg-transparent border-2 border-action-primary text-headline hover:bg-action-secondary hover:text-action-primary active:bg-action-primary-active active:text-action-primary active:scale-[0.98] disabled:border-disabled disabled:text-disabled"
|
|
63
66
|
: variant === "link"
|
|
64
|
-
? "text-brand-700 active:text-brand-700
|
|
65
|
-
: "bg-action-primary text-action-primary hover:bg-action-primary-hover active:bg-action-primary-active
|
|
67
|
+
? "text-brand-700 active:text-brand-700 hover:underline disabled:text-disabled disabled:no-underline"
|
|
68
|
+
: "bg-action-primary text-action-primary hover:bg-action-primary-hover active:bg-action-primary-active active:scale-[0.98]";
|
|
66
69
|
});
|
|
67
70
|
|
|
68
|
-
const buttonClasses = $derived(() => {
|
|
69
|
-
const sizeStyles = sizeClass
|
|
71
|
+
const buttonClasses = $derived.by(() => {
|
|
72
|
+
const sizeStyles = sizeClass;
|
|
70
73
|
const baseClasses =
|
|
71
|
-
"inline-flex items-center justify-center transition-all duration-200 cursor-pointer disabled:opacity-50 disabled:cursor-not-allowed
|
|
74
|
+
"inline-flex focus-ring items-center justify-center transition-all duration-200 cursor-pointer disabled:opacity-50 disabled:cursor-not-allowed disabled:active:scale-100";
|
|
72
75
|
|
|
73
|
-
return `${baseClasses} ${sizeStyles.padding} ${sizeStyles.radius} ${variantClass
|
|
76
|
+
return `${baseClasses} ${sizeStyles.padding} ${sizeStyles.radius} ${variantClass} ${className}`.trim();
|
|
74
77
|
});
|
|
75
78
|
</script>
|
|
76
79
|
|
|
77
80
|
<button
|
|
78
81
|
{type}
|
|
79
|
-
class={buttonClasses
|
|
80
|
-
{
|
|
82
|
+
class={buttonClasses}
|
|
83
|
+
disabled={isDisabled}
|
|
84
|
+
aria-busy={loading ? "true" : undefined}
|
|
81
85
|
{onclick}
|
|
82
86
|
aria-label={label || undefined}
|
|
83
87
|
{...restProps}
|
|
84
88
|
>
|
|
85
|
-
{#if
|
|
89
|
+
{#if loading}
|
|
90
|
+
<span
|
|
91
|
+
class="inline-block {sizeClass.spinner} shrink-0 animate-spin rounded-full border-2 border-current border-t-transparent opacity-80"
|
|
92
|
+
aria-hidden="true"
|
|
93
|
+
></span>
|
|
94
|
+
{:else if children}
|
|
86
95
|
{@render children()}
|
|
87
96
|
{/if}
|
|
88
97
|
</button>
|
|
@@ -1,19 +1,15 @@
|
|
|
1
1
|
import type { Snippet } from "svelte";
|
|
2
|
-
import type { ButtonVariant, SizeVariant } from "
|
|
2
|
+
import type { ButtonVariant, SizeVariant } from "../types/variants.js";
|
|
3
3
|
interface Props {
|
|
4
|
-
/** Visual style variant. */
|
|
5
4
|
variant?: ButtonVariant;
|
|
6
|
-
/** Size variant controlling padding and radius. */
|
|
7
5
|
size?: SizeVariant;
|
|
8
|
-
/** Whether the button is disabled. */
|
|
9
6
|
disabled?: boolean;
|
|
10
|
-
|
|
7
|
+
loading?: boolean;
|
|
11
8
|
type?: "button" | "submit" | "reset";
|
|
12
|
-
/**
|
|
9
|
+
/** Required for icon-only usage (no visible text). */
|
|
13
10
|
label?: string;
|
|
14
|
-
|
|
11
|
+
class?: string;
|
|
15
12
|
onclick?: (event: MouseEvent) => void;
|
|
16
|
-
/** Icon content. */
|
|
17
13
|
children?: Snippet;
|
|
18
14
|
}
|
|
19
15
|
declare const IconButton: import("svelte").Component<Props, {}, "">;
|
package/dist/atoms/Input.svelte
CHANGED
|
@@ -1,17 +1,22 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import { CheckCircle, AlertTriangle, AlertCircle } from "@lucide/svelte";
|
|
3
|
-
import type { SemanticVariant, SizeVariant } from "
|
|
4
|
-
import { generateId } from "
|
|
3
|
+
import type { SemanticVariant, SizeVariant } from "../types/variants.js";
|
|
4
|
+
import { generateId } from "../util/ssr-safe.js";
|
|
5
5
|
|
|
6
6
|
interface Props {
|
|
7
|
+
/** Omit to auto-generate; pair with FormField `id` when used inside FormField. */
|
|
8
|
+
id?: string;
|
|
7
9
|
value?: string;
|
|
8
10
|
type?: string;
|
|
9
11
|
name?: string;
|
|
10
12
|
class?: string;
|
|
11
13
|
label?: string;
|
|
14
|
+
/** True when FormField supplies the visible `<label>`. */
|
|
15
|
+
hideLabel?: boolean;
|
|
12
16
|
placeholder?: string;
|
|
13
17
|
required?: boolean;
|
|
14
18
|
disabled?: boolean;
|
|
19
|
+
loading?: boolean;
|
|
15
20
|
size?: SizeVariant;
|
|
16
21
|
variant?: SemanticVariant;
|
|
17
22
|
message?: string;
|
|
@@ -21,14 +26,17 @@
|
|
|
21
26
|
}
|
|
22
27
|
|
|
23
28
|
let {
|
|
29
|
+
id: idProp,
|
|
24
30
|
value = $bindable(""),
|
|
25
31
|
type = "text",
|
|
26
32
|
name = "",
|
|
27
33
|
class: className = "",
|
|
28
34
|
label = "",
|
|
35
|
+
hideLabel = false,
|
|
29
36
|
placeholder = "",
|
|
30
37
|
required = false,
|
|
31
38
|
disabled = false,
|
|
39
|
+
loading = false,
|
|
32
40
|
size = "md",
|
|
33
41
|
variant = "default",
|
|
34
42
|
message = "",
|
|
@@ -37,7 +45,9 @@
|
|
|
37
45
|
...restProps
|
|
38
46
|
}: Props = $props();
|
|
39
47
|
|
|
40
|
-
const
|
|
48
|
+
const fallbackId = generateId("input");
|
|
49
|
+
const inputId = $derived(idProp ?? fallbackId);
|
|
50
|
+
const isDisabled = $derived(disabled || loading);
|
|
41
51
|
|
|
42
52
|
const sizeClass = $derived(() => {
|
|
43
53
|
if (size === "sm") {
|
|
@@ -45,38 +55,46 @@
|
|
|
45
55
|
padding: "px-4 py-2",
|
|
46
56
|
text: "text-sm",
|
|
47
57
|
leading: "leading-5",
|
|
58
|
+
spinner: "size-4",
|
|
48
59
|
};
|
|
49
60
|
} else if (size === "lg") {
|
|
50
61
|
return {
|
|
51
62
|
padding: "px-4 py-3",
|
|
52
63
|
text: "text-base",
|
|
53
64
|
leading: "leading-6",
|
|
65
|
+
spinner: "size-5",
|
|
54
66
|
};
|
|
55
67
|
} else {
|
|
56
68
|
return {
|
|
57
69
|
padding: "px-4 py-2.5",
|
|
58
70
|
text: "text-base",
|
|
59
71
|
leading: "leading-6",
|
|
72
|
+
spinner: "size-5",
|
|
60
73
|
};
|
|
61
74
|
}
|
|
62
75
|
});
|
|
63
76
|
|
|
64
77
|
const variantClass = $derived(() => {
|
|
65
78
|
return variant === "success"
|
|
66
|
-
? "border-success focus:border-success
|
|
79
|
+
? "border-success focus-visible:border-success"
|
|
67
80
|
: variant === "warning"
|
|
68
|
-
? "border-warning focus:border-warning
|
|
81
|
+
? "border-warning focus-visible:border-warning"
|
|
69
82
|
: variant === "error"
|
|
70
|
-
? "border-error focus:border-error
|
|
71
|
-
: "border-input-border focus:border-input-border
|
|
83
|
+
? "border-error focus-visible:border-error"
|
|
84
|
+
: "border-input-border focus-visible:border-input-border";
|
|
72
85
|
});
|
|
73
86
|
|
|
74
87
|
const inputClasses = $derived(() => {
|
|
75
88
|
const sizeStyles = sizeClass();
|
|
89
|
+
const trailingPad = loading
|
|
90
|
+
? size === "sm"
|
|
91
|
+
? "pr-9"
|
|
92
|
+
: "pr-10"
|
|
93
|
+
: "";
|
|
76
94
|
const baseClasses =
|
|
77
|
-
"w-full min-w-48 border bg-input hover:bg-input-hover focus:bg-input-focus disabled:bg-input-disabled rounded-lg transition-all duration-200 placeholder:text-description text-body focus:outline-none focus:
|
|
95
|
+
"focus-ring w-full min-w-48 border bg-input hover:bg-input-hover focus-visible:bg-input-focus disabled:bg-input-disabled rounded-lg transition-all duration-200 placeholder:text-description text-body focus:outline-none focus-visible:outline-none disabled:opacity-50 disabled:cursor-not-allowed";
|
|
78
96
|
|
|
79
|
-
return `${baseClasses} ${sizeStyles.padding} ${sizeStyles.text} ${sizeStyles.leading} ${variantClass()} ${className}`.trim();
|
|
97
|
+
return `${baseClasses} ${sizeStyles.padding} ${trailingPad} ${sizeStyles.text} ${sizeStyles.leading} ${variantClass()} ${className}`.trim();
|
|
80
98
|
});
|
|
81
99
|
|
|
82
100
|
const labelClasses = $derived(
|
|
@@ -109,25 +127,39 @@
|
|
|
109
127
|
</script>
|
|
110
128
|
|
|
111
129
|
<div>
|
|
112
|
-
{#if label}
|
|
130
|
+
{#if label && !hideLabel}
|
|
113
131
|
<label for={inputId} class={labelClasses()}>{label}</label>
|
|
114
132
|
{/if}
|
|
115
|
-
<
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
133
|
+
<div class="relative">
|
|
134
|
+
<input
|
|
135
|
+
id={inputId}
|
|
136
|
+
{type}
|
|
137
|
+
{name}
|
|
138
|
+
bind:value
|
|
139
|
+
{placeholder}
|
|
140
|
+
{required}
|
|
141
|
+
disabled={isDisabled}
|
|
142
|
+
class={inputClasses()}
|
|
143
|
+
oninput={handleInput}
|
|
144
|
+
{onblur}
|
|
145
|
+
aria-invalid={variant === "error" ? "true" : undefined}
|
|
146
|
+
aria-required={required ? "true" : undefined}
|
|
147
|
+
aria-busy={loading ? "true" : undefined}
|
|
148
|
+
aria-describedby={message ? `${inputId}-message` : undefined}
|
|
149
|
+
{...restProps}
|
|
150
|
+
/>
|
|
151
|
+
{#if loading}
|
|
152
|
+
<span
|
|
153
|
+
class="pointer-events-none absolute inset-y-0 right-3 flex items-center text-description"
|
|
154
|
+
aria-hidden="true"
|
|
155
|
+
>
|
|
156
|
+
<span
|
|
157
|
+
class="inline-block {sizeClass()
|
|
158
|
+
.spinner} shrink-0 animate-spin rounded-full border-2 border-current border-t-transparent opacity-70"
|
|
159
|
+
></span>
|
|
160
|
+
</span>
|
|
161
|
+
{/if}
|
|
162
|
+
</div>
|
|
131
163
|
{#if message && variant !== "default"}
|
|
132
164
|
<p
|
|
133
165
|
id={`${inputId}-message`}
|
|
@@ -1,13 +1,18 @@
|
|
|
1
|
-
import type { SemanticVariant, SizeVariant } from "
|
|
1
|
+
import type { SemanticVariant, SizeVariant } from "../types/variants.js";
|
|
2
2
|
interface Props {
|
|
3
|
+
/** Omit to auto-generate; pair with FormField `id` when used inside FormField. */
|
|
4
|
+
id?: string;
|
|
3
5
|
value?: string;
|
|
4
6
|
type?: string;
|
|
5
7
|
name?: string;
|
|
6
8
|
class?: string;
|
|
7
9
|
label?: string;
|
|
10
|
+
/** True when FormField supplies the visible `<label>`. */
|
|
11
|
+
hideLabel?: boolean;
|
|
8
12
|
placeholder?: string;
|
|
9
13
|
required?: boolean;
|
|
10
14
|
disabled?: boolean;
|
|
15
|
+
loading?: boolean;
|
|
11
16
|
size?: SizeVariant;
|
|
12
17
|
variant?: SemanticVariant;
|
|
13
18
|
message?: string;
|
package/dist/atoms/List.svelte
CHANGED
|
@@ -4,17 +4,12 @@
|
|
|
4
4
|
export type ListItem = ListItemData;
|
|
5
5
|
|
|
6
6
|
interface Props {
|
|
7
|
-
/** Collection of items rendered in the list. */
|
|
8
7
|
items: ListItemData[];
|
|
9
|
-
/**
|
|
8
|
+
/** `aria-label` on the list region. */
|
|
10
9
|
ariaLabel?: string;
|
|
11
|
-
/** Optional active item id for current state styling. */
|
|
12
10
|
selectedId?: string;
|
|
13
|
-
/** Whether to show the arrow icon for each row. */
|
|
14
11
|
showArrow?: boolean;
|
|
15
|
-
/** Optional custom class names for the list container. */
|
|
16
12
|
className?: string;
|
|
17
|
-
/** Item click callback. */
|
|
18
13
|
onclick?: (item: ListItem, event: MouseEvent) => void;
|
|
19
14
|
}
|
|
20
15
|
|
|
@@ -29,7 +24,7 @@
|
|
|
29
24
|
}: Props = $props();
|
|
30
25
|
|
|
31
26
|
const listClasses = $derived(
|
|
32
|
-
`space-y-1 overflow-hidden rounded-xl
|
|
27
|
+
`space-y-1 overflow-hidden rounded-xl ${className}`.trim(),
|
|
33
28
|
);
|
|
34
29
|
</script>
|
|
35
30
|
|