zabi-components 5.0.20 → 5.0.21
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 +354 -81
- package/dist/atoms/Button.svelte +1 -1
- package/dist/atoms/IconButton.svelte +88 -0
- package/dist/atoms/IconButton.svelte.d.ts +21 -0
- package/dist/atoms/Select.svelte +96 -6
- package/dist/atoms/Select.svelte.d.ts +10 -0
- package/dist/atoms/index.d.ts +1 -0
- package/dist/atoms/index.js +1 -0
- package/dist/components/atoms/index.d.ts +1 -0
- package/dist/components/atoms/index.d.ts.map +1 -1
- package/dist/components/molecules/index.d.ts +1 -0
- package/dist/components/molecules/index.d.ts.map +1 -1
- package/dist/molecules/Section.svelte +158 -0
- package/dist/molecules/Section.svelte.d.ts +27 -0
- package/dist/molecules/index.d.ts +1 -0
- package/dist/molecules/index.js +1 -0
- package/dist/organisms/Navigation.svelte +2 -2
- package/dist/zabi-components.css +110 -0
- package/package.json +3 -5
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { Snippet } from "svelte";
|
|
3
|
+
import type { ButtonVariant, SizeVariant } from "../../types/variants.js";
|
|
4
|
+
|
|
5
|
+
interface Props {
|
|
6
|
+
/** Visual style variant. */
|
|
7
|
+
variant?: ButtonVariant;
|
|
8
|
+
/** Size variant controlling padding and radius. */
|
|
9
|
+
size?: SizeVariant;
|
|
10
|
+
/** Whether the button is disabled. */
|
|
11
|
+
disabled?: boolean;
|
|
12
|
+
/** Button type attribute. */
|
|
13
|
+
type?: "button" | "submit" | "reset";
|
|
14
|
+
/** Accessible label for icon-only buttons. */
|
|
15
|
+
label?: string;
|
|
16
|
+
/** Click handler for native click events. */
|
|
17
|
+
onclick?: (event: MouseEvent) => void;
|
|
18
|
+
/** Icon content. */
|
|
19
|
+
children?: Snippet;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
let {
|
|
23
|
+
variant = "primary",
|
|
24
|
+
size = "md",
|
|
25
|
+
disabled = false,
|
|
26
|
+
type = "button",
|
|
27
|
+
label = "",
|
|
28
|
+
onclick,
|
|
29
|
+
children,
|
|
30
|
+
...restProps
|
|
31
|
+
}: Props = $props();
|
|
32
|
+
|
|
33
|
+
const sizeClass = $derived(() => {
|
|
34
|
+
if (size === "sm") {
|
|
35
|
+
return {
|
|
36
|
+
padding: "p-2",
|
|
37
|
+
radius: "rounded-md",
|
|
38
|
+
};
|
|
39
|
+
} else if (size === "lg") {
|
|
40
|
+
return {
|
|
41
|
+
padding: "p-3",
|
|
42
|
+
radius: "rounded-xl",
|
|
43
|
+
};
|
|
44
|
+
} else {
|
|
45
|
+
return {
|
|
46
|
+
padding: "p-2.5",
|
|
47
|
+
radius: "rounded-lg",
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
const variantClass = $derived(() => {
|
|
53
|
+
return variant === "primary"
|
|
54
|
+
? "bg-action-primary text-action-primary hover:bg-action-primary-hover active:bg-action-primary-active focus:ring-2 focus:ring-brand-500 focus:ring-offset-2"
|
|
55
|
+
: variant === "secondary"
|
|
56
|
+
? "bg-action-secondary text-headline hover:bg-action-secondary-hover active:bg-action-secondary-active focus:ring-2 focus:ring-brand-500 focus:ring-offset-2"
|
|
57
|
+
: variant === "danger"
|
|
58
|
+
? "bg-action-danger text-inverse hover:bg-action-danger-hover active:bg-action-danger-active focus:ring-2 focus:ring-red-500 focus:ring-offset-2"
|
|
59
|
+
: variant === "ghost"
|
|
60
|
+
? "bg-transparent text-headline hover:bg-base-100 active:bg-base-200 focus:ring-2 focus:ring-base-500 focus:ring-offset-2 disabled:text-disabled"
|
|
61
|
+
: variant === "outline"
|
|
62
|
+
? "bg-transparent border-2 border-action-primary text-headline hover:bg-action-secondary hover:text-action-primary active:bg-action-primary-active active:text-action-primary focus:ring-2 focus:ring-brand-500 focus:ring-offset-2 disabled:border-disabled disabled:text-disabled"
|
|
63
|
+
: variant === "link"
|
|
64
|
+
? "text-brand-700 active:text-brand-700 underline-offset-4 hover:underline focus:ring-2 focus:ring-brand-500 focus:ring-offset-2 disabled:text-disabled disabled:no-underline"
|
|
65
|
+
: "bg-action-primary text-action-primary hover:bg-action-primary-hover active:bg-action-primary-active focus:ring-2 focus:ring-brand-500 focus:ring-offset-2";
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
const buttonClasses = $derived(() => {
|
|
69
|
+
const sizeStyles = sizeClass();
|
|
70
|
+
const baseClasses =
|
|
71
|
+
"inline-flex items-center justify-center transition-all duration-200 cursor-pointer disabled:opacity-50 disabled:cursor-not-allowed focus:outline-none";
|
|
72
|
+
|
|
73
|
+
return `${baseClasses} ${sizeStyles.padding} ${sizeStyles.radius} ${variantClass()}`.trim();
|
|
74
|
+
});
|
|
75
|
+
</script>
|
|
76
|
+
|
|
77
|
+
<button
|
|
78
|
+
{type}
|
|
79
|
+
class={buttonClasses()}
|
|
80
|
+
{disabled}
|
|
81
|
+
{onclick}
|
|
82
|
+
aria-label={label || undefined}
|
|
83
|
+
{...restProps}
|
|
84
|
+
>
|
|
85
|
+
{#if children}
|
|
86
|
+
{@render children()}
|
|
87
|
+
{/if}
|
|
88
|
+
</button>
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { Snippet } from "svelte";
|
|
2
|
+
import type { ButtonVariant, SizeVariant } from "../../types/variants.js";
|
|
3
|
+
interface Props {
|
|
4
|
+
/** Visual style variant. */
|
|
5
|
+
variant?: ButtonVariant;
|
|
6
|
+
/** Size variant controlling padding and radius. */
|
|
7
|
+
size?: SizeVariant;
|
|
8
|
+
/** Whether the button is disabled. */
|
|
9
|
+
disabled?: boolean;
|
|
10
|
+
/** Button type attribute. */
|
|
11
|
+
type?: "button" | "submit" | "reset";
|
|
12
|
+
/** Accessible label for icon-only buttons. */
|
|
13
|
+
label?: string;
|
|
14
|
+
/** Click handler for native click events. */
|
|
15
|
+
onclick?: (event: MouseEvent) => void;
|
|
16
|
+
/** Icon content. */
|
|
17
|
+
children?: Snippet;
|
|
18
|
+
}
|
|
19
|
+
declare const IconButton: import("svelte").Component<Props, {}, "">;
|
|
20
|
+
type IconButton = ReturnType<typeof IconButton>;
|
|
21
|
+
export default IconButton;
|
package/dist/atoms/Select.svelte
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import Dropdown from "../molecules/Dropdown.svelte";
|
|
3
|
+
import Button from "./Button.svelte";
|
|
3
4
|
import {
|
|
4
5
|
ChevronDown,
|
|
5
6
|
CheckCircle,
|
|
@@ -22,6 +23,16 @@
|
|
|
22
23
|
label: string;
|
|
23
24
|
disabled?: boolean;
|
|
24
25
|
}>;
|
|
26
|
+
/** Enables the search input inside the dropdown. */
|
|
27
|
+
searchable?: boolean;
|
|
28
|
+
/** Placeholder for the search input. */
|
|
29
|
+
searchPlaceholder?: string;
|
|
30
|
+
/** Max height for the options list (supports any valid CSS length). */
|
|
31
|
+
maxMenuHeight?: string;
|
|
32
|
+
/** Width for the dropdown menu (supports any valid CSS length). */
|
|
33
|
+
menuWidth?: string;
|
|
34
|
+
/** Message shown when no options match the search. */
|
|
35
|
+
noResultsText?: string;
|
|
25
36
|
placeholder?: string;
|
|
26
37
|
label?: string;
|
|
27
38
|
disabled?: boolean;
|
|
@@ -34,6 +45,11 @@
|
|
|
34
45
|
let {
|
|
35
46
|
value = undefined,
|
|
36
47
|
options = [],
|
|
48
|
+
searchable = true,
|
|
49
|
+
searchPlaceholder = "Search options",
|
|
50
|
+
maxMenuHeight = "60vh",
|
|
51
|
+
menuWidth = "100%",
|
|
52
|
+
noResultsText = "No results found",
|
|
37
53
|
placeholder = "Select an option",
|
|
38
54
|
label = "",
|
|
39
55
|
disabled = false,
|
|
@@ -46,6 +62,7 @@
|
|
|
46
62
|
|
|
47
63
|
let isOpen = $state(false);
|
|
48
64
|
let selectContainer: HTMLDivElement;
|
|
65
|
+
let searchQuery = $state("");
|
|
49
66
|
|
|
50
67
|
const sizeClass = $derived(() => {
|
|
51
68
|
if (size === "sm") {
|
|
@@ -93,13 +110,13 @@
|
|
|
93
110
|
|
|
94
111
|
const messageClasses = $derived(() => {
|
|
95
112
|
if (variant === "error") {
|
|
96
|
-
return "text-error text-sm mt-1 flex items-center gap-1.5";
|
|
113
|
+
return "text-error text-sm mt-1 flex items-center gap-1.5 w-full";
|
|
97
114
|
} else if (variant === "success") {
|
|
98
|
-
return "text-success text-sm mt-1 flex items-center gap-1.5";
|
|
115
|
+
return "text-success text-sm mt-1 flex items-center gap-1.5 w-full";
|
|
99
116
|
} else if (variant === "warning") {
|
|
100
|
-
return "text-warning text-sm mt-1 flex items-center gap-1.5";
|
|
117
|
+
return "text-warning text-sm mt-1 flex items-center gap-1.5 w-full";
|
|
101
118
|
}
|
|
102
|
-
return "text-description text-sm mt-1 flex items-center gap-1.5";
|
|
119
|
+
return "text-description text-sm mt-1 flex items-center gap-1.5 w-full";
|
|
103
120
|
});
|
|
104
121
|
|
|
105
122
|
const getIcon = $derived(() => {
|
|
@@ -125,6 +142,33 @@
|
|
|
125
142
|
return value === undefined || value === null || value === "";
|
|
126
143
|
});
|
|
127
144
|
|
|
145
|
+
const normalizedOptions = $derived(() => {
|
|
146
|
+
const fallbackOptions = (restProps as { options?: Props["options"] })
|
|
147
|
+
.options;
|
|
148
|
+
return Array.from(options ?? fallbackOptions ?? []);
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
const hasSearchQuery = $derived(() => {
|
|
152
|
+
return searchQuery.trim().length > 0;
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
const filteredOptions = $derived(() => {
|
|
156
|
+
const query = searchQuery.trim().toLowerCase();
|
|
157
|
+
const availableOptions = normalizedOptions();
|
|
158
|
+
if (!searchable || query.length === 0) {
|
|
159
|
+
return availableOptions;
|
|
160
|
+
}
|
|
161
|
+
return availableOptions.filter((option) =>
|
|
162
|
+
option.label.toLowerCase().includes(query),
|
|
163
|
+
);
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
$effect(() => {
|
|
167
|
+
if (!isOpen && searchQuery.length > 0) {
|
|
168
|
+
searchQuery = "";
|
|
169
|
+
}
|
|
170
|
+
});
|
|
171
|
+
|
|
128
172
|
function handleOptionClick(optionValue: string | number) {
|
|
129
173
|
if (disabled) return;
|
|
130
174
|
value = optionValue;
|
|
@@ -179,8 +223,8 @@
|
|
|
179
223
|
{isOpen}
|
|
180
224
|
placement="bottom-start"
|
|
181
225
|
selectedValue={value}
|
|
182
|
-
{options}
|
|
183
226
|
onOptionClick={handleOptionClick}
|
|
227
|
+
ariaLabel="Select options"
|
|
184
228
|
>
|
|
185
229
|
{#snippet trigger()}
|
|
186
230
|
<button
|
|
@@ -194,7 +238,7 @@
|
|
|
194
238
|
aria-describedby={message ? `${selectId}-message` : undefined}
|
|
195
239
|
>
|
|
196
240
|
<span
|
|
197
|
-
class="text-left flex-1 {isEmpty()
|
|
241
|
+
class="text-left flex-1 truncate {isEmpty()
|
|
198
242
|
? 'text-description'
|
|
199
243
|
: 'text-body'}"
|
|
200
244
|
>
|
|
@@ -211,6 +255,52 @@
|
|
|
211
255
|
/>
|
|
212
256
|
</button>
|
|
213
257
|
{/snippet}
|
|
258
|
+
{#snippet children()}
|
|
259
|
+
<div class="px-2 pb-2 pt-1" style:width={menuWidth}>
|
|
260
|
+
{#if searchable}
|
|
261
|
+
<div class="px-1 pb-2">
|
|
262
|
+
<input
|
|
263
|
+
type="text"
|
|
264
|
+
class="w-full rounded-md bg-input hover:bg-input-hover focus:bg-input-focus text-body placeholder:text-description px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-brand-500 disabled:opacity-50 disabled:cursor-not-allowed"
|
|
265
|
+
placeholder={searchPlaceholder}
|
|
266
|
+
bind:value={searchQuery}
|
|
267
|
+
aria-label={searchPlaceholder}
|
|
268
|
+
{disabled}
|
|
269
|
+
/>
|
|
270
|
+
</div>
|
|
271
|
+
{/if}
|
|
272
|
+
<div
|
|
273
|
+
class="overflow-y-auto px-1"
|
|
274
|
+
style:max-height={maxMenuHeight}
|
|
275
|
+
>
|
|
276
|
+
{#if filteredOptions().length > 0}
|
|
277
|
+
{#each filteredOptions() as option (option.value)}
|
|
278
|
+
{@const buttonRestProps = {
|
|
279
|
+
"data-value": String(option.value),
|
|
280
|
+
} as Record<string, string>}
|
|
281
|
+
<div class="w-full my-0.5">
|
|
282
|
+
<Button
|
|
283
|
+
variant={value === option.value
|
|
284
|
+
? "outline"
|
|
285
|
+
: "ghost"}
|
|
286
|
+
size="sm"
|
|
287
|
+
isFullWidth={true}
|
|
288
|
+
disabled={option.disabled}
|
|
289
|
+
onclick={() => handleOptionClick(option.value)}
|
|
290
|
+
{...buttonRestProps}
|
|
291
|
+
>
|
|
292
|
+
{option.label}
|
|
293
|
+
</Button>
|
|
294
|
+
</div>
|
|
295
|
+
{/each}
|
|
296
|
+
{:else if hasSearchQuery()}
|
|
297
|
+
<div class="px-3 py-2 text-sm text-description">
|
|
298
|
+
{noResultsText}
|
|
299
|
+
</div>
|
|
300
|
+
{/if}
|
|
301
|
+
</div>
|
|
302
|
+
</div>
|
|
303
|
+
{/snippet}
|
|
214
304
|
</Dropdown>
|
|
215
305
|
{#if message && variant !== "default"}
|
|
216
306
|
<p id={`${selectId}-message`} class={messageClasses()} role="alert">
|
|
@@ -5,6 +5,16 @@ interface Props {
|
|
|
5
5
|
label: string;
|
|
6
6
|
disabled?: boolean;
|
|
7
7
|
}>;
|
|
8
|
+
/** Enables the search input inside the dropdown. */
|
|
9
|
+
searchable?: boolean;
|
|
10
|
+
/** Placeholder for the search input. */
|
|
11
|
+
searchPlaceholder?: string;
|
|
12
|
+
/** Max height for the options list (supports any valid CSS length). */
|
|
13
|
+
maxMenuHeight?: string;
|
|
14
|
+
/** Width for the dropdown menu (supports any valid CSS length). */
|
|
15
|
+
menuWidth?: string;
|
|
16
|
+
/** Message shown when no options match the search. */
|
|
17
|
+
noResultsText?: string;
|
|
8
18
|
placeholder?: string;
|
|
9
19
|
label?: string;
|
|
10
20
|
disabled?: boolean;
|
package/dist/atoms/index.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export { default as Toggle } from './Toggle.svelte';
|
|
2
2
|
export { default as Badge } from './Badge.svelte';
|
|
3
3
|
export { default as Button } from './Button.svelte';
|
|
4
|
+
export { default as IconButton } from './IconButton.svelte';
|
|
4
5
|
export { default as Card } from './Card.svelte';
|
|
5
6
|
export { default as CardHeader } from './CardHeader.svelte';
|
|
6
7
|
export { default as CardContent } from './CardContent.svelte';
|
package/dist/atoms/index.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export { default as Toggle } from './Toggle.svelte';
|
|
2
2
|
export { default as Badge } from './Badge.svelte';
|
|
3
3
|
export { default as Button } from './Button.svelte';
|
|
4
|
+
export { default as IconButton } from './IconButton.svelte';
|
|
4
5
|
export { default as Card } from './Card.svelte';
|
|
5
6
|
export { default as CardHeader } from './CardHeader.svelte';
|
|
6
7
|
export { default as CardContent } from './CardContent.svelte';
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export { default as Toggle } from './Toggle.svelte';
|
|
2
2
|
export { default as Badge } from './Badge.svelte';
|
|
3
3
|
export { default as Button } from './Button.svelte';
|
|
4
|
+
export { default as IconButton } from './IconButton.svelte';
|
|
4
5
|
export { default as Card } from './Card.svelte';
|
|
5
6
|
export { default as CardHeader } from './CardHeader.svelte';
|
|
6
7
|
export { default as CardContent } from './CardContent.svelte';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/atoms/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,MAAM,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,EAAE,OAAO,IAAI,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAClD,OAAO,EAAE,OAAO,IAAI,MAAM,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,EAAE,OAAO,IAAI,IAAI,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,OAAO,IAAI,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAC9D,OAAO,EAAE,OAAO,IAAI,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,EAAE,OAAO,IAAI,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAClD,OAAO,EAAE,OAAO,IAAI,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AACxD,OAAO,EAAE,OAAO,IAAI,MAAM,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAC9D,OAAO,EAAE,OAAO,IAAI,OAAO,EAAE,MAAM,kBAAkB,CAAC;AACtD,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,sBAAsB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/atoms/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,MAAM,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,EAAE,OAAO,IAAI,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAClD,OAAO,EAAE,OAAO,IAAI,MAAM,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,EAAE,OAAO,IAAI,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,EAAE,OAAO,IAAI,IAAI,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,OAAO,IAAI,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAC9D,OAAO,EAAE,OAAO,IAAI,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,EAAE,OAAO,IAAI,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAClD,OAAO,EAAE,OAAO,IAAI,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AACxD,OAAO,EAAE,OAAO,IAAI,MAAM,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAC9D,OAAO,EAAE,OAAO,IAAI,OAAO,EAAE,MAAM,kBAAkB,CAAC;AACtD,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,sBAAsB,CAAC"}
|
|
@@ -11,6 +11,7 @@ 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 Section } from './Section.svelte';
|
|
14
15
|
export { default as Sidebar } from './Sidebar.svelte';
|
|
15
16
|
export { default as SlideUp } from './SlideUp.svelte';
|
|
16
17
|
export { default as Tabs } from './Tabs.svelte';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/molecules/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAClD,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAClE,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAC9D,OAAO,EAAE,OAAO,IAAI,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AACxD,OAAO,EAAE,OAAO,IAAI,IAAI,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAC9D,OAAO,EAAE,OAAO,IAAI,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAClD,OAAO,EAAE,OAAO,IAAI,cAAc,EAAE,MAAM,yBAAyB,CAAC;AACpE,OAAO,EAAE,OAAO,IAAI,kBAAkB,EAAE,MAAM,6BAA6B,CAAC;AAC5E,OAAO,EAAE,OAAO,IAAI,kBAAkB,EAAE,MAAM,6BAA6B,CAAC;AAC5E,OAAO,EAAE,OAAO,IAAI,qBAAqB,EAAE,MAAM,gCAAgC,CAAC;AAClF,OAAO,EAAE,OAAO,IAAI,qBAAqB,EAAE,MAAM,gCAAgC,CAAC;AAClF,OAAO,EAAE,OAAO,IAAI,kBAAkB,EAAE,MAAM,6BAA6B,CAAC;AAC5E,OAAO,EAAE,OAAO,IAAI,OAAO,EAAE,MAAM,kBAAkB,CAAC;AACtD,OAAO,EAAE,OAAO,IAAI,OAAO,EAAE,MAAM,kBAAkB,CAAC;AACtD,OAAO,EAAE,OAAO,IAAI,IAAI,EAAE,MAAM,eAAe,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/molecules/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAClD,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAClE,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAC9D,OAAO,EAAE,OAAO,IAAI,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AACxD,OAAO,EAAE,OAAO,IAAI,IAAI,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAC9D,OAAO,EAAE,OAAO,IAAI,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAClD,OAAO,EAAE,OAAO,IAAI,cAAc,EAAE,MAAM,yBAAyB,CAAC;AACpE,OAAO,EAAE,OAAO,IAAI,kBAAkB,EAAE,MAAM,6BAA6B,CAAC;AAC5E,OAAO,EAAE,OAAO,IAAI,kBAAkB,EAAE,MAAM,6BAA6B,CAAC;AAC5E,OAAO,EAAE,OAAO,IAAI,qBAAqB,EAAE,MAAM,gCAAgC,CAAC;AAClF,OAAO,EAAE,OAAO,IAAI,qBAAqB,EAAE,MAAM,gCAAgC,CAAC;AAClF,OAAO,EAAE,OAAO,IAAI,kBAAkB,EAAE,MAAM,6BAA6B,CAAC;AAC5E,OAAO,EAAE,OAAO,IAAI,OAAO,EAAE,MAAM,kBAAkB,CAAC;AACtD,OAAO,EAAE,OAAO,IAAI,OAAO,EAAE,MAAM,kBAAkB,CAAC;AACtD,OAAO,EAAE,OAAO,IAAI,OAAO,EAAE,MAAM,kBAAkB,CAAC;AACtD,OAAO,EAAE,OAAO,IAAI,IAAI,EAAE,MAAM,eAAe,CAAC"}
|
|
@@ -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;
|
|
@@ -11,6 +11,7 @@ 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 Section } from './Section.svelte';
|
|
14
15
|
export { default as Sidebar } from './Sidebar.svelte';
|
|
15
16
|
export { default as SlideUp } from './SlideUp.svelte';
|
|
16
17
|
export { default as Tabs } from './Tabs.svelte';
|
package/dist/molecules/index.js
CHANGED
|
@@ -11,6 +11,7 @@ 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 Section } from './Section.svelte';
|
|
14
15
|
export { default as Sidebar } from './Sidebar.svelte';
|
|
15
16
|
export { default as SlideUp } from './SlideUp.svelte';
|
|
16
17
|
export { default as Tabs } from './Tabs.svelte';
|
|
@@ -35,11 +35,11 @@
|
|
|
35
35
|
const ulClasses = $derived(() => {
|
|
36
36
|
return variant === "sidebar"
|
|
37
37
|
? "flex flex-col gap-1"
|
|
38
|
-
: "flex items-center justify-between
|
|
38
|
+
: "flex flex-col gap-1 md:flex-row md:items-center md:justify-between";
|
|
39
39
|
});
|
|
40
40
|
|
|
41
41
|
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";
|
|
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 w-full md:w-auto";
|
|
43
43
|
|
|
44
44
|
return baseClasses;
|
|
45
45
|
}
|