solid-element-ui 0.2.3 → 0.2.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.
Files changed (51) hide show
  1. package/dist/index.css +1 -1
  2. package/dist/index.js +572 -579
  3. package/dist/src/alert-dialog/alert-dialog.d.ts +2 -1
  4. package/package.json +5 -5
  5. package/src/accordion/accordion.tsx +80 -0
  6. package/src/alert/alert.tsx +86 -0
  7. package/src/alert-dialog/alert-dialog.tsx +98 -0
  8. package/src/badge/badge.tsx +52 -0
  9. package/src/breadcrumbs/breadcrumbs.tsx +69 -0
  10. package/src/button/button.tsx +216 -0
  11. package/src/checkbox/checkbox.tsx +64 -0
  12. package/src/collapsible/collapsible.tsx +46 -0
  13. package/src/color-area/color-area.tsx +46 -0
  14. package/src/color-channel-field/color-channel-field.tsx +46 -0
  15. package/src/color-field/color-field.tsx +64 -0
  16. package/src/color-slider/color-slider.tsx +60 -0
  17. package/src/color-swatch/color-swatch.tsx +33 -0
  18. package/src/color-wheel/color-wheel.tsx +50 -0
  19. package/src/combobox/combobox.tsx +97 -0
  20. package/src/context-menu/context-menu.tsx +102 -0
  21. package/src/dialog/dialog.tsx +102 -0
  22. package/src/dropdown-menu/dropdown-menu.tsx +111 -0
  23. package/src/file-field/file-field.tsx +114 -0
  24. package/src/hover-card/hover-card.tsx +62 -0
  25. package/src/image/image.tsx +59 -0
  26. package/src/index.tsx +91 -0
  27. package/src/link/link.tsx +64 -0
  28. package/src/menubar/menubar.tsx +81 -0
  29. package/src/meter/meter.tsx +89 -0
  30. package/src/navigation-menu/navigation-menu.tsx +90 -0
  31. package/src/number-field/number-field.tsx +80 -0
  32. package/src/pagination/pagination.tsx +68 -0
  33. package/src/popover/popover.tsx +59 -0
  34. package/src/progress/progress.tsx +83 -0
  35. package/src/radio-group/radio-group.tsx +94 -0
  36. package/src/rating-group/rating-group.tsx +101 -0
  37. package/src/search/search.tsx +99 -0
  38. package/src/segmented-control/segmented-control.tsx +92 -0
  39. package/src/select/select.tsx +164 -0
  40. package/src/separator/separator.tsx +62 -0
  41. package/src/skeleton/skeleton.tsx +73 -0
  42. package/src/slider/slider.tsx +91 -0
  43. package/src/style/index.css +150 -0
  44. package/src/switch/switch.tsx +104 -0
  45. package/src/tabs/tabs.tsx +73 -0
  46. package/src/text-field/text-field.tsx +97 -0
  47. package/src/time-field/time-field.tsx +103 -0
  48. package/src/toast/toast.tsx +128 -0
  49. package/src/toggle-button/toggle-button.tsx +68 -0
  50. package/src/toggle-group/toggle-group.tsx +86 -0
  51. package/src/tooltip/tooltip.tsx +78 -0
