@proyecto-viviana/solidaria-components 0.2.5 → 0.3.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/LICENSE +21 -0
- package/README.md +39 -272
- package/dist/ActionBar.d.ts +79 -0
- package/dist/ActionBar.d.ts.map +1 -0
- package/dist/ActionGroup.d.ts +74 -0
- package/dist/ActionGroup.d.ts.map +1 -0
- package/dist/Alert.d.ts +70 -0
- package/dist/Alert.d.ts.map +1 -0
- package/dist/Autocomplete.d.ts +5 -5
- package/dist/Autocomplete.d.ts.map +1 -1
- package/dist/Breadcrumbs.d.ts +27 -8
- package/dist/Breadcrumbs.d.ts.map +1 -1
- package/dist/Button.d.ts +28 -5
- package/dist/Button.d.ts.map +1 -1
- package/dist/Calendar.d.ts +51 -7
- package/dist/Calendar.d.ts.map +1 -1
- package/dist/Checkbox.d.ts +33 -8
- package/dist/Checkbox.d.ts.map +1 -1
- package/dist/Collection.d.ts +130 -0
- package/dist/Collection.d.ts.map +1 -0
- package/dist/Color.d.ts +210 -9
- package/dist/Color.d.ts.map +1 -1
- package/dist/ColorEditor.d.ts +42 -0
- package/dist/ColorEditor.d.ts.map +1 -0
- package/dist/ComboBox.d.ts +146 -16
- package/dist/ComboBox.d.ts.map +1 -1
- package/dist/ContextualHelpTrigger.d.ts +40 -0
- package/dist/ContextualHelpTrigger.d.ts.map +1 -0
- package/dist/DateField.d.ts +35 -8
- package/dist/DateField.d.ts.map +1 -1
- package/dist/DatePicker.d.ts +101 -5
- package/dist/DatePicker.d.ts.map +1 -1
- package/dist/DateRangePickerContext.d.ts +30 -0
- package/dist/DateRangePickerContext.d.ts.map +1 -0
- package/dist/Dialog.d.ts +5 -5
- package/dist/Dialog.d.ts.map +1 -1
- package/dist/Disclosure.d.ts +25 -5
- package/dist/Disclosure.d.ts.map +1 -1
- package/dist/DragAndDrop.d.ts +80 -0
- package/dist/DragAndDrop.d.ts.map +1 -0
- package/dist/DragPreview.d.ts +14 -0
- package/dist/DragPreview.d.ts.map +1 -0
- package/dist/DropZone.d.ts +27 -0
- package/dist/DropZone.d.ts.map +1 -0
- package/dist/FieldError.d.ts +27 -0
- package/dist/FieldError.d.ts.map +1 -0
- package/dist/FileTrigger.d.ts +26 -0
- package/dist/FileTrigger.d.ts.map +1 -0
- package/dist/Focusable.d.ts +27 -0
- package/dist/Focusable.d.ts.map +1 -0
- package/dist/Form.d.ts +41 -0
- package/dist/Form.d.ts.map +1 -0
- package/dist/GridList.d.ts +69 -10
- package/dist/GridList.d.ts.map +1 -1
- package/dist/HiddenDateInput.d.ts +26 -0
- package/dist/HiddenDateInput.d.ts.map +1 -0
- package/dist/HiddenTimeInput.d.ts +25 -0
- package/dist/HiddenTimeInput.d.ts.map +1 -0
- package/dist/Icon.d.ts +57 -0
- package/dist/Icon.d.ts.map +1 -0
- package/dist/Keyboard.d.ts +13 -0
- package/dist/Keyboard.d.ts.map +1 -0
- package/dist/Landmark.d.ts +3 -3
- package/dist/Landmark.d.ts.map +1 -1
- package/dist/Link.d.ts +10 -4
- package/dist/Link.d.ts.map +1 -1
- package/dist/ListBox.d.ts +73 -11
- package/dist/ListBox.d.ts.map +1 -1
- package/dist/ListDropTargetDelegate.d.ts +38 -0
- package/dist/ListDropTargetDelegate.d.ts.map +1 -0
- package/dist/Menu.d.ts +79 -10
- package/dist/Menu.d.ts.map +1 -1
- package/dist/Meter.d.ts +4 -4
- package/dist/Meter.d.ts.map +1 -1
- package/dist/Modal.d.ts +6 -4
- package/dist/Modal.d.ts.map +1 -1
- package/dist/NumberField.d.ts +10 -12
- package/dist/NumberField.d.ts.map +1 -1
- package/dist/Popover.d.ts +32 -7
- package/dist/Popover.d.ts.map +1 -1
- package/dist/Pressable.d.ts +27 -0
- package/dist/Pressable.d.ts.map +1 -0
- package/dist/ProgressBar.d.ts +6 -4
- package/dist/ProgressBar.d.ts.map +1 -1
- package/dist/RadioGroup.d.ts +43 -9
- package/dist/RadioGroup.d.ts.map +1 -1
- package/dist/RangeCalendar.d.ts +39 -7
- package/dist/RangeCalendar.d.ts.map +1 -1
- package/dist/RouterProvider.d.ts +75 -0
- package/dist/RouterProvider.d.ts.map +1 -0
- package/dist/SearchField.d.ts +23 -21
- package/dist/SearchField.d.ts.map +1 -1
- package/dist/Select.d.ts +48 -7
- package/dist/Select.d.ts.map +1 -1
- package/dist/SelectionIndicator.d.ts +30 -0
- package/dist/SelectionIndicator.d.ts.map +1 -0
- package/dist/Separator.d.ts +9 -3
- package/dist/Separator.d.ts.map +1 -1
- package/dist/SharedElementTransition.d.ts +41 -0
- package/dist/SharedElementTransition.d.ts.map +1 -0
- package/dist/Slider.d.ts +15 -8
- package/dist/Slider.d.ts.map +1 -1
- package/dist/StepList.d.ts +90 -0
- package/dist/StepList.d.ts.map +1 -0
- package/dist/Switch.d.ts +11 -5
- package/dist/Switch.d.ts.map +1 -1
- package/dist/Table.d.ts +222 -19
- package/dist/Table.d.ts.map +1 -1
- package/dist/Tabs.d.ts +47 -10
- package/dist/Tabs.d.ts.map +1 -1
- package/dist/TagGroup.d.ts +22 -10
- package/dist/TagGroup.d.ts.map +1 -1
- package/dist/Text.d.ts +10 -0
- package/dist/Text.d.ts.map +1 -0
- package/dist/TextField.d.ts +19 -11
- package/dist/TextField.d.ts.map +1 -1
- package/dist/TimeField.d.ts +32 -7
- package/dist/TimeField.d.ts.map +1 -1
- package/dist/Toast.d.ts +29 -14
- package/dist/Toast.d.ts.map +1 -1
- package/dist/ToggleButton.d.ts +36 -0
- package/dist/ToggleButton.d.ts.map +1 -0
- package/dist/ToggleButtonGroup.d.ts +33 -0
- package/dist/ToggleButtonGroup.d.ts.map +1 -0
- package/dist/Toolbar.d.ts +7 -3
- package/dist/Toolbar.d.ts.map +1 -1
- package/dist/Tooltip.d.ts +58 -7
- package/dist/Tooltip.d.ts.map +1 -1
- package/dist/Tree.d.ts +102 -11
- package/dist/Tree.d.ts.map +1 -1
- package/dist/Virtualizer.d.ts +61 -0
- package/dist/Virtualizer.d.ts.map +1 -0
- package/dist/VirtualizerLayouts.d.ts +82 -0
- package/dist/VirtualizerLayouts.d.ts.map +1 -0
- package/dist/VisuallyHidden.d.ts +4 -2
- package/dist/VisuallyHidden.d.ts.map +1 -1
- package/dist/contexts.d.ts +6 -1
- package/dist/contexts.d.ts.map +1 -1
- package/dist/index.d.ts +73 -39
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +23342 -10644
- package/dist/index.js.map +1 -7
- package/dist/index.jsx +18110 -0
- package/dist/index.jsx.map +1 -0
- package/dist/useDragAndDrop.d.ts +93 -0
- package/dist/useDragAndDrop.d.ts.map +1 -0
- package/dist/utils.d.ts +8 -2
- package/dist/utils.d.ts.map +1 -1
- package/dist/virtualizer/Layout.d.ts +79 -0
- package/dist/virtualizer/Layout.d.ts.map +1 -0
- package/package.json +33 -32
- package/src/ActionBar.tsx +251 -0
- package/src/ActionGroup.tsx +277 -0
- package/src/Alert.tsx +152 -0
- package/src/Autocomplete.tsx +39 -44
- package/src/Breadcrumbs.tsx +227 -72
- package/src/Button.tsx +315 -74
- package/src/Calendar.tsx +347 -141
- package/src/Checkbox.tsx +414 -123
- package/src/Collection.tsx +350 -0
- package/src/Color.tsx +1325 -284
- package/src/ColorEditor.tsx +213 -0
- package/src/ComboBox.tsx +644 -245
- package/src/ContextualHelpTrigger.tsx +195 -0
- package/src/DateField.tsx +274 -106
- package/src/DatePicker.tsx +892 -111
- package/src/DateRangePickerContext.tsx +44 -0
- package/src/Dialog.tsx +173 -104
- package/src/Disclosure.tsx +158 -105
- package/src/DragAndDrop.tsx +340 -0
- package/src/DragPreview.tsx +47 -0
- package/src/DropZone.tsx +233 -0
- package/src/FieldError.tsx +89 -0
- package/src/FileTrigger.tsx +83 -0
- package/src/Focusable.tsx +103 -0
- package/src/Form.tsx +140 -0
- package/src/GridList.tsx +542 -128
- package/src/HiddenDateInput.tsx +153 -0
- package/src/HiddenTimeInput.tsx +133 -0
- package/src/Icon.tsx +133 -0
- package/src/Keyboard.tsx +26 -0
- package/src/Landmark.tsx +37 -63
- package/src/Link.tsx +132 -69
- package/src/ListBox.tsx +656 -106
- package/src/ListDropTargetDelegate.ts +283 -0
- package/src/Menu.tsx +1234 -132
- package/src/Meter.tsx +44 -58
- package/src/Modal.tsx +262 -166
- package/src/NumberField.tsx +267 -151
- package/src/Popover.tsx +452 -343
- package/src/Pressable.tsx +108 -0
- package/src/ProgressBar.tsx +54 -59
- package/src/RadioGroup.tsx +533 -121
- package/src/RangeCalendar.tsx +249 -150
- package/src/RouterProvider.tsx +223 -0
- package/src/SearchField.tsx +460 -133
- package/src/Select.tsx +804 -233
- package/src/SelectionIndicator.tsx +108 -0
- package/src/Separator.tsx +47 -49
- package/src/SharedElementTransition.tsx +264 -0
- package/src/Slider.tsx +148 -98
- package/src/StepList.tsx +272 -0
- package/src/Switch.tsx +93 -46
- package/src/Table.tsx +1551 -225
- package/src/Tabs.tsx +377 -123
- package/src/TagGroup.tsx +233 -135
- package/src/Text.tsx +18 -0
- package/src/TextField.tsx +413 -86
- package/src/TimeField.tsx +232 -222
- package/src/Toast.tsx +306 -160
- package/src/ToggleButton.tsx +169 -0
- package/src/ToggleButtonGroup.tsx +141 -0
- package/src/Toolbar.tsx +61 -70
- package/src/Tooltip.tsx +473 -116
- package/src/Tree.tsx +1514 -175
- package/src/Virtualizer.tsx +730 -0
- package/src/VirtualizerLayouts.ts +280 -0
- package/src/VisuallyHidden.tsx +32 -38
- package/src/contexts.ts +29 -36
- package/src/index.ts +972 -620
- package/src/useDragAndDrop.ts +367 -0
- package/src/utils.tsx +69 -50
- package/src/virtualizer/Layout.ts +192 -0
- package/dist/index.ssr.js +0 -9785
- package/dist/index.ssr.js.map +0 -7
package/src/Button.tsx
CHANGED
|
@@ -8,16 +8,23 @@
|
|
|
8
8
|
import {
|
|
9
9
|
type JSX,
|
|
10
10
|
createContext,
|
|
11
|
+
createEffect,
|
|
11
12
|
createMemo,
|
|
13
|
+
createSignal,
|
|
12
14
|
splitProps,
|
|
13
15
|
useContext,
|
|
14
|
-
} from
|
|
16
|
+
} from "solid-js";
|
|
15
17
|
import {
|
|
18
|
+
announce,
|
|
16
19
|
createButton,
|
|
17
20
|
createFocusRing,
|
|
18
21
|
createHover,
|
|
22
|
+
createId,
|
|
23
|
+
mergeProps,
|
|
19
24
|
type AriaButtonProps,
|
|
20
|
-
|
|
25
|
+
type HoverEvent,
|
|
26
|
+
type PressEvent,
|
|
27
|
+
} from "@proyecto-viviana/solidaria";
|
|
21
28
|
import {
|
|
22
29
|
type RenderChildren,
|
|
23
30
|
type ClassNameOrFunction,
|
|
@@ -25,12 +32,70 @@ import {
|
|
|
25
32
|
type SlotProps,
|
|
26
33
|
useRenderProps,
|
|
27
34
|
filterDOMProps,
|
|
28
|
-
} from
|
|
29
|
-
import { DialogTriggerContext, PopoverTriggerContext } from
|
|
35
|
+
} from "./utils";
|
|
36
|
+
import { DialogTriggerContext, PopoverTriggerContext } from "./contexts";
|
|
37
|
+
import { ProgressBarContext } from "./ProgressBar";
|
|
30
38
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
39
|
+
type RefLike<T> = ((el: T) => void) | { current?: T | null } | undefined;
|
|
40
|
+
|
|
41
|
+
function assignRef<T>(ref: RefLike<T>, el: T): void {
|
|
42
|
+
if (!ref) return;
|
|
43
|
+
if (typeof ref === "function") {
|
|
44
|
+
ref(el);
|
|
45
|
+
} else {
|
|
46
|
+
ref.current = el;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function createLiveButtonRenderProps(values: () => ButtonRenderProps): ButtonRenderProps {
|
|
51
|
+
return {
|
|
52
|
+
get isHovered() {
|
|
53
|
+
return values().isHovered;
|
|
54
|
+
},
|
|
55
|
+
get isPressed() {
|
|
56
|
+
return values().isPressed;
|
|
57
|
+
},
|
|
58
|
+
get isFocused() {
|
|
59
|
+
return values().isFocused;
|
|
60
|
+
},
|
|
61
|
+
get isFocusVisible() {
|
|
62
|
+
return values().isFocusVisible;
|
|
63
|
+
},
|
|
64
|
+
get isDisabled() {
|
|
65
|
+
return values().isDisabled;
|
|
66
|
+
},
|
|
67
|
+
get isPending() {
|
|
68
|
+
return values().isPending;
|
|
69
|
+
},
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function createLiveCustomRootProps(
|
|
74
|
+
getProps: () => JSX.ButtonHTMLAttributes<HTMLButtonElement>,
|
|
75
|
+
getChildren: () => JSX.Element,
|
|
76
|
+
ref: (el: HTMLButtonElement) => void,
|
|
77
|
+
): JSX.ButtonHTMLAttributes<HTMLButtonElement> {
|
|
78
|
+
const props = {} as JSX.ButtonHTMLAttributes<HTMLButtonElement>;
|
|
79
|
+
const keys = new Set([...Object.keys(getProps()), "children", "ref"]);
|
|
80
|
+
|
|
81
|
+
for (const key of keys) {
|
|
82
|
+
Object.defineProperty(props, key, {
|
|
83
|
+
enumerable: true,
|
|
84
|
+
configurable: true,
|
|
85
|
+
get() {
|
|
86
|
+
if (key === "children") {
|
|
87
|
+
return getChildren();
|
|
88
|
+
}
|
|
89
|
+
if (key === "ref") {
|
|
90
|
+
return ref;
|
|
91
|
+
}
|
|
92
|
+
return (getProps() as Record<string, unknown>)[key];
|
|
93
|
+
},
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
return props;
|
|
98
|
+
}
|
|
34
99
|
|
|
35
100
|
export interface ButtonRenderProps {
|
|
36
101
|
/** Whether the button is currently hovered with a mouse. */
|
|
@@ -43,28 +108,41 @@ export interface ButtonRenderProps {
|
|
|
43
108
|
isFocusVisible: boolean;
|
|
44
109
|
/** Whether the button is disabled. */
|
|
45
110
|
isDisabled: boolean;
|
|
111
|
+
/** Whether the button is currently in a pending state. */
|
|
112
|
+
isPending: boolean;
|
|
46
113
|
}
|
|
47
114
|
|
|
48
|
-
export interface ButtonProps
|
|
49
|
-
extends Omit<AriaButtonProps, 'children'>,
|
|
50
|
-
SlotProps {
|
|
115
|
+
export interface ButtonProps extends Omit<AriaButtonProps, "children">, SlotProps {
|
|
51
116
|
/** The children of the component. A function may be provided to receive render props. */
|
|
52
117
|
children?: RenderChildren<ButtonRenderProps>;
|
|
53
118
|
/** The CSS className for the element. */
|
|
54
119
|
class?: ClassNameOrFunction<ButtonRenderProps>;
|
|
55
120
|
/** The inline style for the element. */
|
|
56
121
|
style?: StyleOrFunction<ButtonRenderProps>;
|
|
122
|
+
/** Custom renderer for the outer button element. */
|
|
123
|
+
render?: (
|
|
124
|
+
props: JSX.ButtonHTMLAttributes<HTMLButtonElement>,
|
|
125
|
+
renderProps: ButtonRenderProps,
|
|
126
|
+
) => JSX.Element;
|
|
127
|
+
/** Ref for the underlying button element. */
|
|
128
|
+
ref?: RefLike<HTMLButtonElement>;
|
|
129
|
+
/** Whether the button is in a pending state. */
|
|
130
|
+
isPending?: boolean;
|
|
131
|
+
/** Keeps pending buttons focusable by using aria-disabled without a native disabled attribute. */
|
|
132
|
+
isPendingFocusable?: boolean;
|
|
133
|
+
/** Handler called when hover starts. */
|
|
134
|
+
onHoverStart?: (e: HoverEvent) => void;
|
|
135
|
+
/** Handler called when hover ends. */
|
|
136
|
+
onHoverEnd?: (e: HoverEvent) => void;
|
|
137
|
+
/** Handler called when hover state changes. */
|
|
138
|
+
onHoverChange?: (isHovered: boolean) => void;
|
|
57
139
|
}
|
|
58
140
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
export const ButtonContext = createContext<ButtonProps | null>(null);
|
|
141
|
+
export interface ButtonContextValue extends ButtonProps {
|
|
142
|
+
slots?: Record<string, ButtonProps>;
|
|
143
|
+
}
|
|
64
144
|
|
|
65
|
-
|
|
66
|
-
// COMPONENT
|
|
67
|
-
// ============================================
|
|
145
|
+
export const ButtonContext = createContext<ButtonContextValue | null>(null);
|
|
68
146
|
|
|
69
147
|
/**
|
|
70
148
|
* A button allows a user to perform an action.
|
|
@@ -84,12 +162,29 @@ export const ButtonContext = createContext<ButtonProps | null>(null);
|
|
|
84
162
|
* ```
|
|
85
163
|
*/
|
|
86
164
|
export function Button(props: ButtonProps): JSX.Element {
|
|
87
|
-
|
|
88
|
-
const
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
165
|
+
const contextProps = useContext(ButtonContext);
|
|
166
|
+
const contextSlotProps = contextProps?.slots?.[props.slot ?? "default"];
|
|
167
|
+
const contextBaseProps = createMemo<ButtonProps>(() => {
|
|
168
|
+
if (!contextProps) return {};
|
|
169
|
+
const { slots: _slots, ...rest } = contextProps;
|
|
170
|
+
return rest;
|
|
171
|
+
});
|
|
172
|
+
const mergedProps = (
|
|
173
|
+
contextProps ? mergeProps(contextBaseProps(), contextSlotProps ?? {}, props) : props
|
|
174
|
+
) as ButtonProps;
|
|
175
|
+
|
|
176
|
+
const [local, ariaProps] = splitProps(mergedProps, [
|
|
177
|
+
"children",
|
|
178
|
+
"class",
|
|
179
|
+
"style",
|
|
180
|
+
"render",
|
|
181
|
+
"ref",
|
|
182
|
+
"slot",
|
|
183
|
+
"isPending",
|
|
184
|
+
"isPendingFocusable",
|
|
185
|
+
"onHoverStart",
|
|
186
|
+
"onHoverEnd",
|
|
187
|
+
"onHoverChange",
|
|
93
188
|
]);
|
|
94
189
|
|
|
95
190
|
// Check if inside a DialogTrigger or PopoverTrigger - if so, toggle on press
|
|
@@ -103,79 +198,102 @@ export function Button(props: ButtonProps): JSX.Element {
|
|
|
103
198
|
// Helper to resolve isDisabled (handles both boolean and Accessor<boolean>)
|
|
104
199
|
const resolveDisabled = (): boolean => {
|
|
105
200
|
const disabled = ariaProps.isDisabled;
|
|
106
|
-
if (typeof disabled ===
|
|
201
|
+
if (typeof disabled === "function") {
|
|
107
202
|
return disabled();
|
|
108
203
|
}
|
|
109
204
|
return !!disabled;
|
|
110
205
|
};
|
|
111
206
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
//
|
|
120
|
-
|
|
121
|
-
const
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
207
|
+
const resolvePending = (): boolean => !!local.isPending;
|
|
208
|
+
const isPendingFocusable = () => local.isPendingFocusable !== false;
|
|
209
|
+
|
|
210
|
+
const [resolvedButtonEl, setResolvedButtonEl] = createSignal<HTMLButtonElement | null>(null);
|
|
211
|
+
const buttonId = createId((ariaProps as Record<string, unknown>).id as string | undefined);
|
|
212
|
+
const progressId = createId();
|
|
213
|
+
|
|
214
|
+
// Explicit trigger ownership: a button toggles overlays only when it is the
|
|
215
|
+
// registered trigger element for the surrounding trigger context.
|
|
216
|
+
const isDialogTrigger = () =>
|
|
217
|
+
!!dialogTriggerContext &&
|
|
218
|
+
!!resolvedButtonEl() &&
|
|
219
|
+
dialogTriggerContext.triggerRef() === resolvedButtonEl();
|
|
220
|
+
const isPopoverTrigger = () =>
|
|
221
|
+
!!popoverTriggerContext &&
|
|
222
|
+
!!resolvedButtonEl() &&
|
|
223
|
+
popoverTriggerContext.triggerRef() === resolvedButtonEl();
|
|
224
|
+
|
|
225
|
+
const handlePress = (e: PressEvent) => {
|
|
226
|
+
if (resolvePending()) {
|
|
227
|
+
return;
|
|
228
|
+
}
|
|
229
|
+
if (typeof ariaProps.onPress === "function") {
|
|
127
230
|
ariaProps.onPress(e);
|
|
128
231
|
}
|
|
129
|
-
// Toggle
|
|
232
|
+
// Toggle only when this exact button is the registered trigger element.
|
|
130
233
|
if (isDialogTrigger()) {
|
|
131
234
|
dialogTriggerContext!.state.toggle();
|
|
132
235
|
}
|
|
133
|
-
// Toggle popover only if this is a trigger button (has no onPress handler)
|
|
134
236
|
if (isPopoverTrigger()) {
|
|
135
237
|
popoverTriggerContext!.state.toggle();
|
|
136
238
|
}
|
|
137
239
|
};
|
|
138
240
|
|
|
139
|
-
// Create button aria props
|
|
140
241
|
const buttonAria = createButton({
|
|
141
242
|
...ariaProps,
|
|
142
243
|
onPress: handlePress,
|
|
244
|
+
get onPressStart() {
|
|
245
|
+
return resolvePending() ? undefined : ariaProps.onPressStart;
|
|
246
|
+
},
|
|
247
|
+
get onPressEnd() {
|
|
248
|
+
return resolvePending() ? undefined : ariaProps.onPressEnd;
|
|
249
|
+
},
|
|
250
|
+
get onPressUp() {
|
|
251
|
+
return resolvePending() ? undefined : ariaProps.onPressUp;
|
|
252
|
+
},
|
|
253
|
+
get onPressChange() {
|
|
254
|
+
return resolvePending() ? undefined : ariaProps.onPressChange;
|
|
255
|
+
},
|
|
256
|
+
get onClick() {
|
|
257
|
+
return resolvePending() ? undefined : ariaProps.onClick;
|
|
258
|
+
},
|
|
143
259
|
get isDisabled() {
|
|
144
|
-
return resolveDisabled();
|
|
260
|
+
return resolveDisabled() || resolvePending();
|
|
145
261
|
},
|
|
146
262
|
});
|
|
147
263
|
|
|
148
|
-
// Create focus ring
|
|
149
264
|
const { isFocused, isFocusVisible, focusProps } = createFocusRing();
|
|
150
265
|
|
|
151
|
-
// Create hover
|
|
152
266
|
const { isHovered, hoverProps } = createHover({
|
|
153
267
|
get isDisabled() {
|
|
154
|
-
return resolveDisabled();
|
|
268
|
+
return resolveDisabled() || resolvePending();
|
|
155
269
|
},
|
|
270
|
+
onHoverStart: local.onHoverStart,
|
|
271
|
+
onHoverEnd: local.onHoverEnd,
|
|
272
|
+
onHoverChange: local.onHoverChange,
|
|
156
273
|
});
|
|
157
274
|
|
|
158
|
-
// Render props values
|
|
159
275
|
const renderValues = createMemo<ButtonRenderProps>(() => ({
|
|
160
276
|
isHovered: isHovered(),
|
|
161
|
-
isPressed: buttonAria.isPressed(),
|
|
277
|
+
isPressed: buttonAria.isPressed() && !resolvePending(),
|
|
162
278
|
isFocused: isFocused(),
|
|
163
279
|
isFocusVisible: isFocusVisible(),
|
|
164
280
|
isDisabled: resolveDisabled(),
|
|
281
|
+
isPending: resolvePending(),
|
|
165
282
|
}));
|
|
166
283
|
|
|
167
|
-
// Resolve render props
|
|
168
284
|
const renderProps = useRenderProps(
|
|
169
285
|
{
|
|
170
|
-
children
|
|
286
|
+
// Use merged children so ButtonContext can supply slot/default content.
|
|
287
|
+
get children() {
|
|
288
|
+
return local.children;
|
|
289
|
+
},
|
|
171
290
|
class: local.class,
|
|
172
291
|
style: local.style,
|
|
173
|
-
defaultClassName:
|
|
292
|
+
defaultClassName: "solidaria-Button",
|
|
174
293
|
},
|
|
175
|
-
renderValues
|
|
294
|
+
renderValues,
|
|
176
295
|
);
|
|
177
296
|
|
|
178
|
-
// Filter DOM props
|
|
179
297
|
// Remove onClick from DOM props - it's already handled by createPress
|
|
180
298
|
// This matches React Aria Components behavior (Button.tsx line 144: delete DOMProps.onClick)
|
|
181
299
|
const domProps = createMemo(() => {
|
|
@@ -185,12 +303,16 @@ export function Button(props: ButtonProps): JSX.Element {
|
|
|
185
303
|
return filtered;
|
|
186
304
|
});
|
|
187
305
|
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
const
|
|
306
|
+
const buttonPropsRef = (buttonAria.buttonProps as Record<string, unknown>).ref as
|
|
307
|
+
| ((el: HTMLElement) => void)
|
|
308
|
+
| undefined;
|
|
309
|
+
const focusPropsRef = (focusProps as Record<string, unknown>).ref as
|
|
310
|
+
| ((el: HTMLElement) => void)
|
|
311
|
+
| undefined;
|
|
312
|
+
const hoverPropsRef = (hoverProps as Record<string, unknown>).ref as
|
|
313
|
+
| ((el: HTMLElement) => void)
|
|
314
|
+
| undefined;
|
|
192
315
|
|
|
193
|
-
// Remove ref from spread props to avoid type conflicts
|
|
194
316
|
const cleanButtonProps = () => {
|
|
195
317
|
const { ref: _ref1, ...rest } = buttonAria.buttonProps as Record<string, unknown>;
|
|
196
318
|
return rest;
|
|
@@ -203,36 +325,155 @@ export function Button(props: ButtonProps): JSX.Element {
|
|
|
203
325
|
const { ref: _ref3, ...rest } = hoverProps as Record<string, unknown>;
|
|
204
326
|
return rest;
|
|
205
327
|
};
|
|
328
|
+
const ariaLabelledBy = createMemo(() => {
|
|
329
|
+
const labelledBy = cleanButtonProps()["aria-labelledby"] as string | undefined;
|
|
330
|
+
if (!resolvePending()) {
|
|
331
|
+
return labelledBy;
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
if (labelledBy) {
|
|
335
|
+
return `${labelledBy} ${progressId}`;
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
if (cleanButtonProps()["aria-label"]) {
|
|
339
|
+
return `${buttonId} ${progressId}`;
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
return labelledBy;
|
|
343
|
+
});
|
|
206
344
|
|
|
207
|
-
// Ref callback that combines all refs
|
|
208
345
|
const handleRef = (el: HTMLButtonElement) => {
|
|
209
|
-
|
|
346
|
+
setResolvedButtonEl(el);
|
|
347
|
+
assignRef(local.ref, el);
|
|
348
|
+
|
|
210
349
|
buttonPropsRef?.(el);
|
|
211
350
|
focusPropsRef?.(el);
|
|
212
351
|
hoverPropsRef?.(el);
|
|
213
352
|
|
|
214
|
-
//
|
|
215
|
-
if (
|
|
353
|
+
// Register trigger ownership for surrounding trigger contexts.
|
|
354
|
+
if (dialogTriggerContext?.setTriggerRef) {
|
|
355
|
+
if (!el.id) {
|
|
356
|
+
el.id = dialogTriggerContext.triggerId;
|
|
357
|
+
}
|
|
358
|
+
dialogTriggerContext.setTriggerRef(el);
|
|
359
|
+
}
|
|
360
|
+
if (popoverTriggerContext?.setTriggerRef) {
|
|
216
361
|
popoverTriggerContext.setTriggerRef(el);
|
|
217
362
|
}
|
|
218
363
|
};
|
|
364
|
+
const buttonType = () =>
|
|
365
|
+
(buttonAria.buttonProps as Record<string, unknown>).type === "submit" && resolvePending()
|
|
366
|
+
? "button"
|
|
367
|
+
: ((buttonAria.buttonProps as Record<string, unknown>).type as
|
|
368
|
+
| "button"
|
|
369
|
+
| "submit"
|
|
370
|
+
| "reset"
|
|
371
|
+
| undefined);
|
|
372
|
+
const triggerAriaProps = () => {
|
|
373
|
+
const dialogTriggerProps = dialogTriggerContext?.triggerProps;
|
|
374
|
+
if (dialogTriggerProps && isDialogTrigger()) {
|
|
375
|
+
const next: Record<string, unknown> = {};
|
|
376
|
+
for (const name of ["aria-haspopup", "aria-expanded", "aria-controls"]) {
|
|
377
|
+
if (dialogTriggerProps[name] != null) {
|
|
378
|
+
next[name] = dialogTriggerProps[name];
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
return next;
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
const triggerProps = popoverTriggerContext?.triggerProps;
|
|
385
|
+
if (!triggerProps || !isPopoverTrigger()) {
|
|
386
|
+
return {};
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
const next: Record<string, unknown> = {};
|
|
390
|
+
for (const name of ["aria-haspopup", "aria-expanded", "aria-controls"]) {
|
|
391
|
+
if (triggerProps[name] != null) {
|
|
392
|
+
next[name] = triggerProps[name];
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
return next;
|
|
396
|
+
};
|
|
397
|
+
const disablePendingInteractions = (props: Record<string, unknown>) => {
|
|
398
|
+
if (!resolvePending()) {
|
|
399
|
+
return props;
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
const next = { ...props };
|
|
403
|
+
for (const key of Object.keys(next)) {
|
|
404
|
+
if (key.startsWith("on") && !key.includes("Focus") && !key.includes("Blur")) {
|
|
405
|
+
next[key] = undefined;
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
next.href = undefined;
|
|
409
|
+
next.target = undefined;
|
|
410
|
+
return next;
|
|
411
|
+
};
|
|
412
|
+
const dataState = (value: boolean) => (value ? "true" : undefined);
|
|
413
|
+
const buttonChildren = () => renderProps.renderChildren();
|
|
414
|
+
const buttonContent = () => (
|
|
415
|
+
<ProgressBarContext.Provider value={{ id: progressId }}>
|
|
416
|
+
{buttonChildren()}
|
|
417
|
+
</ProgressBarContext.Provider>
|
|
418
|
+
);
|
|
419
|
+
let wasPending = resolvePending();
|
|
420
|
+
createEffect(() => {
|
|
421
|
+
const pending = resolvePending();
|
|
422
|
+
const message = { "aria-labelledby": ariaLabelledBy() || buttonId };
|
|
423
|
+
|
|
424
|
+
if (!wasPending && isFocused() && pending) {
|
|
425
|
+
announce(message, "assertive");
|
|
426
|
+
} else if (wasPending && isFocused() && !pending) {
|
|
427
|
+
announce(message, "assertive");
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
wasPending = pending;
|
|
431
|
+
});
|
|
432
|
+
const rootProps = () =>
|
|
433
|
+
({
|
|
434
|
+
...domProps(),
|
|
435
|
+
...disablePendingInteractions(cleanButtonProps()),
|
|
436
|
+
...triggerAriaProps(),
|
|
437
|
+
...cleanFocusProps(),
|
|
438
|
+
...cleanHoverProps(),
|
|
439
|
+
type: buttonType(),
|
|
440
|
+
id: buttonId,
|
|
441
|
+
class: renderProps.class(),
|
|
442
|
+
style: renderProps.style(),
|
|
443
|
+
slot: local.slot,
|
|
444
|
+
disabled: resolvePending() && isPendingFocusable() ? undefined : cleanButtonProps().disabled,
|
|
445
|
+
"aria-labelledby": ariaLabelledBy(),
|
|
446
|
+
"aria-disabled": resolvePending()
|
|
447
|
+
? "true"
|
|
448
|
+
: (cleanButtonProps()["aria-disabled"] ?? ariaProps["aria-disabled"]),
|
|
449
|
+
"data-pressed": dataState(buttonAria.isPressed() && !resolvePending()),
|
|
450
|
+
"data-hovered": dataState(isHovered()),
|
|
451
|
+
"data-focused": dataState(isFocused()),
|
|
452
|
+
"data-focus-visible": dataState(isFocusVisible()),
|
|
453
|
+
"data-disabled": dataState(resolveDisabled()),
|
|
454
|
+
"data-pending": dataState(resolvePending()),
|
|
455
|
+
}) as JSX.ButtonHTMLAttributes<HTMLButtonElement>;
|
|
456
|
+
const customRootProps = createLiveCustomRootProps(rootProps, buttonContent, handleRef);
|
|
457
|
+
const customRenderValues = createLiveButtonRenderProps(renderValues);
|
|
219
458
|
|
|
220
|
-
return (
|
|
459
|
+
return local.render ? (
|
|
460
|
+
local.render(customRootProps, customRenderValues)
|
|
461
|
+
) : (
|
|
221
462
|
<button
|
|
222
463
|
ref={handleRef}
|
|
223
|
-
{...
|
|
224
|
-
{...cleanButtonProps()}
|
|
225
|
-
{...cleanFocusProps()}
|
|
226
|
-
{...cleanHoverProps()}
|
|
464
|
+
{...rootProps()}
|
|
227
465
|
class={renderProps.class()}
|
|
228
466
|
style={renderProps.style()}
|
|
229
|
-
data-pressed={
|
|
230
|
-
data-hovered={
|
|
231
|
-
data-focused={
|
|
232
|
-
data-focus-visible={
|
|
233
|
-
|
|
467
|
+
attr:data-pressed={(rootProps() as Record<string, unknown>)["data-pressed"] as string}
|
|
468
|
+
attr:data-hovered={(rootProps() as Record<string, unknown>)["data-hovered"] as string}
|
|
469
|
+
attr:data-focused={(rootProps() as Record<string, unknown>)["data-focused"] as string}
|
|
470
|
+
attr:data-focus-visible={
|
|
471
|
+
(rootProps() as Record<string, unknown>)["data-focus-visible"] as string
|
|
472
|
+
}
|
|
473
|
+
attr:data-disabled={(rootProps() as Record<string, unknown>)["data-disabled"] as string}
|
|
474
|
+
attr:data-pending={(rootProps() as Record<string, unknown>)["data-pending"] as string}
|
|
234
475
|
>
|
|
235
|
-
{
|
|
476
|
+
{buttonContent()}
|
|
236
477
|
</button>
|
|
237
478
|
);
|
|
238
479
|
}
|