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
|
@@ -1,17 +1,12 @@
|
|
|
1
1
|
import { type ListItemData } from "./ListItem.svelte";
|
|
2
2
|
export type ListItem = ListItemData;
|
|
3
3
|
interface Props {
|
|
4
|
-
/** Collection of items rendered in the list. */
|
|
5
4
|
items: ListItemData[];
|
|
6
|
-
/**
|
|
5
|
+
/** `aria-label` on the list region. */
|
|
7
6
|
ariaLabel?: string;
|
|
8
|
-
/** Optional active item id for current state styling. */
|
|
9
7
|
selectedId?: string;
|
|
10
|
-
/** Whether to show the arrow icon for each row. */
|
|
11
8
|
showArrow?: boolean;
|
|
12
|
-
/** Optional custom class names for the list container. */
|
|
13
9
|
className?: string;
|
|
14
|
-
/** Item click callback. */
|
|
15
10
|
onclick?: (item: ListItem, event: MouseEvent) => void;
|
|
16
11
|
}
|
|
17
12
|
declare const List: import("svelte").Component<Props, {}, "">;
|
|
@@ -1,34 +1,29 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import { ArrowRight } from "@lucide/svelte";
|
|
3
|
-
import type { Component } from "svelte";
|
|
3
|
+
import type { Component, Snippet } from "svelte";
|
|
4
|
+
import ListItemLeading from "./ListItemLeading.svelte";
|
|
4
5
|
|
|
5
6
|
export interface ListItemData {
|
|
6
|
-
/** Unique identifier for stable rendering and active-state tracking. */
|
|
7
7
|
id: string;
|
|
8
|
-
/** Primary item label. */
|
|
9
8
|
label: string;
|
|
10
|
-
/** Optional secondary text shown under the label. */
|
|
11
9
|
description?: string;
|
|
12
|
-
/** Optional URL; when set, the item renders as an anchor. */
|
|
13
10
|
href?: string;
|
|
14
|
-
/** Optional leading icon rendered before text. */
|
|
15
11
|
icon?: Component<{ size?: number; class?: string }>;
|
|
16
|
-
/**
|
|
12
|
+
/** Leading image; wins over `icon` when both are set. */
|
|
13
|
+
avatar?: string;
|
|
14
|
+
/** `avatar` alt text; `""` if decorative. */
|
|
15
|
+
avatarAlt?: string;
|
|
17
16
|
target?: "_self" | "_blank" | "_parent" | "_top";
|
|
18
|
-
/** Link rel attribute, only used when href is provided. */
|
|
19
17
|
rel?: string;
|
|
20
|
-
/** Disabled state for the item. */
|
|
21
18
|
disabled?: boolean;
|
|
22
19
|
}
|
|
23
20
|
|
|
24
21
|
interface Props {
|
|
25
|
-
/** Item data to render. */
|
|
26
22
|
item: ListItemData;
|
|
27
|
-
/** Active-state styling flag. */
|
|
28
23
|
selected?: boolean;
|
|
29
|
-
/** Whether to show the right-arrow icon. */
|
|
30
24
|
showArrow?: boolean;
|
|
31
|
-
/**
|
|
25
|
+
/** Shown before the chevron when `showArrow` is true. */
|
|
26
|
+
trailing?: Snippet;
|
|
32
27
|
onclick?: (item: ListItemData, event: MouseEvent) => void;
|
|
33
28
|
}
|
|
34
29
|
|
|
@@ -36,16 +31,17 @@
|
|
|
36
31
|
item,
|
|
37
32
|
selected = false,
|
|
38
33
|
showArrow = true,
|
|
34
|
+
trailing,
|
|
39
35
|
onclick,
|
|
40
36
|
...restProps
|
|
41
37
|
}: Props = $props();
|
|
42
38
|
|
|
43
39
|
const itemClasses = $derived.by(() => {
|
|
44
40
|
const baseClasses =
|
|
45
|
-
"group flex w-full items-center gap-3 rounded-xl border border-border px-4 py-3 text-left transition-all duration-150
|
|
41
|
+
"group focus-ring flex w-full items-center gap-3 rounded-xl border border-border px-4 py-3 pr-5 text-left transition-all duration-150";
|
|
46
42
|
const interactiveClasses = item.disabled
|
|
47
43
|
? "cursor-not-allowed opacity-50"
|
|
48
|
-
: "cursor-pointer
|
|
44
|
+
: "cursor-pointer focus-visible:bg-base-100";
|
|
49
45
|
const selectedClasses = selected
|
|
50
46
|
? "bg-action-primary-subtle border-brand-500"
|
|
51
47
|
: "";
|
|
@@ -73,6 +69,47 @@
|
|
|
73
69
|
};
|
|
74
70
|
</script>
|
|
75
71
|
|
|
72
|
+
{#snippet rowContent()}
|
|
73
|
+
{#if item.avatar}
|
|
74
|
+
<ListItemLeading class="rounded-full">
|
|
75
|
+
<img
|
|
76
|
+
src={item.avatar}
|
|
77
|
+
alt={item.avatarAlt ?? ""}
|
|
78
|
+
class="block size-full min-h-0 min-w-0 object-cover"
|
|
79
|
+
loading="lazy"
|
|
80
|
+
decoding="async"
|
|
81
|
+
/>
|
|
82
|
+
</ListItemLeading>
|
|
83
|
+
{:else if item.icon}
|
|
84
|
+
<ListItemLeading>
|
|
85
|
+
<span aria-hidden="true">
|
|
86
|
+
<item.icon size={16} />
|
|
87
|
+
</span>
|
|
88
|
+
</ListItemLeading>
|
|
89
|
+
{/if}
|
|
90
|
+
<span class="min-w-0 flex-1">
|
|
91
|
+
<span class="block text-sm font-medium text-headline">{item.label}</span
|
|
92
|
+
>
|
|
93
|
+
{#if item.description}
|
|
94
|
+
<span class="mt-0.5 block text-sm text-description"
|
|
95
|
+
>{item.description}</span
|
|
96
|
+
>
|
|
97
|
+
{/if}
|
|
98
|
+
</span>
|
|
99
|
+
{#if trailing}
|
|
100
|
+
<span class="flex shrink-0 items-center gap-2 text-sm text-description">
|
|
101
|
+
{@render trailing()}
|
|
102
|
+
</span>
|
|
103
|
+
{/if}
|
|
104
|
+
{#if showArrow}
|
|
105
|
+
<ArrowRight
|
|
106
|
+
size={16}
|
|
107
|
+
class="shrink-0 text-description transition-transform duration-150 group-hover:translate-x-1 group-focus-visible:translate-x-1"
|
|
108
|
+
aria-hidden="true"
|
|
109
|
+
/>
|
|
110
|
+
{/if}
|
|
111
|
+
{/snippet}
|
|
112
|
+
|
|
76
113
|
{#if item.href}
|
|
77
114
|
<a
|
|
78
115
|
href={item.href}
|
|
@@ -85,31 +122,7 @@
|
|
|
85
122
|
onclick={handleItemClick}
|
|
86
123
|
{...restProps}
|
|
87
124
|
>
|
|
88
|
-
{
|
|
89
|
-
<span
|
|
90
|
-
class="flex size-5 shrink-0 items-center justify-center text-description"
|
|
91
|
-
aria-hidden="true"
|
|
92
|
-
>
|
|
93
|
-
<item.icon size={16} />
|
|
94
|
-
</span>
|
|
95
|
-
{/if}
|
|
96
|
-
<span class="min-w-0 flex-1">
|
|
97
|
-
<span class="block text-sm font-medium text-headline"
|
|
98
|
-
>{item.label}</span
|
|
99
|
-
>
|
|
100
|
-
{#if item.description}
|
|
101
|
-
<span class="mt-0.5 block text-sm text-description"
|
|
102
|
-
>{item.description}</span
|
|
103
|
-
>
|
|
104
|
-
{/if}
|
|
105
|
-
</span>
|
|
106
|
-
{#if showArrow}
|
|
107
|
-
<ArrowRight
|
|
108
|
-
size={16}
|
|
109
|
-
class="shrink-0 text-description transition-transform duration-150 group-hover:translate-x-0.5 group-focus-visible:translate-x-0.5"
|
|
110
|
-
aria-hidden="true"
|
|
111
|
-
/>
|
|
112
|
-
{/if}
|
|
125
|
+
{@render rowContent()}
|
|
113
126
|
</a>
|
|
114
127
|
{:else}
|
|
115
128
|
<button
|
|
@@ -119,30 +132,6 @@
|
|
|
119
132
|
onclick={handleItemClick}
|
|
120
133
|
{...restProps}
|
|
121
134
|
>
|
|
122
|
-
{
|
|
123
|
-
<span
|
|
124
|
-
class="flex size-5 shrink-0 items-center justify-center text-description"
|
|
125
|
-
aria-hidden="true"
|
|
126
|
-
>
|
|
127
|
-
<item.icon size={16} />
|
|
128
|
-
</span>
|
|
129
|
-
{/if}
|
|
130
|
-
<span class="min-w-0 flex-1">
|
|
131
|
-
<span class="block text-sm font-medium text-headline"
|
|
132
|
-
>{item.label}</span
|
|
133
|
-
>
|
|
134
|
-
{#if item.description}
|
|
135
|
-
<span class="mt-0.5 block text-sm text-description"
|
|
136
|
-
>{item.description}</span
|
|
137
|
-
>
|
|
138
|
-
{/if}
|
|
139
|
-
</span>
|
|
140
|
-
{#if showArrow}
|
|
141
|
-
<ArrowRight
|
|
142
|
-
size={16}
|
|
143
|
-
class="shrink-0 text-description transition-transform duration-150 group-hover:translate-x-0.5 group-focus-visible:translate-x-0.5"
|
|
144
|
-
aria-hidden="true"
|
|
145
|
-
/>
|
|
146
|
-
{/if}
|
|
135
|
+
{@render rowContent()}
|
|
147
136
|
</button>
|
|
148
137
|
{/if}
|
|
@@ -1,33 +1,27 @@
|
|
|
1
|
-
import type { Component } from "svelte";
|
|
1
|
+
import type { Component, Snippet } from "svelte";
|
|
2
2
|
export interface ListItemData {
|
|
3
|
-
/** Unique identifier for stable rendering and active-state tracking. */
|
|
4
3
|
id: string;
|
|
5
|
-
/** Primary item label. */
|
|
6
4
|
label: string;
|
|
7
|
-
/** Optional secondary text shown under the label. */
|
|
8
5
|
description?: string;
|
|
9
|
-
/** Optional URL; when set, the item renders as an anchor. */
|
|
10
6
|
href?: string;
|
|
11
|
-
/** Optional leading icon rendered before text. */
|
|
12
7
|
icon?: Component<{
|
|
13
8
|
size?: number;
|
|
14
9
|
class?: string;
|
|
15
10
|
}>;
|
|
16
|
-
/**
|
|
11
|
+
/** Leading image; wins over `icon` when both are set. */
|
|
12
|
+
avatar?: string;
|
|
13
|
+
/** `avatar` alt text; `""` if decorative. */
|
|
14
|
+
avatarAlt?: string;
|
|
17
15
|
target?: "_self" | "_blank" | "_parent" | "_top";
|
|
18
|
-
/** Link rel attribute, only used when href is provided. */
|
|
19
16
|
rel?: string;
|
|
20
|
-
/** Disabled state for the item. */
|
|
21
17
|
disabled?: boolean;
|
|
22
18
|
}
|
|
23
19
|
interface Props {
|
|
24
|
-
/** Item data to render. */
|
|
25
20
|
item: ListItemData;
|
|
26
|
-
/** Active-state styling flag. */
|
|
27
21
|
selected?: boolean;
|
|
28
|
-
/** Whether to show the right-arrow icon. */
|
|
29
22
|
showArrow?: boolean;
|
|
30
|
-
/**
|
|
23
|
+
/** Shown before the chevron when `showArrow` is true. */
|
|
24
|
+
trailing?: Snippet;
|
|
31
25
|
onclick?: (item: ListItemData, event: MouseEvent) => void;
|
|
32
26
|
}
|
|
33
27
|
declare const ListItem: Component<Props, {}, "">;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { Snippet } from "svelte";
|
|
3
|
+
|
|
4
|
+
interface Props {
|
|
5
|
+
/** e.g. `rounded-full` for avatars; default is `rounded-md` for icons. */
|
|
6
|
+
class?: string;
|
|
7
|
+
children?: Snippet;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
let { class: className = "", children }: Props = $props();
|
|
11
|
+
|
|
12
|
+
const roundingClass = $derived(className.trim() ? className.trim() : "rounded-md");
|
|
13
|
+
</script>
|
|
14
|
+
|
|
15
|
+
<span
|
|
16
|
+
class="flex size-[length:var(--spacing-xl)] shrink-0 select-none items-center justify-center overflow-hidden text-description {roundingClass}"
|
|
17
|
+
>
|
|
18
|
+
{@render children?.()}
|
|
19
|
+
</span>
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { Snippet } from "svelte";
|
|
2
|
+
interface Props {
|
|
3
|
+
/** e.g. `rounded-full` for avatars; default is `rounded-md` for icons. */
|
|
4
|
+
class?: string;
|
|
5
|
+
children?: Snippet;
|
|
6
|
+
}
|
|
7
|
+
declare const ListItemLeading: import("svelte").Component<Props, {}, "">;
|
|
8
|
+
type ListItemLeading = ReturnType<typeof ListItemLeading>;
|
|
9
|
+
export default ListItemLeading;
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import SelectionControl from "./SelectionControl.svelte";
|
|
3
|
+
import type { SelectionControlMarkProps } from "./SelectionControl.svelte";
|
|
4
|
+
import { RADIO_CHECKED_DOT_CLASSES } from "./selection-control.styles";
|
|
5
|
+
|
|
6
|
+
interface Props {
|
|
7
|
+
id?: string;
|
|
8
|
+
name?: string;
|
|
9
|
+
value?: string;
|
|
10
|
+
label?: string;
|
|
11
|
+
disabled?: boolean;
|
|
12
|
+
defaultChecked?: boolean;
|
|
13
|
+
checked?: boolean;
|
|
14
|
+
onChange?: (event: Event) => void;
|
|
15
|
+
onchange?: (event: Event) => void;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
let {
|
|
19
|
+
id,
|
|
20
|
+
name = "",
|
|
21
|
+
value = "",
|
|
22
|
+
label = "",
|
|
23
|
+
disabled = false,
|
|
24
|
+
defaultChecked = false,
|
|
25
|
+
checked = $bindable(defaultChecked),
|
|
26
|
+
onChange,
|
|
27
|
+
onchange,
|
|
28
|
+
...restProps
|
|
29
|
+
}: Props = $props();
|
|
30
|
+
</script>
|
|
31
|
+
|
|
32
|
+
{#snippet mark(_props: SelectionControlMarkProps)}
|
|
33
|
+
<span class={RADIO_CHECKED_DOT_CLASSES} aria-hidden="true"></span>
|
|
34
|
+
{/snippet}
|
|
35
|
+
|
|
36
|
+
<SelectionControl
|
|
37
|
+
type="radio"
|
|
38
|
+
shape="circle"
|
|
39
|
+
{id}
|
|
40
|
+
{name}
|
|
41
|
+
{value}
|
|
42
|
+
{label}
|
|
43
|
+
{disabled}
|
|
44
|
+
bind:checked
|
|
45
|
+
{defaultChecked}
|
|
46
|
+
{onChange}
|
|
47
|
+
{onchange}
|
|
48
|
+
{mark}
|
|
49
|
+
{...restProps}
|
|
50
|
+
/>
|
|
51
|
+
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
interface Props {
|
|
2
|
+
id?: string;
|
|
3
|
+
name?: string;
|
|
4
|
+
value?: string;
|
|
5
|
+
label?: string;
|
|
6
|
+
disabled?: boolean;
|
|
7
|
+
defaultChecked?: boolean;
|
|
8
|
+
checked?: boolean;
|
|
9
|
+
onChange?: (event: Event) => void;
|
|
10
|
+
onchange?: (event: Event) => void;
|
|
11
|
+
}
|
|
12
|
+
declare const Radio: import("svelte").Component<Props, {}, "checked">;
|
|
13
|
+
type Radio = ReturnType<typeof Radio>;
|
|
14
|
+
export default Radio;
|
package/dist/atoms/Select.svelte
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import Dropdown from "../molecules/Dropdown.svelte";
|
|
3
|
-
import Button from "./Button.svelte";
|
|
4
3
|
import Input from "./Input.svelte";
|
|
5
4
|
import {
|
|
6
5
|
ChevronDown,
|
|
@@ -8,7 +7,7 @@
|
|
|
8
7
|
AlertTriangle,
|
|
9
8
|
AlertCircle,
|
|
10
9
|
} from "@lucide/svelte";
|
|
11
|
-
import { generateId } from "
|
|
10
|
+
import { generateId } from "../util/ssr-safe.js";
|
|
12
11
|
|
|
13
12
|
interface Props {
|
|
14
13
|
value?: string | number | undefined;
|
|
@@ -17,25 +16,15 @@
|
|
|
17
16
|
label: string;
|
|
18
17
|
disabled?: boolean;
|
|
19
18
|
}>;
|
|
20
|
-
/** Enables the search input inside the dropdown. */
|
|
21
19
|
searchable?: boolean;
|
|
22
|
-
/** Placeholder for the search input. */
|
|
23
20
|
searchPlaceholder?: string;
|
|
24
|
-
/** Max height for the options list (supports any valid CSS length). */
|
|
25
21
|
maxMenuHeight?: string;
|
|
26
|
-
/** Width for the dropdown menu (supports any valid CSS length). */
|
|
27
22
|
menuWidth?: string;
|
|
28
|
-
/** Message shown when no options match the search. */
|
|
29
23
|
noResultsText?: string;
|
|
30
|
-
/** Shows a loading state while options are being fetched. */
|
|
31
24
|
isLoading?: boolean;
|
|
32
|
-
/** Loading text shown in trigger and dropdown body. */
|
|
33
25
|
loadingText?: string;
|
|
34
|
-
/** Empty state title shown when there are no available options. */
|
|
35
26
|
emptyStateTitle?: string;
|
|
36
|
-
/** Empty state description shown when there are no available options. */
|
|
37
27
|
emptyStateDescription?: string;
|
|
38
|
-
/** Optional empty state action label. */
|
|
39
28
|
emptyStateActionLabel?: string;
|
|
40
29
|
placeholder?: string;
|
|
41
30
|
label?: string;
|
|
@@ -101,18 +90,18 @@
|
|
|
101
90
|
|
|
102
91
|
const variantClass = $derived(() => {
|
|
103
92
|
return variant === "success"
|
|
104
|
-
? "border-success focus:border-success
|
|
93
|
+
? "border-success focus-visible:border-success"
|
|
105
94
|
: variant === "warning"
|
|
106
|
-
? "border-warning focus:border-warning
|
|
95
|
+
? "border-warning focus-visible:border-warning"
|
|
107
96
|
: variant === "error"
|
|
108
|
-
? "border-error focus:border-error
|
|
109
|
-
: "border-input-border
|
|
97
|
+
? "border-error focus-visible:border-error"
|
|
98
|
+
: "border-input-border";
|
|
110
99
|
});
|
|
111
100
|
|
|
112
101
|
const triggerClasses = $derived(() => {
|
|
113
102
|
const sizeStyles = sizeClass();
|
|
114
103
|
const baseClasses =
|
|
115
|
-
"flex w-full cursor-pointer items-center justify-between rounded-lg border bg-input text-body transition-all duration-200 hover:bg-input-hover focus:bg-input-focus focus:outline-none focus:
|
|
104
|
+
"focus-ring flex w-full cursor-pointer items-center justify-between rounded-lg border bg-input text-body transition-all duration-200 hover:bg-input-hover active:bg-input-focus focus-visible:bg-input-focus focus:outline-none focus-visible:outline-none disabled:cursor-not-allowed disabled:bg-input-disabled disabled:opacity-50";
|
|
116
105
|
|
|
117
106
|
return `${baseClasses} ${sizeStyles.padding} ${sizeStyles.text} ${sizeStyles.leading} ${variantClass()}`.trim();
|
|
118
107
|
});
|
|
@@ -209,7 +198,6 @@
|
|
|
209
198
|
const target = event.target as HTMLElement;
|
|
210
199
|
const clickedSelectContainer = target.closest(".select-container");
|
|
211
200
|
|
|
212
|
-
// Close if clicking outside any select container, or clicking on a different select
|
|
213
201
|
if (
|
|
214
202
|
!clickedSelectContainer ||
|
|
215
203
|
clickedSelectContainer !== selectContainer
|
|
@@ -233,21 +221,21 @@
|
|
|
233
221
|
{/if}
|
|
234
222
|
|
|
235
223
|
<Dropdown
|
|
236
|
-
{isOpen}
|
|
224
|
+
bind:isOpen={isOpen}
|
|
237
225
|
placement="bottom-start"
|
|
238
226
|
selectedValue={value}
|
|
239
227
|
onOptionClick={handleOptionClick}
|
|
240
228
|
ariaLabel="Select options"
|
|
229
|
+
menuRole="listbox"
|
|
241
230
|
>
|
|
242
|
-
{#snippet trigger()}
|
|
231
|
+
{#snippet trigger(aria)}
|
|
243
232
|
<button
|
|
244
233
|
type="button"
|
|
245
234
|
id={selectId}
|
|
246
235
|
class={triggerClasses()}
|
|
247
236
|
{disabled}
|
|
248
237
|
onclick={handleTriggerClick}
|
|
249
|
-
aria
|
|
250
|
-
aria-expanded={isOpen}
|
|
238
|
+
{...aria}
|
|
251
239
|
aria-describedby={message ? `${selectId}-message` : undefined}
|
|
252
240
|
>
|
|
253
241
|
<span
|
|
@@ -305,18 +293,23 @@
|
|
|
305
293
|
"data-value": String(option.value),
|
|
306
294
|
} as Record<string, string>}
|
|
307
295
|
<div class="w-full my-0.5">
|
|
308
|
-
<
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
296
|
+
<button
|
|
297
|
+
type="button"
|
|
298
|
+
role="option"
|
|
299
|
+
aria-selected={value === option.value
|
|
300
|
+
? true
|
|
301
|
+
: undefined}
|
|
302
|
+
class="focus-ring flex w-full items-center justify-start rounded-md border-2 px-3 py-2 text-left text-sm font-medium transition-colors focus:outline-none disabled:cursor-not-allowed disabled:opacity-50 {value ===
|
|
303
|
+
option.value
|
|
304
|
+
? 'border-action-primary bg-transparent text-headline'
|
|
305
|
+
: 'border-transparent bg-transparent text-body hover:bg-base-100'}"
|
|
314
306
|
disabled={option.disabled}
|
|
315
|
-
onclick={() => handleOptionClick(option.value)}
|
|
316
307
|
{...buttonRestProps}
|
|
308
|
+
onclick={() =>
|
|
309
|
+
handleOptionClick(option.value)}
|
|
317
310
|
>
|
|
318
311
|
{option.label}
|
|
319
|
-
</
|
|
312
|
+
</button>
|
|
320
313
|
</div>
|
|
321
314
|
{/each}
|
|
322
315
|
{:else if hasSearchQuery()}
|
|
@@ -5,25 +5,15 @@ interface Props {
|
|
|
5
5
|
label: string;
|
|
6
6
|
disabled?: boolean;
|
|
7
7
|
}>;
|
|
8
|
-
/** Enables the search input inside the dropdown. */
|
|
9
8
|
searchable?: boolean;
|
|
10
|
-
/** Placeholder for the search input. */
|
|
11
9
|
searchPlaceholder?: string;
|
|
12
|
-
/** Max height for the options list (supports any valid CSS length). */
|
|
13
10
|
maxMenuHeight?: string;
|
|
14
|
-
/** Width for the dropdown menu (supports any valid CSS length). */
|
|
15
11
|
menuWidth?: string;
|
|
16
|
-
/** Message shown when no options match the search. */
|
|
17
12
|
noResultsText?: string;
|
|
18
|
-
/** Shows a loading state while options are being fetched. */
|
|
19
13
|
isLoading?: boolean;
|
|
20
|
-
/** Loading text shown in trigger and dropdown body. */
|
|
21
14
|
loadingText?: string;
|
|
22
|
-
/** Empty state title shown when there are no available options. */
|
|
23
15
|
emptyStateTitle?: string;
|
|
24
|
-
/** Empty state description shown when there are no available options. */
|
|
25
16
|
emptyStateDescription?: string;
|
|
26
|
-
/** Optional empty state action label. */
|
|
27
17
|
emptyStateActionLabel?: string;
|
|
28
18
|
placeholder?: string;
|
|
29
19
|
label?: string;
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { Snippet } from "svelte";
|
|
3
|
+
import { generateId } from "../util/ssr-safe.js";
|
|
4
|
+
import {
|
|
5
|
+
SELECTION_CONTROL_LABEL_ROW,
|
|
6
|
+
selectionControlRingOverlayClasses,
|
|
7
|
+
selectionControlShellClasses,
|
|
8
|
+
type SelectionControlShape,
|
|
9
|
+
} from "./selection-control.styles";
|
|
10
|
+
|
|
11
|
+
type SelectionControlType = "checkbox" | "radio";
|
|
12
|
+
|
|
13
|
+
export type SelectionControlMarkProps = {
|
|
14
|
+
checked: boolean;
|
|
15
|
+
loading: boolean;
|
|
16
|
+
disabled: boolean;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
interface Props {
|
|
20
|
+
id?: string;
|
|
21
|
+
type: SelectionControlType;
|
|
22
|
+
shape: SelectionControlShape;
|
|
23
|
+
name?: string;
|
|
24
|
+
value?: string;
|
|
25
|
+
label?: string;
|
|
26
|
+
disabled?: boolean;
|
|
27
|
+
loading?: boolean;
|
|
28
|
+
defaultChecked?: boolean;
|
|
29
|
+
checked?: boolean;
|
|
30
|
+
onChange?: (event: Event) => void;
|
|
31
|
+
onchange?: (event: Event) => void;
|
|
32
|
+
mark?: Snippet<[SelectionControlMarkProps]>;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
let {
|
|
36
|
+
id: idProp,
|
|
37
|
+
type,
|
|
38
|
+
shape,
|
|
39
|
+
name = "",
|
|
40
|
+
value = "",
|
|
41
|
+
label = "",
|
|
42
|
+
disabled = false,
|
|
43
|
+
loading = false,
|
|
44
|
+
defaultChecked = false,
|
|
45
|
+
checked = $bindable(defaultChecked),
|
|
46
|
+
onChange,
|
|
47
|
+
onchange,
|
|
48
|
+
mark,
|
|
49
|
+
...restProps
|
|
50
|
+
}: Props = $props();
|
|
51
|
+
|
|
52
|
+
/** Call once per mount — `generateId()` in `$derived` would churn ids every tick. */
|
|
53
|
+
const fallbackId = generateId("selection-control");
|
|
54
|
+
const controlId = $derived(idProp ?? fallbackId);
|
|
55
|
+
const isDisabled = $derived(disabled || loading);
|
|
56
|
+
|
|
57
|
+
const labelWrapperClasses = SELECTION_CONTROL_LABEL_ROW;
|
|
58
|
+
|
|
59
|
+
const controlContainerClasses = $derived(selectionControlShellClasses(shape));
|
|
60
|
+
|
|
61
|
+
const controlRingClasses = $derived(selectionControlRingOverlayClasses(shape));
|
|
62
|
+
|
|
63
|
+
function handleChange(event: Event) {
|
|
64
|
+
if (isDisabled) return;
|
|
65
|
+
const target = event.target as HTMLInputElement;
|
|
66
|
+
checked = target.checked;
|
|
67
|
+
onChange?.(event);
|
|
68
|
+
onchange?.(event);
|
|
69
|
+
}
|
|
70
|
+
</script>
|
|
71
|
+
|
|
72
|
+
<div class="flex items-center gap-2">
|
|
73
|
+
<label for={controlId} class={labelWrapperClasses}>
|
|
74
|
+
<span class={controlContainerClasses}>
|
|
75
|
+
<input
|
|
76
|
+
{type}
|
|
77
|
+
id={controlId}
|
|
78
|
+
{name}
|
|
79
|
+
{value}
|
|
80
|
+
{checked}
|
|
81
|
+
disabled={isDisabled}
|
|
82
|
+
class="sr-only"
|
|
83
|
+
aria-busy={loading ? "true" : undefined}
|
|
84
|
+
onchange={handleChange}
|
|
85
|
+
{...restProps}
|
|
86
|
+
/>
|
|
87
|
+
<span class={controlRingClasses}></span>
|
|
88
|
+
{#if mark}
|
|
89
|
+
{@render mark({ checked, loading, disabled: isDisabled })}
|
|
90
|
+
{/if}
|
|
91
|
+
</span>
|
|
92
|
+
{#if label}
|
|
93
|
+
<span class="text-sm font-medium text-label">
|
|
94
|
+
{label}
|
|
95
|
+
</span>
|
|
96
|
+
{/if}
|
|
97
|
+
</label>
|
|
98
|
+
</div>
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { Snippet } from "svelte";
|
|
2
|
+
import { type SelectionControlShape } from "./selection-control.styles";
|
|
3
|
+
type SelectionControlType = "checkbox" | "radio";
|
|
4
|
+
export type SelectionControlMarkProps = {
|
|
5
|
+
checked: boolean;
|
|
6
|
+
loading: boolean;
|
|
7
|
+
disabled: boolean;
|
|
8
|
+
};
|
|
9
|
+
interface Props {
|
|
10
|
+
id?: string;
|
|
11
|
+
type: SelectionControlType;
|
|
12
|
+
shape: SelectionControlShape;
|
|
13
|
+
name?: string;
|
|
14
|
+
value?: string;
|
|
15
|
+
label?: string;
|
|
16
|
+
disabled?: boolean;
|
|
17
|
+
loading?: boolean;
|
|
18
|
+
defaultChecked?: boolean;
|
|
19
|
+
checked?: boolean;
|
|
20
|
+
onChange?: (event: Event) => void;
|
|
21
|
+
onchange?: (event: Event) => void;
|
|
22
|
+
mark?: Snippet<[SelectionControlMarkProps]>;
|
|
23
|
+
}
|
|
24
|
+
declare const SelectionControl: import("svelte").Component<Props, {}, "checked">;
|
|
25
|
+
type SelectionControl = ReturnType<typeof SelectionControl>;
|
|
26
|
+
export default SelectionControl;
|