zabi-components 5.0.18 → 5.0.20

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.
Files changed (54) hide show
  1. package/dist/atoms/Button.svelte +6 -3
  2. package/dist/atoms/Button.svelte.d.ts +1 -0
  3. package/dist/atoms/Card.svelte +23 -47
  4. package/dist/atoms/CardContent.svelte +12 -5
  5. package/dist/atoms/CardContent.svelte.d.ts +2 -0
  6. package/dist/atoms/CardHeader.svelte +22 -5
  7. package/dist/atoms/CardHeader.svelte.d.ts +3 -0
  8. package/dist/atoms/ColorPicker.svelte +271 -7
  9. package/dist/atoms/Input.svelte +7 -6
  10. package/dist/atoms/Input.svelte.d.ts +3 -1
  11. package/dist/atoms/Progress.svelte +1 -3
  12. package/dist/atoms/Select.svelte +17 -22
  13. package/dist/atoms/Skeleton.svelte +12 -2
  14. package/dist/atoms/Skeleton.svelte.d.ts +1 -0
  15. package/dist/atoms/Tooltip.svelte +15 -17
  16. package/dist/atoms/index.d.ts +0 -2
  17. package/dist/atoms/index.js +0 -2
  18. package/dist/components/atoms/index.d.ts +0 -2
  19. package/dist/components/atoms/index.d.ts.map +1 -1
  20. package/dist/components/molecules/index.d.ts +7 -0
  21. package/dist/components/molecules/index.d.ts.map +1 -1
  22. package/dist/molecules/Dropdown.svelte +101 -14
  23. package/dist/molecules/Dropdown.svelte.d.ts +7 -0
  24. package/dist/molecules/ImageUpload.svelte +4 -4
  25. package/dist/molecules/Modal.svelte +43 -27
  26. package/dist/molecules/Modal.svelte.d.ts +1 -0
  27. package/dist/molecules/NavigationMenu.svelte +158 -0
  28. package/dist/molecules/NavigationMenu.svelte.d.ts +25 -0
  29. package/dist/molecules/NavigationMenuContent.svelte +83 -0
  30. package/dist/molecules/NavigationMenuContent.svelte.d.ts +9 -0
  31. package/dist/molecules/NavigationMenuItem.svelte +36 -0
  32. package/dist/molecules/NavigationMenuItem.svelte.d.ts +9 -0
  33. package/dist/molecules/NavigationMenuLink.svelte +53 -0
  34. package/dist/molecules/NavigationMenuLink.svelte.d.ts +10 -0
  35. package/dist/molecules/NavigationMenuList.svelte +31 -0
  36. package/dist/molecules/NavigationMenuList.svelte.d.ts +8 -0
  37. package/dist/molecules/NavigationMenuTrigger.svelte +81 -0
  38. package/dist/molecules/NavigationMenuTrigger.svelte.d.ts +9 -0
  39. package/dist/molecules/Sidebar.svelte +324 -0
  40. package/dist/molecules/Sidebar.svelte.d.ts +30 -0
  41. package/dist/molecules/SlideUp.svelte +2 -2
  42. package/dist/molecules/index.d.ts +7 -0
  43. package/dist/molecules/index.js +7 -0
  44. package/dist/routes/lib/focus-utils.d.ts +23 -0
  45. package/dist/routes/lib/focus-utils.ts +112 -0
  46. package/dist/zabi-components-colors.css +2 -2
  47. package/dist/zabi-components-theme-only.css +2 -2
  48. package/dist/zabi-components-theme.css +2 -2
  49. package/dist/zabi-components.css +192 -27
  50. package/package.json +4 -3
  51. package/dist/atoms/CardDescription.svelte +0 -24
  52. package/dist/atoms/CardDescription.svelte.d.ts +0 -8
  53. package/dist/atoms/CardTitle.svelte +0 -33
  54. package/dist/atoms/CardTitle.svelte.d.ts +0 -9
