zabi-components 5.0.20 → 5.0.22
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/LICENSE +21 -0
- package/README.md +355 -81
- package/dist/atoms/Button.svelte +1 -1
- package/dist/atoms/CardContent.svelte +1 -1
- package/dist/atoms/CardHeader.svelte +1 -1
- package/dist/atoms/Checkbox.svelte +1 -7
- package/dist/atoms/CodeBlock.svelte +6 -6
- package/dist/atoms/ColorPicker.svelte +80 -72
- package/dist/atoms/IconButton.svelte +88 -0
- package/dist/atoms/IconButton.svelte.d.ts +21 -0
- package/dist/atoms/Input.svelte +14 -10
- package/dist/atoms/Input.svelte.d.ts +2 -0
- package/dist/atoms/List.svelte +47 -0
- package/dist/atoms/List.svelte.d.ts +19 -0
- package/dist/atoms/ListItem.svelte +148 -0
- package/dist/atoms/ListItem.svelte.d.ts +35 -0
- package/dist/atoms/Progress.svelte +3 -5
- package/dist/atoms/Select.svelte +152 -19
- package/dist/atoms/Select.svelte.d.ts +23 -1
- package/dist/atoms/Textarea.svelte +11 -9
- package/dist/atoms/Textarea.svelte.d.ts +1 -0
- package/dist/atoms/Toggle.svelte +1 -7
- package/dist/atoms/Tooltip.svelte +8 -15
- package/dist/atoms/index.d.ts +3 -0
- package/dist/atoms/index.js +3 -0
- package/dist/components/atoms/index.d.ts +3 -0
- package/dist/components/atoms/index.d.ts.map +1 -1
- package/dist/components/index.d.ts +4 -0
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/molecules/index.d.ts +1 -1
- package/dist/components/molecules/navigation-menu-context.d.ts +7 -0
- package/dist/components/molecules/navigation-menu-context.d.ts.map +1 -0
- package/dist/components/organisms/index.d.ts +2 -0
- package/dist/components/organisms/index.d.ts.map +1 -1
- package/dist/index.d.ts +4 -0
- package/dist/index.js +5 -8
- package/dist/molecules/Alert.svelte +8 -3
- package/dist/molecules/ContactForm.svelte +63 -31
- package/dist/molecules/ContactForm.svelte.d.ts +1 -4
- package/dist/molecules/Dropdown.svelte +2 -1
- package/dist/molecules/ImageUpload.svelte +26 -3
- package/dist/molecules/ImageUpload.svelte.d.ts +1 -0
- package/dist/molecules/Modal.svelte +44 -43
- package/dist/molecules/NavigationMenu.svelte +7 -10
- package/dist/molecules/NavigationMenuContent.svelte +8 -8
- package/dist/molecules/NavigationMenuItem.svelte +7 -6
- package/dist/molecules/NavigationMenuLink.svelte +7 -5
- package/dist/molecules/NavigationMenuList.svelte +0 -7
- package/dist/molecules/NavigationMenuTrigger.svelte +7 -7
- package/dist/molecules/Section.svelte +158 -0
- package/dist/molecules/Section.svelte.d.ts +27 -0
- package/dist/molecules/SlideUp.svelte +30 -0
- package/dist/molecules/Tabs.svelte +71 -4
- package/dist/molecules/index.d.ts +1 -1
- package/dist/molecules/index.js +1 -1
- package/dist/molecules/navigation-menu-context.d.ts +6 -0
- package/dist/molecules/navigation-menu-context.js +1 -0
- package/dist/organisms/Navigation.svelte +9 -6
- package/dist/organisms/Navigation.svelte.d.ts +1 -0
- package/dist/organisms/SidebarNavigation.svelte +420 -0
- package/dist/organisms/SidebarNavigation.svelte.d.ts +44 -0
- package/dist/organisms/SidebarProjectPanel.svelte +174 -0
- package/dist/organisms/SidebarProjectPanel.svelte.d.ts +32 -0
- package/dist/organisms/index.d.ts +2 -0
- package/dist/organisms/index.js +2 -0
- package/dist/zabi-components.css +412 -0
- package/package.json +7 -8
- package/dist/molecules/Sidebar.svelte +0 -324
- package/dist/molecules/Sidebar.svelte.d.ts +0 -30
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import type { Snippet } from "svelte";
|
|
3
3
|
import { getContext } from "svelte";
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
import {
|
|
5
|
+
NAVIGATION_MENU_CONTEXT_KEY,
|
|
6
|
+
type NavigationMenuContextValue,
|
|
7
|
+
} from "./navigation-menu-context.js";
|
|
6
8
|
|
|
7
9
|
interface Props {
|
|
8
10
|
href?: string;
|
|
@@ -19,9 +21,9 @@
|
|
|
19
21
|
...restProps
|
|
20
22
|
}: Props = $props();
|
|
21
23
|
|
|
22
|
-
const context = getContext<
|
|
23
|
-
|
|
24
|
-
|
|
24
|
+
const context = getContext<NavigationMenuContextValue>(
|
|
25
|
+
NAVIGATION_MENU_CONTEXT_KEY,
|
|
26
|
+
);
|
|
25
27
|
|
|
26
28
|
function handleClick() {
|
|
27
29
|
context?.setActiveItem(null);
|
|
@@ -1,8 +1,5 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import type { Snippet } from "svelte";
|
|
3
|
-
import { getContext } from "svelte";
|
|
4
|
-
|
|
5
|
-
const NAVIGATION_MENU_CONTEXT = Symbol("navigation-menu");
|
|
6
3
|
|
|
7
4
|
interface Props {
|
|
8
5
|
className?: string;
|
|
@@ -14,10 +11,6 @@
|
|
|
14
11
|
children,
|
|
15
12
|
...restProps
|
|
16
13
|
}: Props = $props();
|
|
17
|
-
|
|
18
|
-
const context = getContext<{
|
|
19
|
-
isMobile: boolean;
|
|
20
|
-
}>(NAVIGATION_MENU_CONTEXT);
|
|
21
14
|
</script>
|
|
22
15
|
|
|
23
16
|
<ul
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import type { Snippet } from "svelte";
|
|
3
3
|
import { getContext } from "svelte";
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
import {
|
|
5
|
+
NAVIGATION_MENU_CONTEXT_KEY,
|
|
6
|
+
type NavigationMenuContextValue,
|
|
7
|
+
} from "./navigation-menu-context.js";
|
|
6
8
|
|
|
7
9
|
interface Props {
|
|
8
10
|
value?: string;
|
|
@@ -19,11 +21,9 @@
|
|
|
19
21
|
|
|
20
22
|
let triggerElement = $state<HTMLElement | null>(null);
|
|
21
23
|
|
|
22
|
-
const context = getContext<
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
isMobile: boolean;
|
|
26
|
-
}>(NAVIGATION_MENU_CONTEXT);
|
|
24
|
+
const context = getContext<NavigationMenuContextValue>(
|
|
25
|
+
NAVIGATION_MENU_CONTEXT_KEY,
|
|
26
|
+
);
|
|
27
27
|
|
|
28
28
|
const isActive = $derived(context?.activeItem === value);
|
|
29
29
|
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { Snippet } from "svelte";
|
|
3
|
+
import type { SizeVariant } from "../../types/variants.js";
|
|
4
|
+
import Heading from "../atoms/Heading.svelte";
|
|
5
|
+
|
|
6
|
+
interface Props {
|
|
7
|
+
/** Section title */
|
|
8
|
+
title?: string;
|
|
9
|
+
/** Section description/subtitle */
|
|
10
|
+
description?: string;
|
|
11
|
+
/** Heading level for title (1-6) */
|
|
12
|
+
headingLevel?: number;
|
|
13
|
+
/** Section size variant */
|
|
14
|
+
size?: SizeVariant;
|
|
15
|
+
/** Maximum width of the section container */
|
|
16
|
+
maxWidth?: "sm" | "md" | "lg" | "xl" | "2xl" | "full" | "none";
|
|
17
|
+
/** Background variant */
|
|
18
|
+
background?: "default" | "muted" | "accent" | "transparent";
|
|
19
|
+
/** Padding variant */
|
|
20
|
+
padding?: "none" | "sm" | "md" | "lg" | "xl";
|
|
21
|
+
/** Whether to center the content */
|
|
22
|
+
centered?: boolean;
|
|
23
|
+
/** Additional CSS classes */
|
|
24
|
+
className?: string;
|
|
25
|
+
/** Section content */
|
|
26
|
+
children?: Snippet;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
let {
|
|
30
|
+
title = "",
|
|
31
|
+
description = "",
|
|
32
|
+
headingLevel = 2,
|
|
33
|
+
size = "md",
|
|
34
|
+
maxWidth = "xl",
|
|
35
|
+
background = "default",
|
|
36
|
+
padding = "lg",
|
|
37
|
+
centered = false,
|
|
38
|
+
className = "",
|
|
39
|
+
children,
|
|
40
|
+
...restProps
|
|
41
|
+
}: Props = $props();
|
|
42
|
+
|
|
43
|
+
const sizeClasses = $derived(() => {
|
|
44
|
+
switch (size) {
|
|
45
|
+
case "sm":
|
|
46
|
+
return "text-sm";
|
|
47
|
+
case "lg":
|
|
48
|
+
return "text-lg";
|
|
49
|
+
default:
|
|
50
|
+
return "text-base";
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
const maxWidthClasses = $derived(() => {
|
|
55
|
+
switch (maxWidth) {
|
|
56
|
+
case "sm":
|
|
57
|
+
return "max-w-screen-sm";
|
|
58
|
+
case "md":
|
|
59
|
+
return "max-w-screen-md";
|
|
60
|
+
case "lg":
|
|
61
|
+
return "max-w-screen-lg";
|
|
62
|
+
case "xl":
|
|
63
|
+
return "max-w-screen-xl";
|
|
64
|
+
case "2xl":
|
|
65
|
+
return "max-w-screen-2xl";
|
|
66
|
+
case "full":
|
|
67
|
+
return "max-w-full";
|
|
68
|
+
case "none":
|
|
69
|
+
return "";
|
|
70
|
+
default:
|
|
71
|
+
return "max-w-screen-xl";
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
const backgroundClasses = $derived(() => {
|
|
76
|
+
switch (background) {
|
|
77
|
+
case "muted":
|
|
78
|
+
return "bg-base-50";
|
|
79
|
+
case "accent":
|
|
80
|
+
return "bg-brand-50 dark:bg-brand-950";
|
|
81
|
+
case "transparent":
|
|
82
|
+
return "bg-transparent";
|
|
83
|
+
default:
|
|
84
|
+
return "bg-background";
|
|
85
|
+
}
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
const paddingClasses = $derived(() => {
|
|
89
|
+
switch (padding) {
|
|
90
|
+
case "none":
|
|
91
|
+
return "";
|
|
92
|
+
case "sm":
|
|
93
|
+
return "py-8 sm:py-12";
|
|
94
|
+
case "md":
|
|
95
|
+
return "py-12 sm:py-16";
|
|
96
|
+
case "lg":
|
|
97
|
+
return "py-16 sm:py-24";
|
|
98
|
+
case "xl":
|
|
99
|
+
return "py-24 sm:py-32";
|
|
100
|
+
default:
|
|
101
|
+
return "py-16 sm:py-24";
|
|
102
|
+
}
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
const containerClasses = $derived(() => {
|
|
106
|
+
const base = "w-full";
|
|
107
|
+
const maxWidthClass = maxWidthClasses();
|
|
108
|
+
const centeredClass = centered ? "mx-auto" : "";
|
|
109
|
+
return `${base} ${maxWidthClass} ${centeredClass}`.trim();
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
const contentClasses = $derived(() => {
|
|
113
|
+
const base = "px-4 sm:px-6 lg:px-8";
|
|
114
|
+
const centeredClass = centered ? "text-center" : "";
|
|
115
|
+
return `${base} ${centeredClass}`.trim();
|
|
116
|
+
});
|
|
117
|
+
</script>
|
|
118
|
+
|
|
119
|
+
<section
|
|
120
|
+
class="section {backgroundClasses()} {paddingClasses()} {className}"
|
|
121
|
+
{...restProps}
|
|
122
|
+
>
|
|
123
|
+
<div class={containerClasses()}>
|
|
124
|
+
<div class={contentClasses()}>
|
|
125
|
+
{#if title}
|
|
126
|
+
<div class="mb-6 {centered ? 'mx-auto' : ''}">
|
|
127
|
+
<Heading level={headingLevel} text={title} />
|
|
128
|
+
{#if description}
|
|
129
|
+
<p
|
|
130
|
+
class="mt-4 {sizeClasses()} text-description {centered
|
|
131
|
+
? 'mx-auto max-w-2xl'
|
|
132
|
+
: ''}"
|
|
133
|
+
>
|
|
134
|
+
{description}
|
|
135
|
+
</p>
|
|
136
|
+
{/if}
|
|
137
|
+
</div>
|
|
138
|
+
{/if}
|
|
139
|
+
|
|
140
|
+
{#if children}
|
|
141
|
+
<div class="section-content {centered ? 'mx-auto' : ''}">
|
|
142
|
+
{@render children()}
|
|
143
|
+
</div>
|
|
144
|
+
{/if}
|
|
145
|
+
</div>
|
|
146
|
+
</div>
|
|
147
|
+
</section>
|
|
148
|
+
|
|
149
|
+
<style>
|
|
150
|
+
.section {
|
|
151
|
+
position: relative;
|
|
152
|
+
width: 100%;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
.section-content {
|
|
156
|
+
width: 100%;
|
|
157
|
+
}
|
|
158
|
+
</style>
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { Snippet } from "svelte";
|
|
2
|
+
import type { SizeVariant } from "../../types/variants.js";
|
|
3
|
+
interface Props {
|
|
4
|
+
/** Section title */
|
|
5
|
+
title?: string;
|
|
6
|
+
/** Section description/subtitle */
|
|
7
|
+
description?: string;
|
|
8
|
+
/** Heading level for title (1-6) */
|
|
9
|
+
headingLevel?: number;
|
|
10
|
+
/** Section size variant */
|
|
11
|
+
size?: SizeVariant;
|
|
12
|
+
/** Maximum width of the section container */
|
|
13
|
+
maxWidth?: "sm" | "md" | "lg" | "xl" | "2xl" | "full" | "none";
|
|
14
|
+
/** Background variant */
|
|
15
|
+
background?: "default" | "muted" | "accent" | "transparent";
|
|
16
|
+
/** Padding variant */
|
|
17
|
+
padding?: "none" | "sm" | "md" | "lg" | "xl";
|
|
18
|
+
/** Whether to center the content */
|
|
19
|
+
centered?: boolean;
|
|
20
|
+
/** Additional CSS classes */
|
|
21
|
+
className?: string;
|
|
22
|
+
/** Section content */
|
|
23
|
+
children?: Snippet;
|
|
24
|
+
}
|
|
25
|
+
declare const Section: import("svelte").Component<Props, {}, "">;
|
|
26
|
+
type Section = ReturnType<typeof Section>;
|
|
27
|
+
export default Section;
|
|
@@ -1,4 +1,11 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
+
import {
|
|
3
|
+
focusFirstElement,
|
|
4
|
+
returnFocus,
|
|
5
|
+
saveFocus,
|
|
6
|
+
trapFocus,
|
|
7
|
+
} from "../../routes/lib/focus-utils.js";
|
|
8
|
+
|
|
2
9
|
interface Props {
|
|
3
10
|
isOpen?: boolean;
|
|
4
11
|
title?: string;
|
|
@@ -13,13 +20,35 @@
|
|
|
13
20
|
...restProps
|
|
14
21
|
} = $props<Props & { children?: any }>();
|
|
15
22
|
|
|
23
|
+
let slideUpContainer = $state<HTMLDivElement>();
|
|
24
|
+
let cleanupFocusTrap: (() => void) | null = null;
|
|
25
|
+
|
|
16
26
|
function closeSlideUp(event?: Event) {
|
|
17
27
|
isOpen = false;
|
|
28
|
+
if (cleanupFocusTrap) {
|
|
29
|
+
cleanupFocusTrap();
|
|
30
|
+
cleanupFocusTrap = null;
|
|
31
|
+
}
|
|
32
|
+
returnFocus();
|
|
18
33
|
if (onclick && event) {
|
|
19
34
|
(onclick as (event: Event) => void)(event);
|
|
20
35
|
}
|
|
21
36
|
}
|
|
22
37
|
|
|
38
|
+
$effect(() => {
|
|
39
|
+
const container = slideUpContainer;
|
|
40
|
+
if (isOpen && container) {
|
|
41
|
+
saveFocus();
|
|
42
|
+
cleanupFocusTrap = trapFocus(container);
|
|
43
|
+
setTimeout(() => {
|
|
44
|
+
focusFirstElement(container);
|
|
45
|
+
}, 0);
|
|
46
|
+
} else if (!isOpen && cleanupFocusTrap) {
|
|
47
|
+
cleanupFocusTrap();
|
|
48
|
+
cleanupFocusTrap = null;
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
|
|
23
52
|
function handleBackdropClick(event: Event) {
|
|
24
53
|
if (event.target === event.currentTarget) {
|
|
25
54
|
closeSlideUp(event);
|
|
@@ -48,6 +77,7 @@
|
|
|
48
77
|
tabindex="-1"
|
|
49
78
|
>
|
|
50
79
|
<div
|
|
80
|
+
bind:this={slideUpContainer}
|
|
51
81
|
class="fixed bottom-0 left-0 right-0 bg-card rounded-t-3xl shadow-xl z-modal max-h-[90vh] overflow-y-auto animate-[slideUp_0.3s_ease-out] flex flex-col"
|
|
52
82
|
>
|
|
53
83
|
{#if title}
|
|
@@ -1,4 +1,11 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
+
function createId(prefix: string): string {
|
|
3
|
+
if (typeof window !== "undefined") {
|
|
4
|
+
return `${prefix}-${Math.random().toString(36).slice(2, 11)}`;
|
|
5
|
+
}
|
|
6
|
+
return `${prefix}-ssr-${Date.now()}`;
|
|
7
|
+
}
|
|
8
|
+
|
|
2
9
|
interface Props {
|
|
3
10
|
tabs?: Array<{
|
|
4
11
|
id: string;
|
|
@@ -19,17 +26,69 @@
|
|
|
19
26
|
...restProps
|
|
20
27
|
}: Props & { children?: any } = $props();
|
|
21
28
|
|
|
29
|
+
const tabsBaseId = createId("tabs");
|
|
30
|
+
|
|
22
31
|
function selectTab(tabId: string) {
|
|
23
32
|
activeTab = tabId;
|
|
24
33
|
}
|
|
25
34
|
|
|
35
|
+
function getEnabledTabs() {
|
|
36
|
+
return tabs.filter((tab) => !tab.disabled);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function getTabIndex(tabId: string) {
|
|
40
|
+
return tabs.findIndex((tab) => tab.id === tabId);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function getTabId(tabId: string) {
|
|
44
|
+
return `${tabsBaseId}-tab-${tabId}`;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function getPanelId(tabId: string) {
|
|
48
|
+
return `${tabsBaseId}-panel-${tabId}`;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
$effect(() => {
|
|
52
|
+
if (tabs.length === 0) {
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const activeExists = tabs.some((tab) => tab.id === activeTab && !tab.disabled);
|
|
57
|
+
if (!activeExists) {
|
|
58
|
+
const firstEnabledTab = tabs.find((tab) => !tab.disabled);
|
|
59
|
+
if (firstEnabledTab) {
|
|
60
|
+
activeTab = firstEnabledTab.id;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
|
|
26
65
|
function handleKeydown(event: KeyboardEvent) {
|
|
66
|
+
const enabledTabs = getEnabledTabs();
|
|
67
|
+
if (enabledTabs.length === 0) {
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
const currentIndex = enabledTabs.findIndex((tab) => tab.id === activeTab);
|
|
72
|
+
const fallbackIndex = currentIndex === -1 ? 0 : currentIndex;
|
|
73
|
+
|
|
27
74
|
if (event.key === "ArrowLeft" || event.key === "ArrowRight") {
|
|
28
|
-
|
|
75
|
+
event.preventDefault();
|
|
29
76
|
const direction = event.key === "ArrowLeft" ? -1 : 1;
|
|
30
77
|
const nextIndex =
|
|
31
|
-
(
|
|
32
|
-
|
|
78
|
+
(fallbackIndex + direction + enabledTabs.length) %
|
|
79
|
+
enabledTabs.length;
|
|
80
|
+
selectTab(enabledTabs[nextIndex].id);
|
|
81
|
+
} else if (event.key === "Home") {
|
|
82
|
+
event.preventDefault();
|
|
83
|
+
selectTab(enabledTabs[0].id);
|
|
84
|
+
} else if (event.key === "End") {
|
|
85
|
+
event.preventDefault();
|
|
86
|
+
selectTab(enabledTabs[enabledTabs.length - 1].id);
|
|
87
|
+
} else if (event.key === "Enter" || event.key === " ") {
|
|
88
|
+
event.preventDefault();
|
|
89
|
+
if (currentIndex === -1) {
|
|
90
|
+
selectTab(enabledTabs[0].id);
|
|
91
|
+
}
|
|
33
92
|
}
|
|
34
93
|
}
|
|
35
94
|
</script>
|
|
@@ -45,6 +104,7 @@
|
|
|
45
104
|
<button
|
|
46
105
|
type="button"
|
|
47
106
|
role="tab"
|
|
107
|
+
id={getTabId(tab.id)}
|
|
48
108
|
class="px-4 py-2 text-sm font-medium border-b-2 transition-colors {activeTab ===
|
|
49
109
|
tab.id
|
|
50
110
|
? variant === 'pills'
|
|
@@ -54,13 +114,20 @@
|
|
|
54
114
|
onclick={() => selectTab(tab.id)}
|
|
55
115
|
disabled={tab.disabled}
|
|
56
116
|
aria-selected={activeTab === tab.id}
|
|
117
|
+
aria-controls={getPanelId(tab.id)}
|
|
118
|
+
tabindex={activeTab === tab.id ? 0 : -1}
|
|
57
119
|
>
|
|
58
120
|
{tab.label}
|
|
59
121
|
</button>
|
|
60
122
|
{/each}
|
|
61
123
|
</div>
|
|
62
124
|
|
|
63
|
-
<div
|
|
125
|
+
<div
|
|
126
|
+
class="mt-4"
|
|
127
|
+
role="tabpanel"
|
|
128
|
+
id={getPanelId(activeTab)}
|
|
129
|
+
aria-labelledby={getTabId(activeTab)}
|
|
130
|
+
>
|
|
64
131
|
{@render children?.({ activeTab })}
|
|
65
132
|
</div>
|
|
66
133
|
</div>
|
|
@@ -11,6 +11,6 @@ export { default as NavigationMenuItem } from './NavigationMenuItem.svelte';
|
|
|
11
11
|
export { default as NavigationMenuTrigger } from './NavigationMenuTrigger.svelte';
|
|
12
12
|
export { default as NavigationMenuContent } from './NavigationMenuContent.svelte';
|
|
13
13
|
export { default as NavigationMenuLink } from './NavigationMenuLink.svelte';
|
|
14
|
-
export { default as
|
|
14
|
+
export { default as Section } from './Section.svelte';
|
|
15
15
|
export { default as SlideUp } from './SlideUp.svelte';
|
|
16
16
|
export { default as Tabs } from './Tabs.svelte';
|
package/dist/molecules/index.js
CHANGED
|
@@ -11,6 +11,6 @@ export { default as NavigationMenuItem } from './NavigationMenuItem.svelte';
|
|
|
11
11
|
export { default as NavigationMenuTrigger } from './NavigationMenuTrigger.svelte';
|
|
12
12
|
export { default as NavigationMenuContent } from './NavigationMenuContent.svelte';
|
|
13
13
|
export { default as NavigationMenuLink } from './NavigationMenuLink.svelte';
|
|
14
|
-
export { default as
|
|
14
|
+
export { default as Section } from './Section.svelte';
|
|
15
15
|
export { default as SlideUp } from './SlideUp.svelte';
|
|
16
16
|
export { default as Tabs } from './Tabs.svelte';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const NAVIGATION_MENU_CONTEXT_KEY = Symbol("navigation-menu");
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
variant?: "header" | "sidebar";
|
|
13
13
|
items?: NavigationItem[];
|
|
14
14
|
currentPath?: string;
|
|
15
|
+
preventNavigation?: boolean;
|
|
15
16
|
onclick?: (event: Event) => void;
|
|
16
17
|
className?: string;
|
|
17
18
|
}
|
|
@@ -20,13 +21,16 @@
|
|
|
20
21
|
variant = "header",
|
|
21
22
|
items = [],
|
|
22
23
|
currentPath = "",
|
|
24
|
+
preventNavigation = false,
|
|
23
25
|
onclick,
|
|
24
26
|
className = "",
|
|
25
27
|
...restProps
|
|
26
28
|
}: Props & { children?: any } = $props();
|
|
27
29
|
|
|
28
|
-
function handleClick(
|
|
29
|
-
|
|
30
|
+
function handleClick(event: MouseEvent) {
|
|
31
|
+
if (preventNavigation) {
|
|
32
|
+
event.preventDefault();
|
|
33
|
+
}
|
|
30
34
|
if (onclick) {
|
|
31
35
|
onclick(event as any);
|
|
32
36
|
}
|
|
@@ -35,11 +39,11 @@
|
|
|
35
39
|
const ulClasses = $derived(() => {
|
|
36
40
|
return variant === "sidebar"
|
|
37
41
|
? "flex flex-col gap-1"
|
|
38
|
-
: "flex items-center justify-between
|
|
42
|
+
: "flex flex-col gap-1 md:flex-row md:items-center md:justify-between";
|
|
39
43
|
});
|
|
40
44
|
|
|
41
45
|
function getNavItemClasses(itemHref: string): string {
|
|
42
|
-
const baseClasses = "flex flex-col gap-1 grow h-full items-center justify-center min-h-0 min-w-0 relative shrink-0 cursor-pointer";
|
|
46
|
+
const baseClasses = "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";
|
|
43
47
|
|
|
44
48
|
return baseClasses;
|
|
45
49
|
}
|
|
@@ -88,8 +92,7 @@
|
|
|
88
92
|
<a
|
|
89
93
|
href={item.href}
|
|
90
94
|
class={iconContainerClasses}
|
|
91
|
-
onclick={
|
|
92
|
-
role="button"
|
|
95
|
+
onclick={handleClick}
|
|
93
96
|
aria-current={isActive ? "page" : undefined}
|
|
94
97
|
>
|
|
95
98
|
<div class={getStateLayerClasses()}>
|