@@ -0,0 +1,99 @@
1
+ import { TextField as KSearch } from "@kobalte/core/text-field";
2
+ import { splitProps, type ComponentProps, Show } from "solid-js";
3
+ import { tv, type VariantProps } from "tailwind-variants";
4
+ import { Search as SearchIcon, CircleX } from "lucide-solid";
5
+
6
+ const searchStyles = tv(
7
+ {
8
+ slots: {
9
+ root: "relative flex flex-col gap-1.5 w-full",
10
+ inputWrapper: "relative flex items-center transition-all",
11
+ input: [
12
+ "flex h-10 w-full rounded-md border border-slate-200 bg-white px-9 py-2 text-sm",
13
+ "ring-offset-white file:border-0 file:bg-transparent file:text-sm file:font-medium",
14
+ "placeholder:text-slate-500 focus-visible:outline-none focus-visible:ring-2",
15
+ "disabled:cursor-not-allowed disabled:opacity-50 dark:border-slate-800 dark:bg-slate-950",
16
+ ],
17
+ icon: "absolute left-3 h-4 w-4 text-slate-500 pointer-events-none",
18
+ clear: "absolute right-3 h-4 w-4 text-slate-400 hover:text-slate-600 cursor-pointer transition-colors",
19
+ },
20
+ variants: {
21
+ size: {
22
+ sm: {
23
+ input: "h-8 text-xs px-8",
24
+ icon: "h-3.5 w-3.5",
25
+ clear: "h-3.5 w-3.5",
26
+ },
27
+ md: {
28
+ input: "h-10 text-sm",
29
+ icon: "h-4 w-4",
30
+ clear: "h-4 w-4",
31
+ },
32
+ lg: {
33
+ input: "h-12 text-base px-10",
34
+ icon: "h-5 w-5",
35
+ clear: "h-5 w-5",
36
+ },
37
+ },
38
+ ringColor: {
39
+ primary: { input: "focus-visible:ring-blue-500" },
40
+ danger: { input: "focus-visible:ring-red-500" },
41
+ },
42
+ },
43
+ defaultVariants: {
44
+ size: "md",
45
+ ringColor: "primary",
46
+ },
47
+ },
48
+ {
49
+ twMerge: true,
50
+ },
51
+ );
52
+
53
+ type SearchVariants = VariantProps<typeof searchStyles>;
54
+
55
+ export interface SearchProps
56
+ extends Omit<ComponentProps<typeof KSearch>, "class">, SearchVariants {
57
+ class?: string;
58
+ placeholder?: string;
59
+ allowClear?: boolean;
60
+ onClear?: () => void;
61
+ }
62
+
63
+ export const Search = (props: SearchProps) => {
64
+ const [local, variantProps, others] = splitProps(
65
+ props,
66
+ ["class", "placeholder", "allowClear", "onClear", "value", "onChange"],
67
+ ["size", "ringColor"],
68
+ );
69
+
70
+ const styles = searchStyles(variantProps);
71
+
72
+ return (
73
+ <KSearch
74
+ class={styles.root({ class: local.class })}
75
+ value={local.value}
76
+ onChange={local.onChange}
77
+ {...others}
78
+ >
79
+ <div class={styles.inputWrapper()}>
80
+ <SearchIcon class={styles.icon()} />
81
+ <KSearch.Input
82
+ class={styles.input()}
83
+ placeholder={local.placeholder ?? "搜索..."}
84
+ />
85
+ <Show when={local.allowClear && local.value}>
86
+ <button
87
+ onClick={() => local.onClear?.()}
88
+ class={styles.clear()}
89
+ >
90
+ <CircleX
91
+ fill="currentColor"
92
+ class="text-white dark:text-slate-950"
93
+ />
94
+ </button>
95
+ </Show>
96
+ </div>
97
+ </KSearch>
98
+ );
99
+ };
@@ -0,0 +1,92 @@
1
+ import { SegmentedControl as KSegmented } from "@kobalte/core/segmented-control";
2
+ import { splitProps, For, type ComponentProps } from "solid-js";
3
+ import { tv, type VariantProps } from "tailwind-variants";
4
+
5
+ // FIXME 样式问题
6
+
7
+ const segmentedStyles = tv(
8
+ {
9
+ slots: {
10
+ root: "relative flex flex-col",
11
+ container:
12
+ "relative flex items-center w-full rounded-lg bg-slate-100 p-1 text-slate-500 dark:bg-slate-800 dark:text-slate-400",
13
+ item: [
14
+ " z-10 inline-flex flex-1 items-center justify-center whitespace-nowrap rounded-md px-3 py-1.5 text-sm font-medium transition-all cursor-pointer",
15
+ "outline-none focus-visible:ring-2 focus-visible:ring-slate-400 focus-visible:ring-offset-2",
16
+ "data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
17
+ "data-[checked]:text-slate-950 dark:data-[checked]:text-slate-50 transition-colors duration-200",
18
+ ],
19
+ indicator:
20
+ "absolute z-0 bg-white shadow-sm rounded-md transition-all duration-200 ease-in-out dark:bg-slate-950",
21
+ label: "mb-2 text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70",
22
+ itemLabel: "flex w-full cursor-pointer items-center justify-center",
23
+ },
24
+ variants: {
25
+ size: {
26
+ sm: { root: "p-0.5", item: "px-2 py-1 text-xs" },
27
+ md: { root: "p-1", item: "px-3 py-1.5 text-sm" },
28
+ lg: { root: "p-1.5", item: "px-6 py-2 text-base" },
29
+ },
30
+ },
31
+ defaultVariants: {
32
+ size: "md",
33
+ },
34
+ },
35
+ {
36
+ twMerge: true,
37
+ },
38
+ );
39
+
40
+ type SegmentedVariants = VariantProps<typeof segmentedStyles>;
41
+
42
+ interface Option {
43
+ label: string;
44
+ value: string;
45
+ disabled?: boolean;
46
+ }
47
+
48
+ export interface SegmentedControlProps
49
+ extends
50
+ Omit<ComponentProps<typeof KSegmented>, "class">,
51
+ SegmentedVariants {
52
+ options: Option[];
53
+ label?: string;
54
+ class?: string;
55
+ }
56
+
57
+ export const SegmentedControl = (props: SegmentedControlProps) => {
58
+ const [local, variantProps, others] = splitProps(
59
+ props,
60
+ ["options", "class", "label"],
61
+ ["size"],
62
+ );
63
+
64
+ const styles = segmentedStyles(variantProps);
65
+
66
+ return (
67
+ <KSegmented class={styles.root({ class: local.class })} {...others}>
68
+ {local.label && (
69
+ <KSegmented.Label class={styles.label()}>
70
+ {local.label}
71
+ </KSegmented.Label>
72
+ )}
73
+ <div class={styles.container()}>
74
+ <For each={local.options}>
75
+ {(option) => (
76
+ <KSegmented.Item
77
+ value={option.value}
78
+ disabled={option.disabled}
79
+ class={styles.item()}
80
+ >
81
+ <KSegmented.ItemInput />
82
+ <KSegmented.ItemLabel class={styles.itemLabel()}>
83
+ {option.label}
84
+ </KSegmented.ItemLabel>
85
+ </KSegmented.Item>
86
+ )}
87
+ </For>
88
+ <KSegmented.Indicator class={styles.indicator()} />
89
+ </div>
90
+ </KSegmented>
91
+ );
92
+ };
@@ -0,0 +1,164 @@
1
+ import { Select as KSelect } from "@kobalte/core/select";
2
+ import { splitProps, Show, createMemo } from "solid-js";
3
+ import { tv, type VariantProps } from "tailwind-variants";
4
+ import { ChevronDown, Check } from "lucide-solid";
5
+
6
+ const selectStyles = tv(
7
+ {
8
+ slots: {
9
+ root: "flex flex-col gap-1.5 w-full",
10
+ label: "text-sm font-medium text-slate-700 dark:text-slate-300",
11
+ trigger: [
12
+ "flex h-10 w-full items-center justify-between rounded-md border border-slate-200 bg-white px-3 py-2 text-sm",
13
+ "ring-offset-white placeholder:text-slate-500 focus:outline-none focus:ring-2 focus:ring-blue-500",
14
+ "disabled:cursor-not-allowed disabled:opacity-50 dark:border-slate-800 dark:bg-slate-950",
15
+ ],
16
+ content: [
17
+ "relative z-50 min-w-[8rem] overflow-hidden rounded-md border border-slate-200 bg-white text-slate-950 shadow-md",
18
+ "data-[expanded]:animate-in data-[closed]:animate-out dark:border-slate-800 dark:bg-slate-950 dark:text-slate-50",
19
+ ],
20
+ listbox: "p-1",
21
+ item: [
22
+ "relative flex w-full cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none",
23
+ "focus:bg-slate-100 focus:text-slate-900 data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
24
+ "dark:focus:bg-slate-800 dark:focus:text-slate-50",
25
+ ],
26
+ itemIndicator:
27
+ "absolute left-2 flex h-3.5 w-3.5 items-center justify-center",
28
+ description: "text-xs text-slate-500 dark:text-slate-400",
29
+ },
30
+ variants: {
31
+ size: {
32
+ sm: { trigger: "h-8 text-xs", item: "py-1 text-xs" },
33
+ md: { trigger: "h-10 text-sm", item: "py-1.5 text-sm" },
34
+ lg: { trigger: "h-12 text-base", item: "py-2 text-base" },
35
+ },
36
+ },
37
+ defaultVariants: {
38
+ size: "md",
39
+ },
40
+ },
41
+ {
42
+ twMerge: true,
43
+ },
44
+ );
45
+
46
+ type SelectVariants = VariantProps<typeof selectStyles>;
47
+
48
+ interface Option {
49
+ label: string;
50
+ value: string;
51
+ disabled?: boolean;
52
+ }
53
+
54
+ // 重新定义接口,使 value 和 onChange 处理的是 string 类型
55
+ export interface SelectProps extends SelectVariants {
56
+ options: Option[];
57
+ value?: string;
58
+ defaultValue?: string;
59
+ onChange?: (value: string) => void;
60
+ label?: string;
61
+ description?: string;
62
+ placeholder?: string;
63
+ disabled?: boolean;
64
+ name?: string;
65
+ class?: string;
66
+ }
67
+
68
+ export const Select = (props: SelectProps) => {
69
+ const [local, variantProps, others] = splitProps(
70
+ props,
71
+ [
72
+ "options",
73
+ "label",
74
+ "description",
75
+ "placeholder",
76
+ "class",
77
+ "value",
78
+ "defaultValue",
79
+ "onChange",
80
+ ],
81
+ ["size"],
82
+ );
83
+
84
+ const styles = selectStyles(variantProps);
85
+
86
+ const selectedOption = createMemo(() => {
87
+ if (local.value === undefined) return undefined;
88
+ return local.options.find((opt) => opt.value === local.value);
89
+ });
90
+
91
+ const defaultOption = createMemo(() => {
92
+ if (local.defaultValue === undefined) return undefined;
93
+ return local.options.find((opt) => opt.value === local.defaultValue);
94
+ });
95
+
96
+ const handleValueChange = (opt: Option | null) => {
97
+ if (opt === null) {
98
+
99
+ local.onChange?.("");
100
+ return;
101
+ }
102
+ local.onChange?.(opt.value);
103
+ };
104
+
105
+ return (
106
+ <KSelect<Option>
107
+ multiple={false}
108
+ options={local.options}
109
+ optionValue="value"
110
+ optionTextValue="label"
111
+ optionDisabled="disabled"
112
+ placeholder={local.placeholder}
113
+ value={selectedOption()}
114
+ defaultValue={defaultOption()}
115
+ onChange={handleValueChange}
116
+ class={styles.root({ class: local.class })}
117
+ {...others}
118
+ itemComponent={(itemProps) => (
119
+ <KSelect.Item item={itemProps.item} class={styles.item()}>
120
+ <KSelect.ItemIndicator class={styles.itemIndicator()}>
121
+ <Check size={14} />
122
+ </KSelect.ItemIndicator>
123
+ <KSelect.ItemLabel>
124
+ {itemProps.item.textValue}
125
+ </KSelect.ItemLabel>
126
+ </KSelect.Item>
127
+ )}
128
+ >
129
+ <Show when={local.label}>
130
+ <KSelect.Label class={styles.label()}>
131
+ {local.label}
132
+ </KSelect.Label>
133
+ </Show>
134
+
135
+ <KSelect.Trigger class={styles.trigger()}>
136
+ <KSelect.Value<Option>>
137
+ {(state) => (
138
+ <Show
139
+ when={state.selectedOption()}
140
+ fallback={local.placeholder}
141
+ >
142
+ {state.selectedOption()?.label}
143
+ </Show>
144
+ )}
145
+ </KSelect.Value>
146
+ <KSelect.Icon>
147
+ <ChevronDown size={16} class="opacity-50" />
148
+ </KSelect.Icon>
149
+ </KSelect.Trigger>
150
+
151
+ <KSelect.Portal>
152
+ <KSelect.Content class={styles.content()}>
153
+ <KSelect.Listbox class={styles.listbox()} />
154
+ </KSelect.Content>
155
+ </KSelect.Portal>
156
+
157
+ <Show when={local.description}>
158
+ <KSelect.Description class={styles.description()}>
159
+ {local.description}
160
+ </KSelect.Description>
161
+ </Show>
162
+ </KSelect>
163
+ );
164
+ };
@@ -0,0 +1,62 @@
1
+ import { Separator as KSeparator } from "@kobalte/core/separator";
2
+ import { splitProps, type ComponentProps } from "solid-js";
3
+ import { tv, type VariantProps } from "tailwind-variants";
4
+
5
+ const separatorStyles = tv(
6
+ {
7
+ base: "bg-slate-200 dark:bg-slate-800 shrink-0 transition-colors",
8
+ variants: {
9
+ orientation: {
10
+ horizontal: "h-[1px] w-full my-4",
11
+ vertical: "h-full w-[1px] mx-4",
12
+ },
13
+ thickness: {
14
+ thin: "", // 默认 1px
15
+ medium: "data-[orientation=horizontal]:h-[2px] data-[orientation=vertical]:w-[2px]",
16
+ thick: "data-[orientation=horizontal]:h-[4px] data-[orientation=vertical]:w-[4px] rounded-full",
17
+ },
18
+ variant: {
19
+ default: "bg-slate-200 dark:bg-slate-800",
20
+ muted: "bg-slate-100 dark:bg-slate-900",
21
+ primary: "bg-blue-500/50",
22
+ },
23
+ },
24
+ defaultVariants: {
25
+ orientation: "horizontal",
26
+ thickness: "thin",
27
+ variant: "default",
28
+ },
29
+ },
30
+ {
31
+ twMerge: true,
32
+ },
33
+ );
34
+
35
+ type SeparatorVariants = VariantProps<typeof separatorStyles>;
36
+
37
+ export interface SeparatorProps
38
+ extends ComponentProps<typeof KSeparator>,
39
+ SeparatorVariants {
40
+ class?: string;
41
+ }
42
+
43
+ export const Separator = (props: SeparatorProps) => {
44
+ const [local, variantProps, others] = splitProps(
45
+ props,
46
+ ["class"],
47
+ ["orientation", "thickness", "variant"]
48
+ );
49
+
50
+ return (
51
+ <KSeparator
52
+ class={separatorStyles({
53
+ orientation: variantProps.orientation,
54
+ thickness: variantProps.thickness,
55
+ variant: variantProps.variant,
56
+ class: local.class,
57
+ })}
58
+ orientation={variantProps.orientation}
59
+ {...others}
60
+ />
61
+ );
62
+ };
@@ -0,0 +1,73 @@
1
+ import { Skeleton as KSkeleton } from "@kobalte/core/skeleton";
2
+ import { splitProps, type ComponentProps } from "solid-js";
3
+ import { tv, type VariantProps } from "tailwind-variants";
4
+
5
+ const skeletonStyles = tv(
6
+ {
7
+ base: "bg-slate-200 dark:bg-slate-800",
8
+ variants: {
9
+ variant: {
10
+ rect: "rounded-md",
11
+ circle: "rounded-full",
12
+ text: "rounded h-3 w-full",
13
+ },
14
+ animation: {
15
+ pulse: "animate-pulse",
16
+ wave: "relative overflow-hidden before:absolute before:inset-0 before:-translate-x-full before:animate-[wave_2s_linear_infinite] before:bg-gradient-to-r before:from-transparent before:via-white/20 before:to-transparent",
17
+ none: "",
18
+ },
19
+ },
20
+ defaultVariants: {
21
+ variant: "rect",
22
+ animation: "pulse",
23
+ },
24
+ },
25
+ {
26
+ twMerge: true,
27
+ },
28
+ );
29
+
30
+ type SkeletonVariants = VariantProps<typeof skeletonStyles>;
31
+
32
+ // 核心修正:使用 Omit 排除掉冲突的 width 和 height
33
+ export interface SkeletonProps
34
+ extends Omit<
35
+ ComponentProps<typeof KSkeleton>,
36
+ "class" | "width" | "height"
37
+ >,
38
+ SkeletonVariants {
39
+ width?: string | number;
40
+ height?: string | number;
41
+ class?: string;
42
+ }
43
+
44
+ export const Skeleton = (props: SkeletonProps) => {
45
+ // 显式提取这些属性,避免传给 KSkeleton 引起类型或运行时错误
46
+ const [local, variantProps, others] = splitProps(
47
+ props,
48
+ ["class", "width", "height", "style"],
49
+ ["variant", "animation"]
50
+ );
51
+
52
+ const mergedStyle = () => ({
53
+ width:
54
+ typeof local.width === "number" ? `${local.width}px` : local.width,
55
+ height:
56
+ typeof local.height === "number"
57
+ ? `${local.height}px`
58
+ : local.height,
59
+ ...(typeof local.style === "object" ? local.style : {}),
60
+ });
61
+
62
+ return (
63
+ <KSkeleton
64
+ class={skeletonStyles({
65
+ variant: variantProps.variant,
66
+ animation: variantProps.animation,
67
+ class: local.class,
68
+ })}
69
+ style={mergedStyle()}
70
+ {...others}
71
+ />
72
+ );
73
+ };
@@ -0,0 +1,91 @@
1
+ import { Slider as KSlider } from "@kobalte/core/slider";
2
+ import { splitProps, type ComponentProps, For, Show } from "solid-js";
3
+ import { tv, type VariantProps } from "tailwind-variants";
4
+
5
+ const sliderStyles = tv(
6
+ {
7
+ slots: {
8
+ root: "relative flex flex-col items-center select-none touch-none w-full gap-2",
9
+ labelWrapper: "flex w-full justify-between items-center",
10
+ label: "text-sm font-medium text-slate-700 dark:text-slate-300",
11
+ value: "text-sm text-slate-500 font-mono",
12
+ track: "relative h-2 w-full grow rounded-full bg-slate-100 dark:bg-slate-800",
13
+ fill: "absolute h-full rounded-full bg-blue-600 dark:bg-blue-500",
14
+ thumb: [
15
+ "block h-5 w-5 rounded-full border-2 border-blue-600 bg-white ring-offset-white transition-colors",
16
+ "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-blue-400 focus-visible:ring-offset-2",
17
+ "disabled:pointer-events-none disabled:opacity-50 hover:scale-110 active:scale-95 transition-transform",
18
+ ],
19
+ },
20
+ variants: {
21
+ variant: {
22
+ default: { fill: "bg-blue-600", thumb: "border-blue-600" },
23
+ danger: { fill: "bg-red-600", thumb: "border-red-600" },
24
+ success: {
25
+ fill: "bg-emerald-600",
26
+ thumb: "border-emerald-600",
27
+ },
28
+ },
29
+ size: {
30
+ sm: { track: "h-1", thumb: "h-4 w-4" },
31
+ md: { track: "h-2", thumb: "h-5 w-5" },
32
+ lg: { track: "h-3", thumb: "h-6 w-6" },
33
+ },
34
+ },
35
+ defaultVariants: {
36
+ variant: "default",
37
+ size: "md",
38
+ },
39
+ },
40
+ {
41
+ twMerge: true,
42
+ },
43
+ );
44
+
45
+ type SliderVariants = VariantProps<typeof sliderStyles>;
46
+
47
+ export interface SliderProps
48
+ extends Omit<ComponentProps<typeof KSlider>, "class">,
49
+ SliderVariants {
50
+ label?: string;
51
+ showValue?: boolean;
52
+ class?: string;
53
+ }
54
+
55
+ export const Slider = (props: SliderProps) => {
56
+ const [local, variantProps, others] = splitProps(
57
+ props,
58
+ ["label", "showValue", "class"],
59
+ ["variant", "size"]
60
+ );
61
+
62
+ const styles = sliderStyles(variantProps);
63
+
64
+ return (
65
+ <KSlider class={styles.root({ class: local.class })} {...others}>
66
+ <Show when={local.label || local.showValue}>
67
+ <div class={styles.labelWrapper()}>
68
+ <Show when={local.label}>
69
+ <KSlider.Label class={styles.label()}>
70
+ {local.label}
71
+ </KSlider.Label>
72
+ </Show>
73
+ <Show when={local.showValue}>
74
+ <KSlider.ValueLabel class={styles.value()} />
75
+ </Show>
76
+ </div>
77
+ </Show>
78
+
79
+ <KSlider.Track class={styles.track()}>
80
+ <KSlider.Fill class={styles.fill()} />
81
+ <For each={others.value ?? [others.defaultValue]}>
82
+ {() => (
83
+ <KSlider.Thumb class={styles.thumb()}>
84
+ <KSlider.Input />
85
+ </KSlider.Thumb>
86
+ )}
87
+ </For>
88
+ </KSlider.Track>
89
+ </KSlider>
90
+ );
91
+ };