zabi-components 5.0.21 → 6.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.
Files changed (89) hide show
  1. package/README.md +42 -44
  2. package/THEME.md +473 -0
  3. package/THEMING.md +248 -0
  4. package/dist/atoms/Card.svelte +40 -67
  5. package/dist/atoms/Card.svelte.d.ts +3 -3
  6. package/dist/atoms/CardContent.svelte +1 -1
  7. package/dist/atoms/CardHeader.svelte +10 -1
  8. package/dist/atoms/CardHeader.svelte.d.ts +3 -0
  9. package/dist/atoms/Checkbox.svelte +1 -7
  10. package/dist/atoms/CodeBlock.svelte +7 -7
  11. package/dist/atoms/ColorPicker.svelte +81 -73
  12. package/dist/atoms/Input.svelte +16 -12
  13. package/dist/atoms/Input.svelte.d.ts +2 -0
  14. package/dist/atoms/List.svelte +47 -0
  15. package/dist/atoms/List.svelte.d.ts +19 -0
  16. package/dist/atoms/ListItem.svelte +148 -0
  17. package/dist/atoms/ListItem.svelte.d.ts +35 -0
  18. package/dist/atoms/Progress.svelte +4 -6
  19. package/dist/atoms/Select.svelte +65 -20
  20. package/dist/atoms/Select.svelte.d.ts +13 -1
  21. package/dist/atoms/Textarea.svelte +13 -11
  22. package/dist/atoms/Textarea.svelte.d.ts +1 -0
  23. package/dist/atoms/Toast.svelte +1 -1
  24. package/dist/atoms/Toggle.svelte +1 -7
  25. package/dist/atoms/Tooltip.svelte +8 -15
  26. package/dist/atoms/index.d.ts +2 -0
  27. package/dist/atoms/index.js +2 -0
  28. package/dist/components/atoms/index.d.ts +2 -0
  29. package/dist/components/atoms/index.d.ts.map +1 -1
  30. package/dist/components/index.d.ts +4 -1
  31. package/dist/components/index.d.ts.map +1 -1
  32. package/dist/components/molecules/index.d.ts +0 -1
  33. package/dist/components/molecules/index.d.ts.map +1 -1
  34. package/dist/components/molecules/navigation-menu-context.d.ts +7 -0
  35. package/dist/components/molecules/navigation-menu-context.d.ts.map +1 -0
  36. package/dist/components/organisms/index.d.ts +2 -1
  37. package/dist/components/organisms/index.d.ts.map +1 -1
  38. package/dist/index.d.ts +4 -1
  39. package/dist/index.js +5 -9
  40. package/dist/lib/showcase/components-catalog.d.ts +3 -0
  41. package/dist/lib/showcase/components-catalog.d.ts.map +1 -0
  42. package/dist/lib/showcase/components-showcase-constants.d.ts +63 -0
  43. package/dist/lib/showcase/components-showcase-constants.d.ts.map +1 -0
  44. package/dist/lib/showcase/docs-sidebar-helpers.d.ts +15 -0
  45. package/dist/lib/showcase/docs-sidebar-helpers.d.ts.map +1 -0
  46. package/dist/molecules/Alert.svelte +9 -4
  47. package/dist/molecules/ComponentDemo.svelte +53 -50
  48. package/dist/molecules/ContactForm.svelte +113 -76
  49. package/dist/molecules/ContactForm.svelte.d.ts +1 -4
  50. package/dist/molecules/Dropdown.svelte +4 -2
  51. package/dist/molecules/ImageUpload.svelte +27 -4
  52. package/dist/molecules/ImageUpload.svelte.d.ts +1 -0
  53. package/dist/molecules/Modal.svelte +46 -45
  54. package/dist/molecules/NavigationMenu.svelte +7 -10
  55. package/dist/molecules/NavigationMenuContent.svelte +9 -9
  56. package/dist/molecules/NavigationMenuItem.svelte +7 -6
  57. package/dist/molecules/NavigationMenuLink.svelte +8 -6
  58. package/dist/molecules/NavigationMenuList.svelte +0 -7
  59. package/dist/molecules/NavigationMenuTrigger.svelte +8 -11
  60. package/dist/molecules/Section.svelte +12 -12
  61. package/dist/molecules/SlideUp.svelte +32 -2
  62. package/dist/molecules/Tabs.svelte +74 -7
  63. package/dist/molecules/index.d.ts +0 -1
  64. package/dist/molecules/index.js +0 -1
  65. package/dist/molecules/navigation-menu-context.d.ts +6 -0
  66. package/dist/molecules/navigation-menu-context.js +1 -0
  67. package/dist/organisms/Navbar.svelte +170 -53
  68. package/dist/organisms/Navbar.svelte.d.ts +31 -4
  69. package/dist/organisms/SidebarNavigation.svelte +464 -0
  70. package/dist/organisms/SidebarNavigation.svelte.d.ts +49 -0
  71. package/dist/organisms/SidebarPanel.svelte +175 -0
  72. package/dist/organisms/SidebarPanel.svelte.d.ts +32 -0
  73. package/dist/organisms/index.d.ts +2 -1
  74. package/dist/organisms/index.js +2 -1
  75. package/dist/types/page.types.d.ts +32 -0
  76. package/dist/types/page.types.d.ts.map +1 -0
  77. package/dist/types/variants.ts +76 -0
  78. package/dist/zabi-components-colors.css +347 -324
  79. package/dist/zabi-components-theme-dark-only.css +159 -151
  80. package/dist/zabi-components-theme-dark.css +159 -151
  81. package/dist/zabi-components-theme-only.css +245 -230
  82. package/dist/zabi-components-theme.css +245 -230
  83. package/dist/zabi-components.css +722 -84
  84. package/docs/theme-imports.md +112 -0
  85. package/package.json +20 -9
  86. package/dist/molecules/Sidebar.svelte +0 -324
  87. package/dist/molecules/Sidebar.svelte.d.ts +0 -30
  88. package/dist/organisms/Navigation.svelte +0 -116
  89. package/dist/organisms/Navigation.svelte.d.ts +0 -20
