@proyecto-viviana/solidaria-components 0.3.2 → 0.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/dist/ActionBar.js +184 -0
- package/dist/ActionBar.js.map +1 -0
- package/dist/ActionBar.jsx +128 -0
- package/dist/ActionBar.jsx.map +1 -0
- package/dist/ActionGroup.js +179 -0
- package/dist/ActionGroup.js.map +1 -0
- package/dist/ActionGroup.jsx +129 -0
- package/dist/ActionGroup.jsx.map +1 -0
- package/dist/Alert.js +111 -0
- package/dist/Alert.js.map +1 -0
- package/dist/Alert.jsx +82 -0
- package/dist/Alert.jsx.map +1 -0
- package/dist/Autocomplete.js +130 -0
- package/dist/Autocomplete.js.map +1 -0
- package/dist/Autocomplete.jsx +116 -0
- package/dist/Autocomplete.jsx.map +1 -0
- package/dist/Breadcrumbs.d.ts.map +1 -1
- package/dist/Breadcrumbs.js +334 -0
- package/dist/Breadcrumbs.js.map +1 -0
- package/dist/Breadcrumbs.jsx +266 -0
- package/dist/Breadcrumbs.jsx.map +1 -0
- package/dist/Button.d.ts.map +1 -1
- package/dist/Button.js +348 -0
- package/dist/Button.js.map +1 -0
- package/dist/Button.jsx +314 -0
- package/dist/Button.jsx.map +1 -0
- package/dist/Calendar.d.ts +4 -4
- package/dist/Calendar.d.ts.map +1 -1
- package/dist/Calendar.js +538 -0
- package/dist/Calendar.js.map +1 -0
- package/dist/Calendar.jsx +333 -0
- package/dist/Calendar.jsx.map +1 -0
- package/dist/CalendarPicker.d.ts +33 -0
- package/dist/CalendarPicker.d.ts.map +1 -0
- package/dist/CalendarPicker.js +44 -0
- package/dist/CalendarPicker.js.map +1 -0
- package/dist/CalendarPicker.jsx +44 -0
- package/dist/CalendarPicker.jsx.map +1 -0
- package/dist/Checkbox.d.ts +83 -4
- package/dist/Checkbox.d.ts.map +1 -1
- package/dist/Checkbox.js +923 -0
- package/dist/Checkbox.js.map +1 -0
- package/dist/Checkbox.jsx +707 -0
- package/dist/Checkbox.jsx.map +1 -0
- package/dist/Collection.d.ts.map +1 -1
- package/dist/Collection.js +202 -0
- package/dist/Collection.js.map +1 -0
- package/dist/Collection.jsx +152 -0
- package/dist/Collection.jsx.map +1 -0
- package/dist/Color.d.ts.map +1 -1
- package/dist/Color.js +1720 -0
- package/dist/Color.js.map +1 -0
- package/dist/Color.jsx +1344 -0
- package/dist/Color.jsx.map +1 -0
- package/dist/ColorEditor.js +208 -0
- package/dist/ColorEditor.js.map +1 -0
- package/dist/ColorEditor.jsx +120 -0
- package/dist/ColorEditor.jsx.map +1 -0
- package/dist/ComboBox.d.ts +4 -4
- package/dist/ComboBox.d.ts.map +1 -1
- package/dist/ComboBox.js +992 -0
- package/dist/ComboBox.js.map +1 -0
- package/dist/ComboBox.jsx +714 -0
- package/dist/ComboBox.jsx.map +1 -0
- package/dist/ContextualHelpTrigger.js +146 -0
- package/dist/ContextualHelpTrigger.js.map +1 -0
- package/dist/ContextualHelpTrigger.jsx +109 -0
- package/dist/ContextualHelpTrigger.jsx.map +1 -0
- package/dist/DateField.d.ts +3 -3
- package/dist/DateField.d.ts.map +1 -1
- package/dist/DateField.js +4 -0
- package/dist/DateField.jsx +4 -0
- package/dist/DateField2.js +499 -0
- package/dist/DateField2.js.map +1 -0
- package/dist/DateField2.jsx +317 -0
- package/dist/DateField2.jsx.map +1 -0
- package/dist/DatePicker.d.ts +4 -4
- package/dist/DatePicker.d.ts.map +1 -1
- package/dist/DatePicker.js +991 -0
- package/dist/DatePicker.js.map +1 -0
- package/dist/DatePicker.jsx +682 -0
- package/dist/DatePicker.jsx.map +1 -0
- package/dist/Dialog.d.ts.map +1 -1
- package/dist/Dialog.js +337 -0
- package/dist/Dialog.js.map +1 -0
- package/dist/Dialog.jsx +192 -0
- package/dist/Dialog.jsx.map +1 -0
- package/dist/Disclosure.d.ts.map +1 -1
- package/dist/Disclosure.js +328 -0
- package/dist/Disclosure.js.map +1 -0
- package/dist/Disclosure.jsx +230 -0
- package/dist/Disclosure.jsx.map +1 -0
- package/dist/DragAndDrop.d.ts.map +1 -1
- package/dist/DragAndDrop.js +176 -0
- package/dist/DragAndDrop.js.map +1 -0
- package/dist/DragAndDrop.jsx +160 -0
- package/dist/DragAndDrop.jsx.map +1 -0
- package/dist/DropZone.d.ts.map +1 -1
- package/dist/DropZone.js +189 -0
- package/dist/DropZone.js.map +1 -0
- package/dist/DropZone.jsx +144 -0
- package/dist/DropZone.jsx.map +1 -0
- package/dist/FieldError.js +66 -0
- package/dist/FieldError.js.map +1 -0
- package/dist/FieldError.jsx +47 -0
- package/dist/FieldError.jsx.map +1 -0
- package/dist/FileTrigger.js +79 -0
- package/dist/FileTrigger.js.map +1 -0
- package/dist/FileTrigger.jsx +49 -0
- package/dist/FileTrigger.jsx.map +1 -0
- package/dist/Focusable.js +70 -0
- package/dist/Focusable.js.map +1 -0
- package/dist/Focusable.jsx +69 -0
- package/dist/Focusable.jsx.map +1 -0
- package/dist/Form.js +99 -0
- package/dist/Form.js.map +1 -0
- package/dist/Form.jsx +73 -0
- package/dist/Form.jsx.map +1 -0
- package/dist/GridList.d.ts +34 -2
- package/dist/GridList.d.ts.map +1 -1
- package/dist/GridList.js +723 -0
- package/dist/GridList.js.map +1 -0
- package/dist/GridList.jsx +552 -0
- package/dist/GridList.jsx.map +1 -0
- package/dist/HiddenTimeInput.js +104 -0
- package/dist/HiddenTimeInput.js.map +1 -0
- package/dist/HiddenTimeInput.jsx +69 -0
- package/dist/HiddenTimeInput.jsx.map +1 -0
- package/dist/Icon.d.ts.map +1 -1
- package/dist/Icon.js +127 -0
- package/dist/Icon.js.map +1 -0
- package/dist/Icon.jsx +72 -0
- package/dist/Icon.jsx.map +1 -0
- package/dist/Keyboard.js +30 -0
- package/dist/Keyboard.js.map +1 -0
- package/dist/Keyboard.jsx +24 -0
- package/dist/Keyboard.jsx.map +1 -0
- package/dist/Landmark.js +134 -0
- package/dist/Landmark.js.map +1 -0
- package/dist/Landmark.jsx +118 -0
- package/dist/Landmark.jsx.map +1 -0
- package/dist/Link.d.ts.map +1 -1
- package/dist/Link.js +219 -0
- package/dist/Link.js.map +1 -0
- package/dist/Link.jsx +189 -0
- package/dist/Link.jsx.map +1 -0
- package/dist/ListBox.d.ts.map +1 -1
- package/dist/ListBox.js +670 -0
- package/dist/ListBox.js.map +1 -0
- package/dist/ListBox.jsx +508 -0
- package/dist/ListBox.jsx.map +1 -0
- package/dist/Menu.d.ts +27 -9
- package/dist/Menu.d.ts.map +1 -1
- package/dist/Menu.js +1254 -0
- package/dist/Menu.js.map +1 -0
- package/dist/Menu.jsx +1042 -0
- package/dist/Menu.jsx.map +1 -0
- package/dist/Meter.d.ts.map +1 -1
- package/dist/Meter.js +123 -0
- package/dist/Meter.js.map +1 -0
- package/dist/Meter.jsx +107 -0
- package/dist/Meter.jsx.map +1 -0
- package/dist/Modal.d.ts.map +1 -1
- package/dist/Modal.js +380 -0
- package/dist/Modal.js.map +1 -0
- package/dist/Modal.jsx +314 -0
- package/dist/Modal.jsx.map +1 -0
- package/dist/NumberField.d.ts +3 -3
- package/dist/NumberField.d.ts.map +1 -1
- package/dist/NumberField.js +573 -0
- package/dist/NumberField.js.map +1 -0
- package/dist/NumberField.jsx +443 -0
- package/dist/NumberField.jsx.map +1 -0
- package/dist/Popover.d.ts +10 -2
- package/dist/Popover.d.ts.map +1 -1
- package/dist/Popover.js +464 -0
- package/dist/Popover.js.map +1 -0
- package/dist/Popover.jsx +333 -0
- package/dist/Popover.jsx.map +1 -0
- package/dist/Pressable.js +69 -0
- package/dist/Pressable.js.map +1 -0
- package/dist/Pressable.jsx +68 -0
- package/dist/Pressable.jsx.map +1 -0
- package/dist/ProgressBar.d.ts.map +1 -1
- package/dist/ProgressBar.js +130 -0
- package/dist/ProgressBar.js.map +1 -0
- package/dist/ProgressBar.jsx +114 -0
- package/dist/ProgressBar.jsx.map +1 -0
- package/dist/RadioGroup.d.ts +82 -4
- package/dist/RadioGroup.d.ts.map +1 -1
- package/dist/RadioGroup.js +931 -0
- package/dist/RadioGroup.js.map +1 -0
- package/dist/RadioGroup.jsx +681 -0
- package/dist/RadioGroup.jsx.map +1 -0
- package/dist/RangeCalendar.d.ts.map +1 -1
- package/dist/RangeCalendar.js +410 -0
- package/dist/RangeCalendar.js.map +1 -0
- package/dist/RangeCalendar.jsx +253 -0
- package/dist/RangeCalendar.jsx.map +1 -0
- package/dist/RouterProvider.js +118 -0
- package/dist/RouterProvider.js.map +1 -0
- package/dist/RouterProvider.jsx +112 -0
- package/dist/RouterProvider.jsx.map +1 -0
- package/dist/SearchField.d.ts +2 -2
- package/dist/SearchField.d.ts.map +1 -1
- package/dist/SearchField.js +643 -0
- package/dist/SearchField.js.map +1 -0
- package/dist/SearchField.jsx +526 -0
- package/dist/SearchField.jsx.map +1 -0
- package/dist/Select.d.ts.map +1 -1
- package/dist/Select.js +1031 -0
- package/dist/Select.js.map +1 -0
- package/dist/Select.jsx +744 -0
- package/dist/Select.jsx.map +1 -0
- package/dist/SelectionIndicator.d.ts.map +1 -1
- package/dist/SelectionIndicator.js +86 -0
- package/dist/SelectionIndicator.js.map +1 -0
- package/dist/SelectionIndicator.jsx +50 -0
- package/dist/SelectionIndicator.jsx.map +1 -0
- package/dist/Separator.js +97 -0
- package/dist/Separator.js.map +1 -0
- package/dist/Separator.jsx +85 -0
- package/dist/Separator.jsx.map +1 -0
- package/dist/SharedElementTransition.d.ts.map +1 -1
- package/dist/SharedElementTransition.js +165 -0
- package/dist/SharedElementTransition.js.map +1 -0
- package/dist/SharedElementTransition.jsx +138 -0
- package/dist/SharedElementTransition.jsx.map +1 -0
- package/dist/Slider.d.ts +33 -1
- package/dist/Slider.d.ts.map +1 -1
- package/dist/Slider.js +515 -0
- package/dist/Slider.js.map +1 -0
- package/dist/Slider.jsx +403 -0
- package/dist/Slider.jsx.map +1 -0
- package/dist/StepList.js +198 -0
- package/dist/StepList.js.map +1 -0
- package/dist/StepList.jsx +141 -0
- package/dist/StepList.jsx.map +1 -0
- package/dist/Switch.d.ts +65 -2
- package/dist/Switch.d.ts.map +1 -1
- package/dist/Switch.js +534 -0
- package/dist/Switch.js.map +1 -0
- package/dist/Switch.jsx +393 -0
- package/dist/Switch.jsx.map +1 -0
- package/dist/Table.d.ts +48 -0
- package/dist/Table.d.ts.map +1 -1
- package/dist/Table.js +1759 -0
- package/dist/Table.js.map +1 -0
- package/dist/Table.jsx +1348 -0
- package/dist/Table.jsx.map +1 -0
- package/dist/Tabs.d.ts +0 -4
- package/dist/Tabs.d.ts.map +1 -1
- package/dist/Tabs.js +595 -0
- package/dist/Tabs.js.map +1 -0
- package/dist/Tabs.jsx +367 -0
- package/dist/Tabs.jsx.map +1 -0
- package/dist/TagGroup.d.ts.map +1 -1
- package/dist/TagGroup.js +378 -0
- package/dist/TagGroup.js.map +1 -0
- package/dist/TagGroup.jsx +270 -0
- package/dist/TagGroup.jsx.map +1 -0
- package/dist/Text.d.ts +18 -6
- package/dist/Text.d.ts.map +1 -1
- package/dist/Text.js +42 -0
- package/dist/Text.js.map +1 -0
- package/dist/Text.jsx +35 -0
- package/dist/Text.jsx.map +1 -0
- package/dist/TextField.d.ts +6 -6
- package/dist/TextField.d.ts.map +1 -1
- package/dist/TextField.js +436 -0
- package/dist/TextField.js.map +1 -0
- package/dist/TextField.jsx +403 -0
- package/dist/TextField.jsx.map +1 -0
- package/dist/TimeField.d.ts +3 -3
- package/dist/TimeField.d.ts.map +1 -1
- package/dist/TimeField.js +372 -0
- package/dist/TimeField.js.map +1 -0
- package/dist/TimeField.jsx +224 -0
- package/dist/TimeField.jsx.map +1 -0
- package/dist/Toast.d.ts +14 -0
- package/dist/Toast.d.ts.map +1 -1
- package/dist/Toast.js +551 -0
- package/dist/Toast.js.map +1 -0
- package/dist/Toast.jsx +361 -0
- package/dist/Toast.jsx.map +1 -0
- package/dist/ToggleButton.d.ts.map +1 -1
- package/dist/ToggleButton.js +123 -0
- package/dist/ToggleButton.js.map +1 -0
- package/dist/ToggleButton.jsx +88 -0
- package/dist/ToggleButton.jsx.map +1 -0
- package/dist/ToggleButtonGroup.d.ts.map +1 -1
- package/dist/ToggleButtonGroup.js +114 -0
- package/dist/ToggleButtonGroup.js.map +1 -0
- package/dist/ToggleButtonGroup.jsx +85 -0
- package/dist/ToggleButtonGroup.jsx.map +1 -0
- package/dist/Toolbar.js +112 -0
- package/dist/Toolbar.js.map +1 -0
- package/dist/Toolbar.jsx +92 -0
- package/dist/Toolbar.jsx.map +1 -0
- package/dist/Tooltip.d.ts.map +1 -1
- package/dist/Tooltip.js +539 -0
- package/dist/Tooltip.js.map +1 -0
- package/dist/Tooltip.jsx +465 -0
- package/dist/Tooltip.jsx.map +1 -0
- package/dist/Tree.d.ts +14 -2
- package/dist/Tree.d.ts.map +1 -1
- package/dist/Tree.js +1424 -0
- package/dist/Tree.js.map +1 -0
- package/dist/Tree.jsx +1172 -0
- package/dist/Tree.jsx.map +1 -0
- package/dist/Virtualizer.d.ts +16 -2
- package/dist/Virtualizer.d.ts.map +1 -1
- package/dist/Virtualizer.js +2 -0
- package/dist/Virtualizer.jsx +2 -0
- package/dist/Virtualizer2.js +751 -0
- package/dist/Virtualizer2.js.map +1 -0
- package/dist/Virtualizer2.jsx +730 -0
- package/dist/Virtualizer2.jsx.map +1 -0
- package/dist/VirtualizerLayouts.d.ts +18 -0
- package/dist/VirtualizerLayouts.d.ts.map +1 -1
- package/dist/VisuallyHidden.js +42 -0
- package/dist/VisuallyHidden.js.map +1 -0
- package/dist/VisuallyHidden.jsx +35 -0
- package/dist/VisuallyHidden.jsx.map +1 -0
- package/dist/contexts.js +33 -0
- package/dist/contexts.js.map +1 -0
- package/dist/contexts.jsx +33 -0
- package/dist/contexts.jsx.map +1 -0
- package/dist/index.d.ts +7 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +70 -23932
- package/dist/index.jsx +70 -18337
- package/dist/useDragAndDrop.js +2 -0
- package/dist/useDragAndDrop.jsx +2 -0
- package/dist/useDragAndDrop2.js +395 -0
- package/dist/useDragAndDrop2.js.map +1 -0
- package/dist/useDragAndDrop2.jsx +395 -0
- package/dist/useDragAndDrop2.jsx.map +1 -0
- package/dist/utils.d.ts +83 -11
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +285 -0
- package/dist/utils.js.map +1 -0
- package/dist/utils.jsx +277 -0
- package/dist/utils.jsx.map +1 -0
- package/dist/virtualizer/Layout.js +144 -0
- package/dist/virtualizer/Layout.js.map +1 -0
- package/dist/virtualizer/Layout.jsx +144 -0
- package/dist/virtualizer/Layout.jsx.map +1 -0
- package/package.json +401 -4
- package/src/Breadcrumbs.tsx +3 -1
- package/src/Button.tsx +22 -2
- package/src/Calendar.tsx +27 -10
- package/src/CalendarPicker.tsx +73 -0
- package/src/Checkbox.tsx +539 -3
- package/src/Collection.tsx +9 -3
- package/src/Color.tsx +42 -14
- package/src/ComboBox.tsx +50 -6
- package/src/DateField.tsx +20 -2
- package/src/DatePicker.tsx +57 -5
- package/src/Dialog.tsx +13 -5
- package/src/Disclosure.tsx +3 -1
- package/src/DragAndDrop.tsx +3 -1
- package/src/DropZone.tsx +3 -1
- package/src/GridList.tsx +125 -24
- package/src/Icon.tsx +3 -1
- package/src/Link.tsx +3 -1
- package/src/ListBox.tsx +31 -4
- package/src/Menu.tsx +252 -128
- package/src/Meter.tsx +3 -1
- package/src/Modal.tsx +100 -52
- package/src/NumberField.tsx +51 -8
- package/src/Popover.tsx +40 -10
- package/src/ProgressBar.tsx +3 -1
- package/src/RadioGroup.tsx +468 -4
- package/src/RangeCalendar.tsx +3 -1
- package/src/SearchField.tsx +27 -3
- package/src/Select.tsx +22 -7
- package/src/SelectionIndicator.tsx +3 -1
- package/src/SharedElementTransition.tsx +3 -1
- package/src/Slider.tsx +159 -13
- package/src/Switch.tsx +395 -2
- package/src/Table.tsx +409 -95
- package/src/Tabs.tsx +16 -45
- package/src/TagGroup.tsx +3 -1
- package/src/Text.tsx +31 -10
- package/src/TextField.tsx +43 -5
- package/src/TimeField.tsx +20 -2
- package/src/Toast.tsx +79 -14
- package/src/ToggleButton.tsx +3 -1
- package/src/ToggleButtonGroup.tsx +3 -1
- package/src/Tooltip.tsx +3 -1
- package/src/Tree.tsx +77 -9
- package/src/Virtualizer.tsx +180 -31
- package/src/VirtualizerLayouts.ts +45 -10
- package/src/index.ts +50 -0
- package/src/utils.tsx +243 -27
- package/dist/index.js.map +0 -1
- package/dist/index.jsx.map +0 -1
|
@@ -61,7 +61,9 @@ export function SelectionIndicator(props: SelectionIndicatorProps): JSX.Element
|
|
|
61
61
|
|
|
62
62
|
const renderProps = useRenderProps(
|
|
63
63
|
{
|
|
64
|
-
children
|
|
64
|
+
get children() {
|
|
65
|
+
return local.children;
|
|
66
|
+
},
|
|
65
67
|
class: local.class,
|
|
66
68
|
style: local.style,
|
|
67
69
|
defaultClassName: "solidaria-SelectionIndicator",
|
|
@@ -234,7 +234,9 @@ export function SharedElement(props: SharedElementProps): JSX.Element | null {
|
|
|
234
234
|
|
|
235
235
|
const renderProps = useRenderProps(
|
|
236
236
|
{
|
|
237
|
-
children
|
|
237
|
+
get children() {
|
|
238
|
+
return local.children;
|
|
239
|
+
},
|
|
238
240
|
class: local.class,
|
|
239
241
|
style: local.style,
|
|
240
242
|
defaultClassName: "solidaria-SharedElement",
|
package/src/Slider.tsx
CHANGED
|
@@ -12,6 +12,7 @@ import {
|
|
|
12
12
|
createHover,
|
|
13
13
|
mergeProps,
|
|
14
14
|
type AriaSliderProps,
|
|
15
|
+
type HoverEvents,
|
|
15
16
|
} from "@proyecto-viviana/solidaria";
|
|
16
17
|
import {
|
|
17
18
|
createSliderState,
|
|
@@ -124,6 +125,32 @@ export interface SliderThumbProps
|
|
|
124
125
|
style?: StyleOrFunction<SliderThumbRenderProps>;
|
|
125
126
|
}
|
|
126
127
|
|
|
128
|
+
export interface SliderFillRenderProps {
|
|
129
|
+
/** Whether the slider is disabled. */
|
|
130
|
+
isDisabled: boolean;
|
|
131
|
+
/** Whether the slider fill is currently hovered with a mouse. */
|
|
132
|
+
isHovered: boolean;
|
|
133
|
+
/** The value as a percent (0-1). */
|
|
134
|
+
valuePercent: number;
|
|
135
|
+
/** The orientation. */
|
|
136
|
+
orientation: SliderOrientation;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
export interface SliderFillProps
|
|
140
|
+
extends
|
|
141
|
+
SlotProps,
|
|
142
|
+
HoverEvents,
|
|
143
|
+
Omit<JSX.HTMLAttributes<HTMLDivElement>, "class" | "style" | "children"> {
|
|
144
|
+
/** The offset from which to start the fill. Defaults to the slider's minValue. */
|
|
145
|
+
offset?: number;
|
|
146
|
+
/** The children of the fill. */
|
|
147
|
+
children?: RenderChildren<SliderFillRenderProps>;
|
|
148
|
+
/** The CSS className for the element. */
|
|
149
|
+
class?: ClassNameOrFunction<SliderFillRenderProps>;
|
|
150
|
+
/** The inline style for the element. */
|
|
151
|
+
style?: StyleOrFunction<SliderFillRenderProps>;
|
|
152
|
+
}
|
|
153
|
+
|
|
127
154
|
export interface SliderOutputRenderProps {
|
|
128
155
|
/** The current value. */
|
|
129
156
|
value: number;
|
|
@@ -156,6 +183,7 @@ interface SliderContextValue {
|
|
|
156
183
|
export const SliderContext = createContext<SliderContextValue | null>(null);
|
|
157
184
|
export const SliderStateContext = SliderContext;
|
|
158
185
|
export const SliderTrackContext = SliderContext;
|
|
186
|
+
export const SliderFillContext = SliderContext;
|
|
159
187
|
export const SliderOutputContext = SliderContext;
|
|
160
188
|
|
|
161
189
|
/**
|
|
@@ -252,7 +280,9 @@ export function Slider(props: SliderProps): JSX.Element {
|
|
|
252
280
|
|
|
253
281
|
const renderProps = useRenderProps(
|
|
254
282
|
{
|
|
255
|
-
children
|
|
283
|
+
get children() {
|
|
284
|
+
return props.children;
|
|
285
|
+
},
|
|
256
286
|
class: local.class,
|
|
257
287
|
style: local.style,
|
|
258
288
|
defaultClassName: "solidaria-Slider",
|
|
@@ -363,7 +393,9 @@ export function SliderTrack(props: SliderTrackProps): JSX.Element {
|
|
|
363
393
|
|
|
364
394
|
const renderProps = useRenderProps(
|
|
365
395
|
{
|
|
366
|
-
children
|
|
396
|
+
get children() {
|
|
397
|
+
return props.children;
|
|
398
|
+
},
|
|
367
399
|
class: local.class,
|
|
368
400
|
style: local.style,
|
|
369
401
|
defaultClassName: "solidaria-Slider-track",
|
|
@@ -431,7 +463,9 @@ export function SliderThumb(props: SliderThumbProps): JSX.Element {
|
|
|
431
463
|
|
|
432
464
|
const renderProps = useRenderProps(
|
|
433
465
|
{
|
|
434
|
-
children
|
|
466
|
+
get children() {
|
|
467
|
+
return props.children;
|
|
468
|
+
},
|
|
435
469
|
class: local.class,
|
|
436
470
|
style: local.style,
|
|
437
471
|
defaultClassName: "solidaria-Slider-thumb",
|
|
@@ -467,22 +501,131 @@ export function SliderThumb(props: SliderThumbProps): JSX.Element {
|
|
|
467
501
|
cleanFocusProps() as Record<string, unknown>,
|
|
468
502
|
) as JSX.InputHTMLAttributes<HTMLInputElement>;
|
|
469
503
|
|
|
504
|
+
return (
|
|
505
|
+
<>
|
|
506
|
+
<VisuallyHidden>
|
|
507
|
+
<input ref={setInputRef} {...mergedInputProps()} />
|
|
508
|
+
</VisuallyHidden>
|
|
509
|
+
<div
|
|
510
|
+
{...domProps}
|
|
511
|
+
{...cleanThumbProps()}
|
|
512
|
+
{...cleanHoverProps()}
|
|
513
|
+
class={renderProps.class()}
|
|
514
|
+
style={mergedStyle()}
|
|
515
|
+
data-disabled={state.isDisabled || undefined}
|
|
516
|
+
data-dragging={state.isDragging() || undefined}
|
|
517
|
+
data-focused={isFocused() || state.isFocused() || undefined}
|
|
518
|
+
data-focus-visible={isFocusVisible() || undefined}
|
|
519
|
+
data-hovered={isHovered() || undefined}
|
|
520
|
+
>
|
|
521
|
+
{renderProps.renderChildren()}
|
|
522
|
+
</div>
|
|
523
|
+
</>
|
|
524
|
+
);
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
/** Clamp a value between min and max (mirror of upstream's number/clamp). */
|
|
528
|
+
function clampFill(value: number, min: number, max: number): number {
|
|
529
|
+
return Math.min(Math.max(value, min), max);
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
/**
|
|
533
|
+
* The fill element of a slider, displaying the selected range.
|
|
534
|
+
*
|
|
535
|
+
* Port of react-aria-components `SliderFill` (RAC 1.18). Upstream reads the
|
|
536
|
+
* array-based `SliderState` (`values`/`getThumbPercent`); our `SliderState` is
|
|
537
|
+
* single-value, so this fills from `offset` (default the slider's minValue, i.e.
|
|
538
|
+
* 0%) to the current value — the single-thumb branch of upstream's math, using
|
|
539
|
+
* the same `(v - min) / (max - min)` percent formula the state itself uses.
|
|
540
|
+
*/
|
|
541
|
+
export function SliderFill(props: SliderFillProps): JSX.Element {
|
|
542
|
+
const [local, domProps] = splitProps(props, [
|
|
543
|
+
"class",
|
|
544
|
+
"style",
|
|
545
|
+
"slot",
|
|
546
|
+
"offset",
|
|
547
|
+
"children",
|
|
548
|
+
"onHoverStart",
|
|
549
|
+
"onHoverEnd",
|
|
550
|
+
"onHoverChange",
|
|
551
|
+
]);
|
|
552
|
+
|
|
553
|
+
const context = useContext(SliderContext);
|
|
554
|
+
if (!context) {
|
|
555
|
+
throw new Error("SliderFill must be used within a Slider");
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
const { state } = context;
|
|
559
|
+
|
|
560
|
+
const { isHovered, hoverProps } = createHover(() => ({
|
|
561
|
+
onHoverStart: local.onHoverStart,
|
|
562
|
+
onHoverEnd: local.onHoverEnd,
|
|
563
|
+
onHoverChange: local.onHoverChange,
|
|
564
|
+
}));
|
|
565
|
+
|
|
566
|
+
// Percent (0-100) of an arbitrary value within the track — mirrors
|
|
567
|
+
// SliderState.getValuePercent's formula for a value other than the current one.
|
|
568
|
+
const percentOf = (value: number) => {
|
|
569
|
+
const range = state.maxValue - state.minValue;
|
|
570
|
+
return range === 0 ? 0 : ((value - state.minValue) / range) * 100;
|
|
571
|
+
};
|
|
572
|
+
|
|
573
|
+
const offset = () =>
|
|
574
|
+
local.offset != null ? clampFill(local.offset, state.minValue, state.maxValue) : state.minValue;
|
|
575
|
+
const start = () => percentOf(offset());
|
|
576
|
+
const end = () => state.getValuePercent() * 100;
|
|
577
|
+
const startPercent = () => Math.min(start(), end());
|
|
578
|
+
const sizePercent = () => Math.max(0, Math.max(start(), end()) - startPercent());
|
|
579
|
+
|
|
580
|
+
const renderValues = createMemo<SliderFillRenderProps>(() => ({
|
|
581
|
+
isDisabled: state.isDisabled,
|
|
582
|
+
isHovered: isHovered(),
|
|
583
|
+
valuePercent: state.getValuePercent(),
|
|
584
|
+
orientation: state.orientation,
|
|
585
|
+
}));
|
|
586
|
+
|
|
587
|
+
const renderProps = useRenderProps(
|
|
588
|
+
{
|
|
589
|
+
get children() {
|
|
590
|
+
return props.children;
|
|
591
|
+
},
|
|
592
|
+
class: local.class,
|
|
593
|
+
style: local.style,
|
|
594
|
+
defaultClassName: "solidaria-Slider-fill",
|
|
595
|
+
},
|
|
596
|
+
renderValues,
|
|
597
|
+
);
|
|
598
|
+
|
|
599
|
+
// useRenderProps has no defaultStyle; merge the positioning style with the
|
|
600
|
+
// user's, mirroring upstream SliderFill's defaultStyle (and SliderTrack here).
|
|
601
|
+
const mergedStyle = (): JSX.CSSProperties => {
|
|
602
|
+
const fillStyle: JSX.CSSProperties =
|
|
603
|
+
state.orientation === "vertical"
|
|
604
|
+
? {
|
|
605
|
+
position: "absolute",
|
|
606
|
+
bottom: `${startPercent()}%`,
|
|
607
|
+
height: `${sizePercent()}%`,
|
|
608
|
+
width: "100%",
|
|
609
|
+
}
|
|
610
|
+
: {
|
|
611
|
+
position: "absolute",
|
|
612
|
+
"inset-inline-start": `${startPercent()}%`,
|
|
613
|
+
width: `${sizePercent()}%`,
|
|
614
|
+
height: "100%",
|
|
615
|
+
};
|
|
616
|
+
return { ...fillStyle, ...(renderProps.style() || {}) };
|
|
617
|
+
};
|
|
618
|
+
|
|
470
619
|
return (
|
|
471
620
|
<div
|
|
472
621
|
{...domProps}
|
|
473
|
-
{...
|
|
474
|
-
{...cleanHoverProps()}
|
|
622
|
+
{...hoverProps}
|
|
475
623
|
class={renderProps.class()}
|
|
476
624
|
style={mergedStyle()}
|
|
477
|
-
data-disabled={state.isDisabled || undefined}
|
|
478
|
-
data-dragging={state.isDragging() || undefined}
|
|
479
|
-
data-focused={isFocused() || state.isFocused() || undefined}
|
|
480
|
-
data-focus-visible={isFocusVisible() || undefined}
|
|
481
625
|
data-hovered={isHovered() || undefined}
|
|
626
|
+
data-disabled={state.isDisabled || undefined}
|
|
627
|
+
data-orientation={state.orientation}
|
|
482
628
|
>
|
|
483
|
-
<VisuallyHidden>
|
|
484
|
-
<input ref={setInputRef} {...mergedInputProps()} />
|
|
485
|
-
</VisuallyHidden>
|
|
486
629
|
{renderProps.renderChildren()}
|
|
487
630
|
</div>
|
|
488
631
|
);
|
|
@@ -508,7 +651,9 @@ export function SliderOutput(props: SliderOutputProps): JSX.Element {
|
|
|
508
651
|
|
|
509
652
|
const renderProps = useRenderProps(
|
|
510
653
|
{
|
|
511
|
-
children
|
|
654
|
+
get children() {
|
|
655
|
+
return props.children;
|
|
656
|
+
},
|
|
512
657
|
class: local.class,
|
|
513
658
|
style: local.style,
|
|
514
659
|
defaultClassName: "solidaria-Slider-output",
|
|
@@ -547,4 +692,5 @@ export function SliderOutput(props: SliderOutputProps): JSX.Element {
|
|
|
547
692
|
|
|
548
693
|
Slider.Track = SliderTrack;
|
|
549
694
|
Slider.Thumb = SliderThumb;
|
|
695
|
+
Slider.Fill = SliderFill;
|
|
550
696
|
Slider.Output = SliderOutput;
|
package/src/Switch.tsx
CHANGED
|
@@ -9,30 +9,42 @@
|
|
|
9
9
|
|
|
10
10
|
import {
|
|
11
11
|
type JSX,
|
|
12
|
+
type Context,
|
|
12
13
|
createContext,
|
|
13
14
|
createMemo,
|
|
14
15
|
createSignal,
|
|
15
16
|
createUniqueId,
|
|
16
17
|
splitProps,
|
|
17
18
|
untrack,
|
|
19
|
+
useContext,
|
|
18
20
|
Show,
|
|
19
21
|
} from "solid-js";
|
|
20
22
|
import {
|
|
21
23
|
createSwitch,
|
|
22
24
|
createFocusRing,
|
|
23
25
|
createHover,
|
|
26
|
+
mergeProps,
|
|
24
27
|
type AriaSwitchProps,
|
|
28
|
+
type SwitchAria,
|
|
25
29
|
} from "@proyecto-viviana/solidaria";
|
|
26
|
-
import {
|
|
30
|
+
import {
|
|
31
|
+
createToggleState,
|
|
32
|
+
VALID_VALIDITY_STATE,
|
|
33
|
+
type ToggleState,
|
|
34
|
+
type ValidationResult,
|
|
35
|
+
} from "@proyecto-viviana/solid-stately";
|
|
27
36
|
import { VisuallyHidden } from "./VisuallyHidden";
|
|
37
|
+
import { FieldErrorContext, type FieldErrorContextValue } from "./FieldError";
|
|
28
38
|
import {
|
|
29
39
|
type RenderChildren,
|
|
30
40
|
type ClassNameOrFunction,
|
|
31
41
|
type StyleOrFunction,
|
|
32
42
|
type SlotProps,
|
|
43
|
+
Provider,
|
|
33
44
|
useRenderProps,
|
|
34
45
|
filterDOMProps,
|
|
35
46
|
} from "./utils";
|
|
47
|
+
import { TextContext } from "./Text";
|
|
36
48
|
|
|
37
49
|
export interface ToggleSwitchRenderProps {
|
|
38
50
|
/** Whether the switch is selected. */
|
|
@@ -152,7 +164,9 @@ export function ToggleSwitch(props: ToggleSwitchProps): JSX.Element {
|
|
|
152
164
|
|
|
153
165
|
const renderProps = useRenderProps(
|
|
154
166
|
{
|
|
155
|
-
children
|
|
167
|
+
get children() {
|
|
168
|
+
return props.children;
|
|
169
|
+
},
|
|
156
170
|
class: local.class,
|
|
157
171
|
style: local.style,
|
|
158
172
|
defaultClassName: "solidaria-ToggleSwitch",
|
|
@@ -258,3 +272,382 @@ export function ToggleSwitch(props: ToggleSwitchProps): JSX.Element {
|
|
|
258
272
|
</label>
|
|
259
273
|
);
|
|
260
274
|
}
|
|
275
|
+
|
|
276
|
+
// ============================================================================
|
|
277
|
+
// SwitchField + SwitchButton — the RAC form-field split (RAC 1.19)
|
|
278
|
+
// ----------------------------------------------------------------------------
|
|
279
|
+
// Upstream split the monolithic Switch into a SwitchField wrapper (owns state,
|
|
280
|
+
// validation, and help text) containing a SwitchButton control (the clickable
|
|
281
|
+
// label + indicator). Mirrors react-aria-components/src/Switch.tsx. The legacy
|
|
282
|
+
// `ToggleSwitch` above stays as the deprecated monolith for back-compat.
|
|
283
|
+
//
|
|
284
|
+
// Help text wiring mirrors upstream exactly: SwitchField has NO description /
|
|
285
|
+
// errorMessage props. createSwitch mints descriptionProps / errorMessageProps
|
|
286
|
+
// (slot ids) and bakes the combined aria-describedby into inputProps, and the
|
|
287
|
+
// field provides those ids through TextContext slots. Consumers render the help
|
|
288
|
+
// text themselves with `<Text slot="description">` / `<FieldError>`.
|
|
289
|
+
// ============================================================================
|
|
290
|
+
|
|
291
|
+
export interface SwitchFieldRenderProps {
|
|
292
|
+
/** Whether the switch is selected. */
|
|
293
|
+
isSelected: boolean;
|
|
294
|
+
/** Whether the switch is disabled. */
|
|
295
|
+
isDisabled: boolean;
|
|
296
|
+
/** Whether the switch is read only. */
|
|
297
|
+
isReadOnly: boolean;
|
|
298
|
+
/** Whether the switch is invalid. */
|
|
299
|
+
isInvalid: boolean;
|
|
300
|
+
/** Whether the switch is required. */
|
|
301
|
+
isRequired: boolean;
|
|
302
|
+
/** State of the switch. */
|
|
303
|
+
state: ToggleState;
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
export interface SwitchButtonRenderProps extends ToggleSwitchRenderProps {
|
|
307
|
+
/** Whether the switch is required. */
|
|
308
|
+
isRequired: boolean;
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
export interface SwitchFieldProps extends Omit<AriaSwitchProps, "children">, SlotProps {
|
|
312
|
+
/** The children of the component (typically a `SwitchButton`). A function may receive render props. */
|
|
313
|
+
children?: RenderChildren<SwitchFieldRenderProps>;
|
|
314
|
+
/** The CSS className for the element. */
|
|
315
|
+
class?: ClassNameOrFunction<SwitchFieldRenderProps>;
|
|
316
|
+
/** The inline style for the element. */
|
|
317
|
+
style?: StyleOrFunction<SwitchFieldRenderProps>;
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
export interface SwitchButtonProps extends SlotProps {
|
|
321
|
+
/** The children of the component. A function may be provided to receive render props. */
|
|
322
|
+
children?: RenderChildren<SwitchButtonRenderProps>;
|
|
323
|
+
/** The CSS className for the element. */
|
|
324
|
+
class?: ClassNameOrFunction<SwitchButtonRenderProps>;
|
|
325
|
+
/** The inline style for the element. */
|
|
326
|
+
style?: StyleOrFunction<SwitchButtonRenderProps>;
|
|
327
|
+
/** Handler called when hover starts. */
|
|
328
|
+
onHoverStart?: () => void;
|
|
329
|
+
/** Handler called when hover ends. */
|
|
330
|
+
onHoverEnd?: () => void;
|
|
331
|
+
/** Handler called when hover state changes. */
|
|
332
|
+
onHoverChange?: (isHovered: boolean) => void;
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
export interface SwitchFieldContextValue extends SwitchFieldProps {
|
|
336
|
+
slots?: Record<string, SwitchFieldProps>;
|
|
337
|
+
}
|
|
338
|
+
export const SwitchFieldContext = createContext<SwitchFieldContextValue | null>(null);
|
|
339
|
+
|
|
340
|
+
/** Carries the switch aria + state from a SwitchField/Switch wrapper to its SwitchButton. */
|
|
341
|
+
interface InternalSwitchContextValue {
|
|
342
|
+
switchAria: SwitchAria;
|
|
343
|
+
state: ToggleState;
|
|
344
|
+
setInputElement: (el: HTMLInputElement | null) => void;
|
|
345
|
+
defaultClassName: string;
|
|
346
|
+
isRequired: boolean;
|
|
347
|
+
}
|
|
348
|
+
const InternalSwitchContext = createContext<InternalSwitchContextValue | null>(null);
|
|
349
|
+
|
|
350
|
+
/**
|
|
351
|
+
* A switch button is the clickable area of a switch, including the indicator and label.
|
|
352
|
+
* Must be rendered inside a `SwitchField` (or the legacy `ToggleSwitch`).
|
|
353
|
+
*/
|
|
354
|
+
export function SwitchButton(props: SwitchButtonProps): JSX.Element {
|
|
355
|
+
// Accessed reactively so it resolves once the parent provider mounts (HMR-safe).
|
|
356
|
+
const getCtx = createMemo(() => useContext(InternalSwitchContext));
|
|
357
|
+
return (
|
|
358
|
+
<Show when={getCtx()} fallback={null} keyed>
|
|
359
|
+
{(ctx) => <SwitchButtonImpl buttonProps={props} ctx={ctx} />}
|
|
360
|
+
</Show>
|
|
361
|
+
);
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
function SwitchButtonImpl(props: {
|
|
365
|
+
buttonProps: SwitchButtonProps;
|
|
366
|
+
ctx: InternalSwitchContextValue;
|
|
367
|
+
}): JSX.Element {
|
|
368
|
+
const { ctx } = props;
|
|
369
|
+
const switchAria = ctx.switchAria;
|
|
370
|
+
|
|
371
|
+
const { isFocused, isFocusVisible, focusProps } = createFocusRing();
|
|
372
|
+
const { isHovered, hoverProps } = createHover({
|
|
373
|
+
get isDisabled() {
|
|
374
|
+
return switchAria.isDisabled || switchAria.isReadOnly;
|
|
375
|
+
},
|
|
376
|
+
onHoverStart: props.buttonProps.onHoverStart,
|
|
377
|
+
onHoverEnd: props.buttonProps.onHoverEnd,
|
|
378
|
+
onHoverChange: props.buttonProps.onHoverChange,
|
|
379
|
+
});
|
|
380
|
+
|
|
381
|
+
const renderValues = createMemo<SwitchButtonRenderProps>(() => ({
|
|
382
|
+
isSelected: switchAria.isSelected(),
|
|
383
|
+
isHovered: isHovered(),
|
|
384
|
+
isPressed: switchAria.isPressed(),
|
|
385
|
+
isFocused: isFocused(),
|
|
386
|
+
isFocusVisible: isFocusVisible(),
|
|
387
|
+
isDisabled: switchAria.isDisabled,
|
|
388
|
+
isReadOnly: switchAria.isReadOnly,
|
|
389
|
+
isInvalid: switchAria.isInvalid,
|
|
390
|
+
isRequired: ctx.isRequired,
|
|
391
|
+
state: ctx.state,
|
|
392
|
+
}));
|
|
393
|
+
|
|
394
|
+
const renderProps = useRenderProps(
|
|
395
|
+
{
|
|
396
|
+
children: props.buttonProps.children,
|
|
397
|
+
class: props.buttonProps.class,
|
|
398
|
+
style: props.buttonProps.style,
|
|
399
|
+
defaultClassName: ctx.defaultClassName,
|
|
400
|
+
},
|
|
401
|
+
renderValues,
|
|
402
|
+
);
|
|
403
|
+
|
|
404
|
+
const childRenderValues: SwitchButtonRenderProps = {
|
|
405
|
+
get isSelected() {
|
|
406
|
+
return switchAria.isSelected();
|
|
407
|
+
},
|
|
408
|
+
get isHovered() {
|
|
409
|
+
return isHovered();
|
|
410
|
+
},
|
|
411
|
+
get isPressed() {
|
|
412
|
+
return switchAria.isPressed();
|
|
413
|
+
},
|
|
414
|
+
get isFocused() {
|
|
415
|
+
return isFocused();
|
|
416
|
+
},
|
|
417
|
+
get isFocusVisible() {
|
|
418
|
+
return isFocusVisible();
|
|
419
|
+
},
|
|
420
|
+
get isDisabled() {
|
|
421
|
+
return switchAria.isDisabled;
|
|
422
|
+
},
|
|
423
|
+
get isReadOnly() {
|
|
424
|
+
return switchAria.isReadOnly;
|
|
425
|
+
},
|
|
426
|
+
get isInvalid() {
|
|
427
|
+
return switchAria.isInvalid;
|
|
428
|
+
},
|
|
429
|
+
get isRequired() {
|
|
430
|
+
return ctx.isRequired;
|
|
431
|
+
},
|
|
432
|
+
get state() {
|
|
433
|
+
return ctx.state;
|
|
434
|
+
},
|
|
435
|
+
};
|
|
436
|
+
|
|
437
|
+
const cleanLabelProps = () => {
|
|
438
|
+
const { ref: _ref1, ...rest } = switchAria.labelProps as Record<string, unknown>;
|
|
439
|
+
return rest;
|
|
440
|
+
};
|
|
441
|
+
const cleanHoverProps = () => {
|
|
442
|
+
const { ref: _ref2, ...rest } = hoverProps as Record<string, unknown>;
|
|
443
|
+
return rest;
|
|
444
|
+
};
|
|
445
|
+
const cleanInputProps = () => {
|
|
446
|
+
const { ref: _ref3, ...rest } = switchAria.inputProps as Record<string, unknown>;
|
|
447
|
+
return rest;
|
|
448
|
+
};
|
|
449
|
+
const cleanFocusProps = () => {
|
|
450
|
+
const { ref: _ref4, ...rest } = focusProps as Record<string, unknown>;
|
|
451
|
+
return rest;
|
|
452
|
+
};
|
|
453
|
+
|
|
454
|
+
// Resolve the render-prop children ONCE (untracked) — see ToggleSwitch above.
|
|
455
|
+
// The button's own children are leaf visuals (they don't consume context), so
|
|
456
|
+
// untrack is safe and keeps fine-grained reactivity via the getters + <Show>s.
|
|
457
|
+
const switchChildren = untrack(() => {
|
|
458
|
+
const children = props.buttonProps.children;
|
|
459
|
+
return typeof children === "function" ? children(childRenderValues) : children;
|
|
460
|
+
});
|
|
461
|
+
|
|
462
|
+
return (
|
|
463
|
+
<label
|
|
464
|
+
{...cleanLabelProps()}
|
|
465
|
+
{...cleanHoverProps()}
|
|
466
|
+
class={renderProps.class()}
|
|
467
|
+
style={renderProps.style()}
|
|
468
|
+
slot={props.buttonProps.slot}
|
|
469
|
+
data-selected={switchAria.isSelected() || undefined}
|
|
470
|
+
data-pressed={switchAria.isPressed() || undefined}
|
|
471
|
+
data-hovered={isHovered() || undefined}
|
|
472
|
+
data-focused={isFocused() || undefined}
|
|
473
|
+
data-focus-visible={isFocusVisible() || undefined}
|
|
474
|
+
data-disabled={switchAria.isDisabled || undefined}
|
|
475
|
+
data-readonly={switchAria.isReadOnly || undefined}
|
|
476
|
+
data-invalid={switchAria.isInvalid || undefined}
|
|
477
|
+
data-required={ctx.isRequired || undefined}
|
|
478
|
+
>
|
|
479
|
+
<VisuallyHidden>
|
|
480
|
+
<input ref={ctx.setInputElement} {...cleanInputProps()} {...cleanFocusProps()} />
|
|
481
|
+
</VisuallyHidden>
|
|
482
|
+
{switchChildren}
|
|
483
|
+
</label>
|
|
484
|
+
);
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
/**
|
|
488
|
+
* A switch allows a user to turn a setting on or off, with support for validation and help text.
|
|
489
|
+
* Wraps a `SwitchButton` and provides description/error wiring through
|
|
490
|
+
* TextContext slots — render help text with `<Text slot="description">`.
|
|
491
|
+
*
|
|
492
|
+
* @example
|
|
493
|
+
* ```tsx
|
|
494
|
+
* <SwitchField>
|
|
495
|
+
* <SwitchButton>Enable sync</SwitchButton>
|
|
496
|
+
* <Text slot="description">Sync across devices</Text>
|
|
497
|
+
* </SwitchField>
|
|
498
|
+
* ```
|
|
499
|
+
*/
|
|
500
|
+
export function SwitchField(props: SwitchFieldProps): JSX.Element {
|
|
501
|
+
const contextProps = useContext(SwitchFieldContext);
|
|
502
|
+
const contextSlotProps = contextProps?.slots?.[props.slot ?? "default"];
|
|
503
|
+
const contextBaseProps = createMemo<SwitchFieldProps>(() => {
|
|
504
|
+
if (!contextProps) return {};
|
|
505
|
+
const { slots: _slots, ...rest } = contextProps;
|
|
506
|
+
return rest;
|
|
507
|
+
});
|
|
508
|
+
const merged = contextProps
|
|
509
|
+
? (mergeProps(contextBaseProps(), contextSlotProps ?? {}, props) as SwitchFieldProps)
|
|
510
|
+
: props;
|
|
511
|
+
|
|
512
|
+
const [inputElement, setInputElement] = createSignal<HTMLInputElement | null>(null);
|
|
513
|
+
// `children` is split out of ariaProps so the hook accessor's `...ariaProps`
|
|
514
|
+
// spread does not eagerly read it — reading a Solid `children` getter
|
|
515
|
+
// instantiates the nested SwitchButton, and doing so OUTSIDE the
|
|
516
|
+
// InternalSwitchContext provider both breaks its context binding and recurses.
|
|
517
|
+
const [local, ariaProps] = splitProps(merged, ["class", "style", "slot", "children"]);
|
|
518
|
+
|
|
519
|
+
const state = createToggleState(() => ({
|
|
520
|
+
isSelected: ariaProps.isSelected,
|
|
521
|
+
defaultSelected: ariaProps.defaultSelected,
|
|
522
|
+
onChange: ariaProps.onChange,
|
|
523
|
+
isReadOnly: ariaProps.isReadOnly,
|
|
524
|
+
}));
|
|
525
|
+
|
|
526
|
+
const switchAria = createSwitch(
|
|
527
|
+
() => ({
|
|
528
|
+
...ariaProps,
|
|
529
|
+
// The hook reads `children` only to decide if an aria-label is needed; the
|
|
530
|
+
// visible label lives in the SwitchButton, so report presence as a literal.
|
|
531
|
+
children: true,
|
|
532
|
+
}),
|
|
533
|
+
state,
|
|
534
|
+
inputElement,
|
|
535
|
+
);
|
|
536
|
+
|
|
537
|
+
const internalContext: InternalSwitchContextValue = {
|
|
538
|
+
switchAria,
|
|
539
|
+
state,
|
|
540
|
+
setInputElement,
|
|
541
|
+
defaultClassName: "solidaria-SwitchButton",
|
|
542
|
+
get isRequired() {
|
|
543
|
+
return ariaProps.isRequired || false;
|
|
544
|
+
},
|
|
545
|
+
};
|
|
546
|
+
|
|
547
|
+
// The hook mints the description/error slot ids and bakes the combined
|
|
548
|
+
// aria-describedby into the input; the field exposes those ids through
|
|
549
|
+
// TextContext so a `<Text slot="description">` / `<FieldError>` child resolves
|
|
550
|
+
// them. Mirrors react-aria-components' Switch Provider value list.
|
|
551
|
+
const textSlots = {
|
|
552
|
+
slots: {
|
|
553
|
+
get description() {
|
|
554
|
+
return switchAria.descriptionProps;
|
|
555
|
+
},
|
|
556
|
+
get errorMessage() {
|
|
557
|
+
return switchAria.errorMessageProps;
|
|
558
|
+
},
|
|
559
|
+
},
|
|
560
|
+
};
|
|
561
|
+
|
|
562
|
+
const renderValues = createMemo<SwitchFieldRenderProps>(() => ({
|
|
563
|
+
isSelected: switchAria.isSelected(),
|
|
564
|
+
isDisabled: switchAria.isDisabled,
|
|
565
|
+
isReadOnly: switchAria.isReadOnly,
|
|
566
|
+
isInvalid: switchAria.isInvalid,
|
|
567
|
+
isRequired: ariaProps.isRequired || false,
|
|
568
|
+
state,
|
|
569
|
+
}));
|
|
570
|
+
|
|
571
|
+
const renderProps = useRenderProps(
|
|
572
|
+
{
|
|
573
|
+
children: merged.children,
|
|
574
|
+
class: local.class,
|
|
575
|
+
style: local.style,
|
|
576
|
+
defaultClassName: "solidaria-SwitchField",
|
|
577
|
+
},
|
|
578
|
+
renderValues,
|
|
579
|
+
);
|
|
580
|
+
|
|
581
|
+
const fieldErrorContext: FieldErrorContextValue = {
|
|
582
|
+
get validation(): ValidationResult {
|
|
583
|
+
return {
|
|
584
|
+
isInvalid: switchAria.isInvalid,
|
|
585
|
+
validationDetails: VALID_VALIDITY_STATE,
|
|
586
|
+
validationErrors: [],
|
|
587
|
+
};
|
|
588
|
+
},
|
|
589
|
+
get errorMessageProps() {
|
|
590
|
+
return switchAria.errorMessageProps as JSX.HTMLAttributes<HTMLElement>;
|
|
591
|
+
},
|
|
592
|
+
};
|
|
593
|
+
|
|
594
|
+
const domProps = createMemo(() => {
|
|
595
|
+
const filtered = filterDOMProps(ariaProps, { global: true });
|
|
596
|
+
delete (filtered as Record<string, unknown>).id;
|
|
597
|
+
delete (filtered as Record<string, unknown>).onClick;
|
|
598
|
+
return filtered;
|
|
599
|
+
});
|
|
600
|
+
|
|
601
|
+
// Children are accessed inside the providers (component-execution owner) so a
|
|
602
|
+
// nested SwitchButton's useContext binds to InternalSwitchContext. Mirrors
|
|
603
|
+
// RadioGroup's GroupChildren — do NOT pre-resolve outside the provider.
|
|
604
|
+
const FieldChildren = () => {
|
|
605
|
+
const childRenderValues: SwitchFieldRenderProps = {
|
|
606
|
+
get isSelected() {
|
|
607
|
+
return switchAria.isSelected();
|
|
608
|
+
},
|
|
609
|
+
get isDisabled() {
|
|
610
|
+
return switchAria.isDisabled;
|
|
611
|
+
},
|
|
612
|
+
get isReadOnly() {
|
|
613
|
+
return switchAria.isReadOnly;
|
|
614
|
+
},
|
|
615
|
+
get isInvalid() {
|
|
616
|
+
return switchAria.isInvalid;
|
|
617
|
+
},
|
|
618
|
+
get isRequired() {
|
|
619
|
+
return ariaProps.isRequired || false;
|
|
620
|
+
},
|
|
621
|
+
get state() {
|
|
622
|
+
return state;
|
|
623
|
+
},
|
|
624
|
+
};
|
|
625
|
+
const renderedChildren = createMemo(() => {
|
|
626
|
+
const children = merged.children;
|
|
627
|
+
return typeof children === "function" ? children(childRenderValues) : children;
|
|
628
|
+
});
|
|
629
|
+
return <>{renderedChildren()}</>;
|
|
630
|
+
};
|
|
631
|
+
|
|
632
|
+
return (
|
|
633
|
+
<InternalSwitchContext.Provider value={internalContext}>
|
|
634
|
+
<FieldErrorContext.Provider value={fieldErrorContext}>
|
|
635
|
+
<div
|
|
636
|
+
{...domProps()}
|
|
637
|
+
class={renderProps.class()}
|
|
638
|
+
style={renderProps.style()}
|
|
639
|
+
slot={local.slot}
|
|
640
|
+
data-selected={switchAria.isSelected() || undefined}
|
|
641
|
+
data-disabled={switchAria.isDisabled || undefined}
|
|
642
|
+
data-readonly={switchAria.isReadOnly || undefined}
|
|
643
|
+
data-invalid={switchAria.isInvalid || undefined}
|
|
644
|
+
data-required={ariaProps.isRequired || false || undefined}
|
|
645
|
+
>
|
|
646
|
+
<Provider values={[[TextContext, textSlots]] as Array<[Context<unknown>, unknown]>}>
|
|
647
|
+
<FieldChildren />
|
|
648
|
+
</Provider>
|
|
649
|
+
</div>
|
|
650
|
+
</FieldErrorContext.Provider>
|
|
651
|
+
</InternalSwitchContext.Provider>
|
|
652
|
+
);
|
|
653
|
+
}
|