zabi-components 5.0.15 → 5.0.18
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 +175 -23
- package/dist/SSRSafe.svelte +0 -3
- package/dist/atoms/Badge.svelte +32 -47
- package/dist/atoms/Badge.svelte.d.ts +6 -5
- package/dist/atoms/Button.svelte +18 -17
- package/dist/atoms/Button.svelte.d.ts +3 -2
- package/dist/atoms/Card.svelte +74 -23
- package/dist/atoms/Card.svelte.d.ts +3 -1
- package/dist/atoms/CardContent.svelte +24 -0
- package/dist/atoms/CardContent.svelte.d.ts +8 -0
- package/dist/atoms/CardDescription.svelte +24 -0
- package/dist/atoms/CardDescription.svelte.d.ts +8 -0
- package/dist/atoms/CardFooter.svelte +24 -0
- package/dist/atoms/CardFooter.svelte.d.ts +8 -0
- package/dist/atoms/CardHeader.svelte +24 -0
- package/dist/atoms/CardHeader.svelte.d.ts +8 -0
- package/dist/atoms/CardTitle.svelte +33 -0
- package/dist/atoms/CardTitle.svelte.d.ts +9 -0
- package/dist/atoms/Checkbox.svelte +19 -20
- package/dist/atoms/CodeBlock.svelte +4 -7
- package/dist/atoms/ColorPicker.svelte +33 -65
- package/dist/atoms/FeatureCard.svelte +2 -12
- package/dist/atoms/FeatureCard.svelte.d.ts +0 -8
- package/dist/atoms/Heading.svelte +0 -2
- package/dist/atoms/Input.svelte +8 -17
- package/dist/atoms/Input.svelte.d.ts +3 -2
- package/dist/atoms/Progress.svelte +1 -4
- package/dist/atoms/Select.svelte +37 -28
- package/dist/atoms/Skeleton.svelte +1 -1
- package/dist/atoms/Textarea.svelte +5 -11
- package/dist/atoms/Textarea.svelte.d.ts +3 -1
- package/dist/atoms/ThemeToggle.svelte +5 -12
- package/dist/atoms/Toast.svelte +1 -2
- package/dist/atoms/Toggle.svelte +2 -10
- package/dist/atoms/Tooltip.svelte +123 -26
- package/dist/atoms/index.d.ts +5 -0
- package/dist/atoms/index.js +5 -1
- package/dist/components/atoms/index.d.ts +5 -0
- package/dist/components/atoms/index.d.ts.map +1 -1
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/molecules/index.d.ts.map +1 -1
- package/dist/components/organisms/index.d.ts.map +1 -1
- package/dist/index.js +0 -23
- package/dist/molecules/Alert.svelte +9 -13
- package/dist/molecules/Alert.svelte.d.ts +2 -1
- package/dist/molecules/ComponentDemo.svelte +55 -64
- package/dist/molecules/ContactForm.svelte +21 -12
- package/dist/molecules/Dropdown.svelte +104 -8
- package/dist/molecules/Dropdown.svelte.d.ts +1 -0
- package/dist/molecules/Form.svelte +0 -1
- package/dist/molecules/ImageUpload.svelte +2 -6
- package/dist/molecules/Modal.svelte +30 -6
- package/dist/molecules/SlideUp.svelte +2 -4
- package/dist/molecules/Tabs.svelte +2 -4
- package/dist/molecules/index.js +0 -1
- package/dist/organisms/Navbar.svelte +1 -8
- package/dist/organisms/Navigation.svelte +0 -6
- package/dist/organisms/index.js +0 -1
- package/dist/routes/lib/variant-utils.ts +7 -5
- package/dist/zabi-components-colors.css +287 -211
- package/dist/zabi-components-theme-dark-only.css +158 -0
- package/dist/zabi-components-theme-dark.css +160 -0
- package/dist/zabi-components-theme-only.css +235 -0
- package/dist/zabi-components-theme.css +237 -0
- package/dist/zabi-components.css +575 -360
- package/package.json +15 -5
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { Snippet } from "svelte";
|
|
3
|
+
|
|
4
|
+
interface Props {
|
|
5
|
+
className?: string;
|
|
6
|
+
children?: Snippet;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
let {
|
|
10
|
+
className = "",
|
|
11
|
+
children,
|
|
12
|
+
...restProps
|
|
13
|
+
}: Props = $props();
|
|
14
|
+
</script>
|
|
15
|
+
|
|
16
|
+
<div
|
|
17
|
+
class="p-6 pt-0 {className}"
|
|
18
|
+
{...restProps}
|
|
19
|
+
>
|
|
20
|
+
{#if children}
|
|
21
|
+
{@render children()}
|
|
22
|
+
{/if}
|
|
23
|
+
</div>
|
|
24
|
+
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { Snippet } from "svelte";
|
|
3
|
+
|
|
4
|
+
interface Props {
|
|
5
|
+
className?: string;
|
|
6
|
+
children?: Snippet;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
let {
|
|
10
|
+
className = "",
|
|
11
|
+
children,
|
|
12
|
+
...restProps
|
|
13
|
+
}: Props = $props();
|
|
14
|
+
</script>
|
|
15
|
+
|
|
16
|
+
<p
|
|
17
|
+
class="text-sm text-description {className}"
|
|
18
|
+
{...restProps}
|
|
19
|
+
>
|
|
20
|
+
{#if children}
|
|
21
|
+
{@render children()}
|
|
22
|
+
{/if}
|
|
23
|
+
</p>
|
|
24
|
+
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { Snippet } from "svelte";
|
|
2
|
+
interface Props {
|
|
3
|
+
className?: string;
|
|
4
|
+
children?: Snippet;
|
|
5
|
+
}
|
|
6
|
+
declare const CardDescription: import("svelte").Component<Props, {}, "">;
|
|
7
|
+
type CardDescription = ReturnType<typeof CardDescription>;
|
|
8
|
+
export default CardDescription;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { Snippet } from "svelte";
|
|
3
|
+
|
|
4
|
+
interface Props {
|
|
5
|
+
className?: string;
|
|
6
|
+
children?: Snippet;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
let {
|
|
10
|
+
className = "",
|
|
11
|
+
children,
|
|
12
|
+
...restProps
|
|
13
|
+
}: Props = $props();
|
|
14
|
+
</script>
|
|
15
|
+
|
|
16
|
+
<footer
|
|
17
|
+
class="flex items-center p-6 pt-0 {className}"
|
|
18
|
+
{...restProps}
|
|
19
|
+
>
|
|
20
|
+
{#if children}
|
|
21
|
+
{@render children()}
|
|
22
|
+
{/if}
|
|
23
|
+
</footer>
|
|
24
|
+
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { Snippet } from "svelte";
|
|
3
|
+
|
|
4
|
+
interface Props {
|
|
5
|
+
className?: string;
|
|
6
|
+
children?: Snippet;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
let {
|
|
10
|
+
className = "",
|
|
11
|
+
children,
|
|
12
|
+
...restProps
|
|
13
|
+
}: Props = $props();
|
|
14
|
+
</script>
|
|
15
|
+
|
|
16
|
+
<header
|
|
17
|
+
class="flex flex-col space-y-1.5 p-6 {className}"
|
|
18
|
+
{...restProps}
|
|
19
|
+
>
|
|
20
|
+
{#if children}
|
|
21
|
+
{@render children()}
|
|
22
|
+
{/if}
|
|
23
|
+
</header>
|
|
24
|
+
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { Snippet } from "svelte";
|
|
3
|
+
|
|
4
|
+
interface Props {
|
|
5
|
+
level?: 1 | 2 | 3 | 4 | 5 | 6;
|
|
6
|
+
className?: string;
|
|
7
|
+
children?: Snippet;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
let {
|
|
11
|
+
level = 3,
|
|
12
|
+
className = "",
|
|
13
|
+
children,
|
|
14
|
+
...restProps
|
|
15
|
+
}: Props = $props();
|
|
16
|
+
|
|
17
|
+
const headingTag = $derived(`h${level}`);
|
|
18
|
+
const headingClasses = $derived(() => {
|
|
19
|
+
const baseClasses = "text-2xl font-semibold leading-none tracking-tight text-headline";
|
|
20
|
+
return `${baseClasses} ${className}`.trim();
|
|
21
|
+
});
|
|
22
|
+
</script>
|
|
23
|
+
|
|
24
|
+
<svelte:element
|
|
25
|
+
this={headingTag}
|
|
26
|
+
class={headingClasses()}
|
|
27
|
+
{...restProps}
|
|
28
|
+
>
|
|
29
|
+
{#if children}
|
|
30
|
+
{@render children()}
|
|
31
|
+
{/if}
|
|
32
|
+
</svelte:element>
|
|
33
|
+
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { Snippet } from "svelte";
|
|
2
|
+
interface Props {
|
|
3
|
+
level?: 1 | 2 | 3 | 4 | 5 | 6;
|
|
4
|
+
className?: string;
|
|
5
|
+
children?: Snippet;
|
|
6
|
+
}
|
|
7
|
+
declare const CardTitle: import("svelte").Component<Props, {}, "">;
|
|
8
|
+
type CardTitle = ReturnType<typeof CardTitle>;
|
|
9
|
+
export default CardTitle;
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
// SSR-safe ID generation
|
|
3
2
|
function generateId(prefix: string = "id"): string {
|
|
4
3
|
if (typeof window !== "undefined") {
|
|
5
4
|
return `${prefix}-${Math.random().toString(36).substr(2, 9)}`;
|
|
@@ -25,29 +24,27 @@
|
|
|
25
24
|
...restProps
|
|
26
25
|
}: Props = $props();
|
|
27
26
|
|
|
28
|
-
// Generate unique ID - SSR safe (call directly, not in $state)
|
|
29
27
|
const checkboxId = generateId("checkbox");
|
|
30
28
|
|
|
31
|
-
// Checkbox container classes matching M3 design
|
|
32
29
|
const checkboxContainerClasses = $derived(() => {
|
|
33
|
-
const baseClasses =
|
|
34
|
-
|
|
30
|
+
const baseClasses =
|
|
31
|
+
"relative inline-flex items-center justify-center w-5 h-5 rounded transition-all duration-200";
|
|
32
|
+
|
|
35
33
|
if (disabled) {
|
|
36
34
|
return `${baseClasses} opacity-50 cursor-not-allowed`;
|
|
37
35
|
}
|
|
38
36
|
return `${baseClasses} cursor-pointer`;
|
|
39
37
|
});
|
|
40
38
|
|
|
41
|
-
// Checkbox border and background classes matching M3 design
|
|
42
39
|
const checkboxBoxClasses = $derived(() => {
|
|
43
40
|
if (checked) {
|
|
44
|
-
return disabled
|
|
45
|
-
? "border-0 bg-brand-
|
|
46
|
-
: "border-0 bg-brand-
|
|
41
|
+
return disabled
|
|
42
|
+
? "border-0 opacity-50 bg-brand-500"
|
|
43
|
+
: "border-0 bg-brand-500";
|
|
47
44
|
}
|
|
48
45
|
return disabled
|
|
49
|
-
? "border-2 border-
|
|
50
|
-
: "border-2 border-
|
|
46
|
+
? "border-2 border-base-400 bg-transparent"
|
|
47
|
+
: "border-2 border-base-400 bg-transparent";
|
|
51
48
|
});
|
|
52
49
|
|
|
53
50
|
function handleChange(event: Event) {
|
|
@@ -63,7 +60,9 @@
|
|
|
63
60
|
<div class="flex items-center gap-2">
|
|
64
61
|
<label
|
|
65
62
|
for={checkboxId}
|
|
66
|
-
class="flex items-center gap-2 cursor-pointer {disabled
|
|
63
|
+
class="flex items-center gap-2 cursor-pointer {disabled
|
|
64
|
+
? 'opacity-50 cursor-not-allowed'
|
|
65
|
+
: ''}"
|
|
67
66
|
>
|
|
68
67
|
<div class={checkboxContainerClasses()}>
|
|
69
68
|
<input
|
|
@@ -78,16 +77,16 @@
|
|
|
78
77
|
/>
|
|
79
78
|
<div class="absolute inset-0 {checkboxBoxClasses()} rounded"></div>
|
|
80
79
|
{#if checked}
|
|
81
|
-
<svg
|
|
82
|
-
class="absolute w-3 h-3 text-
|
|
83
|
-
fill="none"
|
|
84
|
-
stroke="currentColor"
|
|
80
|
+
<svg
|
|
81
|
+
class="absolute w-3 h-3 text-base-50 pointer-events-none z-10"
|
|
82
|
+
fill="none"
|
|
83
|
+
stroke="currentColor"
|
|
85
84
|
viewBox="0 0 24 24"
|
|
86
85
|
>
|
|
87
|
-
<path
|
|
88
|
-
stroke-linecap="round"
|
|
89
|
-
stroke-linejoin="round"
|
|
90
|
-
stroke-width="2.5"
|
|
86
|
+
<path
|
|
87
|
+
stroke-linecap="round"
|
|
88
|
+
stroke-linejoin="round"
|
|
89
|
+
stroke-width="2.5"
|
|
91
90
|
d="M5 13l4 4L19 7"
|
|
92
91
|
/>
|
|
93
92
|
</svg>
|
|
@@ -30,12 +30,11 @@
|
|
|
30
30
|
</script>
|
|
31
31
|
|
|
32
32
|
<div
|
|
33
|
-
class="code-block relative bg-
|
|
33
|
+
class="code-block relative bg-base-900 rounded-lg overflow-hidden {className}"
|
|
34
34
|
{...restProps}
|
|
35
35
|
>
|
|
36
|
-
<!-- Header -->
|
|
37
36
|
<div
|
|
38
|
-
class="flex items-center justify-between px-4 py-2 bg-
|
|
37
|
+
class="flex items-center justify-between px-4 py-2 bg-base-800 border-b border-base-700"
|
|
39
38
|
>
|
|
40
39
|
<div class="flex items-center gap-2">
|
|
41
40
|
<div class="w-3 h-3 rounded-full bg-red-500"></div>
|
|
@@ -45,7 +44,7 @@
|
|
|
45
44
|
{#if showCopyButton}
|
|
46
45
|
<button
|
|
47
46
|
onclick={copyToClipboard}
|
|
48
|
-
class="flex items-center gap-2 px-3 py-1 text-xs text-
|
|
47
|
+
class="flex items-center gap-2 px-3 py-1 text-xs text-base-300 hover:text-white hover:bg-base-700 rounded transition-colors duration-200"
|
|
49
48
|
aria-label="Copy code to clipboard"
|
|
50
49
|
>
|
|
51
50
|
{#if copied}
|
|
@@ -81,8 +80,7 @@
|
|
|
81
80
|
{/if}
|
|
82
81
|
</div>
|
|
83
82
|
|
|
84
|
-
|
|
85
|
-
<pre class="p-4 overflow-x-auto text-sm text-gray-100 leading-relaxed"><code
|
|
83
|
+
<pre class="p-4 overflow-x-auto text-sm text-base-100 leading-relaxed"><code
|
|
86
84
|
class="language-{language}">{@html code}</code
|
|
87
85
|
></pre>
|
|
88
86
|
</div>
|
|
@@ -92,7 +90,6 @@
|
|
|
92
90
|
font-family: "Monaco", "Menlo", "Ubuntu Mono", monospace;
|
|
93
91
|
}
|
|
94
92
|
|
|
95
|
-
/* Basic syntax highlighting for common languages */
|
|
96
93
|
:global(.language-svelte .token.tag),
|
|
97
94
|
:global(.language-html .token.tag) {
|
|
98
95
|
color: #f92672;
|
|
@@ -1,12 +1,5 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
|
|
3
|
-
function generateId(prefix: string = "id"): string {
|
|
4
|
-
if (typeof window !== "undefined") {
|
|
5
|
-
return `${prefix}-${Math.random().toString(36).substr(2, 9)}`;
|
|
6
|
-
} else {
|
|
7
|
-
return `${prefix}-ssr-${Date.now()}`;
|
|
8
|
-
}
|
|
9
|
-
}
|
|
2
|
+
import Input from "./Input.svelte";
|
|
10
3
|
|
|
11
4
|
interface Props {
|
|
12
5
|
value?: string;
|
|
@@ -25,90 +18,65 @@
|
|
|
25
18
|
...restProps
|
|
26
19
|
}: Props = $props();
|
|
27
20
|
|
|
28
|
-
// Generate unique ID - SSR safe
|
|
29
|
-
const inputId = generateId("color-picker");
|
|
30
|
-
|
|
31
|
-
// Hex color validation
|
|
32
21
|
function isValidHex(hex: string): boolean {
|
|
33
22
|
const hexPattern = /^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/;
|
|
34
23
|
return hexPattern.test(hex);
|
|
35
24
|
}
|
|
36
25
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
26
|
+
const variant = $derived(() => {
|
|
27
|
+
if (value && !isValidHex(value)) {
|
|
28
|
+
return "error";
|
|
29
|
+
}
|
|
30
|
+
return "default";
|
|
31
|
+
});
|
|
41
32
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
33
|
+
const message = $derived(() => {
|
|
34
|
+
if (value && !isValidHex(value)) {
|
|
35
|
+
return "Please enter a valid hex color (e.g., #ff0000 or #f00)";
|
|
45
36
|
}
|
|
37
|
+
return "";
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
function handleInput(event: Event) {
|
|
41
|
+
if (onchange) onchange(event);
|
|
46
42
|
}
|
|
47
43
|
|
|
48
|
-
|
|
49
|
-
function handleHexBlur(event: Event) {
|
|
44
|
+
function handleBlur(event: Event) {
|
|
50
45
|
const target = event.target as HTMLInputElement;
|
|
51
46
|
let hexValue = target.value.trim();
|
|
52
47
|
|
|
53
|
-
// Add # if missing
|
|
54
48
|
if (hexValue && !hexValue.startsWith("#")) {
|
|
55
49
|
hexValue = "#" + hexValue;
|
|
56
50
|
}
|
|
57
51
|
|
|
58
|
-
// Validate and update
|
|
59
52
|
if (hexValue === "" || isValidHex(hexValue)) {
|
|
60
53
|
value = hexValue;
|
|
61
|
-
|
|
62
|
-
} else {
|
|
63
|
-
// Reset to current value if invalid
|
|
64
|
-
target.value = value;
|
|
54
|
+
if (onchange) onchange(event);
|
|
65
55
|
}
|
|
66
56
|
}
|
|
67
|
-
|
|
68
|
-
// Input classes
|
|
69
|
-
const inputClasses = $derived(() => {
|
|
70
|
-
const baseClasses =
|
|
71
|
-
"w-full px-3 py-2 border rounded-lg text-sm transition-colors focus:outline-none focus:ring-2 focus:ring-brand-200";
|
|
72
|
-
const stateClasses =
|
|
73
|
-
isValidHex(value) || value === ""
|
|
74
|
-
? "border-gray-300 focus:border-brand-500"
|
|
75
|
-
: "border-red-300 focus:border-red-500 focus:ring-red-200";
|
|
76
|
-
|
|
77
|
-
return `${baseClasses} ${stateClasses}`.trim();
|
|
78
|
-
});
|
|
79
57
|
</script>
|
|
80
58
|
|
|
81
|
-
<div
|
|
82
|
-
|
|
83
|
-
<
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
{disabled}
|
|
97
|
-
class={inputClasses()}
|
|
98
|
-
aria-label="Hex color input"
|
|
99
|
-
/>
|
|
59
|
+
<div {...restProps}>
|
|
60
|
+
<div class="flex items-start gap-2">
|
|
61
|
+
<div class="flex-1">
|
|
62
|
+
<Input
|
|
63
|
+
bind:value
|
|
64
|
+
{label}
|
|
65
|
+
{placeholder}
|
|
66
|
+
{disabled}
|
|
67
|
+
variant={variant()}
|
|
68
|
+
message={message()}
|
|
69
|
+
oninput={handleInput}
|
|
70
|
+
onblur={handleBlur}
|
|
71
|
+
aria-label="Hex color input"
|
|
72
|
+
/>
|
|
73
|
+
</div>
|
|
100
74
|
{#if value && isValidHex(value)}
|
|
101
75
|
<div
|
|
102
|
-
class="w-8 h-8 rounded border-2 border-
|
|
76
|
+
class="w-8 h-8 rounded border-2 border-base-300 shrink-0 mt-6"
|
|
103
77
|
style="background-color: {value};"
|
|
104
78
|
aria-label="Color preview"
|
|
105
79
|
></div>
|
|
106
80
|
{/if}
|
|
107
81
|
</div>
|
|
108
|
-
|
|
109
|
-
{#if value && !isValidHex(value)}
|
|
110
|
-
<p class="text-xs text-red-500">
|
|
111
|
-
Please enter a valid hex color (e.g., #ff0000 or #f00)
|
|
112
|
-
</p>
|
|
113
|
-
{/if}
|
|
114
82
|
</div>
|
|
@@ -1,19 +1,10 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import { onMount } from "svelte";
|
|
3
3
|
|
|
4
|
-
/**
|
|
5
|
-
* FeatureCard component - SSR-safe implementation
|
|
6
|
-
* @component
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
4
|
interface Props {
|
|
10
|
-
/** Icon to display */
|
|
11
5
|
icon?: string;
|
|
12
|
-
/** Title of the feature */
|
|
13
6
|
title: string;
|
|
14
|
-
/** Description of the feature */
|
|
15
7
|
description: string;
|
|
16
|
-
/** Additional CSS classes */
|
|
17
8
|
className?: string;
|
|
18
9
|
}
|
|
19
10
|
|
|
@@ -34,7 +25,7 @@
|
|
|
34
25
|
|
|
35
26
|
{#if mounted}
|
|
36
27
|
<div
|
|
37
|
-
class="p-6 rounded-lg bg-
|
|
28
|
+
class="p-6 rounded-lg bg-base-50 border border-border hover:border-primary/20 hover:shadow-sm transition-colors duration-200 {className}"
|
|
38
29
|
{...restProps}
|
|
39
30
|
>
|
|
40
31
|
<div class="flex items-start gap-4">
|
|
@@ -52,9 +43,8 @@
|
|
|
52
43
|
</div>
|
|
53
44
|
</div>
|
|
54
45
|
{:else}
|
|
55
|
-
<!-- SSR fallback -->
|
|
56
46
|
<div
|
|
57
|
-
class="p-6 rounded-lg bg-
|
|
47
|
+
class="p-6 rounded-lg bg-base-100 border border-base-300 hover:border-base-400 hover:shadow-sm transition-colors duration-200 {className}"
|
|
58
48
|
{...restProps}
|
|
59
49
|
>
|
|
60
50
|
<div class="flex items-start gap-4">
|
|
@@ -1,15 +1,7 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* FeatureCard component - SSR-safe implementation
|
|
3
|
-
* @component
|
|
4
|
-
*/
|
|
5
1
|
interface Props {
|
|
6
|
-
/** Icon to display */
|
|
7
2
|
icon?: string;
|
|
8
|
-
/** Title of the feature */
|
|
9
3
|
title: string;
|
|
10
|
-
/** Description of the feature */
|
|
11
4
|
description: string;
|
|
12
|
-
/** Additional CSS classes */
|
|
13
5
|
className?: string;
|
|
14
6
|
}
|
|
15
7
|
declare const FeatureCard: import("svelte").Component<Props, {}, "">;
|
|
@@ -6,11 +6,9 @@
|
|
|
6
6
|
|
|
7
7
|
let { level = 1, text }: Props = $props();
|
|
8
8
|
|
|
9
|
-
// Automatic weight and size based on heading level
|
|
10
9
|
const fontWeight = $derived(level <= 2 ? "700" : "500");
|
|
11
10
|
const Tag = $derived(`h${level}`);
|
|
12
11
|
|
|
13
|
-
// Size classes for different heading levels
|
|
14
12
|
const sizeClasses = {
|
|
15
13
|
1: "text-4xl",
|
|
16
14
|
2: "text-3xl",
|
package/dist/atoms/Input.svelte
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import { CheckCircle, AlertTriangle, AlertCircle } from "@lucide/svelte";
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
import type { SemanticVariant, SizeVariant } from "../../types/variants.js";
|
|
4
|
+
|
|
5
5
|
function generateId(prefix: string = "id"): string {
|
|
6
6
|
if (typeof window !== "undefined") {
|
|
7
7
|
return `${prefix}-${Math.random().toString(36).substr(2, 9)}`;
|
|
@@ -17,8 +17,8 @@
|
|
|
17
17
|
label?: string;
|
|
18
18
|
placeholder?: string;
|
|
19
19
|
disabled?: boolean;
|
|
20
|
-
size?:
|
|
21
|
-
variant?:
|
|
20
|
+
size?: SizeVariant;
|
|
21
|
+
variant?: SemanticVariant;
|
|
22
22
|
message?: string;
|
|
23
23
|
oninput?: (event: Event) => void;
|
|
24
24
|
}
|
|
@@ -37,34 +37,30 @@
|
|
|
37
37
|
...restProps
|
|
38
38
|
}: Props = $props();
|
|
39
39
|
|
|
40
|
-
// Generate unique ID - SSR safe (call directly, not in $state)
|
|
41
40
|
const inputId = generateId("input");
|
|
42
41
|
|
|
43
|
-
// Size classes matching M3 design specifications
|
|
44
42
|
const sizeClass = $derived(() => {
|
|
45
43
|
if (size === "sm") {
|
|
46
44
|
return {
|
|
47
45
|
padding: "px-4 py-2",
|
|
48
46
|
text: "text-sm",
|
|
49
|
-
leading: "leading-5"
|
|
47
|
+
leading: "leading-5",
|
|
50
48
|
};
|
|
51
49
|
} else if (size === "lg") {
|
|
52
50
|
return {
|
|
53
51
|
padding: "px-4 py-3",
|
|
54
52
|
text: "text-base",
|
|
55
|
-
leading: "leading-6"
|
|
53
|
+
leading: "leading-6",
|
|
56
54
|
};
|
|
57
55
|
} else {
|
|
58
|
-
// default md
|
|
59
56
|
return {
|
|
60
57
|
padding: "px-4 py-2.5",
|
|
61
58
|
text: "text-base",
|
|
62
|
-
leading: "leading-6"
|
|
59
|
+
leading: "leading-6",
|
|
63
60
|
};
|
|
64
61
|
}
|
|
65
62
|
});
|
|
66
63
|
|
|
67
|
-
// Variant classes using semantic colors
|
|
68
64
|
const variantClass = $derived(() => {
|
|
69
65
|
return variant === "success"
|
|
70
66
|
? "border-success focus:border-success focus:ring-success"
|
|
@@ -75,21 +71,18 @@
|
|
|
75
71
|
: "border-0 focus:ring-2 focus:ring-brand-500"; // default - no border
|
|
76
72
|
});
|
|
77
73
|
|
|
78
|
-
// Input classes matching M3 design
|
|
79
74
|
const inputClasses = $derived(() => {
|
|
80
75
|
const sizeStyles = sizeClass();
|
|
81
76
|
const baseClasses =
|
|
82
|
-
"w-full bg-
|
|
77
|
+
"w-full bg-input hover:bg-input-hover focus:bg-input-focus disabled:bg-input-disabled rounded-lg transition-all duration-200 placeholder:text-description text-body focus:outline-none focus:ring-offset-0 disabled:opacity-50 disabled:cursor-not-allowed";
|
|
83
78
|
|
|
84
79
|
return `${baseClasses} ${sizeStyles.padding} ${sizeStyles.text} ${sizeStyles.leading} ${variantClass()}`.trim();
|
|
85
80
|
});
|
|
86
81
|
|
|
87
|
-
// Label classes using semantic text colors
|
|
88
82
|
const labelClasses = $derived(
|
|
89
83
|
() => "block text-sm font-medium text-label mb-1",
|
|
90
84
|
);
|
|
91
85
|
|
|
92
|
-
// Message classes based on variant
|
|
93
86
|
const messageClasses = $derived(() => {
|
|
94
87
|
if (variant === "error") {
|
|
95
88
|
return "text-error text-sm mt-1 flex items-center gap-1.5";
|
|
@@ -101,7 +94,6 @@
|
|
|
101
94
|
return "text-description text-sm mt-1 flex items-center gap-1.5";
|
|
102
95
|
});
|
|
103
96
|
|
|
104
|
-
// Get icon component based on variant
|
|
105
97
|
const getIcon = $derived(() => {
|
|
106
98
|
if (variant === "error") return AlertCircle;
|
|
107
99
|
if (variant === "success") return CheckCircle;
|
|
@@ -113,7 +105,6 @@
|
|
|
113
105
|
const target = event.target as HTMLInputElement;
|
|
114
106
|
value = target.value;
|
|
115
107
|
|
|
116
|
-
// Call the parent's oninput handler if provided
|
|
117
108
|
if (oninput) {
|
|
118
109
|
oninput(event);
|
|
119
110
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { SemanticVariant, SizeVariant } from "../../types/variants.js";
|
|
1
2
|
interface Props {
|
|
2
3
|
value?: string;
|
|
3
4
|
type?: string;
|
|
@@ -5,8 +6,8 @@ interface Props {
|
|
|
5
6
|
label?: string;
|
|
6
7
|
placeholder?: string;
|
|
7
8
|
disabled?: boolean;
|
|
8
|
-
size?:
|
|
9
|
-
variant?:
|
|
9
|
+
size?: SizeVariant;
|
|
10
|
+
variant?: SemanticVariant;
|
|
10
11
|
message?: string;
|
|
11
12
|
oninput?: (event: Event) => void;
|
|
12
13
|
}
|
|
@@ -14,17 +14,14 @@
|
|
|
14
14
|
...restProps
|
|
15
15
|
}: Props = $props();
|
|
16
16
|
|
|
17
|
-
// Generate unique ID - SSR safe
|
|
18
17
|
let progressId = $state(
|
|
19
18
|
typeof window !== "undefined"
|
|
20
19
|
? `progress-${Math.random().toString(36).substr(2, 9)}`
|
|
21
20
|
: `progress-ssr-${Date.now()}`,
|
|
22
21
|
);
|
|
23
22
|
|
|
24
|
-
// Calculate percentage
|
|
25
23
|
let percentage = $derived(Math.min(Math.max((value / max) * 100, 0), 100));
|
|
26
24
|
|
|
27
|
-
// Simple size classes
|
|
28
25
|
let sizeClasses = $derived({
|
|
29
26
|
sm: "h-1",
|
|
30
27
|
md: "h-2",
|
|
@@ -44,7 +41,7 @@
|
|
|
44
41
|
|
|
45
42
|
<div
|
|
46
43
|
id={progressId}
|
|
47
|
-
class="w-full bg-
|
|
44
|
+
class="w-full bg-base-200 rounded-full overflow-hidden {sizeClasses[
|
|
48
45
|
size
|
|
49
46
|
]}"
|
|
50
47
|
role="progressbar"
|