@@ -1,22 +1,52 @@
1
1
  <script lang="ts">
2
2
  import ThemeToggle from "../atoms/ThemeToggle.svelte";
3
+ import type { Component, Snippet } from "svelte";
4
+
5
+ /** Link shown in the built-in nav list (when not using the `nav` snippet). */
6
+ export interface NavbarNavItem {
7
+ label: string;
8
+ href: string;
9
+ icon?: Component<{ size?: number; class?: string }>;
10
+ iconFilled?: Component<{ size?: number; class?: string }>;
11
+ }
3
12
 
4
13
  interface Props {
5
14
  brand?: string;
15
+ /** When set, the brand is a link (use `""` to show text only). */
16
+ brandHref?: string;
17
+ /** Accessible name for the landmark when you have more than one `nav`. */
18
+ ariaLabel?: string;
6
19
  showThemeToggle?: boolean;
7
20
  className?: string;
21
+ /**
22
+ * When true, renders only the built-in link list (or `nav` snippet) inside a `nav` landmark.
23
+ * Use for headers that are not the full chrome bar.
24
+ */
25
+ embedded?: boolean;
26
+ /** Inline nav links; ignored when the `nav` snippet is provided. */
27
+ items?: NavbarNavItem[];
28
+ navVariant?: "header" | "sidebar";
29
+ currentPath?: string;
30
+ preventNavigation?: boolean;
8
31
  onclick?: (event: Event) => void;
9
32
  }
10
33
 
11
34
  let {
12
35
  brand = "",
36
+ brandHref,
37
+ ariaLabel,
13
38
  showThemeToggle = true,
14
39
  className = "",
15
- children,
40
+ embedded = false,
41
+ items = [],
42
+ navVariant = "header",
43
+ currentPath = "",
44
+ preventNavigation = false,
45
+ onclick,
16
46
  nav,
17
47
  actions,
18
48
  ...restProps
19
- }: Props & { children?: any; nav?: any; actions?: any } = $props();
49
+ }: Props & { nav?: Snippet; actions?: Snippet } = $props();
20
50
 
21
51
  let isMenuOpen = $state(false);
22
52
 
@@ -24,69 +54,156 @@
24
54
  isMenuOpen = !isMenuOpen;
25
55
  }
26
56
 
