sv5ui 1.2.0 → 1.4.0
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 +16 -11
- package/dist/CheckboxGroup/CheckboxGroup.svelte +215 -0
- package/dist/CheckboxGroup/CheckboxGroup.svelte.d.ts +5 -0
- package/dist/CheckboxGroup/checkbox-group.types.d.ts +130 -0
- package/dist/CheckboxGroup/checkbox-group.types.js +1 -0
- package/dist/CheckboxGroup/checkbox-group.variants.d.ts +553 -0
- package/dist/CheckboxGroup/checkbox-group.variants.js +231 -0
- package/dist/CheckboxGroup/index.d.ts +2 -0
- package/dist/CheckboxGroup/index.js +1 -0
- package/dist/Collapsible/Collapsible.svelte +69 -0
- package/dist/Collapsible/Collapsible.svelte.d.ts +6 -0
- package/dist/Collapsible/CollapsibleTestWrapper.svelte +17 -0
- package/dist/Collapsible/CollapsibleTestWrapper.svelte.d.ts +4 -0
- package/dist/Collapsible/collapsible.types.d.ts +75 -0
- package/dist/Collapsible/collapsible.types.js +1 -0
- package/dist/Collapsible/collapsible.variants.d.ts +53 -0
- package/dist/Collapsible/collapsible.variants.js +21 -0
- package/dist/Collapsible/index.d.ts +2 -0
- package/dist/Collapsible/index.js +1 -0
- package/dist/Command/Command.svelte +183 -0
- package/dist/Command/Command.svelte.d.ts +6 -0
- package/dist/Command/CommandTestWrapper.svelte +13 -0
- package/dist/Command/CommandTestWrapper.svelte.d.ts +4 -0
- package/dist/Command/command.types.d.ts +98 -0
- package/dist/Command/command.types.js +1 -0
- package/dist/Command/command.variants.d.ts +226 -0
- package/dist/Command/command.variants.js +86 -0
- package/dist/Command/index.d.ts +2 -0
- package/dist/Command/index.js +1 -0
- package/dist/FileUpload/FileUpload.svelte +561 -0
- package/dist/FileUpload/FileUpload.svelte.d.ts +8 -0
- package/dist/FileUpload/file-upload.types.d.ts +164 -0
- package/dist/FileUpload/file-upload.types.js +1 -0
- package/dist/FileUpload/file-upload.variants.d.ts +397 -0
- package/dist/FileUpload/file-upload.variants.js +224 -0
- package/dist/FileUpload/index.d.ts +2 -0
- package/dist/FileUpload/index.js +1 -0
- package/dist/PinInput/PinInput.svelte +150 -0
- package/dist/PinInput/PinInput.svelte.d.ts +6 -0
- package/dist/PinInput/index.d.ts +2 -0
- package/dist/PinInput/index.js +1 -0
- package/dist/PinInput/pin-input.types.d.ts +99 -0
- package/dist/PinInput/pin-input.types.js +1 -0
- package/dist/PinInput/pin-input.variants.d.ts +303 -0
- package/dist/PinInput/pin-input.variants.js +196 -0
- package/dist/Select/select.variants.js +1 -1
- package/dist/SelectMenu/select-menu.variants.js +1 -1
- package/dist/Slider/Slider.svelte +135 -0
- package/dist/Slider/Slider.svelte.d.ts +6 -0
- package/dist/Slider/index.d.ts +2 -0
- package/dist/Slider/index.js +1 -0
- package/dist/Slider/slider.types.d.ts +55 -0
- package/dist/Slider/slider.types.js +1 -0
- package/dist/Slider/slider.variants.d.ts +383 -0
- package/dist/Slider/slider.variants.js +102 -0
- package/dist/Toast/Toaster.svelte +618 -0
- package/dist/Toast/Toaster.svelte.d.ts +5 -0
- package/dist/Toast/index.d.ts +4 -0
- package/dist/Toast/index.js +2 -0
- package/dist/Toast/toast.d.ts +38 -0
- package/dist/Toast/toast.js +73 -0
- package/dist/Toast/toast.types.d.ts +19 -0
- package/dist/Toast/toast.types.js +1 -0
- package/dist/Toast/toast.variants.d.ts +7 -0
- package/dist/Toast/toast.variants.js +5 -0
- package/dist/config.d.ts +5 -0
- package/dist/config.js +6 -1
- package/dist/index.d.ts +7 -0
- package/dist/index.js +7 -0
- package/dist/theme.css +36 -0
- package/package.json +2 -1
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
import { tv } from 'tailwind-variants';
|
|
2
|
+
export const checkboxGroupVariants = tv({
|
|
3
|
+
slots: {
|
|
4
|
+
root: '',
|
|
5
|
+
fieldset: 'flex m-0 p-0 border-0 min-w-0',
|
|
6
|
+
legend: 'w-full font-medium text-on-surface mb-1',
|
|
7
|
+
item: 'flex items-start',
|
|
8
|
+
container: 'flex items-center',
|
|
9
|
+
wrapper: '',
|
|
10
|
+
base: [
|
|
11
|
+
'inline-flex items-center justify-center shrink-0 rounded-md border',
|
|
12
|
+
'focus-visible:outline-2 focus-visible:outline-offset-2',
|
|
13
|
+
'transition-colors duration-200',
|
|
14
|
+
'border-outline-variant',
|
|
15
|
+
'data-[state=unchecked]:bg-transparent'
|
|
16
|
+
],
|
|
17
|
+
indicator: 'flex items-center justify-center',
|
|
18
|
+
icon: 'shrink-0 text-surface',
|
|
19
|
+
label: 'block font-medium text-on-surface',
|
|
20
|
+
description: 'text-on-surface-variant'
|
|
21
|
+
},
|
|
22
|
+
variants: {
|
|
23
|
+
color: {
|
|
24
|
+
primary: '',
|
|
25
|
+
secondary: '',
|
|
26
|
+
tertiary: '',
|
|
27
|
+
success: '',
|
|
28
|
+
warning: '',
|
|
29
|
+
error: '',
|
|
30
|
+
info: '',
|
|
31
|
+
surface: ''
|
|
32
|
+
},
|
|
33
|
+
size: {
|
|
34
|
+
xs: {
|
|
35
|
+
fieldset: 'gap-2',
|
|
36
|
+
legend: 'text-xs',
|
|
37
|
+
base: 'size-3.5 rounded',
|
|
38
|
+
container: 'h-4',
|
|
39
|
+
icon: 'size-2.5',
|
|
40
|
+
wrapper: 'text-xs'
|
|
41
|
+
},
|
|
42
|
+
sm: {
|
|
43
|
+
fieldset: 'gap-2.5',
|
|
44
|
+
legend: 'text-xs',
|
|
45
|
+
base: 'size-4 rounded',
|
|
46
|
+
container: 'h-4',
|
|
47
|
+
icon: 'size-3',
|
|
48
|
+
wrapper: 'text-xs'
|
|
49
|
+
},
|
|
50
|
+
md: {
|
|
51
|
+
fieldset: 'gap-3',
|
|
52
|
+
legend: 'text-sm',
|
|
53
|
+
base: 'size-4.5 rounded-md',
|
|
54
|
+
container: 'h-5',
|
|
55
|
+
icon: 'size-3.5',
|
|
56
|
+
wrapper: 'text-sm'
|
|
57
|
+
},
|
|
58
|
+
lg: {
|
|
59
|
+
fieldset: 'gap-3.5',
|
|
60
|
+
legend: 'text-sm',
|
|
61
|
+
base: 'size-5 rounded-md',
|
|
62
|
+
container: 'h-5',
|
|
63
|
+
icon: 'size-4',
|
|
64
|
+
wrapper: 'text-sm'
|
|
65
|
+
},
|
|
66
|
+
xl: {
|
|
67
|
+
fieldset: 'gap-4',
|
|
68
|
+
legend: 'text-base',
|
|
69
|
+
base: 'size-5.5 rounded-md',
|
|
70
|
+
container: 'h-6',
|
|
71
|
+
icon: 'size-4.5',
|
|
72
|
+
wrapper: 'text-base'
|
|
73
|
+
}
|
|
74
|
+
},
|
|
75
|
+
orientation: {
|
|
76
|
+
horizontal: {
|
|
77
|
+
fieldset: 'flex-row flex-wrap items-start'
|
|
78
|
+
},
|
|
79
|
+
vertical: {
|
|
80
|
+
fieldset: 'flex-col'
|
|
81
|
+
}
|
|
82
|
+
},
|
|
83
|
+
variant: {
|
|
84
|
+
list: '',
|
|
85
|
+
card: {
|
|
86
|
+
item: 'border border-outline-variant rounded-lg cursor-pointer select-none'
|
|
87
|
+
}
|
|
88
|
+
},
|
|
89
|
+
indicator: {
|
|
90
|
+
start: {
|
|
91
|
+
wrapper: 'ms-2'
|
|
92
|
+
},
|
|
93
|
+
end: {
|
|
94
|
+
item: 'flex-row-reverse',
|
|
95
|
+
wrapper: 'me-2'
|
|
96
|
+
},
|
|
97
|
+
hidden: {
|
|
98
|
+
container: 'sr-only'
|
|
99
|
+
}
|
|
100
|
+
},
|
|
101
|
+
loading: {
|
|
102
|
+
true: {
|
|
103
|
+
icon: 'animate-spin'
|
|
104
|
+
}
|
|
105
|
+
},
|
|
106
|
+
required: {
|
|
107
|
+
true: {
|
|
108
|
+
legend: "after:content-['*'] after:ms-0.5 after:text-error"
|
|
109
|
+
}
|
|
110
|
+
},
|
|
111
|
+
disabled: {
|
|
112
|
+
true: {
|
|
113
|
+
root: 'opacity-75',
|
|
114
|
+
base: 'cursor-not-allowed',
|
|
115
|
+
label: 'cursor-not-allowed',
|
|
116
|
+
description: 'cursor-not-allowed'
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
},
|
|
120
|
+
compoundVariants: [
|
|
121
|
+
// ========== COLOR (checked bg + border + focus ring) ==========
|
|
122
|
+
{
|
|
123
|
+
color: 'primary',
|
|
124
|
+
class: {
|
|
125
|
+
base: 'data-[state=checked]:bg-primary data-[state=checked]:border-primary data-[state=indeterminate]:bg-primary data-[state=indeterminate]:border-primary focus-visible:outline-primary'
|
|
126
|
+
}
|
|
127
|
+
},
|
|
128
|
+
{
|
|
129
|
+
color: 'secondary',
|
|
130
|
+
class: {
|
|
131
|
+
base: 'data-[state=checked]:bg-secondary data-[state=checked]:border-secondary data-[state=indeterminate]:bg-secondary data-[state=indeterminate]:border-secondary focus-visible:outline-secondary'
|
|
132
|
+
}
|
|
133
|
+
},
|
|
134
|
+
{
|
|
135
|
+
color: 'tertiary',
|
|
136
|
+
class: {
|
|
137
|
+
base: 'data-[state=checked]:bg-tertiary data-[state=checked]:border-tertiary data-[state=indeterminate]:bg-tertiary data-[state=indeterminate]:border-tertiary focus-visible:outline-tertiary'
|
|
138
|
+
}
|
|
139
|
+
},
|
|
140
|
+
{
|
|
141
|
+
color: 'success',
|
|
142
|
+
class: {
|
|
143
|
+
base: 'data-[state=checked]:bg-success data-[state=checked]:border-success data-[state=indeterminate]:bg-success data-[state=indeterminate]:border-success focus-visible:outline-success'
|
|
144
|
+
}
|
|
145
|
+
},
|
|
146
|
+
{
|
|
147
|
+
color: 'warning',
|
|
148
|
+
class: {
|
|
149
|
+
base: 'data-[state=checked]:bg-warning data-[state=checked]:border-warning data-[state=indeterminate]:bg-warning data-[state=indeterminate]:border-warning focus-visible:outline-warning'
|
|
150
|
+
}
|
|
151
|
+
},
|
|
152
|
+
{
|
|
153
|
+
color: 'error',
|
|
154
|
+
class: {
|
|
155
|
+
base: 'data-[state=checked]:bg-error data-[state=checked]:border-error data-[state=indeterminate]:bg-error data-[state=indeterminate]:border-error focus-visible:outline-error'
|
|
156
|
+
}
|
|
157
|
+
},
|
|
158
|
+
{
|
|
159
|
+
color: 'info',
|
|
160
|
+
class: {
|
|
161
|
+
base: 'data-[state=checked]:bg-info data-[state=checked]:border-info data-[state=indeterminate]:bg-info data-[state=indeterminate]:border-info focus-visible:outline-info'
|
|
162
|
+
}
|
|
163
|
+
},
|
|
164
|
+
{
|
|
165
|
+
color: 'surface',
|
|
166
|
+
class: {
|
|
167
|
+
base: 'data-[state=checked]:bg-on-surface data-[state=checked]:border-on-surface data-[state=indeterminate]:bg-on-surface data-[state=indeterminate]:border-on-surface focus-visible:outline-outline'
|
|
168
|
+
}
|
|
169
|
+
},
|
|
170
|
+
// ========== CARD × SIZE (padding) ==========
|
|
171
|
+
{ variant: 'card', size: 'xs', class: { item: 'p-2' } },
|
|
172
|
+
{ variant: 'card', size: 'sm', class: { item: 'p-2.5' } },
|
|
173
|
+
{ variant: 'card', size: 'md', class: { item: 'p-3' } },
|
|
174
|
+
{ variant: 'card', size: 'lg', class: { item: 'p-3.5' } },
|
|
175
|
+
{ variant: 'card', size: 'xl', class: { item: 'p-4' } },
|
|
176
|
+
// ========== CARD × COLOR (checked border) ==========
|
|
177
|
+
{
|
|
178
|
+
variant: 'card',
|
|
179
|
+
color: 'primary',
|
|
180
|
+
class: { item: 'has-[[data-state=checked]]:border-primary' }
|
|
181
|
+
},
|
|
182
|
+
{
|
|
183
|
+
variant: 'card',
|
|
184
|
+
color: 'secondary',
|
|
185
|
+
class: { item: 'has-[[data-state=checked]]:border-secondary' }
|
|
186
|
+
},
|
|
187
|
+
{
|
|
188
|
+
variant: 'card',
|
|
189
|
+
color: 'tertiary',
|
|
190
|
+
class: { item: 'has-[[data-state=checked]]:border-tertiary' }
|
|
191
|
+
},
|
|
192
|
+
{
|
|
193
|
+
variant: 'card',
|
|
194
|
+
color: 'success',
|
|
195
|
+
class: { item: 'has-[[data-state=checked]]:border-success' }
|
|
196
|
+
},
|
|
197
|
+
{
|
|
198
|
+
variant: 'card',
|
|
199
|
+
color: 'warning',
|
|
200
|
+
class: { item: 'has-[[data-state=checked]]:border-warning' }
|
|
201
|
+
},
|
|
202
|
+
{
|
|
203
|
+
variant: 'card',
|
|
204
|
+
color: 'error',
|
|
205
|
+
class: { item: 'has-[[data-state=checked]]:border-error' }
|
|
206
|
+
},
|
|
207
|
+
{
|
|
208
|
+
variant: 'card',
|
|
209
|
+
color: 'info',
|
|
210
|
+
class: { item: 'has-[[data-state=checked]]:border-info' }
|
|
211
|
+
},
|
|
212
|
+
{
|
|
213
|
+
variant: 'card',
|
|
214
|
+
color: 'surface',
|
|
215
|
+
class: { item: 'has-[[data-state=checked]]:border-on-surface' }
|
|
216
|
+
},
|
|
217
|
+
// ========== CARD × DISABLED ==========
|
|
218
|
+
{ variant: 'card', disabled: true, class: { item: 'cursor-not-allowed' } }
|
|
219
|
+
],
|
|
220
|
+
defaultVariants: {
|
|
221
|
+
color: 'primary',
|
|
222
|
+
size: 'md',
|
|
223
|
+
variant: 'list',
|
|
224
|
+
indicator: 'start',
|
|
225
|
+
orientation: 'vertical'
|
|
226
|
+
}
|
|
227
|
+
});
|
|
228
|
+
export const checkboxGroupDefaults = {
|
|
229
|
+
defaultVariants: checkboxGroupVariants.defaultVariants,
|
|
230
|
+
slots: {}
|
|
231
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default as CheckboxGroup } from './CheckboxGroup.svelte';
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
<script lang="ts" module>
|
|
2
|
+
import type { CollapsibleProps } from './collapsible.types.js'
|
|
3
|
+
|
|
4
|
+
export type Props = CollapsibleProps
|
|
5
|
+
</script>
|
|
6
|
+
|
|
7
|
+
<script lang="ts">
|
|
8
|
+
import { Collapsible } from 'bits-ui'
|
|
9
|
+
import { collapsibleVariants, collapsibleDefaults } from './collapsible.variants.js'
|
|
10
|
+
import { getComponentConfig } from '../config.js'
|
|
11
|
+
|
|
12
|
+
const config = getComponentConfig('collapsible', collapsibleDefaults)
|
|
13
|
+
|
|
14
|
+
let {
|
|
15
|
+
ref = $bindable(null),
|
|
16
|
+
open = $bindable(false),
|
|
17
|
+
onOpenChange,
|
|
18
|
+
onOpenChangeComplete,
|
|
19
|
+
disabled = false,
|
|
20
|
+
trigger: triggerSlot,
|
|
21
|
+
content: contentSlot,
|
|
22
|
+
children,
|
|
23
|
+
ui,
|
|
24
|
+
class: className,
|
|
25
|
+
...restProps
|
|
26
|
+
}: Props = $props()
|
|
27
|
+
|
|
28
|
+
const slots = $derived(collapsibleVariants({ disabled }))
|
|
29
|
+
const classes = $derived.by(() => {
|
|
30
|
+
const u = ui ?? {}
|
|
31
|
+
return {
|
|
32
|
+
root: slots.root({ class: [config.slots.root, className, u.root] }),
|
|
33
|
+
content: slots.content({ class: [config.slots.content, u.content] })
|
|
34
|
+
}
|
|
35
|
+
})
|
|
36
|
+
|
|
37
|
+
function handleOpenChange(value: boolean) {
|
|
38
|
+
open = value
|
|
39
|
+
onOpenChange?.(value)
|
|
40
|
+
}
|
|
41
|
+
</script>
|
|
42
|
+
|
|
43
|
+
<Collapsible.Root
|
|
44
|
+
{...restProps}
|
|
45
|
+
bind:ref
|
|
46
|
+
{open}
|
|
47
|
+
onOpenChange={handleOpenChange}
|
|
48
|
+
{onOpenChangeComplete}
|
|
49
|
+
{disabled}
|
|
50
|
+
class={classes.root}
|
|
51
|
+
>
|
|
52
|
+
{#if triggerSlot}
|
|
53
|
+
<Collapsible.Trigger>
|
|
54
|
+
{#snippet child({ props })}
|
|
55
|
+
{@render triggerSlot({ open, props })}
|
|
56
|
+
{/snippet}
|
|
57
|
+
</Collapsible.Trigger>
|
|
58
|
+
{/if}
|
|
59
|
+
|
|
60
|
+
{#if contentSlot}
|
|
61
|
+
<Collapsible.Content class={classes.content}>
|
|
62
|
+
{@render contentSlot()}
|
|
63
|
+
</Collapsible.Content>
|
|
64
|
+
{/if}
|
|
65
|
+
|
|
66
|
+
{#if children}
|
|
67
|
+
{@render children()}
|
|
68
|
+
{/if}
|
|
69
|
+
</Collapsible.Root>
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { CollapsibleProps } from './collapsible.types.js';
|
|
2
|
+
export type Props = CollapsibleProps;
|
|
3
|
+
import { Collapsible } from 'bits-ui';
|
|
4
|
+
declare const Collapsible: import("svelte").Component<CollapsibleProps, {}, "ref" | "open">;
|
|
5
|
+
type Collapsible = ReturnType<typeof Collapsible>;
|
|
6
|
+
export default Collapsible;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import Collapsible from './Collapsible.svelte'
|
|
3
|
+
import type { CollapsibleProps } from './collapsible.types.js'
|
|
4
|
+
|
|
5
|
+
let { ...props }: Omit<CollapsibleProps, 'trigger' | 'content' | 'children'> = $props()
|
|
6
|
+
</script>
|
|
7
|
+
|
|
8
|
+
<Collapsible {...props}>
|
|
9
|
+
{#snippet trigger({ open, props: triggerProps })}
|
|
10
|
+
<button type="button" {...triggerProps}>
|
|
11
|
+
{open ? 'Close' : 'Open'}
|
|
12
|
+
</button>
|
|
13
|
+
{/snippet}
|
|
14
|
+
{#snippet content()}
|
|
15
|
+
<div data-testid="collapsible-body">Collapsible content</div>
|
|
16
|
+
{/snippet}
|
|
17
|
+
</Collapsible>
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { CollapsibleProps } from './collapsible.types.js';
|
|
2
|
+
declare const CollapsibleTestWrapper: import("svelte").Component<Omit<CollapsibleProps, "children" | "content" | "trigger">, {}, "">;
|
|
3
|
+
type CollapsibleTestWrapper = ReturnType<typeof CollapsibleTestWrapper>;
|
|
4
|
+
export default CollapsibleTestWrapper;
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import type { Snippet } from 'svelte';
|
|
2
|
+
import type { ClassNameValue } from 'tailwind-merge';
|
|
3
|
+
import type { CollapsibleRootPropsWithoutHTML } from 'bits-ui';
|
|
4
|
+
import type { CollapsibleSlots } from './collapsible.variants.js';
|
|
5
|
+
/**
|
|
6
|
+
* Props for the Collapsible component.
|
|
7
|
+
*
|
|
8
|
+
* Wraps bits-ui's Collapsible primitives with a themed, slot-based API.
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* ```svelte
|
|
12
|
+
* <Collapsible>
|
|
13
|
+
* {#snippet trigger({ open })}
|
|
14
|
+
* <Button>{open ? 'Hide' : 'Show'}</Button>
|
|
15
|
+
* {/snippet}
|
|
16
|
+
* {#snippet content()}
|
|
17
|
+
* <p>Collapsible content here</p>
|
|
18
|
+
* {/snippet}
|
|
19
|
+
* </Collapsible>
|
|
20
|
+
* ```
|
|
21
|
+
*
|
|
22
|
+
* @see https://bits-ui.com/docs/components/collapsible
|
|
23
|
+
*/
|
|
24
|
+
export interface CollapsibleProps extends Pick<CollapsibleRootPropsWithoutHTML, 'open' | 'onOpenChange' | 'onOpenChangeComplete' | 'disabled'> {
|
|
25
|
+
/**
|
|
26
|
+
* Bindable reference to the root DOM element.
|
|
27
|
+
*/
|
|
28
|
+
ref?: HTMLElement | null;
|
|
29
|
+
/**
|
|
30
|
+
* Override classes for collapsible component slots.
|
|
31
|
+
*
|
|
32
|
+
* @example
|
|
33
|
+
* ```ts
|
|
34
|
+
* ui={{ root: 'border rounded-lg', content: 'p-4' }}
|
|
35
|
+
* ```
|
|
36
|
+
*/
|
|
37
|
+
ui?: Partial<Record<CollapsibleSlots, ClassNameValue>>;
|
|
38
|
+
/**
|
|
39
|
+
* Additional CSS classes for the root element.
|
|
40
|
+
*/
|
|
41
|
+
class?: ClassNameValue;
|
|
42
|
+
/**
|
|
43
|
+
* Snippet for the trigger element that toggles the collapsible.
|
|
44
|
+
* Receives `{ open }` to reflect the current state.
|
|
45
|
+
*
|
|
46
|
+
* @example
|
|
47
|
+
* ```svelte
|
|
48
|
+
* {#snippet trigger({ open })}
|
|
49
|
+
* <Button variant="ghost">
|
|
50
|
+
* {open ? 'Collapse' : 'Expand'}
|
|
51
|
+
* </Button>
|
|
52
|
+
* {/snippet}
|
|
53
|
+
* ```
|
|
54
|
+
*/
|
|
55
|
+
trigger?: Snippet<[{
|
|
56
|
+
open: boolean;
|
|
57
|
+
props: Record<string, unknown>;
|
|
58
|
+
}]>;
|
|
59
|
+
/**
|
|
60
|
+
* Snippet for the collapsible content area.
|
|
61
|
+
*
|
|
62
|
+
* @example
|
|
63
|
+
* ```svelte
|
|
64
|
+
* {#snippet content()}
|
|
65
|
+
* <p>Hidden content revealed on expand.</p>
|
|
66
|
+
* {/snippet}
|
|
67
|
+
* ```
|
|
68
|
+
*/
|
|
69
|
+
content?: Snippet;
|
|
70
|
+
/**
|
|
71
|
+
* Default slot children. If provided, rendered inside the root
|
|
72
|
+
* for full custom layouts using bits-ui primitives directly.
|
|
73
|
+
*/
|
|
74
|
+
children?: Snippet;
|
|
75
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { type VariantProps } from 'tailwind-variants';
|
|
2
|
+
export declare const collapsibleVariants: import("tailwind-variants").TVReturnType<{
|
|
3
|
+
disabled: {
|
|
4
|
+
true: {
|
|
5
|
+
root: string;
|
|
6
|
+
};
|
|
7
|
+
};
|
|
8
|
+
}, {
|
|
9
|
+
root: string;
|
|
10
|
+
content: string;
|
|
11
|
+
}, undefined, {
|
|
12
|
+
disabled: {
|
|
13
|
+
true: {
|
|
14
|
+
root: string;
|
|
15
|
+
};
|
|
16
|
+
};
|
|
17
|
+
}, {
|
|
18
|
+
root: string;
|
|
19
|
+
content: string;
|
|
20
|
+
}, import("tailwind-variants").TVReturnType<{
|
|
21
|
+
disabled: {
|
|
22
|
+
true: {
|
|
23
|
+
root: string;
|
|
24
|
+
};
|
|
25
|
+
};
|
|
26
|
+
}, {
|
|
27
|
+
root: string;
|
|
28
|
+
content: string;
|
|
29
|
+
}, undefined, unknown, unknown, undefined>>;
|
|
30
|
+
export type CollapsibleVariantProps = VariantProps<typeof collapsibleVariants>;
|
|
31
|
+
export type CollapsibleSlots = keyof ReturnType<typeof collapsibleVariants>;
|
|
32
|
+
export declare const collapsibleDefaults: {
|
|
33
|
+
defaultVariants: import("tailwind-variants").TVDefaultVariants<{
|
|
34
|
+
disabled: {
|
|
35
|
+
true: {
|
|
36
|
+
root: string;
|
|
37
|
+
};
|
|
38
|
+
};
|
|
39
|
+
}, {
|
|
40
|
+
root: string;
|
|
41
|
+
content: string;
|
|
42
|
+
}, {
|
|
43
|
+
disabled: {
|
|
44
|
+
true: {
|
|
45
|
+
root: string;
|
|
46
|
+
};
|
|
47
|
+
};
|
|
48
|
+
}, {
|
|
49
|
+
root: string;
|
|
50
|
+
content: string;
|
|
51
|
+
}>;
|
|
52
|
+
slots: Partial<Record<CollapsibleSlots, string>>;
|
|
53
|
+
};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { tv } from 'tailwind-variants';
|
|
2
|
+
export const collapsibleVariants = tv({
|
|
3
|
+
slots: {
|
|
4
|
+
root: '',
|
|
5
|
+
content: 'data-[state=open]:animate-[collapsible-down_200ms_ease-out] data-[state=closed]:animate-[collapsible-up_200ms_ease-out] overflow-hidden'
|
|
6
|
+
},
|
|
7
|
+
variants: {
|
|
8
|
+
disabled: {
|
|
9
|
+
true: {
|
|
10
|
+
root: 'opacity-75 cursor-not-allowed'
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
defaultVariants: {
|
|
15
|
+
disabled: false
|
|
16
|
+
}
|
|
17
|
+
});
|
|
18
|
+
export const collapsibleDefaults = {
|
|
19
|
+
defaultVariants: collapsibleVariants.defaultVariants,
|
|
20
|
+
slots: {}
|
|
21
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default as Collapsible } from './Collapsible.svelte';
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
<script lang="ts" module>
|
|
2
|
+
import type { CommandProps } from './command.types.js'
|
|
3
|
+
|
|
4
|
+
export type Props = CommandProps
|
|
5
|
+
</script>
|
|
6
|
+
|
|
7
|
+
<script lang="ts">
|
|
8
|
+
import { Command } from 'bits-ui'
|
|
9
|
+
import { commandVariants, commandDefaults } from './command.variants.js'
|
|
10
|
+
import { getComponentConfig, iconsDefaults } from '../config.js'
|
|
11
|
+
import Icon from '../Icon/Icon.svelte'
|
|
12
|
+
|
|
13
|
+
const config = getComponentConfig('command', commandDefaults)
|
|
14
|
+
const icons = getComponentConfig('icons', iconsDefaults)
|
|
15
|
+
|
|
16
|
+
let {
|
|
17
|
+
ref = $bindable(null),
|
|
18
|
+
value = $bindable(''),
|
|
19
|
+
search = $bindable(''),
|
|
20
|
+
onValueChange,
|
|
21
|
+
groups = [],
|
|
22
|
+
placeholder = 'Type a command or search...',
|
|
23
|
+
loading = false,
|
|
24
|
+
emptyText = 'No results found.',
|
|
25
|
+
icon,
|
|
26
|
+
label,
|
|
27
|
+
filter,
|
|
28
|
+
shouldFilter = true,
|
|
29
|
+
loop = false,
|
|
30
|
+
vimBindings = true,
|
|
31
|
+
size = config.defaultVariants.size,
|
|
32
|
+
item: itemSlot,
|
|
33
|
+
itemLeading: itemLeadingSlot,
|
|
34
|
+
itemLabel: itemLabelSlot,
|
|
35
|
+
itemTrailing: itemTrailingSlot,
|
|
36
|
+
empty: emptySlot,
|
|
37
|
+
footer: footerSlot,
|
|
38
|
+
ui,
|
|
39
|
+
class: className,
|
|
40
|
+
...restProps
|
|
41
|
+
}: Props = $props()
|
|
42
|
+
|
|
43
|
+
const slots = $derived(commandVariants({ size }))
|
|
44
|
+
const classes = $derived.by(() => {
|
|
45
|
+
const u = ui ?? {}
|
|
46
|
+
return {
|
|
47
|
+
root: slots.root({ class: [config.slots.root, className, u.root] }),
|
|
48
|
+
inputWrapper: slots.inputWrapper({
|
|
49
|
+
class: [config.slots.inputWrapper, u.inputWrapper]
|
|
50
|
+
}),
|
|
51
|
+
inputIcon: slots.inputIcon({ class: [config.slots.inputIcon, u.inputIcon] }),
|
|
52
|
+
input: slots.input({ class: [config.slots.input, u.input] }),
|
|
53
|
+
list: slots.list({ class: [config.slots.list, u.list] }),
|
|
54
|
+
empty: slots.empty({ class: [config.slots.empty, u.empty] }),
|
|
55
|
+
loading: slots.loading({ class: [config.slots.loading, u.loading] }),
|
|
56
|
+
group: slots.group({ class: [config.slots.group, u.group] }),
|
|
57
|
+
groupHeading: slots.groupHeading({
|
|
58
|
+
class: [config.slots.groupHeading, u.groupHeading]
|
|
59
|
+
}),
|
|
60
|
+
groupItems: slots.groupItems({ class: [config.slots.groupItems, u.groupItems] }),
|
|
61
|
+
separator: slots.separator({ class: [config.slots.separator, u.separator] }),
|
|
62
|
+
item: slots.item({ class: [config.slots.item, u.item] }),
|
|
63
|
+
itemIcon: slots.itemIcon({ class: [config.slots.itemIcon, u.itemIcon] }),
|
|
64
|
+
itemWrapper: slots.itemWrapper({ class: [config.slots.itemWrapper, u.itemWrapper] }),
|
|
65
|
+
itemLabel: slots.itemLabel({ class: [config.slots.itemLabel, u.itemLabel] }),
|
|
66
|
+
itemDescription: slots.itemDescription({
|
|
67
|
+
class: [config.slots.itemDescription, u.itemDescription]
|
|
68
|
+
}),
|
|
69
|
+
itemTrailing: slots.itemTrailing({
|
|
70
|
+
class: [config.slots.itemTrailing, u.itemTrailing]
|
|
71
|
+
}),
|
|
72
|
+
footer: slots.footer({ class: [config.slots.footer, u.footer] })
|
|
73
|
+
}
|
|
74
|
+
})
|
|
75
|
+
|
|
76
|
+
function handleValueChange(v: string) {
|
|
77
|
+
value = v
|
|
78
|
+
onValueChange?.(v)
|
|
79
|
+
}
|
|
80
|
+
</script>
|
|
81
|
+
|
|
82
|
+
<Command.Root
|
|
83
|
+
{...restProps}
|
|
84
|
+
bind:ref
|
|
85
|
+
{value}
|
|
86
|
+
{label}
|
|
87
|
+
onValueChange={handleValueChange}
|
|
88
|
+
{filter}
|
|
89
|
+
{shouldFilter}
|
|
90
|
+
{loop}
|
|
91
|
+
{vimBindings}
|
|
92
|
+
class={classes.root}
|
|
93
|
+
>
|
|
94
|
+
<div class={classes.inputWrapper}>
|
|
95
|
+
<Icon name={icon ?? icons.search ?? 'lucide:search'} class={classes.inputIcon} />
|
|
96
|
+
<Command.Input bind:value={search} {placeholder} class={classes.input} />
|
|
97
|
+
</div>
|
|
98
|
+
|
|
99
|
+
<Command.List class={classes.list}>
|
|
100
|
+
{#if loading}
|
|
101
|
+
<Command.Loading class={classes.loading}>
|
|
102
|
+
<Icon name={icons.loading} class="mx-auto size-5 animate-spin" />
|
|
103
|
+
</Command.Loading>
|
|
104
|
+
{:else}
|
|
105
|
+
<Command.Empty class={classes.empty}>
|
|
106
|
+
{#if emptySlot}
|
|
107
|
+
{@render emptySlot({ search })}
|
|
108
|
+
{:else}
|
|
109
|
+
{emptyText}
|
|
110
|
+
{/if}
|
|
111
|
+
</Command.Empty>
|
|
112
|
+
|
|
113
|
+
{#each groups as group, gi (group.id)}
|
|
114
|
+
{#if gi > 0}
|
|
115
|
+
<Command.Separator class={classes.separator} />
|
|
116
|
+
{/if}
|
|
117
|
+
|
|
118
|
+
<Command.Group value={group.id} class={classes.group}>
|
|
119
|
+
{#if group.label}
|
|
120
|
+
<Command.GroupHeading class={classes.groupHeading}>
|
|
121
|
+
{group.label}
|
|
122
|
+
</Command.GroupHeading>
|
|
123
|
+
{/if}
|
|
124
|
+
|
|
125
|
+
<Command.GroupItems class={classes.groupItems}>
|
|
126
|
+
{#each group.items as cmdItem, i (cmdItem.value)}
|
|
127
|
+
{#if itemSlot}
|
|
128
|
+
{@render itemSlot({ item: cmdItem, index: i })}
|
|
129
|
+
{:else}
|
|
130
|
+
<Command.Item
|
|
131
|
+
value={cmdItem.value}
|
|
132
|
+
keywords={cmdItem.keywords}
|
|
133
|
+
disabled={cmdItem.disabled}
|
|
134
|
+
onSelect={cmdItem.onSelect}
|
|
135
|
+
class={cmdItem.class
|
|
136
|
+
? slots.item({
|
|
137
|
+
class: [config.slots.item, ui?.item, cmdItem.class]
|
|
138
|
+
})
|
|
139
|
+
: classes.item}
|
|
140
|
+
>
|
|
141
|
+
{#if itemLeadingSlot}
|
|
142
|
+
{@render itemLeadingSlot({ item: cmdItem, index: i })}
|
|
143
|
+
{:else if cmdItem.icon}
|
|
144
|
+
<Icon name={cmdItem.icon} class={classes.itemIcon} />
|
|
145
|
+
{/if}
|
|
146
|
+
|
|
147
|
+
{#if itemLabelSlot}
|
|
148
|
+
{@render itemLabelSlot({ item: cmdItem, index: i })}
|
|
149
|
+
{:else}
|
|
150
|
+
<div class={classes.itemWrapper}>
|
|
151
|
+
{#if cmdItem.label}
|
|
152
|
+
<span class={classes.itemLabel}
|
|
153
|
+
>{cmdItem.label}</span
|
|
154
|
+
>
|
|
155
|
+
{/if}
|
|
156
|
+
{#if cmdItem.description}
|
|
157
|
+
<span class={classes.itemDescription}
|
|
158
|
+
>{cmdItem.description}</span
|
|
159
|
+
>
|
|
160
|
+
{/if}
|
|
161
|
+
</div>
|
|
162
|
+
{/if}
|
|
163
|
+
|
|
164
|
+
{#if itemTrailingSlot}
|
|
165
|
+
<span class={classes.itemTrailing}>
|
|
166
|
+
{@render itemTrailingSlot({ item: cmdItem, index: i })}
|
|
167
|
+
</span>
|
|
168
|
+
{/if}
|
|
169
|
+
</Command.Item>
|
|
170
|
+
{/if}
|
|
171
|
+
{/each}
|
|
172
|
+
</Command.GroupItems>
|
|
173
|
+
</Command.Group>
|
|
174
|
+
{/each}
|
|
175
|
+
{/if}
|
|
176
|
+
</Command.List>
|
|
177
|
+
|
|
178
|
+
{#if footerSlot}
|
|
179
|
+
<div class={classes.footer}>
|
|
180
|
+
{@render footerSlot()}
|
|
181
|
+
</div>
|
|
182
|
+
{/if}
|
|
183
|
+
</Command.Root>
|