@adea-ai/ui 0.72.0 → 0.72.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/dist/components/ui/checkbox/checkbox.d.ts +2 -0
- package/dist/components/ui/checkbox/checkbox.d.ts.map +1 -1
- package/dist/components/ui/checkbox/checkbox.js +52 -13
- package/dist/components/ui/checkbox/checkbox.js.map +1 -1
- package/dist/components/ui/combobox/combobox.d.ts.map +1 -1
- package/dist/components/ui/combobox/combobox.js +10 -6
- package/dist/components/ui/combobox/combobox.js.map +1 -1
- package/dist/components/ui/radio-group/radio-group.d.ts +2 -1
- package/dist/components/ui/radio-group/radio-group.d.ts.map +1 -1
- package/dist/components/ui/radio-group/radio-group.js +46 -13
- package/dist/components/ui/radio-group/radio-group.js.map +1 -1
- package/dist/components/ui/slider/slider.d.ts +5 -1
- package/dist/components/ui/slider/slider.d.ts.map +1 -1
- package/dist/components/ui/slider/slider.js +36 -20
- package/dist/components/ui/slider/slider.js.map +1 -1
- package/dist/components/ui/switch/switch.d.ts +2 -0
- package/dist/components/ui/switch/switch.d.ts.map +1 -1
- package/dist/components/ui/switch/switch.js +51 -12
- package/dist/components/ui/switch/switch.js.map +1 -1
- package/dist/r/src/components/ui/checkbox/checkbox.tsx +34 -9
- package/dist/r/src/components/ui/combobox/combobox.tsx +1 -0
- package/dist/r/src/components/ui/radio-group/radio-group.tsx +22 -5
- package/dist/r/src/components/ui/slider/slider.tsx +43 -15
- package/dist/r/src/components/ui/switch/switch.tsx +34 -9
- package/package.json +1 -1
- package/src/components/ui/checkbox/checkbox.tsx +34 -9
- package/src/components/ui/combobox/combobox.tsx +1 -0
- package/src/components/ui/radio-group/radio-group.tsx +22 -5
- package/src/components/ui/slider/slider.tsx +43 -15
- package/src/components/ui/switch/switch.tsx +34 -9
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"switch.js","names":["Switch","KobalteSwitch","ComponentProps","JSX","splitProps","cn","SwitchProps","Omit","controlClass","thumbClass","labelClass","descriptionClass","
|
|
1
|
+
{"version":3,"file":"switch.js","names":["Switch","KobalteSwitch","ComponentProps","JSX","splitProps","cn","SwitchProps","Omit","controlClass","thumbClass","labelClass","descriptionClass","label","Element","description","children","props","local","rest","_$createComponent","_$mergeProps","title","class","Input","aria-label","aria-labelledby","aria-describedby","aria-invalid","aria-busy","Control","Thumb","_$memo","_el$","_tmpl$","_$insert","_c$","Label","_c$2","Description","SwitchLabel","SwitchDescription","Switch","_$createComponent","KobalteSwitch","_$mergeProps","_$memo"],"sources":["../../../../src/components/ui/switch/switch.tsx"],"sourcesContent":["import { Switch as KobalteSwitch } from '@kobalte/core/switch'\nimport type { ComponentProps, JSX } from 'solid-js'\nimport { splitProps } from 'solid-js'\nimport { cn } from '#lib/utils'\n\n/**\n * Switch.\n *\n * For a setting that takes effect the moment it is flipped. The distinction\n * from Checkbox is behaviour, not looks: a switch applies immediately and\n * belongs in a settings row, while a checkbox is a value the user is still\n * composing and is applied when a form is submitted. A switch inside an unsaved\n * form is the mistake this split exists to prevent.\n *\n * `Switch.Input` renders a real hidden checkbox, so the control is\n * form-native, keyboard-operable, and its `aria-checked` follows the state the\n * user sees.\n */\nexport type SwitchProps = Omit<ComponentProps<typeof KobalteSwitch>, 'children'> & {\n controlClass?: string\n thumbClass?: string\n labelClass?: string\n descriptionClass?: string\n label?: JSX.Element\n description?: JSX.Element\n /**\n * Replaces the control and label. Omit it to get the default control beside\n * `label` and `description`; supply it to compose the parts yourself.\n */\n children?: JSX.Element\n}\n\nexport function Switch(props: SwitchProps) {\n const [local, rest] = splitProps(props, [\n 'class',\n 'controlClass',\n 'thumbClass',\n 'labelClass',\n 'descriptionClass',\n 'children',\n 'label',\n 'description',\n 'aria-label',\n 'aria-labelledby',\n 'aria-describedby',\n 'aria-invalid',\n 'aria-busy',\n 'title',\n ])\n\n return (\n <KobalteSwitch\n title={local.title}\n class={cn('group/switch flex items-center gap-2.5', local.class)}\n {...rest}\n >\n {/* The name belongs on the input; see Checkbox for why. */}\n <KobalteSwitch.Input\n aria-label={local['aria-label']}\n aria-labelledby={local['aria-labelledby']}\n aria-describedby={local['aria-describedby']}\n aria-invalid={local['aria-invalid']}\n aria-busy={local['aria-busy']}\n title={local.title}\n />\n <KobalteSwitch.Control\n class={cn(\n 'bg-input inline-flex h-5 w-9 shrink-0 items-center rounded-full border border-transparent',\n 'transition-colors ease-out outline-none',\n 'focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-primary-subtle',\n 'data-[checked]:bg-primary',\n 'data-[invalid]:border-destructive',\n 'data-[disabled]:cursor-not-allowed data-[disabled]:opacity-50',\n local.controlClass\n )}\n >\n <KobalteSwitch.Thumb\n class={cn(\n 'bg-background pointer-events-none block size-4 rounded-full shadow-xs',\n 'transition-transform ease-out',\n 'data-[checked]:translate-x-4',\n local.thumbClass\n )}\n />\n </KobalteSwitch.Control>\n {local.children ??\n (local.label || local.description ? (\n <div class=\"grid gap-0.5\">\n {local.label ? (\n <KobalteSwitch.Label class={cn('text-sm leading-none font-medium', local.labelClass)}>\n {local.label}\n </KobalteSwitch.Label>\n ) : null}\n {local.description ? (\n <KobalteSwitch.Description\n class={cn('text-muted-foreground text-sm', local.descriptionClass)}\n >\n {local.description}\n </KobalteSwitch.Description>\n ) : null}\n </div>\n ) : null)}\n </KobalteSwitch>\n )\n}\n\n/**\n * The switch's own label. Valid only inside a `<Switch>`: it is Kobalte's label\n * for that root's control, and outside one there is nothing to associate with.\n * A label drawn *beside* a switch — a settings row with the control trailing —\n * is plain text, and the switch takes an `aria-label` instead.\n */\nexport function SwitchLabel(props: ComponentProps<typeof KobalteSwitch.Label>) {\n const [local, rest] = splitProps(props, ['class'])\n return (\n <KobalteSwitch.Label class={cn('text-sm leading-none font-medium', local.class)} {...rest} />\n )\n}\n\nexport function SwitchDescription(props: ComponentProps<typeof KobalteSwitch.Description>) {\n const [local, rest] = splitProps(props, ['class'])\n return (\n <KobalteSwitch.Description class={cn('text-muted-foreground text-sm', local.class)} {...rest} />\n )\n}\n"],"mappings":";;;;;;AAgCA,SAAgBA,SAAOgB,OAAoB;CACzC,MAAM,CAACC,OAAOC,QAAQd,WAAWY,OAAO;EACtC;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;CAAO,CACR;CAED,OAAAG,gBACGlB,QAAamB,WAAA;EAAA,IACZC,QAAK;GAAA,OAAEJ,MAAMI;EAAK;EAAA,KAAA,WAAA;GAAA,OACXhB,GAAG,0CAA0CY,MAAMK,KAAK;EAAC;CAAA,GAC5DJ,MAAI,EAAA,IAAAH,WAAA;EAAA,OAAA;GAAAI,gBAGPlB,OAAcsB,OAAK;IAAA,KAAA,gBAAA;KAAA,OACNN,MAAM;IAAa;IAAA,KAAA,qBAAA;KAAA,OACdA,MAAM;IAAkB;IAAA,KAAA,sBAAA;KAAA,OACvBA,MAAM;IAAmB;IAAA,KAAA,kBAAA;KAAA,OAC7BA,MAAM;IAAe;IAAA,KAAA,eAAA;KAAA,OACxBA,MAAM;IAAY;IAAA,IAC7BI,QAAK;KAAA,OAAEJ,MAAMI;IAAK;GAAA,CAAA;GAAAF,gBAEnBlB,OAAc4B,SAAO;IAAA,KAAA,WAAA;KAAA,OACbxB,GACL,6FACA,2CACA,oFACA,6BACA,qCACA,iEACAY,MAAMT,YACR;IAAC;IAAA,IAAAO,WAAA;KAAA,OAAAI,gBAEAlB,OAAc6B,OAAK,EAAA,KAAA,WAAA;MAAA,OACXzB,GACL,yEACA,iCACA,gCACAY,MAAMR,UACR;KAAC,EAAA,CAAA;IAAA;GAAA,CAAA;GAAAsB,WAGJd,MAAMF,aACJE,MAAML,SAASK,MAAMH,qBAAW;IAAA,IAAAkB,OAAAC,OAAA;IAAAC,OAAAF,aAAA;KAAA,IAAAG,MAAAJ,WAAA,CAAA,CAE5Bd,MAAML,KAAK;KAAA,aAAXuB,IAAA,IAAAhB,gBACElB,OAAcmC,OAAK;MAAA,KAAA,WAAA;OAAA,OAAQ/B,GAAG,oCAAoCY,MAAMP,UAAU;MAAC;MAAA,IAAAK,WAAA;OAAA,OACjFE,MAAML;MAAK;KAAA,CAAA,IAEZ;IAAI,EAAA,CAAA,GAAA,IAAA;IAAAsB,OAAAF,aAAA;KAAA,IAAAK,OAAAN,WAAA,CAAA,CACPd,MAAMH,WAAW;KAAA,aAAjBuB,KAAA,IAAAlB,gBACElB,OAAcqC,aAAW;MAAA,KAAA,WAAA;OAAA,OACjBjC,GAAG,iCAAiCY,MAAMN,gBAAgB;MAAC;MAAA,IAAAI,WAAA;OAAA,OAEjEE,MAAMH;MAAW;KAAA,CAAA,IAElB;IAAI,EAAA,CAAA,GAAA,IAAA;IAAA,OAAAkB;GAAA,EAAA,CAAA,IAER,KAAK;EAAA;CAAA,EAAA,CAAA,CAAA;AAGjB;;;;;;;AAQA,SAAgBO,YAAYvB,OAAmD;CAC7E,MAAM,CAACC,OAAOC,QAAQd,WAAWY,OAAO,CAAC,OAAO,CAAC;CACjD,OAAAG,gBACGlB,OAAcmC,OAAKhB,WAAA,EAAA,KAAA,WAAA;EAAA,OAAQf,GAAG,oCAAoCY,MAAMK,KAAK;CAAC,EAAA,GAAMJ,IAAI,CAAA;AAE7F;AAEA,SAAgBsB,kBAAkBxB,OAAyD;CACzF,MAAM,CAACC,OAAOC,QAAQd,WAAWY,OAAO,CAAC,OAAO,CAAC;CACjD,OAAAG,gBACGlB,OAAcqC,aAAWlB,WAAA,EAAA,KAAA,WAAA;EAAA,OAAQf,GAAG,iCAAiCY,MAAMK,KAAK;CAAC,EAAA,GAAMJ,IAAI,CAAA;AAEhG"}
|
|
@@ -21,6 +21,8 @@ export type CheckboxProps = Omit<ComponentProps<typeof KobalteCheckbox>, 'childr
|
|
|
21
21
|
controlClass?: string
|
|
22
22
|
labelClass?: string
|
|
23
23
|
descriptionClass?: string
|
|
24
|
+
label?: JSX.Element
|
|
25
|
+
description?: JSX.Element
|
|
24
26
|
/**
|
|
25
27
|
* Replaces the control and label. Omit it to get the default control beside
|
|
26
28
|
* `label` and `description`; supply it to compose the parts yourself.
|
|
@@ -35,13 +37,23 @@ export function Checkbox(props: CheckboxProps) {
|
|
|
35
37
|
'labelClass',
|
|
36
38
|
'descriptionClass',
|
|
37
39
|
'children',
|
|
40
|
+
'label',
|
|
41
|
+
'description',
|
|
38
42
|
'indeterminate',
|
|
39
43
|
'aria-label',
|
|
40
44
|
'aria-labelledby',
|
|
45
|
+
'aria-describedby',
|
|
46
|
+
'aria-invalid',
|
|
47
|
+
'aria-busy',
|
|
48
|
+
'title',
|
|
41
49
|
])
|
|
42
50
|
|
|
43
51
|
return (
|
|
44
|
-
<KobalteCheckbox
|
|
52
|
+
<KobalteCheckbox
|
|
53
|
+
title={local.title}
|
|
54
|
+
class={cn('group/checkbox flex items-start gap-2.5', local.class)}
|
|
55
|
+
{...rest}
|
|
56
|
+
>
|
|
45
57
|
{/*
|
|
46
58
|
* The name goes on the input, which is what carries the value and takes
|
|
47
59
|
* focus. On the Root it would land on a plain div and name nothing — the
|
|
@@ -50,6 +62,10 @@ export function Checkbox(props: CheckboxProps) {
|
|
|
50
62
|
<KobalteCheckbox.Input
|
|
51
63
|
aria-label={local['aria-label']}
|
|
52
64
|
aria-labelledby={local['aria-labelledby']}
|
|
65
|
+
aria-describedby={local['aria-describedby']}
|
|
66
|
+
aria-invalid={local['aria-invalid']}
|
|
67
|
+
aria-busy={local['aria-busy']}
|
|
68
|
+
title={local.title}
|
|
53
69
|
/>
|
|
54
70
|
<KobalteCheckbox.Control
|
|
55
71
|
class={cn(
|
|
@@ -67,14 +83,23 @@ export function Checkbox(props: CheckboxProps) {
|
|
|
67
83
|
{local.indeterminate ? <Minus class="size-3" /> : <Check class="size-3" />}
|
|
68
84
|
</KobalteCheckbox.Indicator>
|
|
69
85
|
</KobalteCheckbox.Control>
|
|
70
|
-
{local.children ??
|
|
71
|
-
|
|
72
|
-
<
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
86
|
+
{local.children ??
|
|
87
|
+
(local.label || local.description ? (
|
|
88
|
+
<div class="grid gap-0.5">
|
|
89
|
+
{local.label ? (
|
|
90
|
+
<KobalteCheckbox.Label class={cn('text-sm font-medium', local.labelClass)}>
|
|
91
|
+
{local.label}
|
|
92
|
+
</KobalteCheckbox.Label>
|
|
93
|
+
) : null}
|
|
94
|
+
{local.description ? (
|
|
95
|
+
<KobalteCheckbox.Description
|
|
96
|
+
class={cn('text-muted-foreground text-sm', local.descriptionClass)}
|
|
97
|
+
>
|
|
98
|
+
{local.description}
|
|
99
|
+
</KobalteCheckbox.Description>
|
|
100
|
+
) : null}
|
|
101
|
+
</div>
|
|
102
|
+
) : null)}
|
|
78
103
|
</KobalteCheckbox>
|
|
79
104
|
)
|
|
80
105
|
}
|
|
@@ -96,6 +96,7 @@ export function ComboboxContent(props: ComponentProps<typeof KobalteCombobox.Con
|
|
|
96
96
|
{...rest}
|
|
97
97
|
>
|
|
98
98
|
<KobalteCombobox.Listbox class={cn('max-h-72 overflow-y-auto', menuContentPadding)} />
|
|
99
|
+
{local.children}
|
|
99
100
|
<KobalteCombobox.Arrow aria-hidden="true" class={popoverArrow} />
|
|
100
101
|
</KobalteCombobox.Content>
|
|
101
102
|
</KobalteCombobox.Portal>
|
|
@@ -25,7 +25,8 @@ export type RadioGroupItemProps = ComponentProps<typeof KobalteRadioGroup.Item>
|
|
|
25
25
|
controlClass?: string
|
|
26
26
|
/**
|
|
27
27
|
* The option's visible label. A radio with no accessible name is unreachable
|
|
28
|
-
* by a screen reader and by voice control, so supply this
|
|
28
|
+
* by a screen reader and by voice control, so supply this, a labelled child,
|
|
29
|
+
* `aria-label`, or `aria-labelledby`.
|
|
29
30
|
*/
|
|
30
31
|
label?: string
|
|
31
32
|
description?: string
|
|
@@ -38,14 +39,28 @@ export function RadioGroupItem(props: RadioGroupItemProps) {
|
|
|
38
39
|
'label',
|
|
39
40
|
'description',
|
|
40
41
|
'children',
|
|
42
|
+
'aria-label',
|
|
43
|
+
'aria-labelledby',
|
|
44
|
+
'aria-describedby',
|
|
45
|
+
'aria-invalid',
|
|
46
|
+
'aria-busy',
|
|
47
|
+
'title',
|
|
41
48
|
])
|
|
42
49
|
|
|
43
50
|
return (
|
|
44
51
|
<KobalteRadioGroup.Item
|
|
52
|
+
title={local.title}
|
|
45
53
|
class={cn('group/radio flex items-start gap-2.5', local.class)}
|
|
46
54
|
{...rest}
|
|
47
55
|
>
|
|
48
|
-
<KobalteRadioGroup.ItemInput
|
|
56
|
+
<KobalteRadioGroup.ItemInput
|
|
57
|
+
aria-label={local['aria-label']}
|
|
58
|
+
aria-labelledby={local['aria-labelledby']}
|
|
59
|
+
aria-describedby={local['aria-describedby']}
|
|
60
|
+
aria-invalid={local['aria-invalid']}
|
|
61
|
+
aria-busy={local['aria-busy']}
|
|
62
|
+
title={local.title}
|
|
63
|
+
/>
|
|
49
64
|
<KobalteRadioGroup.ItemControl
|
|
50
65
|
class={cn(
|
|
51
66
|
'border-input bg-transparent flex size-4 shrink-0 items-center justify-center rounded-full border',
|
|
@@ -63,9 +78,11 @@ export function RadioGroupItem(props: RadioGroupItemProps) {
|
|
|
63
78
|
</KobalteRadioGroup.ItemControl>
|
|
64
79
|
{local.children ?? (
|
|
65
80
|
<div class="grid gap-0.5 leading-none">
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
81
|
+
{local.label ? (
|
|
82
|
+
<KobalteRadioGroup.ItemLabel class="text-sm font-medium">
|
|
83
|
+
{local.label}
|
|
84
|
+
</KobalteRadioGroup.ItemLabel>
|
|
85
|
+
) : null}
|
|
69
86
|
{local.description ? (
|
|
70
87
|
<KobalteRadioGroup.ItemDescription class="text-muted-foreground text-sm">
|
|
71
88
|
{local.description}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Slider as KobalteSlider } from '@kobalte/core/slider'
|
|
2
2
|
import type { ComponentProps } from 'solid-js'
|
|
3
|
-
import { Show, splitProps } from 'solid-js'
|
|
3
|
+
import { For, Show, createUniqueId, createRenderEffect, splitProps } from 'solid-js'
|
|
4
4
|
import { cn } from '../../../lib/utils'
|
|
5
5
|
|
|
6
6
|
/**
|
|
@@ -12,9 +12,13 @@ import { cn } from '../../../lib/utils'
|
|
|
12
12
|
* nobody can set exactly.
|
|
13
13
|
*
|
|
14
14
|
* Kobalte handles pointer capture, keyboard stepping and the ARIA value
|
|
15
|
-
* wiring; this paints the track, fill and thumb.
|
|
15
|
+
* wiring; this paints the track, fill and one thumb per value. Each thumb
|
|
16
|
+
* contains a form-native input, hidden from accessibility because the visible
|
|
17
|
+
* thumb already exposes the slider role.
|
|
16
18
|
*/
|
|
17
19
|
export type SliderProps = ComponentProps<typeof KobalteSlider> & {
|
|
20
|
+
/** Accessible names for individual thumbs, in value order (for example minimum and maximum). */
|
|
21
|
+
thumbLabels?: readonly string[]
|
|
18
22
|
trackClass?: string
|
|
19
23
|
rangeClass?: string
|
|
20
24
|
thumbClass?: string
|
|
@@ -23,11 +27,13 @@ export type SliderProps = ComponentProps<typeof KobalteSlider> & {
|
|
|
23
27
|
}
|
|
24
28
|
|
|
25
29
|
export function Slider(props: SliderProps) {
|
|
30
|
+
const inputId = createUniqueId()
|
|
26
31
|
const [local, rest] = splitProps(props, [
|
|
27
32
|
'class',
|
|
28
33
|
'trackClass',
|
|
29
34
|
'rangeClass',
|
|
30
35
|
'thumbClass',
|
|
36
|
+
'thumbLabels',
|
|
31
37
|
'valueLabel',
|
|
32
38
|
'children',
|
|
33
39
|
'aria-label',
|
|
@@ -61,21 +67,43 @@ export function Slider(props: SliderProps) {
|
|
|
61
67
|
/>
|
|
62
68
|
</KobalteSlider.Track>
|
|
63
69
|
{local.children}
|
|
64
|
-
<
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
'border-primary bg-background block size-4 shrink-0 rounded-full border-2 shadow-xs',
|
|
69
|
-
'transition-[color,box-shadow] ease-out outline-none',
|
|
70
|
-
'hover:ring-4 hover:ring-primary-subtle',
|
|
71
|
-
'focus-visible:ring-4 focus-visible:ring-primary-subtle',
|
|
72
|
-
local.thumbClass
|
|
70
|
+
<For
|
|
71
|
+
each={Array.from(
|
|
72
|
+
{ length: (props.value ?? props.defaultValue ?? [0]).length },
|
|
73
|
+
(_, index) => index
|
|
73
74
|
)}
|
|
74
75
|
>
|
|
75
|
-
|
|
76
|
-
<KobalteSlider.
|
|
77
|
-
|
|
78
|
-
|
|
76
|
+
{(index) => (
|
|
77
|
+
<KobalteSlider.Thumb
|
|
78
|
+
aria-label={local.thumbLabels?.[index] ?? local['aria-label']}
|
|
79
|
+
aria-labelledby={local.thumbLabels?.[index] ? undefined : local['aria-labelledby']}
|
|
80
|
+
class={cn(
|
|
81
|
+
'border-primary bg-background block size-4 shrink-0 rounded-full border-2 shadow-xs',
|
|
82
|
+
'transition-[color,box-shadow] ease-out outline-none',
|
|
83
|
+
'hover:ring-4 hover:ring-primary-subtle',
|
|
84
|
+
'focus-visible:ring-4 focus-visible:ring-primary-subtle',
|
|
85
|
+
local.thumbClass
|
|
86
|
+
)}
|
|
87
|
+
>
|
|
88
|
+
{/* Native reset uses the value property’s default, not an HTML defaultValue attribute. */}
|
|
89
|
+
<KobalteSlider.Input
|
|
90
|
+
id={`slider-${inputId}-${index}`}
|
|
91
|
+
ref={(input) => {
|
|
92
|
+
createRenderEffect(() => {
|
|
93
|
+
input.defaultValue = String(
|
|
94
|
+
props.defaultValue?.[index] ?? props.value?.[index] ?? props.minValue ?? 0
|
|
95
|
+
)
|
|
96
|
+
})
|
|
97
|
+
}}
|
|
98
|
+
hidden
|
|
99
|
+
aria-hidden="true"
|
|
100
|
+
/>
|
|
101
|
+
<Show when={local.valueLabel}>
|
|
102
|
+
<KobalteSlider.ValueLabel class="bg-popover text-popover-foreground absolute -top-6 left-1/2 -translate-x-1/2 rounded-sm border border-border px-1 text-2xs tabular-nums" />
|
|
103
|
+
</Show>
|
|
104
|
+
</KobalteSlider.Thumb>
|
|
105
|
+
)}
|
|
106
|
+
</For>
|
|
79
107
|
</KobalteSlider>
|
|
80
108
|
)
|
|
81
109
|
}
|
|
@@ -21,6 +21,8 @@ export type SwitchProps = Omit<ComponentProps<typeof KobalteSwitch>, 'children'>
|
|
|
21
21
|
thumbClass?: string
|
|
22
22
|
labelClass?: string
|
|
23
23
|
descriptionClass?: string
|
|
24
|
+
label?: JSX.Element
|
|
25
|
+
description?: JSX.Element
|
|
24
26
|
/**
|
|
25
27
|
* Replaces the control and label. Omit it to get the default control beside
|
|
26
28
|
* `label` and `description`; supply it to compose the parts yourself.
|
|
@@ -36,16 +38,30 @@ export function Switch(props: SwitchProps) {
|
|
|
36
38
|
'labelClass',
|
|
37
39
|
'descriptionClass',
|
|
38
40
|
'children',
|
|
41
|
+
'label',
|
|
42
|
+
'description',
|
|
39
43
|
'aria-label',
|
|
40
44
|
'aria-labelledby',
|
|
45
|
+
'aria-describedby',
|
|
46
|
+
'aria-invalid',
|
|
47
|
+
'aria-busy',
|
|
48
|
+
'title',
|
|
41
49
|
])
|
|
42
50
|
|
|
43
51
|
return (
|
|
44
|
-
<KobalteSwitch
|
|
52
|
+
<KobalteSwitch
|
|
53
|
+
title={local.title}
|
|
54
|
+
class={cn('group/switch flex items-center gap-2.5', local.class)}
|
|
55
|
+
{...rest}
|
|
56
|
+
>
|
|
45
57
|
{/* The name belongs on the input; see Checkbox for why. */}
|
|
46
58
|
<KobalteSwitch.Input
|
|
47
59
|
aria-label={local['aria-label']}
|
|
48
60
|
aria-labelledby={local['aria-labelledby']}
|
|
61
|
+
aria-describedby={local['aria-describedby']}
|
|
62
|
+
aria-invalid={local['aria-invalid']}
|
|
63
|
+
aria-busy={local['aria-busy']}
|
|
64
|
+
title={local.title}
|
|
49
65
|
/>
|
|
50
66
|
<KobalteSwitch.Control
|
|
51
67
|
class={cn(
|
|
@@ -67,14 +83,23 @@ export function Switch(props: SwitchProps) {
|
|
|
67
83
|
)}
|
|
68
84
|
/>
|
|
69
85
|
</KobalteSwitch.Control>
|
|
70
|
-
{local.children ??
|
|
71
|
-
|
|
72
|
-
<
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
86
|
+
{local.children ??
|
|
87
|
+
(local.label || local.description ? (
|
|
88
|
+
<div class="grid gap-0.5">
|
|
89
|
+
{local.label ? (
|
|
90
|
+
<KobalteSwitch.Label class={cn('text-sm leading-none font-medium', local.labelClass)}>
|
|
91
|
+
{local.label}
|
|
92
|
+
</KobalteSwitch.Label>
|
|
93
|
+
) : null}
|
|
94
|
+
{local.description ? (
|
|
95
|
+
<KobalteSwitch.Description
|
|
96
|
+
class={cn('text-muted-foreground text-sm', local.descriptionClass)}
|
|
97
|
+
>
|
|
98
|
+
{local.description}
|
|
99
|
+
</KobalteSwitch.Description>
|
|
100
|
+
) : null}
|
|
101
|
+
</div>
|
|
102
|
+
) : null)}
|
|
78
103
|
</KobalteSwitch>
|
|
79
104
|
)
|
|
80
105
|
}
|
package/package.json
CHANGED
|
@@ -21,6 +21,8 @@ export type CheckboxProps = Omit<ComponentProps<typeof KobalteCheckbox>, 'childr
|
|
|
21
21
|
controlClass?: string
|
|
22
22
|
labelClass?: string
|
|
23
23
|
descriptionClass?: string
|
|
24
|
+
label?: JSX.Element
|
|
25
|
+
description?: JSX.Element
|
|
24
26
|
/**
|
|
25
27
|
* Replaces the control and label. Omit it to get the default control beside
|
|
26
28
|
* `label` and `description`; supply it to compose the parts yourself.
|
|
@@ -35,13 +37,23 @@ export function Checkbox(props: CheckboxProps) {
|
|
|
35
37
|
'labelClass',
|
|
36
38
|
'descriptionClass',
|
|
37
39
|
'children',
|
|
40
|
+
'label',
|
|
41
|
+
'description',
|
|
38
42
|
'indeterminate',
|
|
39
43
|
'aria-label',
|
|
40
44
|
'aria-labelledby',
|
|
45
|
+
'aria-describedby',
|
|
46
|
+
'aria-invalid',
|
|
47
|
+
'aria-busy',
|
|
48
|
+
'title',
|
|
41
49
|
])
|
|
42
50
|
|
|
43
51
|
return (
|
|
44
|
-
<KobalteCheckbox
|
|
52
|
+
<KobalteCheckbox
|
|
53
|
+
title={local.title}
|
|
54
|
+
class={cn('group/checkbox flex items-start gap-2.5', local.class)}
|
|
55
|
+
{...rest}
|
|
56
|
+
>
|
|
45
57
|
{/*
|
|
46
58
|
* The name goes on the input, which is what carries the value and takes
|
|
47
59
|
* focus. On the Root it would land on a plain div and name nothing — the
|
|
@@ -50,6 +62,10 @@ export function Checkbox(props: CheckboxProps) {
|
|
|
50
62
|
<KobalteCheckbox.Input
|
|
51
63
|
aria-label={local['aria-label']}
|
|
52
64
|
aria-labelledby={local['aria-labelledby']}
|
|
65
|
+
aria-describedby={local['aria-describedby']}
|
|
66
|
+
aria-invalid={local['aria-invalid']}
|
|
67
|
+
aria-busy={local['aria-busy']}
|
|
68
|
+
title={local.title}
|
|
53
69
|
/>
|
|
54
70
|
<KobalteCheckbox.Control
|
|
55
71
|
class={cn(
|
|
@@ -67,14 +83,23 @@ export function Checkbox(props: CheckboxProps) {
|
|
|
67
83
|
{local.indeterminate ? <Minus class="size-3" /> : <Check class="size-3" />}
|
|
68
84
|
</KobalteCheckbox.Indicator>
|
|
69
85
|
</KobalteCheckbox.Control>
|
|
70
|
-
{local.children ??
|
|
71
|
-
|
|
72
|
-
<
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
86
|
+
{local.children ??
|
|
87
|
+
(local.label || local.description ? (
|
|
88
|
+
<div class="grid gap-0.5">
|
|
89
|
+
{local.label ? (
|
|
90
|
+
<KobalteCheckbox.Label class={cn('text-sm font-medium', local.labelClass)}>
|
|
91
|
+
{local.label}
|
|
92
|
+
</KobalteCheckbox.Label>
|
|
93
|
+
) : null}
|
|
94
|
+
{local.description ? (
|
|
95
|
+
<KobalteCheckbox.Description
|
|
96
|
+
class={cn('text-muted-foreground text-sm', local.descriptionClass)}
|
|
97
|
+
>
|
|
98
|
+
{local.description}
|
|
99
|
+
</KobalteCheckbox.Description>
|
|
100
|
+
) : null}
|
|
101
|
+
</div>
|
|
102
|
+
) : null)}
|
|
78
103
|
</KobalteCheckbox>
|
|
79
104
|
)
|
|
80
105
|
}
|
|
@@ -96,6 +96,7 @@ export function ComboboxContent(props: ComponentProps<typeof KobalteCombobox.Con
|
|
|
96
96
|
{...rest}
|
|
97
97
|
>
|
|
98
98
|
<KobalteCombobox.Listbox class={cn('max-h-72 overflow-y-auto', menuContentPadding)} />
|
|
99
|
+
{local.children}
|
|
99
100
|
<KobalteCombobox.Arrow aria-hidden="true" class={popoverArrow} />
|
|
100
101
|
</KobalteCombobox.Content>
|
|
101
102
|
</KobalteCombobox.Portal>
|
|
@@ -25,7 +25,8 @@ export type RadioGroupItemProps = ComponentProps<typeof KobalteRadioGroup.Item>
|
|
|
25
25
|
controlClass?: string
|
|
26
26
|
/**
|
|
27
27
|
* The option's visible label. A radio with no accessible name is unreachable
|
|
28
|
-
* by a screen reader and by voice control, so supply this
|
|
28
|
+
* by a screen reader and by voice control, so supply this, a labelled child,
|
|
29
|
+
* `aria-label`, or `aria-labelledby`.
|
|
29
30
|
*/
|
|
30
31
|
label?: string
|
|
31
32
|
description?: string
|
|
@@ -38,14 +39,28 @@ export function RadioGroupItem(props: RadioGroupItemProps) {
|
|
|
38
39
|
'label',
|
|
39
40
|
'description',
|
|
40
41
|
'children',
|
|
42
|
+
'aria-label',
|
|
43
|
+
'aria-labelledby',
|
|
44
|
+
'aria-describedby',
|
|
45
|
+
'aria-invalid',
|
|
46
|
+
'aria-busy',
|
|
47
|
+
'title',
|
|
41
48
|
])
|
|
42
49
|
|
|
43
50
|
return (
|
|
44
51
|
<KobalteRadioGroup.Item
|
|
52
|
+
title={local.title}
|
|
45
53
|
class={cn('group/radio flex items-start gap-2.5', local.class)}
|
|
46
54
|
{...rest}
|
|
47
55
|
>
|
|
48
|
-
<KobalteRadioGroup.ItemInput
|
|
56
|
+
<KobalteRadioGroup.ItemInput
|
|
57
|
+
aria-label={local['aria-label']}
|
|
58
|
+
aria-labelledby={local['aria-labelledby']}
|
|
59
|
+
aria-describedby={local['aria-describedby']}
|
|
60
|
+
aria-invalid={local['aria-invalid']}
|
|
61
|
+
aria-busy={local['aria-busy']}
|
|
62
|
+
title={local.title}
|
|
63
|
+
/>
|
|
49
64
|
<KobalteRadioGroup.ItemControl
|
|
50
65
|
class={cn(
|
|
51
66
|
'border-input bg-transparent flex size-4 shrink-0 items-center justify-center rounded-full border',
|
|
@@ -63,9 +78,11 @@ export function RadioGroupItem(props: RadioGroupItemProps) {
|
|
|
63
78
|
</KobalteRadioGroup.ItemControl>
|
|
64
79
|
{local.children ?? (
|
|
65
80
|
<div class="grid gap-0.5 leading-none">
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
81
|
+
{local.label ? (
|
|
82
|
+
<KobalteRadioGroup.ItemLabel class="text-sm font-medium">
|
|
83
|
+
{local.label}
|
|
84
|
+
</KobalteRadioGroup.ItemLabel>
|
|
85
|
+
) : null}
|
|
69
86
|
{local.description ? (
|
|
70
87
|
<KobalteRadioGroup.ItemDescription class="text-muted-foreground text-sm">
|
|
71
88
|
{local.description}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Slider as KobalteSlider } from '@kobalte/core/slider'
|
|
2
2
|
import type { ComponentProps } from 'solid-js'
|
|
3
|
-
import { Show, splitProps } from 'solid-js'
|
|
3
|
+
import { For, Show, createUniqueId, createRenderEffect, splitProps } from 'solid-js'
|
|
4
4
|
import { cn } from '#lib/utils'
|
|
5
5
|
|
|
6
6
|
/**
|
|
@@ -12,9 +12,13 @@ import { cn } from '#lib/utils'
|
|
|
12
12
|
* nobody can set exactly.
|
|
13
13
|
*
|
|
14
14
|
* Kobalte handles pointer capture, keyboard stepping and the ARIA value
|
|
15
|
-
* wiring; this paints the track, fill and thumb.
|
|
15
|
+
* wiring; this paints the track, fill and one thumb per value. Each thumb
|
|
16
|
+
* contains a form-native input, hidden from accessibility because the visible
|
|
17
|
+
* thumb already exposes the slider role.
|
|
16
18
|
*/
|
|
17
19
|
export type SliderProps = ComponentProps<typeof KobalteSlider> & {
|
|
20
|
+
/** Accessible names for individual thumbs, in value order (for example minimum and maximum). */
|
|
21
|
+
thumbLabels?: readonly string[]
|
|
18
22
|
trackClass?: string
|
|
19
23
|
rangeClass?: string
|
|
20
24
|
thumbClass?: string
|
|
@@ -23,11 +27,13 @@ export type SliderProps = ComponentProps<typeof KobalteSlider> & {
|
|
|
23
27
|
}
|
|
24
28
|
|
|
25
29
|
export function Slider(props: SliderProps) {
|
|
30
|
+
const inputId = createUniqueId()
|
|
26
31
|
const [local, rest] = splitProps(props, [
|
|
27
32
|
'class',
|
|
28
33
|
'trackClass',
|
|
29
34
|
'rangeClass',
|
|
30
35
|
'thumbClass',
|
|
36
|
+
'thumbLabels',
|
|
31
37
|
'valueLabel',
|
|
32
38
|
'children',
|
|
33
39
|
'aria-label',
|
|
@@ -61,21 +67,43 @@ export function Slider(props: SliderProps) {
|
|
|
61
67
|
/>
|
|
62
68
|
</KobalteSlider.Track>
|
|
63
69
|
{local.children}
|
|
64
|
-
<
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
'border-primary bg-background block size-4 shrink-0 rounded-full border-2 shadow-xs',
|
|
69
|
-
'transition-[color,box-shadow] ease-out outline-none',
|
|
70
|
-
'hover:ring-4 hover:ring-primary-subtle',
|
|
71
|
-
'focus-visible:ring-4 focus-visible:ring-primary-subtle',
|
|
72
|
-
local.thumbClass
|
|
70
|
+
<For
|
|
71
|
+
each={Array.from(
|
|
72
|
+
{ length: (props.value ?? props.defaultValue ?? [0]).length },
|
|
73
|
+
(_, index) => index
|
|
73
74
|
)}
|
|
74
75
|
>
|
|
75
|
-
|
|
76
|
-
<KobalteSlider.
|
|
77
|
-
|
|
78
|
-
|
|
76
|
+
{(index) => (
|
|
77
|
+
<KobalteSlider.Thumb
|
|
78
|
+
aria-label={local.thumbLabels?.[index] ?? local['aria-label']}
|
|
79
|
+
aria-labelledby={local.thumbLabels?.[index] ? undefined : local['aria-labelledby']}
|
|
80
|
+
class={cn(
|
|
81
|
+
'border-primary bg-background block size-4 shrink-0 rounded-full border-2 shadow-xs',
|
|
82
|
+
'transition-[color,box-shadow] ease-out outline-none',
|
|
83
|
+
'hover:ring-4 hover:ring-primary-subtle',
|
|
84
|
+
'focus-visible:ring-4 focus-visible:ring-primary-subtle',
|
|
85
|
+
local.thumbClass
|
|
86
|
+
)}
|
|
87
|
+
>
|
|
88
|
+
{/* Native reset uses the value property’s default, not an HTML defaultValue attribute. */}
|
|
89
|
+
<KobalteSlider.Input
|
|
90
|
+
id={`slider-${inputId}-${index}`}
|
|
91
|
+
ref={(input) => {
|
|
92
|
+
createRenderEffect(() => {
|
|
93
|
+
input.defaultValue = String(
|
|
94
|
+
props.defaultValue?.[index] ?? props.value?.[index] ?? props.minValue ?? 0
|
|
95
|
+
)
|
|
96
|
+
})
|
|
97
|
+
}}
|
|
98
|
+
hidden
|
|
99
|
+
aria-hidden="true"
|
|
100
|
+
/>
|
|
101
|
+
<Show when={local.valueLabel}>
|
|
102
|
+
<KobalteSlider.ValueLabel class="bg-popover text-popover-foreground absolute -top-6 left-1/2 -translate-x-1/2 rounded-sm border border-border px-1 text-2xs tabular-nums" />
|
|
103
|
+
</Show>
|
|
104
|
+
</KobalteSlider.Thumb>
|
|
105
|
+
)}
|
|
106
|
+
</For>
|
|
79
107
|
</KobalteSlider>
|
|
80
108
|
)
|
|
81
109
|
}
|