27
- function handleBrandClick() {
57
+ function handleNavLinkClick(event: MouseEvent) {
58
+ if (preventNavigation) {
59
+ event.preventDefault();
60
+ }
61
+ if (onclick) {
62
+ onclick(event);
63
+ }
64
+ }
65
+
66
+ const ulClasses = $derived(() => {
67
+ return navVariant === "sidebar"
68
+ ? "flex flex-col gap-1"
69
+ : "flex flex-col gap-1 md:flex-row md:items-center md:justify-between";
70
+ });
71
+
72
+ function getNavItemClasses(): string {
73
+ 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";
74
+ }
75
+
76
+ function getIconContainerClasses(): string {
77
+ return "group/nav-item flex flex-col items-center justify-center overflow-clip relative rounded-[20px] shrink-0 text-nav-menu-item transition-colors duration-200 outline-none hover:bg-nav-menu-hover hover:text-nav-menu-item-hover aria-[current=page]:bg-nav-menu-active aria-[current=page]:text-nav-menu-item-active focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-nav-menu-focus";
78
+ }
79
+
80
+ function getStateLayerClasses(): string {
81
+ return "box-border flex gap-1 h-10 items-center px-4 py-2 relative shrink-0";
82
+ }
83
+
84
+ function getLabelClasses(): string {
85
+ return "font-medium leading-4 relative shrink-0 text-center text-nowrap tracking-[0.5px] whitespace-pre text-xs text-inherit";
86
+ }
87
+
88
+ function getIconWrapperClasses(): string {
89
+ return "overflow-clip relative shrink-0 size-4 text-current";
28
90
  }
29
91
  </script>
30
92
 
31
- <nav
32
- class="bg-base-50 border-b border-border sticky top-0 z-50 {className}"
33
- {...restProps}
34
- >
35
- <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
36
- <div class="flex justify-between items-center h-16">
37
- <div class="shrink-0">
38
- <button
39
- type="button"
40
- class="text-xl font-bold text-headline"
41
- onclick={handleBrandClick}
93
+ {#snippet defaultNavList()}
94
+ <ul class="{ulClasses()} list-none m-0 p-0">
95
+ {#each items as item}
96
+ {@const isActive = currentPath === item.href}
97
+ <li class={getNavItemClasses()}>
98
+ <a
99
+ href={item.href}
100
+ class={getIconContainerClasses()}
101
+ onclick={handleNavLinkClick}
102
+ aria-current={isActive ? "page" : undefined}
42
103
  >
43
- {brand}
44
- </button>
45
- </div>
46
-
47
- <div class="hidden md:block">
48
- <div class="ml-10 flex items-baseline space-x-4">
49
- {@render nav?.()}
50
- </div>
51
- </div>
104
+ <div class={getStateLayerClasses()}>
105
+ {#if item.iconFilled && isActive}
106
+ {@const Icon = item.iconFilled}
107
+ <div class={getIconWrapperClasses()}>
108
+ <Icon size={16} class="w-4 h-4" />
109
+ </div>
110
+ {:else if item.icon}
111
+ {@const Icon = item.icon}
112
+ <div class={getIconWrapperClasses()}>
113
+ <Icon size={16} class="w-4 h-4" />
114
+ </div>
115
+ {/if}
116
+ <p class={getLabelClasses()}>
117
+ {item.label}
118
+ </p>
119
+ </div>
120
+ </a>
121
+ </li>
122
+ {/each}
123
+ </ul>
124
+ {/snippet}
52
125
 
53
- <div class="hidden md:block">
54
- <div class="ml-4 flex items-center space-x-4">
55
- {@render actions?.()}
56
- {#if showThemeToggle}
57
- <ThemeToggle />
126
+ {#if embedded}
127
+ <nav class={className} aria-label={ariaLabel} {...restProps}>
128
+ {#if nav}
129
+ {@render nav()}
130
+ {:else}
131
+ {@render defaultNavList()}
132
+ {/if}
133
+ </nav>
134
+ {:else}
135
+ <nav
136
+ class="bg-base-50 border-b border-border sticky top-0 z-50 {className}"
137
+ aria-label={ariaLabel}
138
+ {...restProps}
139
+ >
140
+ <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
141
+ <div class="flex justify-between items-center h-16">
142
+ <div class="shrink-0">
143
+ {#if brandHref}
144
+ <a
145
+ href={brandHref}
146
+ class="text-xl font-bold text-headline hover:opacity-90 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-brand-600"
147
+ >
148
+ {brand}
149
+ </a>
150
+ {:else}
151
+ <span class="text-xl font-bold text-headline">{brand}</span>
58
152
  {/if}
59
153
  </div>
60
- </div>
61
154
 
62
- <div class="md:hidden">
63
- <button
64
- type="button"
65
- class="text-description hover:text-body"
66
- onclick={toggleMenu}
67
- aria-label="Toggle menu"
68
- >
69
- <span class="text-2xl">☰</span>
70
- </button>
71
- </div>
72
- </div>
155
+ <div class="hidden md:block">
156
+ <div class="ml-10 flex items-baseline space-x-4">
157
+ {#if nav}
158
+ {@render nav()}
159
+ {:else if items.length > 0}
160
+ {@render defaultNavList()}
161
+ {/if}
162
+ </div>
163
+ </div>
73
164
 
74
- {#if isMenuOpen}
75
- <div class="md:hidden">
76
- <div
77
- class="px-2 pt-2 pb-3 space-y-1 sm:px-3 border-t border-border"
78
- >
79
- {@render nav?.()}
80
- <div class="pt-4">
165
+ <div class="hidden md:block">
166
+ <div class="ml-4 flex items-center space-x-4">
81
167
  {@render actions?.()}
82
168
  {#if showThemeToggle}
83
- <div class="mt-2">
84
- <ThemeToggle />
85
- </div>
169
+ <ThemeToggle />
86
170
  {/if}
87
171
  </div>
88
172
  </div>
173
+
174
+ <div class="md:hidden">
175
+ <button
176
+ type="button"
177
+ class="cursor-pointer text-description hover:text-body"
178
+ onclick={toggleMenu}
179
+ aria-label="Toggle menu"
180
+ >
181
+ <span class="text-2xl">☰</span>
182
+ </button>
183
+ </div>
89
184
  </div>
90
- {/if}
91
- </div>
92
- </nav>
185
+
186
+ {#if isMenuOpen}
187
+ <div class="md:hidden">
188
+ <div
189
+ class="px-2 pt-2 pb-3 space-y-1 sm:px-3 border-t border-border"
190
+ >
191
+ {#if nav}
192
+ {@render nav()}
193
+ {:else if items.length > 0}
194
+ {@render defaultNavList()}
195
+ {/if}
196
+ <div class="pt-4">
197
+ {@render actions?.()}
198
+ {#if showThemeToggle}
199
+ <div class="mt-2">
200
+ <ThemeToggle />
201
+ </div>
202
+ {/if}
203
+ </div>
204
+ </div>
205
+ </div>
206
+ {/if}
207
+ </div>
208
+ </nav>
209
+ {/if}
@@ -1,14 +1,41 @@
1
+ import type { Component, Snippet } from "svelte";
2
+ /** Link shown in the built-in nav list (when not using the `nav` snippet). */
3
+ export interface NavbarNavItem {
4
+ label: string;
5
+ href: string;
6
+ icon?: Component<{
7
+ size?: number;
8
+ class?: string;
9
+ }>;
10
+ iconFilled?: Component<{
11
+ size?: number;
12
+ class?: string;
13
+ }>;
14
+ }
1
15
  interface Props {
2
16
  brand?: string;
17
+ /** When set, the brand is a link (use `""` to show text only). */
18
+ brandHref?: string;
19
+ /** Accessible name for the landmark when you have more than one `nav`. */
20
+ ariaLabel?: string;
3
21
  showThemeToggle?: boolean;
4
22
  className?: string;
23
+ /**
24
+ * When true, renders only the built-in link list (or `nav` snippet) inside a `nav` landmark.
25
+ * Use for headers that are not the full chrome bar.
26
+ */
27
+ embedded?: boolean;
28
+ /** Inline nav links; ignored when the `nav` snippet is provided. */
29
+ items?: NavbarNavItem[];
30
+ navVariant?: "header" | "sidebar";
31
+ currentPath?: string;
32
+ preventNavigation?: boolean;
5
33
  onclick?: (event: Event) => void;
6
34
  }
7
35
  type $$ComponentProps = Props & {
8
- children?: any;
9
- nav?: any;
10
- actions?: any;
36
+ nav?: Snippet;
37
+ actions?: Snippet;
11
38
  };
12
- declare const Navbar: import("svelte").Component<$$ComponentProps, {}, "">;
39
+ declare const Navbar: Component<$$ComponentProps, {}, "">;
13
40
  type Navbar = ReturnType<typeof Navbar>;
14
41
  export default Navbar;