zabi-components 4.0.2 → 5.0.2
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 +2 -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 -23
- 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 +32 -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 +31 -15
- package/dist/index.js +75 -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 -13
- 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 -5
- 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 +41 -17
- package/dist/CodeBlock-pT5-FgZd.js +0 -431
- package/dist/ContactForm-CHI_jeFY.js +0 -580
- package/dist/FeatureCard-iBFGbgVE.js +0 -656
- package/dist/Navigation-BOT-UHg0.js +0 -104
- package/dist/ThemeToggle-BlNPkAQy.js +0 -48
- package/dist/index/index.js +0 -63
- package/dist/molecules/KeyValueForm.types.d.ts +0 -11
- package/dist/ssr-safe-bsWGK4V4.js +0 -2232
- package/dist/types/index.d.ts +0 -4
- package/dist/types/index.js +0 -1
- package/dist/vite.svg +0 -1
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
// SSR-safe ID generation
|
|
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
|
+
}
|
|
10
|
+
|
|
11
|
+
// Input variant classes
|
|
12
|
+
function getInputVariantClasses(
|
|
13
|
+
variant: "default" | "success" | "warning" | "error" | "info",
|
|
14
|
+
): string {
|
|
15
|
+
const variantMap = {
|
|
16
|
+
default:
|
|
17
|
+
"border-gray-300 focus:border-blue-500 focus:ring-blue-500",
|
|
18
|
+
success:
|
|
19
|
+
"border-green-300 focus:border-green-500 focus:ring-green-500",
|
|
20
|
+
warning:
|
|
21
|
+
"border-yellow-300 focus:border-yellow-500 focus:ring-yellow-500",
|
|
22
|
+
error: "border-red-300 focus:border-red-500 focus:ring-red-500",
|
|
23
|
+
info: "border-blue-300 focus:border-blue-500 focus:ring-blue-500",
|
|
24
|
+
};
|
|
25
|
+
return variantMap[variant] || variantMap.default;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
interface Props {
|
|
29
|
+
value?: string;
|
|
30
|
+
name?: string;
|
|
31
|
+
label?: string;
|
|
32
|
+
placeholder?: string;
|
|
33
|
+
disabled?: boolean;
|
|
34
|
+
rows?: number;
|
|
35
|
+
size?: "sm" | "md" | "lg";
|
|
36
|
+
variant?: "default" | "success" | "warning" | "error";
|
|
37
|
+
oninput?: (event: Event) => void;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
let {
|
|
41
|
+
value = "",
|
|
42
|
+
name = "",
|
|
43
|
+
label = "",
|
|
44
|
+
placeholder = "",
|
|
45
|
+
disabled = false,
|
|
46
|
+
rows = 4,
|
|
47
|
+
size = "md",
|
|
48
|
+
variant = "default",
|
|
49
|
+
oninput,
|
|
50
|
+
...restProps
|
|
51
|
+
}: Props = $props();
|
|
52
|
+
|
|
53
|
+
// Generate unique ID - SSR safe (call directly, not in $state)
|
|
54
|
+
const textareaId = generateId("textarea");
|
|
55
|
+
|
|
56
|
+
// Size classes using full class names
|
|
57
|
+
const sizeClass = $derived(() => {
|
|
58
|
+
return size === "sm"
|
|
59
|
+
? "px-3 py-1.5 text-sm"
|
|
60
|
+
: size === "lg"
|
|
61
|
+
? "px-5 py-3 text-base"
|
|
62
|
+
: "px-4 py-2 text-sm"; // default md
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
// Variant classes using full class names
|
|
66
|
+
const variantClass = $derived(() => {
|
|
67
|
+
return variant === "success"
|
|
68
|
+
? "border-green-300 focus:border-green-500 focus:ring-green-500"
|
|
69
|
+
: variant === "warning"
|
|
70
|
+
? "border-yellow-300 focus:border-yellow-500 focus:ring-yellow-500"
|
|
71
|
+
: variant === "error"
|
|
72
|
+
? "border-red-300 focus:border-red-500 focus:ring-red-500"
|
|
73
|
+
: "border-gray-300 focus:border-blue-500 focus:ring-blue-500"; // default
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
// Textarea classes using Badge pattern
|
|
77
|
+
const textareaClasses = $derived(() => {
|
|
78
|
+
const baseClasses =
|
|
79
|
+
"w-full rounded-md transition-colors duration-200 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-offset-surface disabled:opacity-50 disabled:cursor-not-allowed disabled:bg-surface-disabled resize-y";
|
|
80
|
+
|
|
81
|
+
return `${baseClasses} ${sizeClass()} ${variantClass()}`.trim();
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
// Label classes using semantic text colors
|
|
85
|
+
const labelClasses = $derived(
|
|
86
|
+
() => "block text-sm font-medium text-label mb-1",
|
|
87
|
+
);
|
|
88
|
+
|
|
89
|
+
function handleInput(event: Event) {
|
|
90
|
+
const target = event.target as HTMLTextAreaElement;
|
|
91
|
+
value = target.value;
|
|
92
|
+
|
|
93
|
+
// Call the parent's oninput handler if provided
|
|
94
|
+
if (oninput) {
|
|
95
|
+
oninput(event);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
</script>
|
|
99
|
+
|
|
100
|
+
<div>
|
|
101
|
+
{#if label}
|
|
102
|
+
<label for={textareaId} class={labelClasses()}>{label}</label>
|
|
103
|
+
{/if}
|
|
104
|
+
|
|
105
|
+
<textarea
|
|
106
|
+
id={textareaId}
|
|
107
|
+
{name}
|
|
108
|
+
{value}
|
|
109
|
+
{placeholder}
|
|
110
|
+
{disabled}
|
|
111
|
+
{rows}
|
|
112
|
+
class={textareaClasses()}
|
|
113
|
+
oninput={handleInput}
|
|
114
|
+
{...restProps}
|
|
115
|
+
></textarea>
|
|
116
|
+
</div>
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
interface Props {
|
|
2
|
+
value?: string;
|
|
3
|
+
name?: string;
|
|
4
|
+
label?: string;
|
|
5
|
+
placeholder?: string;
|
|
6
|
+
disabled?: boolean;
|
|
7
|
+
rows?: number;
|
|
8
|
+
size?: "sm" | "md" | "lg";
|
|
9
|
+
variant?: "default" | "success" | "warning" | "error";
|
|
10
|
+
oninput?: (event: Event) => void;
|
|
11
|
+
}
|
|
12
|
+
declare const Textarea: import("svelte").Component<Props, {}, "">;
|
|
13
|
+
type Textarea = ReturnType<typeof Textarea>;
|
|
14
|
+
export default Textarea;
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { onMount } from "svelte";
|
|
3
|
+
// SSR-safe utilities
|
|
4
|
+
function safeLocalStorage(): Storage | undefined {
|
|
5
|
+
return typeof window !== "undefined" ? localStorage : undefined;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
function safeDocument(): Document | undefined {
|
|
9
|
+
return typeof window !== "undefined" ? document : undefined;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
interface Props {
|
|
13
|
+
isDark?: boolean;
|
|
14
|
+
onclick?: (event: Event) => void;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
let { isDark = false, ...restProps }: Props = $props();
|
|
18
|
+
|
|
19
|
+
let mounted = $state(false);
|
|
20
|
+
|
|
21
|
+
onMount(() => {
|
|
22
|
+
mounted = true;
|
|
23
|
+
// Check for saved theme preference or default to light mode
|
|
24
|
+
const storage = safeLocalStorage();
|
|
25
|
+
if (storage) {
|
|
26
|
+
const savedTheme = storage.getItem("theme");
|
|
27
|
+
let prefersDark = false;
|
|
28
|
+
|
|
29
|
+
// Only check media query when mounted and in browser
|
|
30
|
+
if (mounted && typeof window !== "undefined" && window.matchMedia) {
|
|
31
|
+
try {
|
|
32
|
+
prefersDark = window.matchMedia(
|
|
33
|
+
"(prefers-color-scheme: dark)",
|
|
34
|
+
).matches;
|
|
35
|
+
} catch (e) {
|
|
36
|
+
// Fallback if matchMedia fails
|
|
37
|
+
prefersDark = false;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
isDark = savedTheme === "dark" || (!savedTheme && prefersDark);
|
|
42
|
+
updateTheme();
|
|
43
|
+
}
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
function toggleTheme(event: Event) {
|
|
47
|
+
isDark = !isDark;
|
|
48
|
+
updateTheme();
|
|
49
|
+
const storage = safeLocalStorage();
|
|
50
|
+
if (mounted && storage) {
|
|
51
|
+
storage.setItem("theme", isDark ? "dark" : "light");
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function updateTheme() {
|
|
56
|
+
const doc = safeDocument();
|
|
57
|
+
if (mounted && doc) {
|
|
58
|
+
if (isDark) {
|
|
59
|
+
doc.documentElement.classList.add("dark");
|
|
60
|
+
} else {
|
|
61
|
+
doc.documentElement.classList.remove("dark");
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
</script>
|
|
66
|
+
|
|
67
|
+
{#if mounted}
|
|
68
|
+
<button
|
|
69
|
+
onclick={toggleTheme}
|
|
70
|
+
class="w-10 h-10 bg-gray-100 hover:bg-gray-200 border border-gray-300 rounded-lg flex items-center justify-center text-gray-700 focus:outline-none focus:ring-2 focus:ring-blue-500"
|
|
71
|
+
aria-label={isDark ? "Switch to light mode" : "Switch to dark mode"}
|
|
72
|
+
{...restProps}
|
|
73
|
+
>
|
|
74
|
+
{#if isDark}
|
|
75
|
+
<span class="text-lg">☀️</span>
|
|
76
|
+
{:else}
|
|
77
|
+
<span class="text-lg">🌙</span>
|
|
78
|
+
{/if}
|
|
79
|
+
</button>
|
|
80
|
+
{:else}
|
|
81
|
+
<!-- SSR fallback -->
|
|
82
|
+
<button
|
|
83
|
+
class="w-10 h-10 bg-gray-100 border border-gray-300 rounded-lg flex items-center justify-center text-gray-700"
|
|
84
|
+
aria-label="Theme toggle"
|
|
85
|
+
{...restProps}
|
|
86
|
+
>
|
|
87
|
+
<span class="text-lg">🌙</span>
|
|
88
|
+
</button>
|
|
89
|
+
{/if}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
interface Props {
|
|
3
|
+
message?: string;
|
|
4
|
+
type?: "success" | "error" | "warning" | "info";
|
|
5
|
+
closable?: boolean;
|
|
6
|
+
onclick?: (event: Event) => void;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
let {
|
|
10
|
+
message = "",
|
|
11
|
+
type = "info",
|
|
12
|
+
closable = true,
|
|
13
|
+
onclick,
|
|
14
|
+
...restProps
|
|
15
|
+
}: Props = $props();
|
|
16
|
+
|
|
17
|
+
let isVisible = $state(true);
|
|
18
|
+
|
|
19
|
+
// Simple type classes
|
|
20
|
+
const typeClasses = {
|
|
21
|
+
success: "bg-green-100 border-green-300 text-success",
|
|
22
|
+
error: "bg-red-100 border-red-300 text-error",
|
|
23
|
+
warning: "bg-yellow-100 border-yellow-300 text-warning",
|
|
24
|
+
info: "bg-blue-100 border-blue-300 text-body",
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
function closeToast(event: Event) {
|
|
28
|
+
isVisible = false;
|
|
29
|
+
if (onclick) {
|
|
30
|
+
onclick(event);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
</script>
|
|
34
|
+
|
|
35
|
+
{#if isVisible}
|
|
36
|
+
<div
|
|
37
|
+
class="fixed top-4 right-4 max-w-sm w-full bg-white border rounded-lg shadow-lg p-4 z-50"
|
|
38
|
+
role="alert"
|
|
39
|
+
{...restProps}
|
|
40
|
+
>
|
|
41
|
+
<div class="flex items-start">
|
|
42
|
+
<div class="flex-1">
|
|
43
|
+
<p class="text-sm {typeClasses[type]}">{message}</p>
|
|
44
|
+
</div>
|
|
45
|
+
|
|
46
|
+
{#if closable}
|
|
47
|
+
<button
|
|
48
|
+
type="button"
|
|
49
|
+
class="ml-3 text-gray-400 hover:text-gray-600"
|
|
50
|
+
onclick={closeToast}
|
|
51
|
+
aria-label="Close notification"
|
|
52
|
+
>
|
|
53
|
+
×
|
|
54
|
+
</button>
|
|
55
|
+
{/if}
|
|
56
|
+
</div>
|
|
57
|
+
</div>
|
|
58
|
+
{/if}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
interface Props {
|
|
2
|
+
message?: string;
|
|
3
|
+
type?: "success" | "error" | "warning" | "info";
|
|
4
|
+
closable?: boolean;
|
|
5
|
+
onclick?: (event: Event) => void;
|
|
6
|
+
}
|
|
7
|
+
declare const Toast: import("svelte").Component<Props, {}, "">;
|
|
8
|
+
type Toast = ReturnType<typeof Toast>;
|
|
9
|
+
export default Toast;
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
// SSR-safe ID generation
|
|
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
|
+
}
|
|
10
|
+
|
|
11
|
+
// Props using Svelte 5 runes
|
|
12
|
+
interface Props {
|
|
13
|
+
checked?: boolean;
|
|
14
|
+
disabled?: boolean;
|
|
15
|
+
label?: string;
|
|
16
|
+
onclick?: (event: MouseEvent) => void;
|
|
17
|
+
onchange?: (event: { checked: boolean }) => void;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
let {
|
|
21
|
+
checked = false,
|
|
22
|
+
disabled = false,
|
|
23
|
+
label = "",
|
|
24
|
+
onclick,
|
|
25
|
+
onchange,
|
|
26
|
+
...restProps
|
|
27
|
+
}: Props = $props();
|
|
28
|
+
|
|
29
|
+
// SSR-safe ID generation (call directly, not in onMount)
|
|
30
|
+
const toggleId = generateId("toggle");
|
|
31
|
+
|
|
32
|
+
// Handle click
|
|
33
|
+
function handleClick(event: MouseEvent) {
|
|
34
|
+
if (disabled) return;
|
|
35
|
+
checked = !checked;
|
|
36
|
+
|
|
37
|
+
// Call parent handlers if provided
|
|
38
|
+
if (onclick) onclick(event);
|
|
39
|
+
if (onchange) onchange({ checked });
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// Toggle button classes using full class names
|
|
43
|
+
const toggleButtonClasses = $derived(() => {
|
|
44
|
+
const baseClasses =
|
|
45
|
+
"relative inline-flex w-11 h-6 flex-shrink-0 cursor-pointer rounded-full border-2 border-transparent transition-colors duration-200 ease-in-out focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2";
|
|
46
|
+
const stateClasses = checked ? "bg-blue-600" : "bg-gray-200";
|
|
47
|
+
const disabledClasses = disabled ? "opacity-50 cursor-not-allowed" : "";
|
|
48
|
+
|
|
49
|
+
return `${baseClasses} ${stateClasses} ${disabledClasses}`.trim();
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
// Toggle thumb classes using full class names
|
|
53
|
+
const toggleThumbClasses = $derived(() => {
|
|
54
|
+
const baseClasses =
|
|
55
|
+
"pointer-events-none inline-block w-5 h-5 transform rounded-full bg-white shadow-lg transition duration-200 ease-in-out";
|
|
56
|
+
const positionClasses = checked ? "translate-x-5" : "translate-x-0";
|
|
57
|
+
|
|
58
|
+
return `${baseClasses} ${positionClasses}`.trim();
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
// Handle keyboard
|
|
62
|
+
function handleKeydown(event: KeyboardEvent) {
|
|
63
|
+
if (disabled) return;
|
|
64
|
+
if (event.key === " " || event.key === "Enter") {
|
|
65
|
+
event.preventDefault();
|
|
66
|
+
handleClick(event as any);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
</script>
|
|
70
|
+
|
|
71
|
+
<div class="flex items-center gap-3">
|
|
72
|
+
<button
|
|
73
|
+
type="button"
|
|
74
|
+
role="switch"
|
|
75
|
+
id={toggleId}
|
|
76
|
+
aria-checked={checked}
|
|
77
|
+
aria-label={label || "Toggle"}
|
|
78
|
+
{disabled}
|
|
79
|
+
onclick={handleClick}
|
|
80
|
+
onkeydown={handleKeydown}
|
|
81
|
+
class={toggleButtonClasses()}
|
|
82
|
+
>
|
|
83
|
+
<span class={toggleThumbClasses()}></span>
|
|
84
|
+
</button>
|
|
85
|
+
|
|
86
|
+
{#if label}
|
|
87
|
+
<label
|
|
88
|
+
for={toggleId}
|
|
89
|
+
class="text-sm font-medium text-label cursor-pointer"
|
|
90
|
+
>
|
|
91
|
+
{label}
|
|
92
|
+
</label>
|
|
93
|
+
{/if}
|
|
94
|
+
</div>
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
interface Props {
|
|
2
|
+
checked?: boolean;
|
|
3
|
+
disabled?: boolean;
|
|
4
|
+
label?: string;
|
|
5
|
+
onclick?: (event: MouseEvent) => void;
|
|
6
|
+
onchange?: (event: {
|
|
7
|
+
checked: boolean;
|
|
8
|
+
}) => void;
|
|
9
|
+
}
|
|
10
|
+
declare const Toggle: import("svelte").Component<Props, {}, "">;
|
|
11
|
+
type Toggle = ReturnType<typeof Toggle>;
|
|
12
|
+
export default Toggle;
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
interface Props {
|
|
3
|
+
content?: string;
|
|
4
|
+
placement?: "top" | "bottom" | "left" | "right";
|
|
5
|
+
delay?: number;
|
|
6
|
+
disabled?: boolean;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
let {
|
|
10
|
+
content = "",
|
|
11
|
+
placement = "top",
|
|
12
|
+
delay = 0,
|
|
13
|
+
disabled = false,
|
|
14
|
+
children,
|
|
15
|
+
...restProps
|
|
16
|
+
}: Props & { children?: any } = $props();
|
|
17
|
+
</script>
|
|
18
|
+
|
|
19
|
+
<div
|
|
20
|
+
class="tooltip-container group relative inline-block"
|
|
21
|
+
data-placement={placement}
|
|
22
|
+
data-delay={delay}
|
|
23
|
+
data-disabled={disabled}
|
|
24
|
+
{...restProps}
|
|
25
|
+
>
|
|
26
|
+
{@render children?.()}
|
|
27
|
+
|
|
28
|
+
{#if content && !disabled}
|
|
29
|
+
<div
|
|
30
|
+
class="tooltip group-hover:opacity-100 group-hover:visible group-focus-within:opacity-100 group-focus-within:visible"
|
|
31
|
+
role="tooltip"
|
|
32
|
+
aria-hidden="true"
|
|
33
|
+
>
|
|
34
|
+
{content}
|
|
35
|
+
</div>
|
|
36
|
+
{/if}
|
|
37
|
+
</div>
|
|
38
|
+
|
|
39
|
+
<style>
|
|
40
|
+
:root {
|
|
41
|
+
--tooltip-bg: #1f2937;
|
|
42
|
+
--tooltip-color: white;
|
|
43
|
+
--tooltip-padding: 0.5rem 0.75rem;
|
|
44
|
+
--tooltip-radius: 0.375rem;
|
|
45
|
+
--tooltip-font-size: 0.875rem;
|
|
46
|
+
--tooltip-line-height: 1.25rem;
|
|
47
|
+
--tooltip-max-width: 200px;
|
|
48
|
+
--tooltip-gap: 0.5rem;
|
|
49
|
+
--tooltip-arrow-size: 4px;
|
|
50
|
+
--tooltip-transition: opacity 0.2s ease-in-out,
|
|
51
|
+
visibility 0.2s ease-in-out;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
.tooltip-container {
|
|
55
|
+
position: relative;
|
|
56
|
+
display: inline-block;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
.tooltip {
|
|
60
|
+
position: absolute;
|
|
61
|
+
z-index: 50;
|
|
62
|
+
padding: var(--tooltip-padding);
|
|
63
|
+
background-color: var(--tooltip-bg);
|
|
64
|
+
color: var(--tooltip-color);
|
|
65
|
+
border-radius: var(--tooltip-radius);
|
|
66
|
+
font-size: var(--tooltip-font-size);
|
|
67
|
+
line-height: var(--tooltip-line-height);
|
|
68
|
+
max-width: var(--tooltip-max-width);
|
|
69
|
+
white-space: normal;
|
|
70
|
+
word-wrap: break-word;
|
|
71
|
+
opacity: 0;
|
|
72
|
+
visibility: hidden;
|
|
73
|
+
transition: var(--tooltip-transition);
|
|
74
|
+
pointer-events: none;
|
|
75
|
+
/* Use logical properties for better internationalization */
|
|
76
|
+
inset-inline-start: 50%;
|
|
77
|
+
inset-block-start: 50%;
|
|
78
|
+
transform: translate(-50%, -50%);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/* Simplified positioning using CSS custom properties and logical properties */
|
|
82
|
+
.tooltip-container[data-placement="top"] .tooltip {
|
|
83
|
+
inset-block-end: 100%;
|
|
84
|
+
inset-inline-start: 50%;
|
|
85
|
+
transform: translateX(-50%);
|
|
86
|
+
margin-block-end: var(--tooltip-gap);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
.tooltip-container[data-placement="bottom"] .tooltip {
|
|
90
|
+
inset-block-start: 100%;
|
|
91
|
+
inset-inline-start: 50%;
|
|
92
|
+
transform: translateX(-50%);
|
|
93
|
+
margin-block-start: var(--tooltip-gap);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
.tooltip-container[data-placement="left"] .tooltip {
|
|
97
|
+
inset-inline-end: 100%;
|
|
98
|
+
inset-block-start: 50%;
|
|
99
|
+
transform: translateY(-50%);
|
|
100
|
+
margin-inline-end: var(--tooltip-gap);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
.tooltip-container[data-placement="right"] .tooltip {
|
|
104
|
+
inset-inline-start: 100%;
|
|
105
|
+
inset-block-start: 50%;
|
|
106
|
+
transform: translateY(-50%);
|
|
107
|
+
margin-inline-start: var(--tooltip-gap);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/* Modern arrow implementation using CSS clip-path for better performance */
|
|
111
|
+
.tooltip::before {
|
|
112
|
+
content: "";
|
|
113
|
+
position: absolute;
|
|
114
|
+
width: calc(var(--tooltip-arrow-size) * 2);
|
|
115
|
+
height: calc(var(--tooltip-arrow-size) * 2);
|
|
116
|
+
background-color: var(--tooltip-bg);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
.tooltip-container[data-placement="top"] .tooltip::before {
|
|
120
|
+
inset-block-start: 100%;
|
|
121
|
+
inset-inline-start: 50%;
|
|
122
|
+
transform: translateX(-50%);
|
|
123
|
+
clip-path: polygon(50% 100%, 0 0, 100% 0);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
.tooltip-container[data-placement="bottom"] .tooltip::before {
|
|
127
|
+
inset-block-end: 100%;
|
|
128
|
+
inset-inline-start: 50%;
|
|
129
|
+
transform: translateX(-50%);
|
|
130
|
+
clip-path: polygon(0 100%, 50% 0, 100% 100%);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
.tooltip-container[data-placement="left"] .tooltip::before {
|
|
134
|
+
inset-inline-start: 100%;
|
|
135
|
+
inset-block-start: 50%;
|
|
136
|
+
transform: translateY(-50%);
|
|
137
|
+
clip-path: polygon(0 50%, 100% 0, 100% 100%);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
.tooltip-container[data-placement="right"] .tooltip::before {
|
|
141
|
+
inset-inline-end: 100%;
|
|
142
|
+
inset-block-start: 50%;
|
|
143
|
+
transform: translateY(-50%);
|
|
144
|
+
clip-path: polygon(0 0, 100% 50%, 0 100%);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/* Delay support using CSS custom properties */
|
|
148
|
+
.tooltip-container[data-delay] .tooltip {
|
|
149
|
+
transition-delay: calc(var(--tooltip-delay, 0) * 1ms);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/* Responsive design with modern CSS */
|
|
153
|
+
@media (max-width: 640px) {
|
|
154
|
+
.tooltip {
|
|
155
|
+
--tooltip-max-width: calc(100vw - 2rem);
|
|
156
|
+
inset-inline-start: 50% !important;
|
|
157
|
+
inset-inline-end: auto !important;
|
|
158
|
+
transform: translateX(-50%) !important;
|
|
159
|
+
margin: var(--tooltip-gap) 0 !important;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
.tooltip::before {
|
|
163
|
+
display: none;
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/* Dark mode support */
|
|
168
|
+
@media (prefers-color-scheme: dark) {
|
|
169
|
+
:root {
|
|
170
|
+
--tooltip-bg: #374151;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/* High contrast mode support */
|
|
175
|
+
@media (prefers-contrast: high) {
|
|
176
|
+
:root {
|
|
177
|
+
--tooltip-bg: #000000;
|
|
178
|
+
--tooltip-color: #ffffff;
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/* Reduced motion support */
|
|
183
|
+
@media (prefers-reduced-motion: reduce) {
|
|
184
|
+
.tooltip {
|
|
185
|
+
transition: none;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
</style>
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
interface Props {
|
|
2
|
+
content?: string;
|
|
3
|
+
placement?: "top" | "bottom" | "left" | "right";
|
|
4
|
+
delay?: number;
|
|
5
|
+
disabled?: boolean;
|
|
6
|
+
}
|
|
7
|
+
type $$ComponentProps = Props & {
|
|
8
|
+
children?: any;
|
|
9
|
+
};
|
|
10
|
+
declare const Tooltip: import("svelte").Component<$$ComponentProps, {}, "">;
|
|
11
|
+
type Tooltip = ReturnType<typeof Tooltip>;
|
|
12
|
+
export default Tooltip;
|
package/dist/atoms/index.d.ts
CHANGED
|
@@ -1,20 +1,9 @@
|
|
|
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
4
|
export { default as Card } from './Card.svelte';
|
|
5
|
-
export { default as Checkbox } from './Checkbox.svelte';
|
|
6
|
-
export { default as ColorPicker } from './ColorPicker.svelte';
|
|
7
|
-
export { default as Heading } from './Heading.svelte';
|
|
8
5
|
export { default as Input } from './Input.svelte';
|
|
9
|
-
export { default as OptimizedImage } from './OptimizedImage.svelte';
|
|
10
|
-
export { default as DebugPanel } from './PerformanceMonitor.svelte';
|
|
11
|
-
export { default as Progress } from './Progress.svelte';
|
|
12
|
-
export { default as ScaleDemo } from './ScaleDemo.svelte';
|
|
13
|
-
export { default as Select } from './Select.svelte';
|
|
14
|
-
export { default as Skeleton } from './Skeleton.svelte';
|
|
15
6
|
export { default as Textarea } from './Textarea.svelte';
|
|
16
|
-
export { default as
|
|
17
|
-
export { default as
|
|
18
|
-
export { default as
|
|
19
|
-
export { default as Toggle } from './Toggle.svelte';
|
|
20
|
-
export { default as Tooltip } from './Tooltip.svelte';
|
|
7
|
+
export { default as Select } from './Select.svelte';
|
|
8
|
+
export { default as ColorPicker } from './ColorPicker.svelte';
|
|
9
|
+
export { default as Heading } from './Heading.svelte';
|
package/dist/atoms/index.js
CHANGED
|
@@ -1,23 +1,10 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
export {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
t as FeatureCard,
|
|
12
|
-
T as Heading,
|
|
13
|
-
n as Input,
|
|
14
|
-
g as OptimizedImage,
|
|
15
|
-
d as Progress,
|
|
16
|
-
l as Select,
|
|
17
|
-
C as Skeleton,
|
|
18
|
-
f as Textarea,
|
|
19
|
-
I as ThemeToggle,
|
|
20
|
-
m as Toast,
|
|
21
|
-
p as Toggle,
|
|
22
|
-
c as Tooltip
|
|
23
|
-
};
|
|
1
|
+
// Export atom components - All SSR-safe components
|
|
2
|
+
export { default as Toggle } from './Toggle.svelte';
|
|
3
|
+
export { default as Badge } from './Badge.svelte';
|
|
4
|
+
export { default as Button } from './Button.svelte';
|
|
5
|
+
export { default as Card } from './Card.svelte';
|
|
6
|
+
export { default as Input } from './Input.svelte';
|
|
7
|
+
export { default as Textarea } from './Textarea.svelte';
|
|
8
|
+
export { default as Select } from './Select.svelte';
|
|
9
|
+
export { default as ColorPicker } from './ColorPicker.svelte';
|
|
10
|
+
export { default as Heading } from './Heading.svelte';
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export { default as Toggle } from './Toggle.svelte';
|
|
2
|
+
export { default as Badge } from './Badge.svelte';
|
|
3
|
+
export { default as Button } from './Button.svelte';
|
|
4
|
+
export { default as Card } from './Card.svelte';
|
|
5
|
+
export { default as Input } from './Input.svelte';
|
|
6
|
+
export { default as Textarea } from './Textarea.svelte';
|
|
7
|
+
export { default as Select } from './Select.svelte';
|
|
8
|
+
export { default as ColorPicker } from './ColorPicker.svelte';
|
|
9
|
+
export { default as Heading } from './Heading.svelte';
|
|
10
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/atoms/index.ts"],"names":[],"mappings":"AACA,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,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"}
|