@@ -0,0 +1,158 @@
1
+ <script lang="ts">
2
+ import type { Snippet } from "svelte";
3
+ import { getContext, setContext } from "svelte";
4
+ import { onMount } from "svelte";
5
+ import NavigationMenuList from "./NavigationMenuList.svelte";
6
+ import NavigationMenuItem from "./NavigationMenuItem.svelte";
7
+ import NavigationMenuTrigger from "./NavigationMenuTrigger.svelte";
8
+ import NavigationMenuContent from "./NavigationMenuContent.svelte";
9
+ import NavigationMenuLink from "./NavigationMenuLink.svelte";
10
+
11
+ interface NavigationMenuContext {
12
+ activeItem: string | null;
13
+ setActiveItem: (item: string | null) => void;
14
+ isMobile: boolean;
15
+ }
16
+
17
+ const NAVIGATION_MENU_CONTEXT = Symbol("navigation-menu");
18
+
19
+ export interface NavigationMenuItemData {
20
+ value: string;
21
+ label: string;
22
+ href?: string;
23
+ content?: NavigationMenuLinkData[];
24
+ children?: Snippet;
25
+ }
26
+
27
+ export interface NavigationMenuLinkData {
28
+ href: string;
29
+ label?: string;
30
+ description?: string;
31
+ children?: Snippet;
32
+ asChild?: boolean;
33
+ }
34
+
35
+ interface Props {
36
+ viewport?: boolean | "mobile";
37
+ className?: string;
38
+ items?: NavigationMenuItemData[];
39
+ children?: Snippet;
40
+ listClassName?: string;
41
+ }
42
+
43
+ let {
44
+ viewport = true,
45
+ className = "",
46
+ items = [],
47
+ children,
48
+ listClassName = "",
49
+ ...restProps
50
+ }: Props = $props();
51
+
52
+ let activeItem = $state<string | null>(null);
53
+ let isMobile = $state(false);
54
+ let containerElement = $state<HTMLElement | null>(null);
55
+
56
+ function setActiveItem(item: string | null) {
57
+ activeItem = item;
58
+ }
59
+
60
+ function checkMobile() {
61
+ if (viewport === "mobile") {
62
+ isMobile = true;
63
+ } else if (viewport === true) {
64
+ isMobile = window.innerWidth < 768;
65
+ } else {
66
+ isMobile = false;
67
+ }
68
+ }
69
+
70
+ onMount(() => {
71
+ checkMobile();
72
+ if (viewport !== false) {
73
+ const handleResize = () => checkMobile();
74
+ window.addEventListener("resize", handleResize);
75
+ return () => window.removeEventListener("resize", handleResize);
76
+ }
77
+ });
78
+
79
+ const context: NavigationMenuContext = {
80
+ get activeItem() {
81
+ return activeItem;
82
+ },
83
+ setActiveItem,
84
+ get isMobile() {
85
+ return isMobile;
86
+ },
87
+ };
88
+
89
+ setContext(NAVIGATION_MENU_CONTEXT, context);
90
+ </script>
91
+
92
+ <nav
93
+ bind:this={containerElement}
94
+ class="relative {className}"
95
+ aria-label="Main navigation"
96
+ {...restProps}
97
+ >
98
+ {#if items.length > 0}
99
+ <NavigationMenuList className={listClassName}>
100
+ {#each items as item}
101
+ <NavigationMenuItem value={item.value}>
102
+ {#if item.content && item.content.length > 0}
103
+ <NavigationMenuTrigger value={item.value}>
104
+ {item.label}
105
+ </NavigationMenuTrigger>
106
+ <NavigationMenuContent value={item.value}>
107
+ {#if item.children}
108
+ {@render item.children()}
109
+ {:else}
110
+ <ul class="grid gap-2">
111
+ {#each item.content as link}
112
+ <li>
113
+ <NavigationMenuLink
114
+ href={link.href}
115
+ asChild={link.asChild}
116
+ >
117
+ {#if link.children}
118
+ {@render link.children()}
119
+ {:else if link.label}
120
+ <div
121
+ class="text-sm font-medium leading-none"
122
+ >
123
+ {link.label}
124
+ </div>
125
+ {#if link.description}
126
+ <p
127
+ class="line-clamp-2 text-sm leading-snug text-description"
128
+ >
129
+ {link.description}
130
+ </p>
131
+ {/if}
132
+ {/if}
133
+ </NavigationMenuLink>
134
+ </li>
135
+ {/each}
136
+ </ul>
137
+ {/if}
138
+ </NavigationMenuContent>
139
+ {:else if item.href}
140
+ <NavigationMenuLink href={item.href}>
141
+ {item.label}
142
+ </NavigationMenuLink>
143
+ {:else if item.children}
144
+ {@render item.children()}
145
+ {/if}
146
+ </NavigationMenuItem>
147
+ {/each}
148
+ </NavigationMenuList>
149
+ {:else if children}
150
+ {@render children()}
151
+ {/if}
152
+ </nav>
153
+
154
+ <style>
155
+ :global([data-navigation-menu]) {
156
+ position: relative;
157
+ }
158
+ </style>
@@ -0,0 +1,25 @@
1
+ import type { Snippet } from "svelte";
2
+ export interface NavigationMenuLinkData {
3
+ href: string;
4
+ label?: string;
5
+ description?: string;
6
+ children?: Snippet;
7
+ asChild?: boolean;
8
+ }
9
+ export interface NavigationMenuItemData {
10
+ value: string;
11
+ label: string;
12
+ href?: string;
13
+ content?: NavigationMenuLinkData[];
14
+ children?: Snippet;
15
+ }
16
+ interface Props {
17
+ viewport?: boolean | "mobile";
18
+ className?: string;
19
+ items?: NavigationMenuItemData[];
20
+ children?: Snippet;
21
+ listClassName?: string;
22
+ }
23
+ declare const NavigationMenu: import("svelte").Component<Props, {}, "">;
24
+ type NavigationMenu = ReturnType<typeof NavigationMenu>;
25
+ export default NavigationMenu;
@@ -0,0 +1,83 @@
1
+ <script lang="ts">
2
+ import type { Snippet } from "svelte";
3
+ import { getContext } from "svelte";
4
+ import { onMount, onDestroy } from "svelte";
5
+
6
+ const NAVIGATION_MENU_CONTEXT = Symbol("navigation-menu");
7
+
8
+ interface Props {
9
+ value?: string;
10
+ className?: string;
11
+ children?: Snippet;
12
+ }
13
+
14
+ let {
15
+ value = "",
16
+ className = "",
17
+ children,
18
+ ...restProps
19
+ }: Props = $props();
20
+
21
+ let contentElement = $state<HTMLElement | null>(null);
22
+ let parentItem = $state<HTMLElement | null>(null);
23
+
24
+ const context = getContext<{
25
+ activeItem: string | null;
26
+ setActiveItem: (item: string | null) => void;
27
+ isMobile: boolean;
28
+ }>(NAVIGATION_MENU_CONTEXT);
29
+
30
+ const isActive = $derived(context?.activeItem === value);
31
+
32
+ function handleKeydown(event: KeyboardEvent) {
33
+ if (event.key === "Escape") {
34
+ event.preventDefault();
35
+ context?.setActiveItem(null);
36
+ const trigger = parentItem?.querySelector('[data-navigation-menu-trigger]') as HTMLElement;
37
+ trigger?.focus();
38
+ }
39
+ }
40
+
41
+ function handleClickOutside(event: MouseEvent) {
42
+ if (
43
+ contentElement &&
44
+ !contentElement.contains(event.target as Node) &&
45
+ parentItem &&
46
+ !parentItem.contains(event.target as Node)
47
+ ) {
48
+ context?.setActiveItem(null);
49
+ }
50
+ }
51
+
52
+ onMount(() => {
53
+ if (contentElement) {
54
+ parentItem = contentElement.closest('[data-navigation-menu-item]') as HTMLElement;
55
+ }
56
+ if (isActive) {
57
+ document.addEventListener("mousedown", handleClickOutside);
58
+ }
59
+ });
60
+
61
+ $effect(() => {
62
+ if (isActive) {
63
+ document.addEventListener("mousedown", handleClickOutside);
64
+ return () => {
65
+ document.removeEventListener("mousedown", handleClickOutside);
66
+ };
67
+ }
68
+ });
69
+ </script>
70
+
71
+ {#if isActive}
72
+ <div
73
+ bind:this={contentElement}
74
+ class="absolute left-0 top-full mt-2 bg-input rounded-lg shadow-lg border border-border p-4 z-dropdown min-w-[200px] transition-all duration-200 ease-in-out {className}"
75
+ role="menu"
76
+ onkeydown={handleKeydown}
77
+ data-navigation-menu-content
78
+ tabindex="-1"
79
+ {...restProps}
80
+ >
81
+ {@render children?.()}
82
+ </div>
83
+ {/if}
@@ -0,0 +1,9 @@
1
+ import type { Snippet } from "svelte";
2
+ interface Props {
3
+ value?: string;
4
+ className?: string;
5
+ children?: Snippet;
6
+ }
7
+ declare const NavigationMenuContent: import("svelte").Component<Props, {}, "">;
8
+ type NavigationMenuContent = ReturnType<typeof NavigationMenuContent>;
9
+ export default NavigationMenuContent;
@@ -0,0 +1,36 @@
1
+ <script lang="ts">
2
+ import type { Snippet } from "svelte";
3
+ import { getContext } from "svelte";
4
+
5
+ const NAVIGATION_MENU_CONTEXT = Symbol("navigation-menu");
6
+
7
+ interface Props {
8
+ value?: string;
9
+ className?: string;
10
+ children?: Snippet;
11
+ }
12
+
13
+ let {
14
+ value = "",
15
+ className = "",
16
+ children,
17
+ ...restProps
18
+ }: Props = $props();
19
+
20
+ const context = getContext<{
21
+ activeItem: string | null;
22
+ setActiveItem: (item: string | null) => void;
23
+ }>(NAVIGATION_MENU_CONTEXT);
24
+
25
+ const isActive = $derived(context?.activeItem === value);
26
+ </script>
27
+
28
+ <li
29
+ class="relative {className}"
30
+ role="none"
31
+ data-navigation-menu-item
32
+ data-active={isActive}
33
+ {...restProps}
34
+ >
35
+ {@render children?.()}
36
+ </li>
@@ -0,0 +1,9 @@
1
+ import type { Snippet } from "svelte";
2
+ interface Props {
3
+ value?: string;
4
+ className?: string;
5
+ children?: Snippet;
6
+ }
7
+ declare const NavigationMenuItem: import("svelte").Component<Props, {}, "">;
8
+ type NavigationMenuItem = ReturnType<typeof NavigationMenuItem>;
9
+ export default NavigationMenuItem;
@@ -0,0 +1,53 @@
1
+ <script lang="ts">
2
+ import type { Snippet } from "svelte";
3
+ import { getContext } from "svelte";
4
+
5
+ const NAVIGATION_MENU_CONTEXT = Symbol("navigation-menu");
6
+
7
+ interface Props {
8
+ href?: string;
9
+ asChild?: boolean;
10
+ className?: string;
11
+ children?: Snippet;
12
+ }
13
+
14
+ let {
15
+ href = "#",
16
+ asChild = false,
17
+ className = "",
18
+ children,
19
+ ...restProps
20
+ }: Props = $props();
21
+
22
+ const context = getContext<{
23
+ setActiveItem: (item: string | null) => void;
24
+ }>(NAVIGATION_MENU_CONTEXT);
25
+
26
+ function handleClick() {
27
+ context?.setActiveItem(null);
28
+ }
29
+
30
+ const linkClasses =
31
+ "block px-4 py-2 text-sm text-headline hover:bg-base-100 rounded-md transition-colors focus:outline-none focus:ring-2 focus:ring-brand-500 focus:ring-offset-2 no-underline {className}";
32
+ </script>
33
+
34
+ {#if asChild}
35
+ <div
36
+ class={linkClasses}
37
+ onclick={handleClick}
38
+ data-navigation-menu-link
39
+ {...restProps}
40
+ >
41
+ {@render children?.()}
42
+ </div>
43
+ {:else}
44
+ <a
45
+ {href}
46
+ class={linkClasses}
47
+ onclick={handleClick}
48
+ data-navigation-menu-link
49
+ {...restProps}
50
+ >
51
+ {@render children?.()}
52
+ </a>
53
+ {/if}
@@ -0,0 +1,10 @@
1
+ import type { Snippet } from "svelte";
2
+ interface Props {
3
+ href?: string;
4
+ asChild?: boolean;
5
+ className?: string;
6
+ children?: Snippet;
7
+ }
8
+ declare const NavigationMenuLink: import("svelte").Component<Props, {}, "">;
9
+ type NavigationMenuLink = ReturnType<typeof NavigationMenuLink>;
10
+ export default NavigationMenuLink;
@@ -0,0 +1,31 @@
1
+ <script lang="ts">
2
+ import type { Snippet } from "svelte";
3
+ import { getContext } from "svelte";
4
+
5
+ const NAVIGATION_MENU_CONTEXT = Symbol("navigation-menu");
6
+
7
+ interface Props {
8
+ className?: string;
9
+ children?: Snippet;
10
+ }
11
+
12
+ let {
13
+ className = "",
14
+ children,
15
+ ...restProps
16
+ }: Props = $props();
17
+
18
+ const context = getContext<{
19
+ isMobile: boolean;
20
+ }>(NAVIGATION_MENU_CONTEXT);
21
+ </script>
22
+
23
+ <ul
24
+ class="flex flex-row items-center gap-1 list-none m-0 p-0 {className}"
25
+ role="menubar"
26
+ aria-orientation="horizontal"
27
+ data-navigation-menu-list
28
+ {...restProps}
29
+ >
30
+ {@render children?.()}
31
+ </ul>
@@ -0,0 +1,8 @@
1
+ import type { Snippet } from "svelte";
2
+ interface Props {
3
+ className?: string;
4
+ children?: Snippet;
5
+ }
6
+ declare const NavigationMenuList: import("svelte").Component<Props, {}, "">;
7
+ type NavigationMenuList = ReturnType<typeof NavigationMenuList>;
8
+ export default NavigationMenuList;
@@ -0,0 +1,81 @@
1
+ <script lang="ts">
2
+ import type { Snippet } from "svelte";
3
+ import { getContext } from "svelte";
4
+
5
+ const NAVIGATION_MENU_CONTEXT = Symbol("navigation-menu");
6
+
7
+ interface Props {
8
+ value?: string;
9
+ className?: string;
10
+ children?: Snippet;
11
+ }
12
+
13
+ let {
14
+ value = "",
15
+ className = "",
16
+ children,
17
+ ...restProps
18
+ }: Props = $props();
19
+
20
+ let triggerElement = $state<HTMLElement | null>(null);
21
+
22
+ const context = getContext<{
23
+ activeItem: string | null;
24
+ setActiveItem: (item: string | null) => void;
25
+ isMobile: boolean;
26
+ }>(NAVIGATION_MENU_CONTEXT);
27
+
28
+ const isActive = $derived(context?.activeItem === value);
29
+
30
+ function handleClick() {
31
+ if (context) {
32
+ if (isActive) {
33
+ context.setActiveItem(null);
34
+ } else {
35
+ context.setActiveItem(value);
36
+ }
37
+ }
38
+ }
39
+
40
+ function handleKeydown(event: KeyboardEvent) {
41
+ if (event.key === "Enter" || event.key === " ") {
42
+ event.preventDefault();
43
+ handleClick();
44
+ } else if (event.key === "Escape" && isActive) {
45
+ event.preventDefault();
46
+ context?.setActiveItem(null);
47
+ } else if (event.key === "ArrowDown" && !isActive) {
48
+ event.preventDefault();
49
+ handleClick();
50
+ }
51
+ }
52
+ </script>
53
+
54
+ <button
55
+ bind:this={triggerElement}
56
+ type="button"
57
+ class="inline-flex items-center justify-center gap-2 px-4 py-2 text-sm font-medium text-headline bg-transparent hover:bg-base-100 rounded-lg transition-colors focus:outline-none focus:ring-2 focus:ring-brand-500 focus:ring-offset-2 {className}"
58
+ aria-expanded={isActive ? 'true' : 'false'}
59
+ aria-haspopup="true"
60
+ onclick={handleClick}
61
+ onkeydown={handleKeydown}
62
+ data-navigation-menu-trigger
63
+ data-active={isActive}
64
+ {...restProps}
65
+ >
66
+ {@render children?.()}
67
+ <svg
68
+ class="ml-1 h-4 w-4 transition-transform {isActive ? 'rotate-180' : ''}"
69
+ fill="none"
70
+ stroke="currentColor"
71
+ viewBox="0 0 24 24"
72
+ aria-hidden="true"
73
+ >
74
+ <path
75
+ stroke-linecap="round"
76
+ stroke-linejoin="round"
77
+ stroke-width="2"
78
+ d="M19 9l-7 7-7-7"
79
+ />
80
+ </svg>
81
+ </button>
@@ -0,0 +1,9 @@
1
+ import type { Snippet } from "svelte";
2
+ interface Props {
3
+ value?: string;
4
+ className?: string;
5
+ children?: Snippet;
6
+ }
7
+ declare const NavigationMenuTrigger: import("svelte").Component<Props, {}, "">;
8
+ type NavigationMenuTrigger = ReturnType<typeof NavigationMenuTrigger>;
9
+ export default NavigationMenuTrigger;