zabi-components 4.0.0 → 5.0.1
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 +70 -2
- package/dist/SSRSafe.svelte +47 -0
- package/dist/SSRSafe.svelte.d.ts +11 -0
- package/dist/atoms/Badge.svelte +76 -0
- package/dist/atoms/Badge.svelte.d.ts +9 -0
- package/dist/atoms/Button.svelte +72 -0
- package/dist/atoms/Button.svelte.d.ts +13 -0
- package/dist/atoms/Card.svelte +59 -0
- package/dist/atoms/Card.svelte.d.ts +12 -0
- package/dist/atoms/Checkbox.svelte +60 -0
- package/dist/atoms/Checkbox.svelte.d.ts +10 -0
- package/dist/atoms/CodeBlock.svelte +125 -0
- package/dist/atoms/CodeBlock.svelte.d.ts +8 -0
- package/dist/atoms/ColorPicker.svelte +171 -0
- package/dist/atoms/ColorPicker.svelte.d.ts +9 -0
- package/dist/atoms/FeatureCard.svelte +74 -0
- package/dist/atoms/FeatureCard.svelte.d.ts +17 -0
- package/dist/atoms/Heading.svelte +5 -0
- package/dist/atoms/Heading.svelte.d.ts +7 -0
- package/dist/atoms/Input.svelte +98 -0
- package/dist/atoms/Input.svelte.d.ts +14 -0
- package/dist/atoms/OptimizedImage.svelte +32 -0
- package/dist/atoms/OptimizedImage.svelte.d.ts +13 -0
- package/dist/atoms/Progress.svelte +61 -0
- package/dist/atoms/Progress.svelte.d.ts +9 -0
- package/dist/atoms/Select.svelte +85 -0
- package/dist/atoms/Select.svelte.d.ts +16 -0
- package/dist/atoms/Skeleton.svelte +20 -0
- package/dist/atoms/Skeleton.svelte.d.ts +8 -0
- package/dist/atoms/Textarea.svelte +116 -0
- package/dist/atoms/Textarea.svelte.d.ts +14 -0
- package/dist/atoms/ThemeToggle.svelte +89 -0
- package/dist/atoms/ThemeToggle.svelte.d.ts +7 -0
- package/dist/atoms/Toast.svelte +58 -0
- package/dist/atoms/Toast.svelte.d.ts +9 -0
- package/dist/atoms/Toggle.svelte +94 -0
- package/dist/atoms/Toggle.svelte.d.ts +12 -0
- package/dist/atoms/Tooltip.svelte +188 -0
- package/dist/atoms/Tooltip.svelte.d.ts +12 -0
- package/dist/atoms/index.d.ts +4 -15
- package/dist/atoms/index.js +10 -664
- package/dist/components/atoms/index.d.ts +10 -0
- package/dist/components/atoms/index.d.ts.map +1 -0
- package/dist/components/index.d.ts +31 -0
- package/dist/components/index.d.ts.map +1 -0
- package/dist/components/molecules/index.d.ts +1 -0
- package/dist/components/molecules/index.d.ts.map +1 -0
- package/dist/components/organisms/index.d.ts +1 -0
- package/dist/components/organisms/index.d.ts.map +1 -0
- package/dist/index.d.ts +30 -15
- package/dist/index.js +74 -0
- package/dist/molecules/Alert.svelte +114 -0
- package/dist/molecules/Alert.svelte.d.ts +14 -0
- package/dist/molecules/ComponentDemo.svelte +96 -0
- package/dist/molecules/ComponentDemo.svelte.d.ts +13 -0
- package/dist/molecules/ContactForm.svelte +98 -0
- package/dist/molecules/ContactForm.svelte.d.ts +10 -0
- package/dist/molecules/Dropdown.svelte +128 -0
- package/dist/molecules/Dropdown.svelte.d.ts +11 -0
- package/dist/molecules/Form.svelte +37 -0
- package/dist/molecules/Form.svelte.d.ts +12 -0
- package/dist/molecules/ImageUpload.svelte +112 -0
- package/dist/molecules/ImageUpload.svelte.d.ts +14 -0
- package/dist/molecules/Modal.svelte +85 -0
- package/dist/molecules/Modal.svelte.d.ts +13 -0
- package/dist/molecules/SlideUp.svelte +73 -0
- package/dist/molecules/SlideUp.svelte.d.ts +12 -0
- package/dist/molecules/Tabs.svelte +68 -0
- package/dist/molecules/Tabs.svelte.d.ts +17 -0
- package/dist/molecules/index.d.ts +0 -11
- package/dist/molecules/index.js +2 -580
- package/dist/organisms/Navbar.svelte +99 -0
- package/dist/organisms/Navbar.svelte.d.ts +14 -0
- package/dist/organisms/Navigation.svelte +48 -0
- package/dist/organisms/Navigation.svelte.d.ts +15 -0
- package/dist/organisms/index.d.ts +0 -4
- package/dist/organisms/index.js +2 -104
- package/dist/routes/lib/ssr-safe.ts +57 -0
- package/dist/routes/lib/variant-utils.ts +98 -0
- package/dist/zabi-components.css +399 -1
- package/package.json +43 -18
- package/dist/CodeBlock-Bbv6JfD2.js +0 -422
- package/dist/ThemeToggle-Z2Ndc0if.js +0 -42
- package/dist/index/index.js +0 -51
- package/dist/molecules/KeyValueForm.types.d.ts +0 -11
- package/dist/props-BKbHJRuR.js +0 -2213
- package/dist/types/index.d.ts +0 -4
- package/dist/types/index.js +0 -1
- package/dist/vite.svg +0 -1
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
interface Props {
|
|
3
|
+
method?: "get" | "post";
|
|
4
|
+
action?: string;
|
|
5
|
+
className?: string;
|
|
6
|
+
onsubmit?: (event: SubmitEvent) => void;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
let {
|
|
10
|
+
method = "post",
|
|
11
|
+
action = "",
|
|
12
|
+
className = "",
|
|
13
|
+
onsubmit,
|
|
14
|
+
children,
|
|
15
|
+
...restProps
|
|
16
|
+
} = $props<Props & { children?: any }>();
|
|
17
|
+
|
|
18
|
+
function handleSubmit(event: SubmitEvent) {
|
|
19
|
+
const formData = new FormData(event.target as HTMLFormElement);
|
|
20
|
+
const data = Object.fromEntries(formData.entries());
|
|
21
|
+
|
|
22
|
+
// Call the parent's onsubmit handler if provided
|
|
23
|
+
if (onsubmit) {
|
|
24
|
+
onsubmit(event);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
</script>
|
|
28
|
+
|
|
29
|
+
<form
|
|
30
|
+
{method}
|
|
31
|
+
{action}
|
|
32
|
+
class="space-y-4 {className}"
|
|
33
|
+
onsubmit={handleSubmit}
|
|
34
|
+
{...restProps}
|
|
35
|
+
>
|
|
36
|
+
{@render children?.()}
|
|
37
|
+
</form>
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
interface Props {
|
|
2
|
+
method?: "get" | "post";
|
|
3
|
+
action?: string;
|
|
4
|
+
className?: string;
|
|
5
|
+
onsubmit?: (event: SubmitEvent) => void;
|
|
6
|
+
}
|
|
7
|
+
type $$ComponentProps = Props & {
|
|
8
|
+
children?: any;
|
|
9
|
+
};
|
|
10
|
+
declare const Form: import("svelte").Component<$$ComponentProps, {}, "">;
|
|
11
|
+
type Form = ReturnType<typeof Form>;
|
|
12
|
+
export default Form;
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import Button from "../atoms/Button.svelte";
|
|
3
|
+
|
|
4
|
+
interface Props {
|
|
5
|
+
value?: string | null;
|
|
6
|
+
disabled?: boolean;
|
|
7
|
+
accept?: string;
|
|
8
|
+
placeholder?: string;
|
|
9
|
+
onchange?: (event: Event) => void;
|
|
10
|
+
onclick?: (event: Event) => void;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
let {
|
|
14
|
+
value = null,
|
|
15
|
+
disabled = false,
|
|
16
|
+
accept = "image/*",
|
|
17
|
+
placeholder = "No image selected",
|
|
18
|
+
children,
|
|
19
|
+
...restProps
|
|
20
|
+
} = $props<Props & { children?: any }>();
|
|
21
|
+
|
|
22
|
+
let fileInput = $state<HTMLInputElement>();
|
|
23
|
+
|
|
24
|
+
function handleFileSelect(event: Event) {
|
|
25
|
+
const input = event.target as HTMLInputElement;
|
|
26
|
+
if (!input.files || input.files.length === 0) return;
|
|
27
|
+
|
|
28
|
+
const file = input.files[0];
|
|
29
|
+
|
|
30
|
+
// SSR-safe URL creation
|
|
31
|
+
if (typeof URL !== "undefined" && URL.createObjectURL) {
|
|
32
|
+
const url = URL.createObjectURL(file);
|
|
33
|
+
value = url;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function removeImage() {
|
|
38
|
+
if (value && typeof URL !== "undefined" && URL.revokeObjectURL) {
|
|
39
|
+
URL.revokeObjectURL(value);
|
|
40
|
+
}
|
|
41
|
+
value = null;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function triggerFileSelect() {
|
|
45
|
+
fileInput?.click();
|
|
46
|
+
}
|
|
47
|
+
</script>
|
|
48
|
+
|
|
49
|
+
<div class="space-y-3">
|
|
50
|
+
{#if value}
|
|
51
|
+
<!-- Image Display -->
|
|
52
|
+
<div class="relative group">
|
|
53
|
+
<img
|
|
54
|
+
src={value}
|
|
55
|
+
alt=""
|
|
56
|
+
class="w-full h-32 object-cover rounded-lg border border-gray-300"
|
|
57
|
+
/>
|
|
58
|
+
<div
|
|
59
|
+
class="absolute inset-0 bg-black/50 opacity-0 group-hover:opacity-100 transition-opacity rounded-lg flex items-center justify-center"
|
|
60
|
+
>
|
|
61
|
+
<div class="flex gap-2">
|
|
62
|
+
<Button
|
|
63
|
+
variant="secondary"
|
|
64
|
+
size="sm"
|
|
65
|
+
onclick={triggerFileSelect}
|
|
66
|
+
{disabled}
|
|
67
|
+
>
|
|
68
|
+
Change
|
|
69
|
+
</Button>
|
|
70
|
+
<Button
|
|
71
|
+
variant="danger"
|
|
72
|
+
size="sm"
|
|
73
|
+
onclick={removeImage}
|
|
74
|
+
{disabled}
|
|
75
|
+
>
|
|
76
|
+
Remove
|
|
77
|
+
</Button>
|
|
78
|
+
</div>
|
|
79
|
+
</div>
|
|
80
|
+
</div>
|
|
81
|
+
{:else}
|
|
82
|
+
<!-- Empty State -->
|
|
83
|
+
<div
|
|
84
|
+
class="border-2 border-dashed border-gray-300 rounded-lg p-6 text-center hover:border-gray-400 transition-colors cursor-pointer"
|
|
85
|
+
onclick={triggerFileSelect}
|
|
86
|
+
role="button"
|
|
87
|
+
tabindex="0"
|
|
88
|
+
onkeydown={(e) => e.key === "Enter" && triggerFileSelect()}
|
|
89
|
+
>
|
|
90
|
+
<div class="space-y-3">
|
|
91
|
+
<div
|
|
92
|
+
class="w-12 h-12 mx-auto bg-gray-100 rounded-lg flex items-center justify-center"
|
|
93
|
+
>
|
|
94
|
+
<span class="text-2xl">📷</span>
|
|
95
|
+
</div>
|
|
96
|
+
<div>
|
|
97
|
+
<p class="font-medium text-gray-900">{placeholder}</p>
|
|
98
|
+
<p class="text-sm text-gray-500">Click to choose a file</p>
|
|
99
|
+
</div>
|
|
100
|
+
</div>
|
|
101
|
+
</div>
|
|
102
|
+
{/if}
|
|
103
|
+
|
|
104
|
+
<!-- Hidden File Input -->
|
|
105
|
+
<input
|
|
106
|
+
bind:this={fileInput}
|
|
107
|
+
type="file"
|
|
108
|
+
{accept}
|
|
109
|
+
onchange={handleFileSelect}
|
|
110
|
+
class="hidden"
|
|
111
|
+
/>
|
|
112
|
+
</div>
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
interface Props {
|
|
2
|
+
value?: string | null;
|
|
3
|
+
disabled?: boolean;
|
|
4
|
+
accept?: string;
|
|
5
|
+
placeholder?: string;
|
|
6
|
+
onchange?: (event: Event) => void;
|
|
7
|
+
onclick?: (event: Event) => void;
|
|
8
|
+
}
|
|
9
|
+
type $$ComponentProps = Props & {
|
|
10
|
+
children?: any;
|
|
11
|
+
};
|
|
12
|
+
declare const ImageUpload: import("svelte").Component<$$ComponentProps, {}, "">;
|
|
13
|
+
type ImageUpload = ReturnType<typeof ImageUpload>;
|
|
14
|
+
export default ImageUpload;
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
interface Props {
|
|
3
|
+
isOpen?: boolean;
|
|
4
|
+
title?: string;
|
|
5
|
+
onclick?: (event: Event) => void;
|
|
6
|
+
onkeydown?: (event: Event) => void;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
let {
|
|
10
|
+
isOpen = false,
|
|
11
|
+
title = "",
|
|
12
|
+
onclick,
|
|
13
|
+
onkeydown,
|
|
14
|
+
children,
|
|
15
|
+
footer,
|
|
16
|
+
...restProps
|
|
17
|
+
}: Props & { children?: any; footer?: any } = $props();
|
|
18
|
+
|
|
19
|
+
function closeModal(event?: Event) {
|
|
20
|
+
isOpen = false;
|
|
21
|
+
if (onclick && event) {
|
|
22
|
+
onclick(event);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function handleBackdropClick(event: Event) {
|
|
27
|
+
if (event.target === event.currentTarget) {
|
|
28
|
+
closeModal(event);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function handleKeydown(event: Event) {
|
|
33
|
+
const keyboardEvent = event as KeyboardEvent;
|
|
34
|
+
if (keyboardEvent.key === "Escape") {
|
|
35
|
+
closeModal(event);
|
|
36
|
+
}
|
|
37
|
+
if (onkeydown) {
|
|
38
|
+
onkeydown(event);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
</script>
|
|
42
|
+
|
|
43
|
+
{#if isOpen}
|
|
44
|
+
<div
|
|
45
|
+
class="fixed inset-0 bg-black/50 flex items-center justify-center p-4 z-50"
|
|
46
|
+
onclick={handleBackdropClick}
|
|
47
|
+
onkeydown={handleKeydown}
|
|
48
|
+
role="dialog"
|
|
49
|
+
aria-modal="true"
|
|
50
|
+
tabindex="-1"
|
|
51
|
+
>
|
|
52
|
+
<div
|
|
53
|
+
class="bg-white rounded-lg shadow-xl max-w-md w-full max-h-[90vh] overflow-y-auto"
|
|
54
|
+
>
|
|
55
|
+
<!-- Header -->
|
|
56
|
+
<div
|
|
57
|
+
class="flex items-center justify-between p-6 border-b border-gray-200"
|
|
58
|
+
>
|
|
59
|
+
<h2 class="text-xl font-semibold text-headline">{title}</h2>
|
|
60
|
+
<button
|
|
61
|
+
type="button"
|
|
62
|
+
onclick={closeModal}
|
|
63
|
+
class="text-gray-400 hover:text-gray-600 text-2xl"
|
|
64
|
+
aria-label="Close"
|
|
65
|
+
>
|
|
66
|
+
×
|
|
67
|
+
</button>
|
|
68
|
+
</div>
|
|
69
|
+
|
|
70
|
+
<!-- Content -->
|
|
71
|
+
<div class="p-6">
|
|
72
|
+
{@render children?.()}
|
|
73
|
+
</div>
|
|
74
|
+
|
|
75
|
+
<!-- Footer -->
|
|
76
|
+
{#if footer}
|
|
77
|
+
<div
|
|
78
|
+
class="flex justify-end gap-3 p-6 border-t border-gray-200"
|
|
79
|
+
>
|
|
80
|
+
{@render footer?.()}
|
|
81
|
+
</div>
|
|
82
|
+
{/if}
|
|
83
|
+
</div>
|
|
84
|
+
</div>
|
|
85
|
+
{/if}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
interface Props {
|
|
2
|
+
isOpen?: boolean;
|
|
3
|
+
title?: string;
|
|
4
|
+
onclick?: (event: Event) => void;
|
|
5
|
+
onkeydown?: (event: Event) => void;
|
|
6
|
+
}
|
|
7
|
+
type $$ComponentProps = Props & {
|
|
8
|
+
children?: any;
|
|
9
|
+
footer?: any;
|
|
10
|
+
};
|
|
11
|
+
declare const Modal: import("svelte").Component<$$ComponentProps, {}, "">;
|
|
12
|
+
type Modal = ReturnType<typeof Modal>;
|
|
13
|
+
export default Modal;
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
interface Props {
|
|
3
|
+
isOpen?: boolean;
|
|
4
|
+
title?: string;
|
|
5
|
+
onclick?: (event: Event) => void;
|
|
6
|
+
onkeydown?: (event: Event) => void;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
let {
|
|
10
|
+
isOpen = false,
|
|
11
|
+
title = "",
|
|
12
|
+
children,
|
|
13
|
+
...restProps
|
|
14
|
+
} = $props<Props & { children?: any }>();
|
|
15
|
+
|
|
16
|
+
function closeSlideUp() {
|
|
17
|
+
isOpen = false;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function handleBackdropClick(event: Event) {
|
|
21
|
+
if (event.target === event.currentTarget) {
|
|
22
|
+
closeSlideUp();
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function handleKeydown(event: Event) {
|
|
27
|
+
const keyboardEvent = event as KeyboardEvent;
|
|
28
|
+
if (keyboardEvent.key === "Escape") {
|
|
29
|
+
closeSlideUp();
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
</script>
|
|
33
|
+
|
|
34
|
+
{#if isOpen}
|
|
35
|
+
<!-- Backdrop -->
|
|
36
|
+
<div
|
|
37
|
+
class="fixed inset-0 bg-black/50 z-50"
|
|
38
|
+
onclick={handleBackdropClick}
|
|
39
|
+
onkeydown={handleKeydown}
|
|
40
|
+
role="dialog"
|
|
41
|
+
aria-modal="true"
|
|
42
|
+
tabindex="-1"
|
|
43
|
+
></div>
|
|
44
|
+
|
|
45
|
+
<!-- SlideUp Content -->
|
|
46
|
+
<div
|
|
47
|
+
class="fixed bottom-0 left-0 right-0 bg-white border-t border-gray-200 rounded-t-xl shadow-xl z-50 max-h-[80vh] overflow-y-auto"
|
|
48
|
+
role="dialog"
|
|
49
|
+
aria-modal="true"
|
|
50
|
+
>
|
|
51
|
+
<!-- Header -->
|
|
52
|
+
{#if title}
|
|
53
|
+
<div
|
|
54
|
+
class="flex items-center justify-between p-4 border-b border-gray-200"
|
|
55
|
+
>
|
|
56
|
+
<h3 class="text-lg font-semibold text-gray-900">{title}</h3>
|
|
57
|
+
<button
|
|
58
|
+
type="button"
|
|
59
|
+
class="text-gray-400 hover:text-gray-600 text-2xl"
|
|
60
|
+
onclick={closeSlideUp}
|
|
61
|
+
aria-label="Close"
|
|
62
|
+
>
|
|
63
|
+
×
|
|
64
|
+
</button>
|
|
65
|
+
</div>
|
|
66
|
+
{/if}
|
|
67
|
+
|
|
68
|
+
<!-- Content -->
|
|
69
|
+
<div class="p-4">
|
|
70
|
+
{@render children?.()}
|
|
71
|
+
</div>
|
|
72
|
+
</div>
|
|
73
|
+
{/if}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
interface Props {
|
|
2
|
+
isOpen?: boolean;
|
|
3
|
+
title?: string;
|
|
4
|
+
onclick?: (event: Event) => void;
|
|
5
|
+
onkeydown?: (event: Event) => void;
|
|
6
|
+
}
|
|
7
|
+
type $$ComponentProps = Props & {
|
|
8
|
+
children?: any;
|
|
9
|
+
};
|
|
10
|
+
declare const SlideUp: import("svelte").Component<$$ComponentProps, {}, "">;
|
|
11
|
+
type SlideUp = ReturnType<typeof SlideUp>;
|
|
12
|
+
export default SlideUp;
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
interface Props {
|
|
3
|
+
tabs?: Array<{
|
|
4
|
+
id: string;
|
|
5
|
+
label: string;
|
|
6
|
+
disabled?: boolean;
|
|
7
|
+
}>;
|
|
8
|
+
activeTab?: string;
|
|
9
|
+
variant?: "default" | "pills";
|
|
10
|
+
onclick?: (event: Event) => void;
|
|
11
|
+
onkeydown?: (event: Event) => void;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
let {
|
|
15
|
+
tabs = [],
|
|
16
|
+
activeTab = "",
|
|
17
|
+
variant = "default",
|
|
18
|
+
children,
|
|
19
|
+
...restProps
|
|
20
|
+
}: Props & { children?: any } = $props();
|
|
21
|
+
|
|
22
|
+
function selectTab(tabId: string) {
|
|
23
|
+
activeTab = tabId;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function handleKeydown(event: KeyboardEvent) {
|
|
27
|
+
if (event.key === "ArrowLeft" || event.key === "ArrowRight") {
|
|
28
|
+
const currentIndex = tabs.findIndex((tab) => tab.id === activeTab);
|
|
29
|
+
const direction = event.key === "ArrowLeft" ? -1 : 1;
|
|
30
|
+
const nextIndex =
|
|
31
|
+
(currentIndex + direction + tabs.length) % tabs.length;
|
|
32
|
+
selectTab(tabs[nextIndex].id);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
</script>
|
|
36
|
+
|
|
37
|
+
<div class="tabs-container">
|
|
38
|
+
<!-- Tab List -->
|
|
39
|
+
<div
|
|
40
|
+
class="flex border-b border-gray-200"
|
|
41
|
+
role="tablist"
|
|
42
|
+
tabindex="0"
|
|
43
|
+
onkeydown={handleKeydown}
|
|
44
|
+
>
|
|
45
|
+
{#each tabs as tab}
|
|
46
|
+
<button
|
|
47
|
+
type="button"
|
|
48
|
+
role="tab"
|
|
49
|
+
class="px-4 py-2 text-sm font-medium border-b-2 transition-colors {activeTab ===
|
|
50
|
+
tab.id
|
|
51
|
+
? variant === 'pills'
|
|
52
|
+
? 'bg-blue-100 text-blue-700 border-blue-500'
|
|
53
|
+
: 'border-blue-500 text-body'
|
|
54
|
+
: 'border-transparent text-description hover:text-body hover:border-gray-300'}"
|
|
55
|
+
onclick={() => selectTab(tab.id)}
|
|
56
|
+
disabled={tab.disabled}
|
|
57
|
+
aria-selected={activeTab === tab.id}
|
|
58
|
+
>
|
|
59
|
+
{tab.label}
|
|
60
|
+
</button>
|
|
61
|
+
{/each}
|
|
62
|
+
</div>
|
|
63
|
+
|
|
64
|
+
<!-- Tab Content -->
|
|
65
|
+
<div class="mt-4">
|
|
66
|
+
{@render children?.({ activeTab })}
|
|
67
|
+
</div>
|
|
68
|
+
</div>
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
interface Props {
|
|
2
|
+
tabs?: Array<{
|
|
3
|
+
id: string;
|
|
4
|
+
label: string;
|
|
5
|
+
disabled?: boolean;
|
|
6
|
+
}>;
|
|
7
|
+
activeTab?: string;
|
|
8
|
+
variant?: "default" | "pills";
|
|
9
|
+
onclick?: (event: Event) => void;
|
|
10
|
+
onkeydown?: (event: Event) => void;
|
|
11
|
+
}
|
|
12
|
+
type $$ComponentProps = Props & {
|
|
13
|
+
children?: any;
|
|
14
|
+
};
|
|
15
|
+
declare const Tabs: import("svelte").Component<$$ComponentProps, {}, "">;
|
|
16
|
+
type Tabs = ReturnType<typeof Tabs>;
|
|
17
|
+
export default Tabs;
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
// Molecular Components - Simple combinations of atoms
|
|
2
|
-
export { default as Alert } from './Alert.svelte';
|
|
3
|
-
export { default as Dropdown } from './Dropdown.svelte';
|
|
4
|
-
export { default as FileUpload } from './ImageUpload.svelte';
|
|
5
|
-
export { default as DynamicForm } from './KeyValueForm.svelte';
|
|
6
|
-
export { default as Modal } from './Modal.svelte';
|
|
7
|
-
export { default as SlideUp } from './SlideUp.svelte';
|
|
8
|
-
export { default as Tabs } from './Tabs.svelte';
|
|
9
|
-
|
|
10
|
-
// Types
|
|
11
|
-
export type { FieldConfig } from './KeyValueForm.types';
|