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
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import ThemeToggle from "../atoms/ThemeToggle.svelte";
|
|
3
|
+
import IconButton from "../atoms/IconButton.svelte";
|
|
4
|
+
import { ExternalLink, Menu, X } from "@lucide/svelte";
|
|
3
5
|
import type { Component, Snippet } from "svelte";
|
|
6
|
+
import { generateId } from "../util/ssr-safe.js";
|
|
7
|
+
import { cn } from "../util/cn.js";
|
|
4
8
|
|
|
5
9
|
export interface TopNavbarNavItem {
|
|
6
10
|
label: string;
|
|
@@ -15,6 +19,8 @@
|
|
|
15
19
|
/** `aria-label` on `<nav>` when multiple nav landmarks exist. */
|
|
16
20
|
ariaLabel?: string;
|
|
17
21
|
showThemeToggle?: boolean;
|
|
22
|
+
class?: string;
|
|
23
|
+
/** @deprecated use `class`. */
|
|
18
24
|
className?: string;
|
|
19
25
|
/** Slim mode: only the `nav` region (no full chrome bar). */
|
|
20
26
|
embedded?: boolean;
|
|
@@ -30,7 +36,8 @@
|
|
|
30
36
|
brandHref,
|
|
31
37
|
ariaLabel,
|
|
32
38
|
showThemeToggle = true,
|
|
33
|
-
|
|
39
|
+
class: classAttr = "",
|
|
40
|
+
className: legacyClass = "",
|
|
34
41
|
embedded = false,
|
|
35
42
|
items = [],
|
|
36
43
|
navVariant = "header",
|
|
@@ -42,12 +49,24 @@
|
|
|
42
49
|
...restProps
|
|
43
50
|
}: Props & { nav?: Snippet; actions?: Snippet } = $props();
|
|
44
51
|
|
|
52
|
+
/** `class` is the public prop; `className` is a deprecated alias.
|
|
53
|
+
* Both are merged here so existing call sites keep working. */
|
|
54
|
+
const className = $derived(cn(`${classAttr} ${legacyClass}`));
|
|
55
|
+
|
|
56
|
+
const mobileMenuId = generateId("topnavbar-menu");
|
|
57
|
+
|
|
45
58
|
let isMenuOpen = $state(false);
|
|
46
59
|
|
|
47
60
|
function toggleMenu() {
|
|
48
61
|
isMenuOpen = !isMenuOpen;
|
|
49
62
|
}
|
|
50
63
|
|
|
64
|
+
function handleWindowKeydown(event: KeyboardEvent) {
|
|
65
|
+
if (event.key === "Escape" && isMenuOpen) {
|
|
66
|
+
isMenuOpen = false;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
51
70
|
function handleNavLinkClick(event: MouseEvent) {
|
|
52
71
|
if (preventNavigation) {
|
|
53
72
|
event.preventDefault();
|
|
@@ -57,6 +76,11 @@
|
|
|
57
76
|
}
|
|
58
77
|
}
|
|
59
78
|
|
|
79
|
+
/** Absolute URLs leave the site, so they are marked and open in a new tab. */
|
|
80
|
+
function isExternal(href: string): boolean {
|
|
81
|
+
return href.startsWith("http://") || href.startsWith("https://");
|
|
82
|
+
}
|
|
83
|
+
|
|
60
84
|
/** App routes: prefix match except `/` and absolute URLs (exact match). */
|
|
61
85
|
function isNavItemActive(href: string): boolean {
|
|
62
86
|
if (href.startsWith("http://") || href.startsWith("https://")) {
|
|
@@ -78,8 +102,30 @@
|
|
|
78
102
|
return "flex flex-col gap-1 grow h-full items-center justify-center min-h-0 min-w-0 relative shrink-0 cursor-pointer w-full md:w-auto";
|
|
79
103
|
}
|
|
80
104
|
|
|
81
|
-
|
|
82
|
-
|
|
105
|
+
/**
|
|
106
|
+
* The active state is resolved here rather than with
|
|
107
|
+
* `aria-[current=page]:text-nav-menu-item-active`.
|
|
108
|
+
*
|
|
109
|
+
* That variant was dead: the semantic utilities are hand-written in
|
|
110
|
+
* app.css and sit outside Tailwind's cascade layer, so an unlayered
|
|
111
|
+
* `.text-nav-menu-item` beats anything Tailwind generates for a variant of
|
|
112
|
+
* the same property. The fill happened to survive only because no plain
|
|
113
|
+
* `bg-*` class competed with it — so the selected tab painted its pill but
|
|
114
|
+
* kept the idle label colour (#27272a where #3c52ba was intended), which
|
|
115
|
+
* is exactly the "active state does almost nothing" failure the sidebar
|
|
116
|
+
* had.
|
|
117
|
+
*
|
|
118
|
+
* Plain classes chosen in JS cannot lose that way.
|
|
119
|
+
*/
|
|
120
|
+
function getIconContainerClasses(isActive: boolean): string {
|
|
121
|
+
const base =
|
|
122
|
+
"focus-ring focus-ring--nav group/nav-item flex flex-col items-center justify-center overflow-clip relative rounded-pill shrink-0 transition-colors duration-200 outline-none";
|
|
123
|
+
return isActive
|
|
124
|
+
? cn(base, "bg-nav-menu-active text-nav-menu-item-active")
|
|
125
|
+
: cn(
|
|
126
|
+
base,
|
|
127
|
+
"text-nav-menu-item hover:bg-nav-menu-hover hover:text-nav-menu-item-hover",
|
|
128
|
+
);
|
|
83
129
|
}
|
|
84
130
|
|
|
85
131
|
function getStateLayerClasses(): string {
|
|
@@ -87,7 +133,9 @@
|
|
|
87
133
|
}
|
|
88
134
|
|
|
89
135
|
function getLabelClasses(): string {
|
|
90
|
-
|
|
136
|
+
// `whitespace-pre` used to sit beside `text-nowrap` — same property,
|
|
137
|
+
// and it preserved literal whitespace as a side effect.
|
|
138
|
+
return "font-medium leading-4 relative shrink-0 text-center text-nowrap tracking-wide text-xs text-inherit";
|
|
91
139
|
}
|
|
92
140
|
|
|
93
141
|
function getIconWrapperClasses(): string {
|
|
@@ -99,12 +147,15 @@
|
|
|
99
147
|
<ul class="{ulClasses} list-none m-0 p-0">
|
|
100
148
|
{#each items as item (item.href)}
|
|
101
149
|
{@const isActive = isNavItemActive(item.href)}
|
|
150
|
+
{@const external = isExternal(item.href)}
|
|
102
151
|
<li class={getNavItemClasses()}>
|
|
103
152
|
<a
|
|
104
153
|
href={item.href}
|
|
105
|
-
class={getIconContainerClasses()}
|
|
154
|
+
class={getIconContainerClasses(isActive)}
|
|
106
155
|
onclick={handleNavLinkClick}
|
|
107
156
|
aria-current={isActive ? "page" : undefined}
|
|
157
|
+
target={external ? "_blank" : undefined}
|
|
158
|
+
rel={external ? "noopener noreferrer" : undefined}
|
|
108
159
|
>
|
|
109
160
|
<div class={getStateLayerClasses()}>
|
|
110
161
|
{#if item.iconFilled && isActive}
|
|
@@ -118,9 +169,17 @@
|
|
|
118
169
|
<Icon size={16} class="w-4 h-4" />
|
|
119
170
|
</div>
|
|
120
171
|
{/if}
|
|
121
|
-
<
|
|
172
|
+
<span class={getLabelClasses()}>
|
|
122
173
|
{item.label}
|
|
123
|
-
</
|
|
174
|
+
</span>
|
|
175
|
+
{#if external}
|
|
176
|
+
<ExternalLink
|
|
177
|
+
size={12}
|
|
178
|
+
class="shrink-0 text-current opacity-70"
|
|
179
|
+
aria-hidden="true"
|
|
180
|
+
/>
|
|
181
|
+
<span class="sr-only">(opens in a new tab)</span>
|
|
182
|
+
{/if}
|
|
124
183
|
</div>
|
|
125
184
|
</a>
|
|
126
185
|
</li>
|
|
@@ -128,6 +187,8 @@
|
|
|
128
187
|
</ul>
|
|
129
188
|
{/snippet}
|
|
130
189
|
|
|
190
|
+
<svelte:window onkeydown={handleWindowKeydown} />
|
|
191
|
+
|
|
131
192
|
{#if embedded}
|
|
132
193
|
<nav class={className} aria-label={ariaLabel} {...restProps}>
|
|
133
194
|
{#if nav}
|
|
@@ -138,7 +199,7 @@
|
|
|
138
199
|
</nav>
|
|
139
200
|
{:else}
|
|
140
201
|
<nav
|
|
141
|
-
class="border-b border-border bg-background sticky top-0 z-
|
|
202
|
+
class={cn("border-b border-border bg-background sticky top-0 z-sticky", className)}
|
|
142
203
|
aria-label={ariaLabel}
|
|
143
204
|
{...restProps}
|
|
144
205
|
>
|
|
@@ -148,7 +209,7 @@
|
|
|
148
209
|
{#if brandHref}
|
|
149
210
|
<a
|
|
150
211
|
href={brandHref}
|
|
151
|
-
class="focus-ring text-xl font-bold text-headline hover:
|
|
212
|
+
class="focus-ring text-xl font-bold text-headline transition-colors hover:text-link"
|
|
152
213
|
>
|
|
153
214
|
{brand}
|
|
154
215
|
</a>
|
|
@@ -158,7 +219,7 @@
|
|
|
158
219
|
</div>
|
|
159
220
|
|
|
160
221
|
<div class="hidden md:block">
|
|
161
|
-
<div class="ml-10 flex items-
|
|
222
|
+
<div class="ml-10 flex items-center space-x-4">
|
|
162
223
|
{#if nav}
|
|
163
224
|
{@render nav()}
|
|
164
225
|
{:else if items.length > 0}
|
|
@@ -177,19 +238,29 @@
|
|
|
177
238
|
</div>
|
|
178
239
|
|
|
179
240
|
<div class="md:hidden">
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
241
|
+
<!--
|
|
242
|
+
Was a bare ☰ glyph in a text-2xl span: font-dependent,
|
|
243
|
+
off the icon scale, and with no disclosure semantics, so
|
|
244
|
+
a screen reader could not tell the menu was open.
|
|
245
|
+
-->
|
|
246
|
+
<IconButton
|
|
247
|
+
variant="ghost"
|
|
248
|
+
label={isMenuOpen ? "Close menu" : "Open menu"}
|
|
183
249
|
onclick={toggleMenu}
|
|
184
|
-
aria-
|
|
250
|
+
aria-expanded={isMenuOpen}
|
|
251
|
+
aria-controls={mobileMenuId}
|
|
185
252
|
>
|
|
186
|
-
|
|
187
|
-
|
|
253
|
+
{#if isMenuOpen}
|
|
254
|
+
<X size={20} />
|
|
255
|
+
{:else}
|
|
256
|
+
<Menu size={20} />
|
|
257
|
+
{/if}
|
|
258
|
+
</IconButton>
|
|
188
259
|
</div>
|
|
189
260
|
</div>
|
|
190
261
|
|
|
191
262
|
{#if isMenuOpen}
|
|
192
|
-
<div class="md:hidden">
|
|
263
|
+
<div class="md:hidden" id={mobileMenuId}>
|
|
193
264
|
<div
|
|
194
265
|
class="px-2 pt-2 pb-3 space-y-1 sm:px-3 border-t border-border"
|
|
195
266
|
>
|
|
@@ -17,6 +17,8 @@ interface Props {
|
|
|
17
17
|
/** `aria-label` on `<nav>` when multiple nav landmarks exist. */
|
|
18
18
|
ariaLabel?: string;
|
|
19
19
|
showThemeToggle?: boolean;
|
|
20
|
+
class?: string;
|
|
21
|
+
/** @deprecated use `class`. */
|
|
20
22
|
className?: string;
|
|
21
23
|
/** Slim mode: only the `nav` region (no full chrome bar). */
|
|
22
24
|
embedded?: boolean;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export { default as TopNavbar } from './TopNavbar.svelte';
|
|
2
2
|
export { default as SidebarNavigation } from './SidebarNavigation.svelte';
|
|
3
|
+
export { default as SidebarShell } from './SidebarShell.svelte';
|
|
3
4
|
export { default as SidebarAccountPanel } from './SidebarAccountPanel.svelte';
|
|
4
5
|
export { default as SidebarPanel } from './SidebarPanel.svelte';
|
package/dist/organisms/index.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export { default as TopNavbar } from './TopNavbar.svelte';
|
|
2
2
|
export { default as SidebarNavigation } from './SidebarNavigation.svelte';
|
|
3
|
+
export { default as SidebarShell } from './SidebarShell.svelte';
|
|
3
4
|
export { default as SidebarAccountPanel } from './SidebarAccountPanel.svelte';
|
|
4
5
|
export { default as SidebarPanel } from './SidebarPanel.svelte';
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Variant class helpers — semantic design tokens only (see src/app.css).
|
|
3
|
+
*/
|
|
4
|
+
import type { SemanticVariant } from '../../types/variants.js';
|
|
5
|
+
export type Variant = SemanticVariant;
|
|
6
|
+
/**
|
|
7
|
+
* Border + focus ring classes for text inputs (Input, Textarea).
|
|
8
|
+
*/
|
|
9
|
+
export declare function getInputVariantClasses(variant: Variant): string;
|
|
10
|
+
/**
|
|
11
|
+
* Card surfaces — border + background using semantic tokens.
|
|
12
|
+
*/
|
|
13
|
+
export declare function getCardVariantClasses(variant: Variant): string;
|
|
14
|
+
/**
|
|
15
|
+
* Generic variant classes for borders, text, or backgrounds.
|
|
16
|
+
*/
|
|
17
|
+
export declare function getVariantClasses(variant: Variant, type: 'border' | 'text' | 'bg'): string;
|
|
18
|
+
export declare function getAllVariantClasses(variant: Variant): {
|
|
19
|
+
border: string;
|
|
20
|
+
text: string;
|
|
21
|
+
bg: string;
|
|
22
|
+
};
|
|
23
|
+
/**
|
|
24
|
+
* Create a variant class map for use in reactive statements
|
|
25
|
+
*/
|
|
26
|
+
export declare function createVariantClassMap<T extends string>(variants: T[], prefix: string): Record<T, string>;
|
|
@@ -1,55 +1,37 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Variant class helpers — semantic design tokens only (see src/app.css).
|
|
3
3
|
*/
|
|
4
|
-
|
|
5
|
-
import type { SemanticVariant } from '../../types/variants.js';
|
|
6
|
-
|
|
7
|
-
export type Variant = SemanticVariant;
|
|
8
|
-
|
|
9
4
|
/**
|
|
10
5
|
* Border + focus ring classes for text inputs (Input, Textarea).
|
|
11
6
|
*/
|
|
12
|
-
export function getInputVariantClasses(variant
|
|
13
|
-
const variantMap
|
|
14
|
-
default:
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
'focus-ring border-success focus-visible:border-success',
|
|
18
|
-
warning:
|
|
19
|
-
'focus-ring border-warning focus-visible:border-warning',
|
|
7
|
+
export function getInputVariantClasses(variant) {
|
|
8
|
+
const variantMap = {
|
|
9
|
+
default: 'focus-ring border-input-border focus-visible:border-input-border',
|
|
10
|
+
success: 'focus-ring border-success focus-visible:border-success',
|
|
11
|
+
warning: 'focus-ring border-warning focus-visible:border-warning',
|
|
20
12
|
error: 'focus-ring border-error focus-visible:border-error',
|
|
21
13
|
info: 'focus-ring border-info focus-visible:border-info',
|
|
22
14
|
};
|
|
23
|
-
|
|
24
15
|
return variantMap[variant] || variantMap.default;
|
|
25
16
|
}
|
|
26
|
-
|
|
27
17
|
/**
|
|
28
18
|
* Card surfaces — border + background using semantic tokens.
|
|
29
19
|
*/
|
|
30
|
-
export function getCardVariantClasses(variant
|
|
31
|
-
const variantMap
|
|
20
|
+
export function getCardVariantClasses(variant) {
|
|
21
|
+
const variantMap = {
|
|
32
22
|
default: 'border-border bg-card',
|
|
33
23
|
success: 'border-success bg-card',
|
|
34
24
|
warning: 'border-warning bg-card',
|
|
35
25
|
error: 'border-error bg-card',
|
|
36
26
|
info: 'border-info bg-card',
|
|
37
27
|
};
|
|
38
|
-
|
|
39
28
|
return variantMap[variant] || variantMap.default;
|
|
40
29
|
}
|
|
41
|
-
|
|
42
30
|
/**
|
|
43
31
|
* Generic variant classes for borders, text, or backgrounds.
|
|
44
32
|
*/
|
|
45
|
-
export function getVariantClasses(
|
|
46
|
-
|
|
47
|
-
type: 'border' | 'text' | 'bg',
|
|
48
|
-
): string {
|
|
49
|
-
const variantMap: Record<
|
|
50
|
-
Variant,
|
|
51
|
-
Record<'border' | 'text' | 'bg', string>
|
|
52
|
-
> = {
|
|
33
|
+
export function getVariantClasses(variant, type) {
|
|
34
|
+
const variantMap = {
|
|
53
35
|
default: {
|
|
54
36
|
border: 'border-border',
|
|
55
37
|
text: 'text-body',
|
|
@@ -76,34 +58,21 @@ export function getVariantClasses(
|
|
|
76
58
|
bg: 'bg-card',
|
|
77
59
|
},
|
|
78
60
|
};
|
|
79
|
-
|
|
80
61
|
return variantMap[variant]?.[type] || variantMap.default[type];
|
|
81
62
|
}
|
|
82
|
-
|
|
83
|
-
export function getAllVariantClasses(variant: Variant): {
|
|
84
|
-
border: string;
|
|
85
|
-
text: string;
|
|
86
|
-
bg: string;
|
|
87
|
-
} {
|
|
63
|
+
export function getAllVariantClasses(variant) {
|
|
88
64
|
return {
|
|
89
65
|
border: getVariantClasses(variant, 'border'),
|
|
90
66
|
text: getVariantClasses(variant, 'text'),
|
|
91
67
|
bg: getVariantClasses(variant, 'bg'),
|
|
92
68
|
};
|
|
93
69
|
}
|
|
94
|
-
|
|
95
70
|
/**
|
|
96
71
|
* Create a variant class map for use in reactive statements
|
|
97
72
|
*/
|
|
98
|
-
export function createVariantClassMap
|
|
99
|
-
variants
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
(acc, variant) => {
|
|
104
|
-
acc[variant] = `${prefix}-${variant}`;
|
|
105
|
-
return acc;
|
|
106
|
-
},
|
|
107
|
-
{} as Record<T, string>,
|
|
108
|
-
);
|
|
73
|
+
export function createVariantClassMap(variants, prefix) {
|
|
74
|
+
return variants.reduce((acc, variant) => {
|
|
75
|
+
acc[variant] = `${prefix}-${variant}`;
|
|
76
|
+
return acc;
|
|
77
|
+
}, {});
|
|
109
78
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/dist/util/cn.js
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { extendTailwindMerge } from "tailwind-merge";
|
|
2
|
+
/**
|
|
3
|
+
* Class merger for every component's final `class` value.
|
|
4
|
+
*
|
|
5
|
+
* The library promises that a call-site utility wins over the component's own.
|
|
6
|
+
* Plain concatenation does not deliver that: `rounded-control` and
|
|
7
|
+
* `rounded-container` are equal-specificity utilities, so the winner is
|
|
8
|
+
* whichever Tailwind emits later in the stylesheet, not whichever the caller
|
|
9
|
+
* passed. The sidebar's search field asked for `rounded-container` and rendered
|
|
10
|
+
* at 8px, because `rounded-control` happened to come later.
|
|
11
|
+
*
|
|
12
|
+
* tailwind-merge resolves conflicts by class group and keeps the last one, so
|
|
13
|
+
* the promise holds for real.
|
|
14
|
+
*
|
|
15
|
+
* Almost all of this repo's semantic utilities already work with the stock
|
|
16
|
+
* config — `bg-card` vs `bg-surface-overlay`, `text-headline` vs
|
|
17
|
+
* `text-description`, `border-border` vs `border-input-border` all resolve,
|
|
18
|
+
* because tailwind-merge treats an unrecognised colour-ish value as a colour.
|
|
19
|
+
* The radii are the exception: `control`, `container`, `overlay` and `pill` are
|
|
20
|
+
* role names, not scale values, so they have to be declared or tailwind-merge
|
|
21
|
+
* keeps both and we are back to stylesheet order deciding.
|
|
22
|
+
*/
|
|
23
|
+
const RADIUS_ROLES = ["control", "container", "overlay", "pill"];
|
|
24
|
+
/**
|
|
25
|
+
* Every corner group tailwind-merge knows about, so `rounded-t-overlay` on a
|
|
26
|
+
* sheet is still beaten by a call-site `rounded-t-control`. Declaring only the
|
|
27
|
+
* base `rounded` group silently leaves the per-side ones unmerged.
|
|
28
|
+
*/
|
|
29
|
+
const RADIUS_GROUPS = [
|
|
30
|
+
"rounded",
|
|
31
|
+
"rounded-s", "rounded-e", "rounded-t", "rounded-r", "rounded-b", "rounded-l",
|
|
32
|
+
"rounded-ss", "rounded-se", "rounded-ee", "rounded-es",
|
|
33
|
+
"rounded-tl", "rounded-tr", "rounded-br", "rounded-bl",
|
|
34
|
+
];
|
|
35
|
+
const twMerge = extendTailwindMerge({
|
|
36
|
+
extend: {
|
|
37
|
+
classGroups: Object.fromEntries(RADIUS_GROUPS.map((group) => [group, [{ [group]: RADIUS_ROLES }]])),
|
|
38
|
+
},
|
|
39
|
+
});
|
|
40
|
+
/**
|
|
41
|
+
* Merge class values, last conflicting utility wins.
|
|
42
|
+
*
|
|
43
|
+
* Falsy entries are dropped, so `cn(base, isActive && activeClasses, className)`
|
|
44
|
+
* is safe.
|
|
45
|
+
*/
|
|
46
|
+
export function cn(...classes) {
|
|
47
|
+
return twMerge(classes.filter(Boolean).join(" "));
|
|
48
|
+
}
|
package/dist/util/ssr-safe.d.ts
CHANGED
|
@@ -9,8 +9,8 @@ export declare function safeDocument(): Document | undefined;
|
|
|
9
9
|
export declare function safeLocalStorage(): Storage | undefined;
|
|
10
10
|
export declare function safeSessionStorage(): Storage | undefined;
|
|
11
11
|
export declare function safeRequestAnimationFrame(callback: FrameRequestCallback): number | undefined;
|
|
12
|
-
export declare function safeSetTimeout(callback: () => void, delay: number):
|
|
13
|
-
export declare function safeClearTimeout(id:
|
|
14
|
-
export declare function safeSetInterval(callback: () => void, delay: number):
|
|
15
|
-
export declare function safeClearInterval(id:
|
|
12
|
+
export declare function safeSetTimeout(callback: () => void, delay: number): ReturnType<typeof setTimeout> | undefined;
|
|
13
|
+
export declare function safeClearTimeout(id: ReturnType<typeof setTimeout> | undefined): void;
|
|
14
|
+
export declare function safeSetInterval(callback: () => void, delay: number): ReturnType<typeof setInterval> | undefined;
|
|
15
|
+
export declare function safeClearInterval(id: ReturnType<typeof setInterval> | undefined): void;
|
|
16
16
|
export declare function generateId(prefix?: string): string;
|