uisv 0.0.3 → 0.0.5
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/dist/components/alert.svelte +274 -0
- package/dist/components/alert.svelte.d.ts +24 -0
- package/dist/components/badge.svelte +227 -0
- package/dist/components/badge.svelte.d.ts +19 -0
- package/dist/components/banner.svelte +257 -0
- package/dist/components/banner.svelte.d.ts +24 -0
- package/dist/components/button.svelte +380 -0
- package/dist/components/button.svelte.d.ts +50 -0
- package/dist/components/card.svelte +70 -0
- package/dist/components/card.svelte.d.ts +17 -0
- package/dist/components/checkbox.svelte +176 -0
- package/dist/components/checkbox.svelte.d.ts +27 -0
- package/dist/components/checkboxgroup.svelte +260 -0
- package/dist/components/checkboxgroup.svelte.d.ts +26 -0
- package/dist/components/chip.svelte +82 -0
- package/dist/components/chip.svelte.d.ts +17 -0
- package/dist/components/index.d.ts +22 -0
- package/dist/components/index.js +22 -0
- package/dist/components/placeholder.svelte +32 -0
- package/dist/components/placeholder.svelte.d.ts +7 -0
- package/dist/components/progress.svelte +124 -0
- package/dist/components/progress.svelte.d.ts +21 -0
- package/dist/components/slider.svelte +172 -0
- package/dist/components/slider.svelte.d.ts +44 -0
- package/dist/components/switch.svelte +180 -0
- package/dist/components/switch.svelte.d.ts +27 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +2 -0
- package/dist/types.d.ts +7 -0
- package/dist/types.js +1 -0
- package/dist/utils/common.d.ts +14 -0
- package/dist/utils/common.js +18 -0
- package/dist/utils/keys.d.ts +8 -0
- package/dist/utils/keys.js +8 -0
- package/dist/utils/types.d.ts +1 -0
- package/dist/utils/types.js +1 -0
- package/dist/vite.d.ts +38 -0
- package/dist/vite.js +57 -0
- package/package.json +1 -1
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export * from './button.svelte';
|
|
2
|
+
export { default as Button } from './button.svelte';
|
|
3
|
+
export * from './badge.svelte';
|
|
4
|
+
export { default as Badge } from './badge.svelte';
|
|
5
|
+
export * from './alert.svelte';
|
|
6
|
+
export { default as Alert } from './alert.svelte';
|
|
7
|
+
export * from './banner.svelte';
|
|
8
|
+
export { default as Banner } from './banner.svelte';
|
|
9
|
+
export * from './progress.svelte';
|
|
10
|
+
export { default as Progress } from './progress.svelte';
|
|
11
|
+
export * from './card.svelte';
|
|
12
|
+
export { default as Card } from './card.svelte';
|
|
13
|
+
export * from './chip.svelte';
|
|
14
|
+
export { default as Chip } from './chip.svelte';
|
|
15
|
+
export * from './switch.svelte';
|
|
16
|
+
export { default as Switch } from './switch.svelte';
|
|
17
|
+
export * from './slider.svelte';
|
|
18
|
+
export { default as Slider } from './slider.svelte';
|
|
19
|
+
export * from './checkbox.svelte';
|
|
20
|
+
export { default as Checkbox } from './checkbox.svelte';
|
|
21
|
+
export * from './checkboxgroup.svelte';
|
|
22
|
+
export { default as CheckboxGroup } from './checkboxgroup.svelte';
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { ClassNameValue } from 'tailwind-merge';
|
|
3
|
+
|
|
4
|
+
let { class: klass }: { class?: ClassNameValue } = $props();
|
|
5
|
+
</script>
|
|
6
|
+
|
|
7
|
+
<svg
|
|
8
|
+
class={[
|
|
9
|
+
'inset-0 w-full stroke-secondary/10 border border-dashed border-secondary rounded-md',
|
|
10
|
+
klass
|
|
11
|
+
]}
|
|
12
|
+
fill="none"
|
|
13
|
+
>
|
|
14
|
+
<defs>
|
|
15
|
+
<pattern
|
|
16
|
+
id="pattern-5c1e4f0e-62d5-498b-8ff0-cf77bb448c8e"
|
|
17
|
+
x="0"
|
|
18
|
+
y="0"
|
|
19
|
+
width="10"
|
|
20
|
+
height="10"
|
|
21
|
+
patternUnits="userSpaceOnUse"
|
|
22
|
+
>
|
|
23
|
+
<path d="M-3 13 15-5M-5 5l18-18M-1 21 17 3"> </path>
|
|
24
|
+
</pattern>
|
|
25
|
+
</defs>
|
|
26
|
+
<rect
|
|
27
|
+
stroke="none"
|
|
28
|
+
fill="url(#pattern-5c1e4f0e-62d5-498b-8ff0-cf77bb448c8e)"
|
|
29
|
+
width="100%"
|
|
30
|
+
height="100%"
|
|
31
|
+
></rect>
|
|
32
|
+
</svg>
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { ClassNameValue } from 'tailwind-merge';
|
|
2
|
+
type $$ComponentProps = {
|
|
3
|
+
class?: ClassNameValue;
|
|
4
|
+
};
|
|
5
|
+
declare const Placeholder: import("svelte").Component<$$ComponentProps, {}, "">;
|
|
6
|
+
type Placeholder = ReturnType<typeof Placeholder>;
|
|
7
|
+
export default Placeholder;
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
<script module lang="ts">
|
|
2
|
+
import type { PropColor } from '../types.js';
|
|
3
|
+
import type { ClassNameValue } from 'tailwind-merge';
|
|
4
|
+
import { tv } from 'tailwind-variants';
|
|
5
|
+
|
|
6
|
+
export type ProgressProps = {
|
|
7
|
+
value?: number;
|
|
8
|
+
max?: number | string[];
|
|
9
|
+
animation?: 'swing' | 'carousel' | 'carousel-inverse' | 'elastic';
|
|
10
|
+
orientation?: 'horizontal' | 'veritcal';
|
|
11
|
+
color?: PropColor;
|
|
12
|
+
height?: number;
|
|
13
|
+
inverted?: boolean;
|
|
14
|
+
status?: boolean;
|
|
15
|
+
ui?: {
|
|
16
|
+
base?: ClassNameValue;
|
|
17
|
+
header?: ClassNameValue;
|
|
18
|
+
content?: ClassNameValue;
|
|
19
|
+
footer?: ClassNameValue;
|
|
20
|
+
};
|
|
21
|
+
};
|
|
22
|
+
</script>
|
|
23
|
+
|
|
24
|
+
<script lang="ts">
|
|
25
|
+
let {
|
|
26
|
+
max,
|
|
27
|
+
animation,
|
|
28
|
+
inverted,
|
|
29
|
+
status,
|
|
30
|
+
value,
|
|
31
|
+
orientation = 'horizontal',
|
|
32
|
+
color = 'primary',
|
|
33
|
+
height = '',
|
|
34
|
+
ui = {}
|
|
35
|
+
}: ProgressProps = $props();
|
|
36
|
+
|
|
37
|
+
const percentage = $derived.by(() => {
|
|
38
|
+
if (value === undefined) return null;
|
|
39
|
+
if (Array.isArray(max)) return (value / (max.length - 1)) * 100;
|
|
40
|
+
|
|
41
|
+
return (value / (max || 100)) * 100;
|
|
42
|
+
});
|
|
43
|
+
const indeterminate = $derived.by(() => {
|
|
44
|
+
if (value === undefined || percentage === null) return true;
|
|
45
|
+
if (value < 0) return true;
|
|
46
|
+
if (percentage > 100) return true;
|
|
47
|
+
|
|
48
|
+
return false;
|
|
49
|
+
});
|
|
50
|
+
const classes = $derived.by(() =>
|
|
51
|
+
tv({
|
|
52
|
+
slots: {
|
|
53
|
+
root: 'relative w-full rounded-full overflow-hidden bg-secondary-300',
|
|
54
|
+
status: '',
|
|
55
|
+
indicator: 'absolute transition-all rounded-full',
|
|
56
|
+
steps: ''
|
|
57
|
+
},
|
|
58
|
+
variants: {
|
|
59
|
+
color: {
|
|
60
|
+
primary: {
|
|
61
|
+
indicator: 'bg-primary-500'
|
|
62
|
+
},
|
|
63
|
+
secondary: {
|
|
64
|
+
indicator: 'bg-secondary-500'
|
|
65
|
+
},
|
|
66
|
+
info: {
|
|
67
|
+
indicator: 'bg-info-500'
|
|
68
|
+
},
|
|
69
|
+
success: {
|
|
70
|
+
indicator: 'bg-success-500'
|
|
71
|
+
},
|
|
72
|
+
warning: {
|
|
73
|
+
indicator: 'bg-warning-500'
|
|
74
|
+
},
|
|
75
|
+
error: {
|
|
76
|
+
indicator: 'bg-error-500'
|
|
77
|
+
}
|
|
78
|
+
},
|
|
79
|
+
animation: {
|
|
80
|
+
swing: [indeterminate ? 'animate-[swing_2s_ease-in-out_infinite' : ''],
|
|
81
|
+
carousel: [indeterminate ? '' : ''],
|
|
82
|
+
'carousel-inverse': [indeterminate ? '' : ''],
|
|
83
|
+
elastic: [indeterminate ? '' : '']
|
|
84
|
+
}
|
|
85
|
+
},
|
|
86
|
+
compoundVariants: []
|
|
87
|
+
})({
|
|
88
|
+
color,
|
|
89
|
+
animation: animation ?? 'swing'
|
|
90
|
+
})
|
|
91
|
+
);
|
|
92
|
+
</script>
|
|
93
|
+
|
|
94
|
+
<div data-state-indeterminate={indeterminate}>
|
|
95
|
+
<div class={classes.root({ class: [ui.base] })} style:height={`${height || 8}px`}>
|
|
96
|
+
<span class={classes.indicator({ class: ['h-full left-0'] })} style:width={`${percentage}%`}>
|
|
97
|
+
</span>
|
|
98
|
+
</div>
|
|
99
|
+
|
|
100
|
+
{#if Array.isArray(max)}
|
|
101
|
+
<p
|
|
102
|
+
class={[
|
|
103
|
+
'text-right transition',
|
|
104
|
+
value && value > 0 && max[value] ? 'text-primary-500' : 'text-secondary-500'
|
|
105
|
+
]}
|
|
106
|
+
>
|
|
107
|
+
{(value && max[value]) || max[0]}
|
|
108
|
+
</p>
|
|
109
|
+
{/if}
|
|
110
|
+
</div>
|
|
111
|
+
|
|
112
|
+
<style>
|
|
113
|
+
@keyframe swing {
|
|
114
|
+
0% {
|
|
115
|
+
width: 0%;
|
|
116
|
+
}
|
|
117
|
+
50% {
|
|
118
|
+
width: 100%;
|
|
119
|
+
}
|
|
120
|
+
100% {
|
|
121
|
+
width: 0%;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
</style>
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { PropColor } from '../types.js';
|
|
2
|
+
import type { ClassNameValue } from 'tailwind-merge';
|
|
3
|
+
export type ProgressProps = {
|
|
4
|
+
value?: number;
|
|
5
|
+
max?: number | string[];
|
|
6
|
+
animation?: 'swing' | 'carousel' | 'carousel-inverse' | 'elastic';
|
|
7
|
+
orientation?: 'horizontal' | 'veritcal';
|
|
8
|
+
color?: PropColor;
|
|
9
|
+
height?: number;
|
|
10
|
+
inverted?: boolean;
|
|
11
|
+
status?: boolean;
|
|
12
|
+
ui?: {
|
|
13
|
+
base?: ClassNameValue;
|
|
14
|
+
header?: ClassNameValue;
|
|
15
|
+
content?: ClassNameValue;
|
|
16
|
+
footer?: ClassNameValue;
|
|
17
|
+
};
|
|
18
|
+
};
|
|
19
|
+
declare const Progress: import("svelte").Component<ProgressProps, {}, "">;
|
|
20
|
+
type Progress = ReturnType<typeof Progress>;
|
|
21
|
+
export default Progress;
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
<script module lang="ts">
|
|
2
|
+
import { Slider } from 'bits-ui';
|
|
3
|
+
import type { PropColor } from '../types.js';
|
|
4
|
+
import type { ClassNameValue } from 'tailwind-merge';
|
|
5
|
+
import { tv } from 'tailwind-variants';
|
|
6
|
+
|
|
7
|
+
export type SliderProps<T> = {
|
|
8
|
+
value?: T;
|
|
9
|
+
default?: number | number[];
|
|
10
|
+
color?: PropColor;
|
|
11
|
+
size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl';
|
|
12
|
+
disabled?: boolean;
|
|
13
|
+
thumblabel?: boolean;
|
|
14
|
+
orientation?: 'vertical' | 'horizontal';
|
|
15
|
+
step?: number;
|
|
16
|
+
min?: number;
|
|
17
|
+
max?: number;
|
|
18
|
+
ui?: {
|
|
19
|
+
root?: ClassNameValue;
|
|
20
|
+
range?: ClassNameValue;
|
|
21
|
+
thumb?: ClassNameValue;
|
|
22
|
+
};
|
|
23
|
+
};
|
|
24
|
+
</script>
|
|
25
|
+
|
|
26
|
+
<script lang="ts" generics="T extends number | number[]">
|
|
27
|
+
let {
|
|
28
|
+
value = $bindable(),
|
|
29
|
+
default: def_value = 0,
|
|
30
|
+
color = 'primary',
|
|
31
|
+
size = 'md',
|
|
32
|
+
disabled,
|
|
33
|
+
thumblabel,
|
|
34
|
+
orientation = 'horizontal',
|
|
35
|
+
step,
|
|
36
|
+
min,
|
|
37
|
+
max,
|
|
38
|
+
ui = {}
|
|
39
|
+
}: SliderProps<T> = $props();
|
|
40
|
+
|
|
41
|
+
const default_value = $derived.by(() => {
|
|
42
|
+
if (typeof def_value === 'number') return [def_value];
|
|
43
|
+
|
|
44
|
+
return def_value;
|
|
45
|
+
});
|
|
46
|
+
let slider_value = $derived({
|
|
47
|
+
get() {
|
|
48
|
+
if (typeof value === 'number') return [value];
|
|
49
|
+
|
|
50
|
+
return (value as number[]) ?? default_value;
|
|
51
|
+
},
|
|
52
|
+
set(v: number[]) {
|
|
53
|
+
value = (v?.length !== 1 ? v : v[0]) as T;
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
const thumbs = $derived(slider_value.get()?.length ?? 1);
|
|
57
|
+
const classes = $derived.by(() =>
|
|
58
|
+
tv({
|
|
59
|
+
slots: {
|
|
60
|
+
root: [
|
|
61
|
+
'relative w-full flex rounded-full bg-neutral-300',
|
|
62
|
+
orientation === 'horizontal' ? 'items-center' : 'justify-center mx-1'
|
|
63
|
+
],
|
|
64
|
+
range: [
|
|
65
|
+
'rounded-full bg-neutral-200 p-0.5 relative transition',
|
|
66
|
+
orientation === 'horizontal' ? 'h-full' : 'w-full'
|
|
67
|
+
],
|
|
68
|
+
thumb: 'bg-white rounded-full border-2 outline-none transition',
|
|
69
|
+
tick: ''
|
|
70
|
+
},
|
|
71
|
+
variants: {
|
|
72
|
+
color: {
|
|
73
|
+
primary: {
|
|
74
|
+
root: '',
|
|
75
|
+
range: 'bg-primary-500',
|
|
76
|
+
thumb: 'border-primary-500'
|
|
77
|
+
},
|
|
78
|
+
secondary: {
|
|
79
|
+
range: ['bg-neutral-900'],
|
|
80
|
+
thumb: 'border-neutral-900'
|
|
81
|
+
},
|
|
82
|
+
info: {
|
|
83
|
+
range: ['bg-info-500'],
|
|
84
|
+
thumb: 'border-info-500'
|
|
85
|
+
},
|
|
86
|
+
success: {
|
|
87
|
+
range: ['bg-success-500'],
|
|
88
|
+
thumb: 'border-success-500'
|
|
89
|
+
},
|
|
90
|
+
warning: {
|
|
91
|
+
range: ['bg-warning-500'],
|
|
92
|
+
thumb: 'border-warning-500'
|
|
93
|
+
},
|
|
94
|
+
error: {
|
|
95
|
+
range: ['bg-error-500'],
|
|
96
|
+
thumb: 'border-error-500'
|
|
97
|
+
}
|
|
98
|
+
},
|
|
99
|
+
size: {
|
|
100
|
+
xs: {
|
|
101
|
+
root: [orientation === 'horizontal' ? 'h-1.5' : ''],
|
|
102
|
+
thumb: 'size-4',
|
|
103
|
+
tick: 'size-2.5'
|
|
104
|
+
},
|
|
105
|
+
sm: {
|
|
106
|
+
root: [orientation === 'horizontal' ? 'h-1.75' : ''],
|
|
107
|
+
thumb: 'size-4.5',
|
|
108
|
+
tick: 'size-3'
|
|
109
|
+
},
|
|
110
|
+
md: {
|
|
111
|
+
root: [orientation === 'horizontal' ? 'h-2' : 'w-2 h-48'],
|
|
112
|
+
thumb: 'size-5',
|
|
113
|
+
tick: 'size-3.5'
|
|
114
|
+
},
|
|
115
|
+
lg: {
|
|
116
|
+
root: [orientation === 'horizontal' ? 'h-2.5' : ''],
|
|
117
|
+
thumb: 'size-5.5',
|
|
118
|
+
tick: 'size-4'
|
|
119
|
+
},
|
|
120
|
+
xl: {
|
|
121
|
+
root: [orientation === 'horizontal' ? 'h-3' : 'w-3'],
|
|
122
|
+
thumb: 'size-6',
|
|
123
|
+
tick: 'size-4.5'
|
|
124
|
+
}
|
|
125
|
+
},
|
|
126
|
+
orientation: {
|
|
127
|
+
horizontal: {
|
|
128
|
+
root: '',
|
|
129
|
+
thumb: '',
|
|
130
|
+
tick: ''
|
|
131
|
+
},
|
|
132
|
+
vertical: {
|
|
133
|
+
root: '',
|
|
134
|
+
thumb: '',
|
|
135
|
+
tick: ''
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
},
|
|
139
|
+
compoundVariants: []
|
|
140
|
+
})({ color, size, orientation })
|
|
141
|
+
);
|
|
142
|
+
</script>
|
|
143
|
+
|
|
144
|
+
<Slider.Root
|
|
145
|
+
type="multiple"
|
|
146
|
+
bind:value={slider_value.get, slider_value.set}
|
|
147
|
+
{min}
|
|
148
|
+
{max}
|
|
149
|
+
{step}
|
|
150
|
+
{orientation}
|
|
151
|
+
{disabled}
|
|
152
|
+
class={classes.root({ class: [disabled ? 'opacity-75 cursor-not-allowed' : '', ui.root] })}
|
|
153
|
+
>
|
|
154
|
+
<Slider.Range class={classes.range({ class: [ui.range] })} />
|
|
155
|
+
|
|
156
|
+
{#each { length: thumbs }, index (index)}
|
|
157
|
+
<Slider.Thumb {index} class={classes.thumb({ class: ['group', ui.thumb] })}>
|
|
158
|
+
{#if thumblabel}
|
|
159
|
+
<Slider.ThumbLabel
|
|
160
|
+
{index}
|
|
161
|
+
position="bottom"
|
|
162
|
+
class={[
|
|
163
|
+
'opacity-0 transition pointer-events-none text-sm shadow-md px-2 h-6 flex items-center rounded-md mt-1 border border-secondary-200',
|
|
164
|
+
'data-[active=""]:(opacity-100) group-hover:(opacity-100)'
|
|
165
|
+
]}
|
|
166
|
+
>
|
|
167
|
+
{slider_value.get()[index]}
|
|
168
|
+
</Slider.ThumbLabel>
|
|
169
|
+
{/if}
|
|
170
|
+
</Slider.Thumb>
|
|
171
|
+
{/each}
|
|
172
|
+
</Slider.Root>
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { Slider } from 'bits-ui';
|
|
2
|
+
import type { PropColor } from '../types.js';
|
|
3
|
+
import type { ClassNameValue } from 'tailwind-merge';
|
|
4
|
+
export type SliderProps<T> = {
|
|
5
|
+
value?: T;
|
|
6
|
+
default?: number | number[];
|
|
7
|
+
color?: PropColor;
|
|
8
|
+
size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl';
|
|
9
|
+
disabled?: boolean;
|
|
10
|
+
thumblabel?: boolean;
|
|
11
|
+
orientation?: 'vertical' | 'horizontal';
|
|
12
|
+
step?: number;
|
|
13
|
+
min?: number;
|
|
14
|
+
max?: number;
|
|
15
|
+
ui?: {
|
|
16
|
+
root?: ClassNameValue;
|
|
17
|
+
range?: ClassNameValue;
|
|
18
|
+
thumb?: ClassNameValue;
|
|
19
|
+
};
|
|
20
|
+
};
|
|
21
|
+
declare function $$render<T extends number | number[]>(): {
|
|
22
|
+
props: SliderProps<T>;
|
|
23
|
+
exports: {};
|
|
24
|
+
bindings: "value";
|
|
25
|
+
slots: {};
|
|
26
|
+
events: {};
|
|
27
|
+
};
|
|
28
|
+
declare class __sveltets_Render<T extends number | number[]> {
|
|
29
|
+
props(): ReturnType<typeof $$render<T>>['props'];
|
|
30
|
+
events(): ReturnType<typeof $$render<T>>['events'];
|
|
31
|
+
slots(): ReturnType<typeof $$render<T>>['slots'];
|
|
32
|
+
bindings(): "value";
|
|
33
|
+
exports(): {};
|
|
34
|
+
}
|
|
35
|
+
interface $$IsomorphicComponent {
|
|
36
|
+
new <T extends number | number[]>(options: import('svelte').ComponentConstructorOptions<ReturnType<__sveltets_Render<T>['props']>>): import('svelte').SvelteComponent<ReturnType<__sveltets_Render<T>['props']>, ReturnType<__sveltets_Render<T>['events']>, ReturnType<__sveltets_Render<T>['slots']>> & {
|
|
37
|
+
$$bindings?: ReturnType<__sveltets_Render<T>['bindings']>;
|
|
38
|
+
} & ReturnType<__sveltets_Render<T>['exports']>;
|
|
39
|
+
<T extends number | number[]>(internal: unknown, props: ReturnType<__sveltets_Render<T>['props']> & {}): ReturnType<__sveltets_Render<T>['exports']>;
|
|
40
|
+
z_$$bindings?: ReturnType<__sveltets_Render<any>['bindings']>;
|
|
41
|
+
}
|
|
42
|
+
declare const Slider: $$IsomorphicComponent;
|
|
43
|
+
type Slider<T extends number | number[]> = InstanceType<typeof Slider<T>>;
|
|
44
|
+
export default Slider;
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
<script module lang="ts">
|
|
2
|
+
import type { PropColor } from '../types.js';
|
|
3
|
+
import { isComponent, isSnippet } from '../utils/common.js';
|
|
4
|
+
import type { Snippet } from 'svelte';
|
|
5
|
+
import type { ClassNameValue } from 'tailwind-merge';
|
|
6
|
+
import { tv } from 'tailwind-variants';
|
|
7
|
+
import type { Component } from 'vitest-browser-svelte';
|
|
8
|
+
|
|
9
|
+
export type SwitchProps = {
|
|
10
|
+
value?: boolean;
|
|
11
|
+
color?: PropColor;
|
|
12
|
+
size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl';
|
|
13
|
+
disabled?: boolean;
|
|
14
|
+
loading?: boolean;
|
|
15
|
+
loadingicon?: string | Snippet | Component;
|
|
16
|
+
uncheckedicon?: string | Snippet | Component;
|
|
17
|
+
checkedicon?: string | Snippet | Component;
|
|
18
|
+
label?: string | Snippet;
|
|
19
|
+
description?: string | Snippet;
|
|
20
|
+
required?: boolean;
|
|
21
|
+
ui?: {
|
|
22
|
+
root?: ClassNameValue;
|
|
23
|
+
container?: ClassNameValue;
|
|
24
|
+
thumb?: ClassNameValue;
|
|
25
|
+
label?: ClassNameValue;
|
|
26
|
+
description?: ClassNameValue;
|
|
27
|
+
};
|
|
28
|
+
};
|
|
29
|
+
</script>
|
|
30
|
+
|
|
31
|
+
<script lang="ts">
|
|
32
|
+
let {
|
|
33
|
+
value = $bindable(false),
|
|
34
|
+
color = 'primary',
|
|
35
|
+
size = 'md',
|
|
36
|
+
disabled,
|
|
37
|
+
loading,
|
|
38
|
+
loadingicon = 'i-lucide-loader-circle',
|
|
39
|
+
uncheckedicon,
|
|
40
|
+
checkedicon,
|
|
41
|
+
label,
|
|
42
|
+
description,
|
|
43
|
+
required,
|
|
44
|
+
ui = {}
|
|
45
|
+
}: SwitchProps = $props();
|
|
46
|
+
|
|
47
|
+
const classes = $derived.by(() =>
|
|
48
|
+
tv({
|
|
49
|
+
slots: {
|
|
50
|
+
root: 'flex-inline gap-2',
|
|
51
|
+
container: 'rounded-full bg-neutral-200 p-0.5 relative transition',
|
|
52
|
+
thumb: [
|
|
53
|
+
'bg-white block rounded-full absolute top-0.5 transition grid place-items-center',
|
|
54
|
+
value ? 'translate-x-full' : 'text-neutral-500'
|
|
55
|
+
],
|
|
56
|
+
icon: 'pi',
|
|
57
|
+
label: 'text-sm',
|
|
58
|
+
description: 'text-sm text-neutral-500'
|
|
59
|
+
},
|
|
60
|
+
variants: {
|
|
61
|
+
color: {
|
|
62
|
+
primary: {
|
|
63
|
+
container: ['', value && 'bg-primary-500 text-primary-500']
|
|
64
|
+
},
|
|
65
|
+
secondary: {
|
|
66
|
+
container: ['', value && 'bg-neutral-900 text-neutral-900']
|
|
67
|
+
},
|
|
68
|
+
info: {
|
|
69
|
+
container: ['', value && 'bg-info-500 text-info-500']
|
|
70
|
+
},
|
|
71
|
+
success: {
|
|
72
|
+
container: ['', value && 'bg-success-500 text-success-500']
|
|
73
|
+
},
|
|
74
|
+
warning: {
|
|
75
|
+
container: ['', value && 'bg-warning-500 text-warning-500']
|
|
76
|
+
},
|
|
77
|
+
error: {
|
|
78
|
+
container: ['', value && 'bg-error-500 text-error-500']
|
|
79
|
+
}
|
|
80
|
+
},
|
|
81
|
+
size: {
|
|
82
|
+
xs: {
|
|
83
|
+
container: 'w-7 min-w-7 h-4',
|
|
84
|
+
thumb: 'size-3',
|
|
85
|
+
icon: 'size-2.5'
|
|
86
|
+
},
|
|
87
|
+
sm: {
|
|
88
|
+
container: 'w-8 min-w-8 h-4.5',
|
|
89
|
+
thumb: 'size-3.5',
|
|
90
|
+
icon: 'size-3'
|
|
91
|
+
},
|
|
92
|
+
md: {
|
|
93
|
+
container: 'w-9 min-w-9 h-5',
|
|
94
|
+
thumb: 'size-4',
|
|
95
|
+
icon: 'size-3.5'
|
|
96
|
+
},
|
|
97
|
+
lg: {
|
|
98
|
+
container: 'w-10 min-w-10 h-5.5',
|
|
99
|
+
thumb: 'size-4.5',
|
|
100
|
+
icon: 'size-4'
|
|
101
|
+
},
|
|
102
|
+
xl: {
|
|
103
|
+
container: 'w-11 min-w-11 h-6',
|
|
104
|
+
thumb: 'size-5',
|
|
105
|
+
icon: 'size-4.5'
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
},
|
|
109
|
+
compoundVariants: []
|
|
110
|
+
})({ color, size })
|
|
111
|
+
);
|
|
112
|
+
</script>
|
|
113
|
+
|
|
114
|
+
<div
|
|
115
|
+
data-state={value ? 'checked' : 'unchecked'}
|
|
116
|
+
class={classes.root({
|
|
117
|
+
class: [(loading || disabled) && 'opacity-50', ui.thumb]
|
|
118
|
+
})}
|
|
119
|
+
>
|
|
120
|
+
<button
|
|
121
|
+
aria-label="switch"
|
|
122
|
+
data-state={value ? 'checked' : 'unchecked'}
|
|
123
|
+
class={classes.container({ class: [loading && 'cursor-not-allowed', ui.thumb] })}
|
|
124
|
+
onclick={() => {
|
|
125
|
+
if (loading) return;
|
|
126
|
+
value = !value;
|
|
127
|
+
}}
|
|
128
|
+
>
|
|
129
|
+
<span data-state={value ? 'checked' : 'unchecked'} class={classes.thumb({ class: ui.thumb })}>
|
|
130
|
+
{@render Icon(uncheckedicon, [(loading || value) && 'opacity-0'])}
|
|
131
|
+
{@render Icon(checkedicon, [(loading || !value) && 'opacity-0'])}
|
|
132
|
+
{@render Icon(loadingicon || 'i-lucide-loader-circle', [
|
|
133
|
+
'animate-spin',
|
|
134
|
+
!loading && 'opacity-0'
|
|
135
|
+
])}
|
|
136
|
+
</span>
|
|
137
|
+
</button>
|
|
138
|
+
|
|
139
|
+
{#if label}
|
|
140
|
+
<span>
|
|
141
|
+
<div
|
|
142
|
+
class={classes.label({
|
|
143
|
+
class: [required ? 'after:content-["*"] after:text-error-500' : '', ui.thumb]
|
|
144
|
+
})}
|
|
145
|
+
>
|
|
146
|
+
{#if typeof label === 'string'}
|
|
147
|
+
{label}
|
|
148
|
+
{:else}
|
|
149
|
+
{@render label()}
|
|
150
|
+
{/if}
|
|
151
|
+
</div>
|
|
152
|
+
|
|
153
|
+
{#if description}
|
|
154
|
+
<div class={classes.description({ class: ui.thumb })}>
|
|
155
|
+
{#if typeof description === 'string'}
|
|
156
|
+
{description}
|
|
157
|
+
{:else}
|
|
158
|
+
{@render description()}
|
|
159
|
+
{/if}
|
|
160
|
+
</div>
|
|
161
|
+
{/if}
|
|
162
|
+
</span>
|
|
163
|
+
{/if}
|
|
164
|
+
</div>
|
|
165
|
+
|
|
166
|
+
{#snippet Icon(ico?: SwitchProps['checkedicon'], icon_class?: ClassNameValue)}
|
|
167
|
+
<div class={['absolute', icon_class]}>
|
|
168
|
+
{#if typeof ico === 'string'}
|
|
169
|
+
<div
|
|
170
|
+
data-state={value ? 'checked' : 'unchecked'}
|
|
171
|
+
class={classes.icon({ class: [ico] })}
|
|
172
|
+
></div>
|
|
173
|
+
{:else if isSnippet(ico)}
|
|
174
|
+
{@render ico()}
|
|
175
|
+
{:else if isComponent(ico)}
|
|
176
|
+
{@const Iconn = ico}
|
|
177
|
+
<Iconn />
|
|
178
|
+
{/if}
|
|
179
|
+
</div>
|
|
180
|
+
{/snippet}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { PropColor } from '../types.js';
|
|
2
|
+
import type { Snippet } from 'svelte';
|
|
3
|
+
import type { ClassNameValue } from 'tailwind-merge';
|
|
4
|
+
import type { Component } from 'vitest-browser-svelte';
|
|
5
|
+
export type SwitchProps = {
|
|
6
|
+
value?: boolean;
|
|
7
|
+
color?: PropColor;
|
|
8
|
+
size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl';
|
|
9
|
+
disabled?: boolean;
|
|
10
|
+
loading?: boolean;
|
|
11
|
+
loadingicon?: string | Snippet | Component;
|
|
12
|
+
uncheckedicon?: string | Snippet | Component;
|
|
13
|
+
checkedicon?: string | Snippet | Component;
|
|
14
|
+
label?: string | Snippet;
|
|
15
|
+
description?: string | Snippet;
|
|
16
|
+
required?: boolean;
|
|
17
|
+
ui?: {
|
|
18
|
+
root?: ClassNameValue;
|
|
19
|
+
container?: ClassNameValue;
|
|
20
|
+
thumb?: ClassNameValue;
|
|
21
|
+
label?: ClassNameValue;
|
|
22
|
+
description?: ClassNameValue;
|
|
23
|
+
};
|
|
24
|
+
};
|
|
25
|
+
declare const Switch: import("svelte").Component<SwitchProps, {}, "value">;
|
|
26
|
+
type Switch = ReturnType<typeof Switch>;
|
|
27
|
+
export default Switch;
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
package/dist/types.d.ts
ADDED
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { Snippet, Component } from 'svelte';
|
|
2
|
+
export declare const tv: import("tailwind-variants").TV;
|
|
3
|
+
/**
|
|
4
|
+
* Checks if a value is a Svelte snippet
|
|
5
|
+
* @param v - The value to check (should be Snippet | Component)
|
|
6
|
+
* @returns true if the value is a snippet, false otherwise
|
|
7
|
+
*/
|
|
8
|
+
export declare const isSnippet: (v: unknown) => v is Snippet;
|
|
9
|
+
/**
|
|
10
|
+
* Checks if a value is a Svelte component
|
|
11
|
+
* @param v - The value to check (should be Snippet | Component)
|
|
12
|
+
* @returns true if the value is a component, false otherwise
|
|
13
|
+
*/
|
|
14
|
+
export declare const isComponent: (v: unknown) => v is Component;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { createTV } from 'tailwind-variants';
|
|
2
|
+
export const tv = createTV({});
|
|
3
|
+
/**
|
|
4
|
+
* Checks if a value is a Svelte snippet
|
|
5
|
+
* @param v - The value to check (should be Snippet | Component)
|
|
6
|
+
* @returns true if the value is a snippet, false otherwise
|
|
7
|
+
*/
|
|
8
|
+
export const isSnippet = (v) => {
|
|
9
|
+
return typeof v === 'object' && v !== null && '$$render' in v;
|
|
10
|
+
};
|
|
11
|
+
/**
|
|
12
|
+
* Checks if a value is a Svelte component
|
|
13
|
+
* @param v - The value to check (should be Snippet | Component)
|
|
14
|
+
* @returns true if the value is a component, false otherwise
|
|
15
|
+
*/
|
|
16
|
+
export const isComponent = (v) => {
|
|
17
|
+
return typeof v === 'function' || (typeof v === 'object' && v !== null && !('$$render' in v));
|
|
18
|
+
};
|