@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/TimeField.tsx
CHANGED
|
@@ -14,18 +14,20 @@ import {
|
|
|
14
14
|
useContext,
|
|
15
15
|
For,
|
|
16
16
|
Show,
|
|
17
|
-
} from
|
|
17
|
+
} from "solid-js";
|
|
18
18
|
import {
|
|
19
19
|
createTimeField,
|
|
20
|
+
createTimeSegment,
|
|
20
21
|
type AriaTimeFieldProps,
|
|
21
|
-
} from
|
|
22
|
+
} from "@proyecto-viviana/solidaria";
|
|
22
23
|
import {
|
|
23
24
|
createTimeFieldState,
|
|
25
|
+
access,
|
|
24
26
|
type TimeFieldState,
|
|
25
27
|
type TimeFieldStateProps,
|
|
26
28
|
type TimeSegment as TimeSegmentType,
|
|
27
29
|
type TimeValue,
|
|
28
|
-
} from
|
|
30
|
+
} from "@proyecto-viviana/solid-stately";
|
|
29
31
|
import {
|
|
30
32
|
type RenderChildren,
|
|
31
33
|
type ClassNameOrFunction,
|
|
@@ -34,11 +36,9 @@ import {
|
|
|
34
36
|
useRenderProps,
|
|
35
37
|
dataAttr,
|
|
36
38
|
useIsHydrated,
|
|
37
|
-
} from
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
// TYPES
|
|
41
|
-
// ============================================
|
|
39
|
+
} from "./utils";
|
|
40
|
+
import { HiddenTimeInput } from "./HiddenTimeInput";
|
|
41
|
+
import { FormContext, type FormProps } from "./Form";
|
|
42
42
|
|
|
43
43
|
export interface TimeFieldRenderProps {
|
|
44
44
|
/** Whether the field is disabled. */
|
|
@@ -52,8 +52,9 @@ export interface TimeFieldRenderProps {
|
|
|
52
52
|
}
|
|
53
53
|
|
|
54
54
|
export interface TimeFieldProps<T extends TimeValue = TimeValue>
|
|
55
|
-
extends
|
|
56
|
-
Omit<
|
|
55
|
+
extends
|
|
56
|
+
Omit<AriaTimeFieldProps, "id" | "isDisabled" | "isReadOnly" | "isRequired">,
|
|
57
|
+
Omit<TimeFieldStateProps<T>, "locale">,
|
|
57
58
|
SlotProps {
|
|
58
59
|
/** The children of the component. */
|
|
59
60
|
children?: JSX.Element | ((segment: TimeSegmentType) => JSX.Element);
|
|
@@ -89,7 +90,7 @@ export interface TimeSegmentRenderProps {
|
|
|
89
90
|
/** Whether the segment is a placeholder. */
|
|
90
91
|
isPlaceholder: boolean;
|
|
91
92
|
/** The segment type. */
|
|
92
|
-
type: TimeSegmentType[
|
|
93
|
+
type: TimeSegmentType["type"];
|
|
93
94
|
/** The text to display. */
|
|
94
95
|
text: string;
|
|
95
96
|
}
|
|
@@ -105,23 +106,77 @@ export interface TimeSegmentProps extends SlotProps {
|
|
|
105
106
|
style?: StyleOrFunction<TimeSegmentRenderProps>;
|
|
106
107
|
}
|
|
107
108
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
109
|
+
export interface TimeFieldContextValue {
|
|
110
|
+
state: TimeFieldState<TimeValue>;
|
|
111
|
+
aria: {
|
|
112
|
+
labelProps: Record<string, unknown>;
|
|
113
|
+
inputProps: Record<string, unknown>;
|
|
114
|
+
descriptionProps: Record<string, unknown>;
|
|
115
|
+
errorMessageProps: Record<string, unknown>;
|
|
116
|
+
};
|
|
117
|
+
}
|
|
111
118
|
|
|
112
|
-
export const TimeFieldContext = createContext<
|
|
119
|
+
export const TimeFieldContext = createContext<TimeFieldContextValue | null>(null);
|
|
120
|
+
export const TimeFieldStateContext = createContext<TimeFieldState<TimeValue> | null>(null);
|
|
113
121
|
|
|
114
|
-
|
|
122
|
+
function withFormValidationBehavior<P extends object>(props: P, formContext: FormProps | null): P {
|
|
123
|
+
if (!formContext?.validationBehavior) {
|
|
124
|
+
return props;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
return new Proxy(props, {
|
|
128
|
+
get(target, property, receiver) {
|
|
129
|
+
const localValue = Reflect.get(target, property, receiver);
|
|
130
|
+
if (property === "validationBehavior" && localValue === undefined) {
|
|
131
|
+
return formContext.validationBehavior;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
return localValue;
|
|
135
|
+
},
|
|
136
|
+
has(target, property) {
|
|
137
|
+
return (
|
|
138
|
+
Reflect.has(target, property) ||
|
|
139
|
+
(property === "validationBehavior" && formContext.validationBehavior !== undefined)
|
|
140
|
+
);
|
|
141
|
+
},
|
|
142
|
+
ownKeys(target) {
|
|
143
|
+
const keys = new Set(Reflect.ownKeys(target));
|
|
144
|
+
if (formContext.validationBehavior !== undefined) {
|
|
145
|
+
keys.add("validationBehavior");
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
return Array.from(keys);
|
|
149
|
+
},
|
|
150
|
+
getOwnPropertyDescriptor(target, property) {
|
|
151
|
+
const descriptor = Reflect.getOwnPropertyDescriptor(target, property);
|
|
152
|
+
if (descriptor) {
|
|
153
|
+
return descriptor;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
if (property === "validationBehavior" && formContext.validationBehavior !== undefined) {
|
|
157
|
+
return {
|
|
158
|
+
enumerable: true,
|
|
159
|
+
configurable: true,
|
|
160
|
+
get: () => formContext.validationBehavior,
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
return undefined;
|
|
165
|
+
},
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
function useTimeFieldContextValue(): TimeFieldContextValue {
|
|
115
170
|
const context = useContext(TimeFieldContext);
|
|
116
171
|
if (!context) {
|
|
117
|
-
throw new Error(
|
|
172
|
+
throw new Error("TimeField components must be used within a TimeField");
|
|
118
173
|
}
|
|
119
174
|
return context;
|
|
120
175
|
}
|
|
121
176
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
177
|
+
export function useTimeFieldContext(): TimeFieldState<TimeValue> {
|
|
178
|
+
return useTimeFieldContextValue().state;
|
|
179
|
+
}
|
|
125
180
|
|
|
126
181
|
/**
|
|
127
182
|
* A time field allows users to enter and edit time values using a keyboard.
|
|
@@ -136,57 +191,75 @@ export function useTimeFieldContext(): TimeFieldState<TimeValue> {
|
|
|
136
191
|
* </TimeField>
|
|
137
192
|
* ```
|
|
138
193
|
*/
|
|
139
|
-
export function TimeField<T extends TimeValue = TimeValue>(
|
|
140
|
-
props: TimeFieldProps<T>
|
|
141
|
-
): JSX.Element {
|
|
194
|
+
export function TimeField<T extends TimeValue = TimeValue>(props: TimeFieldProps<T>): JSX.Element {
|
|
142
195
|
// Use hydration-safe pattern for client-only rendering
|
|
143
196
|
const isHydrated = useIsHydrated();
|
|
197
|
+
const formContext = useContext(FormContext);
|
|
144
198
|
|
|
145
199
|
return (
|
|
146
200
|
<Show
|
|
147
201
|
when={isHydrated()}
|
|
148
|
-
fallback={
|
|
202
|
+
fallback={
|
|
203
|
+
<div class="solidaria-TimeField solidaria-TimeField--placeholder" aria-hidden="true" />
|
|
204
|
+
}
|
|
149
205
|
>
|
|
150
|
-
<TimeFieldInner {...props} />
|
|
206
|
+
<TimeFieldInner {...props} __formContext={formContext} />
|
|
151
207
|
</Show>
|
|
152
208
|
);
|
|
153
209
|
}
|
|
154
210
|
|
|
211
|
+
type TimeFieldInnerProps<T extends TimeValue = TimeValue> = TimeFieldProps<T> & {
|
|
212
|
+
__formContext?: FormProps | null;
|
|
213
|
+
};
|
|
214
|
+
|
|
155
215
|
/**
|
|
156
216
|
* Internal TimeField component that renders after client mount.
|
|
157
217
|
*/
|
|
158
218
|
function TimeFieldInner<T extends TimeValue = TimeValue>(
|
|
159
|
-
props:
|
|
219
|
+
props: TimeFieldInnerProps<T>,
|
|
160
220
|
): JSX.Element {
|
|
221
|
+
const formContext = props.__formContext ?? useContext(FormContext);
|
|
222
|
+
const mergedProps = withFormValidationBehavior(props, formContext);
|
|
161
223
|
const [local, stateProps, rest] = splitProps(
|
|
162
|
-
|
|
163
|
-
[
|
|
224
|
+
mergedProps,
|
|
225
|
+
["children", "class", "style", "slot", "__formContext"],
|
|
164
226
|
[
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
227
|
+
"value",
|
|
228
|
+
"defaultValue",
|
|
229
|
+
"onChange",
|
|
230
|
+
"minValue",
|
|
231
|
+
"maxValue",
|
|
232
|
+
"isInvalid",
|
|
233
|
+
"isDisabled",
|
|
234
|
+
"isReadOnly",
|
|
235
|
+
"isRequired",
|
|
236
|
+
"locale",
|
|
237
|
+
"granularity",
|
|
238
|
+
"hourCycle",
|
|
239
|
+
"shouldForceLeadingZeros",
|
|
240
|
+
"validationState",
|
|
241
|
+
"validationBehavior",
|
|
242
|
+
"validate",
|
|
243
|
+
"description",
|
|
244
|
+
"errorMessage",
|
|
245
|
+
"placeholderValue",
|
|
246
|
+
],
|
|
179
247
|
);
|
|
180
248
|
|
|
181
249
|
const [fieldRef, setFieldRef] = createSignal<HTMLDivElement | null>(null);
|
|
182
250
|
|
|
183
|
-
// Create time field state
|
|
184
251
|
const state = createTimeFieldState(stateProps);
|
|
185
252
|
|
|
186
|
-
|
|
187
|
-
|
|
253
|
+
const fieldAria = createTimeField(
|
|
254
|
+
() => ({
|
|
255
|
+
...(rest as Record<string, unknown>),
|
|
256
|
+
description: stateProps.description,
|
|
257
|
+
errorMessage: stateProps.errorMessage,
|
|
258
|
+
}),
|
|
259
|
+
state as unknown as TimeFieldState<TimeValue>,
|
|
260
|
+
fieldRef,
|
|
261
|
+
);
|
|
188
262
|
|
|
189
|
-
// Render props values
|
|
190
263
|
const renderValues = createMemo<TimeFieldRenderProps>(() => ({
|
|
191
264
|
isDisabled: state.isDisabled(),
|
|
192
265
|
isReadOnly: state.isReadOnly(),
|
|
@@ -194,64 +267,92 @@ function TimeFieldInner<T extends TimeValue = TimeValue>(
|
|
|
194
267
|
isInvalid: state.isInvalid(),
|
|
195
268
|
}));
|
|
196
269
|
|
|
197
|
-
// Resolve render props
|
|
198
270
|
const renderProps = useRenderProps(
|
|
199
271
|
{
|
|
200
272
|
class: local.class,
|
|
201
273
|
style: local.style,
|
|
202
|
-
defaultClassName:
|
|
274
|
+
defaultClassName: "solidaria-TimeField",
|
|
203
275
|
},
|
|
204
|
-
renderValues
|
|
276
|
+
renderValues,
|
|
205
277
|
);
|
|
206
278
|
|
|
279
|
+
const validationBehavior = () =>
|
|
280
|
+
(stateProps as { validationBehavior?: "aria" | "native" }).validationBehavior ??
|
|
281
|
+
formContext?.validationBehavior ??
|
|
282
|
+
"native";
|
|
283
|
+
|
|
207
284
|
return (
|
|
208
|
-
<
|
|
209
|
-
<
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
285
|
+
<TimeFieldStateContext.Provider value={state as unknown as TimeFieldState<TimeValue>}>
|
|
286
|
+
<TimeFieldContext.Provider
|
|
287
|
+
value={{
|
|
288
|
+
state: state as unknown as TimeFieldState<TimeValue>,
|
|
289
|
+
aria: {
|
|
290
|
+
labelProps: fieldAria.labelProps,
|
|
291
|
+
inputProps: fieldAria.inputProps,
|
|
292
|
+
descriptionProps: fieldAria.descriptionProps,
|
|
293
|
+
errorMessageProps: fieldAria.errorMessageProps,
|
|
294
|
+
},
|
|
295
|
+
}}
|
|
218
296
|
>
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
297
|
+
<div
|
|
298
|
+
ref={setFieldRef}
|
|
299
|
+
{...fieldAria.fieldProps}
|
|
300
|
+
class={renderProps.class()}
|
|
301
|
+
style={renderProps.style()}
|
|
302
|
+
data-disabled={dataAttr(state.isDisabled())}
|
|
303
|
+
data-readonly={dataAttr(state.isReadOnly())}
|
|
304
|
+
data-required={dataAttr(state.isRequired())}
|
|
305
|
+
data-invalid={dataAttr(state.isInvalid())}
|
|
306
|
+
>
|
|
307
|
+
{local.children as JSX.Element}
|
|
308
|
+
</div>
|
|
309
|
+
<Show when={(rest as Record<string, unknown>).name}>
|
|
310
|
+
<HiddenTimeInput
|
|
311
|
+
name={(rest as Record<string, unknown>).name as string | undefined}
|
|
312
|
+
form={(rest as Record<string, unknown>).form as string | undefined}
|
|
313
|
+
value={state.value()}
|
|
314
|
+
autoComplete={(rest as Record<string, unknown>).autoComplete as string | undefined}
|
|
315
|
+
isDisabled={state.isDisabled()}
|
|
316
|
+
isRequired={state.isRequired()}
|
|
317
|
+
validationBehavior={validationBehavior()}
|
|
318
|
+
validationState={state}
|
|
319
|
+
focus={() => {
|
|
320
|
+
fieldRef()?.querySelector<HTMLElement>('[role="spinbutton"]')?.focus();
|
|
321
|
+
}}
|
|
322
|
+
minValue={access(stateProps.minValue) as TimeValue | undefined}
|
|
323
|
+
maxValue={access(stateProps.maxValue) as TimeValue | undefined}
|
|
324
|
+
granularity={state.granularity}
|
|
325
|
+
/>
|
|
326
|
+
</Show>
|
|
327
|
+
</TimeFieldContext.Provider>
|
|
328
|
+
</TimeFieldStateContext.Provider>
|
|
222
329
|
);
|
|
223
330
|
}
|
|
224
331
|
|
|
225
|
-
// ============================================
|
|
226
|
-
// TIME INPUT COMPONENT
|
|
227
|
-
// ============================================
|
|
228
|
-
|
|
229
332
|
/**
|
|
230
333
|
* The input area containing time segments.
|
|
231
334
|
*/
|
|
232
335
|
export function TimeInput(props: TimeInputProps): JSX.Element {
|
|
233
|
-
const state =
|
|
336
|
+
const { state, aria } = useTimeFieldContextValue();
|
|
234
337
|
const [isFocused, setIsFocused] = createSignal(false);
|
|
235
338
|
|
|
236
|
-
// Render props values
|
|
237
339
|
const renderValues = createMemo<TimeInputRenderProps>(() => ({
|
|
238
340
|
isDisabled: state.isDisabled(),
|
|
239
341
|
isFocused: isFocused(),
|
|
240
342
|
}));
|
|
241
343
|
|
|
242
|
-
// Resolve render props
|
|
243
344
|
const renderProps = useRenderProps(
|
|
244
345
|
{
|
|
245
346
|
class: props.class,
|
|
246
347
|
style: props.style,
|
|
247
|
-
defaultClassName:
|
|
348
|
+
defaultClassName: "solidaria-TimeInput",
|
|
248
349
|
},
|
|
249
|
-
renderValues
|
|
350
|
+
renderValues,
|
|
250
351
|
);
|
|
251
352
|
|
|
252
353
|
return (
|
|
253
354
|
<div
|
|
254
|
-
|
|
355
|
+
{...aria.inputProps}
|
|
255
356
|
class={renderProps.class()}
|
|
256
357
|
style={renderProps.style()}
|
|
257
358
|
data-disabled={dataAttr(state.isDisabled())}
|
|
@@ -259,172 +360,59 @@ export function TimeInput(props: TimeInputProps): JSX.Element {
|
|
|
259
360
|
onFocusIn={() => setIsFocused(true)}
|
|
260
361
|
onFocusOut={() => setIsFocused(false)}
|
|
261
362
|
>
|
|
262
|
-
<For each={state.segments()}>
|
|
263
|
-
{(segment) => props.children?.(segment)}
|
|
264
|
-
</For>
|
|
363
|
+
<For each={state.segments()}>{(segment) => props.children?.(segment)}</For>
|
|
265
364
|
</div>
|
|
266
365
|
);
|
|
267
366
|
}
|
|
268
367
|
|
|
269
|
-
// ============================================
|
|
270
|
-
// TIME SEGMENT COMPONENT
|
|
271
|
-
// ============================================
|
|
272
|
-
|
|
273
368
|
/**
|
|
274
369
|
* A segment of a time field (hour, minute, second, AM/PM).
|
|
275
370
|
*/
|
|
276
371
|
export function TimeSegment(props: TimeSegmentProps): JSX.Element {
|
|
277
372
|
const state = useTimeFieldContext();
|
|
278
|
-
const [
|
|
279
|
-
|
|
280
|
-
// Create segment ARIA props
|
|
281
|
-
// We use a simplified version for time segments
|
|
282
|
-
const [isFocused, setIsFocused] = createSignal(false);
|
|
283
|
-
const [enteredKeys, setEnteredKeys] = createSignal('');
|
|
284
|
-
|
|
285
|
-
const isEditable = createMemo(() => {
|
|
286
|
-
const seg = props.segment;
|
|
287
|
-
return seg.isEditable && !state.isDisabled() && !state.isReadOnly();
|
|
288
|
-
});
|
|
289
|
-
|
|
290
|
-
const handleKeyDown = (e: KeyboardEvent) => {
|
|
291
|
-
if (!isEditable()) return;
|
|
292
|
-
|
|
293
|
-
const seg = props.segment;
|
|
294
|
-
const type = seg.type;
|
|
295
|
-
|
|
296
|
-
if (type === 'literal') return;
|
|
297
|
-
|
|
298
|
-
switch (e.key) {
|
|
299
|
-
case 'ArrowUp':
|
|
300
|
-
e.preventDefault();
|
|
301
|
-
state.incrementSegment(type);
|
|
302
|
-
break;
|
|
303
|
-
case 'ArrowDown':
|
|
304
|
-
e.preventDefault();
|
|
305
|
-
state.decrementSegment(type);
|
|
306
|
-
break;
|
|
307
|
-
case 'Backspace':
|
|
308
|
-
case 'Delete':
|
|
309
|
-
e.preventDefault();
|
|
310
|
-
state.clearSegment(type);
|
|
311
|
-
setEnteredKeys('');
|
|
312
|
-
break;
|
|
313
|
-
default:
|
|
314
|
-
if (/^\d$/.test(e.key)) {
|
|
315
|
-
e.preventDefault();
|
|
316
|
-
const newKeys = enteredKeys() + e.key;
|
|
317
|
-
const numValue = parseInt(newKeys, 10);
|
|
318
|
-
const maxValue = seg.maxValue ?? 59;
|
|
319
|
-
const minValue = seg.minValue ?? 0;
|
|
320
|
-
|
|
321
|
-
if (numValue <= maxValue) {
|
|
322
|
-
state.setSegment(type, numValue);
|
|
323
|
-
if (numValue * 10 > maxValue || newKeys.length >= 2) {
|
|
324
|
-
setEnteredKeys('');
|
|
325
|
-
} else {
|
|
326
|
-
setEnteredKeys(newKeys);
|
|
327
|
-
}
|
|
328
|
-
} else {
|
|
329
|
-
const singleValue = parseInt(e.key, 10);
|
|
330
|
-
if (singleValue >= minValue && singleValue <= maxValue) {
|
|
331
|
-
state.setSegment(type, singleValue);
|
|
332
|
-
}
|
|
333
|
-
setEnteredKeys(e.key);
|
|
334
|
-
}
|
|
335
|
-
}
|
|
336
|
-
break;
|
|
337
|
-
}
|
|
338
|
-
};
|
|
373
|
+
const [segmentRef, setSegmentRef] = createSignal<HTMLDivElement | null>(null);
|
|
339
374
|
|
|
340
|
-
const
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
const handleBlur = () => {
|
|
346
|
-
setIsFocused(false);
|
|
347
|
-
setEnteredKeys('');
|
|
348
|
-
};
|
|
349
|
-
|
|
350
|
-
// Segment props
|
|
351
|
-
const segmentProps = createMemo(() => {
|
|
352
|
-
const seg = props.segment;
|
|
353
|
-
const type = seg.type;
|
|
354
|
-
|
|
355
|
-
if (type === 'literal') {
|
|
356
|
-
return {
|
|
357
|
-
'aria-hidden': true,
|
|
358
|
-
};
|
|
359
|
-
}
|
|
360
|
-
|
|
361
|
-
return {
|
|
362
|
-
role: 'spinbutton' as const,
|
|
363
|
-
tabIndex: isEditable() ? 0 : -1,
|
|
364
|
-
'aria-label': getTimeSegmentLabel(type),
|
|
365
|
-
'aria-valuenow': seg.value,
|
|
366
|
-
'aria-valuemin': seg.minValue,
|
|
367
|
-
'aria-valuemax': seg.maxValue,
|
|
368
|
-
'aria-valuetext': seg.isPlaceholder ? seg.placeholder : seg.text,
|
|
369
|
-
'aria-readonly': state.isReadOnly() || undefined,
|
|
370
|
-
'aria-disabled': state.isDisabled() || undefined,
|
|
371
|
-
'aria-invalid': state.isInvalid() || undefined,
|
|
372
|
-
contentEditable: isEditable(),
|
|
373
|
-
inputMode: 'numeric' as const,
|
|
374
|
-
autoCorrect: 'off',
|
|
375
|
-
enterKeyHint: 'next' as const,
|
|
376
|
-
spellCheck: false,
|
|
377
|
-
onKeyDown: handleKeyDown,
|
|
378
|
-
onFocus: handleFocus,
|
|
379
|
-
onBlur: handleBlur,
|
|
380
|
-
onMouseDown: (e: MouseEvent) => {
|
|
381
|
-
e.preventDefault();
|
|
382
|
-
},
|
|
383
|
-
};
|
|
384
|
-
});
|
|
385
|
-
|
|
386
|
-
const text = createMemo(() => {
|
|
387
|
-
const seg = props.segment;
|
|
388
|
-
return seg.isPlaceholder ? seg.placeholder : seg.text;
|
|
389
|
-
});
|
|
375
|
+
const segmentAria = createTimeSegment(
|
|
376
|
+
{ segment: props.segment },
|
|
377
|
+
state as unknown as TimeFieldState,
|
|
378
|
+
segmentRef,
|
|
379
|
+
);
|
|
390
380
|
|
|
391
|
-
// Render props values
|
|
392
381
|
const renderValues = createMemo<TimeSegmentRenderProps>(() => ({
|
|
393
|
-
isFocused: isFocused
|
|
394
|
-
isEditable: isEditable
|
|
395
|
-
isPlaceholder:
|
|
382
|
+
isFocused: segmentAria.isFocused,
|
|
383
|
+
isEditable: segmentAria.isEditable,
|
|
384
|
+
isPlaceholder: segmentAria.isPlaceholder,
|
|
396
385
|
type: props.segment.type,
|
|
397
|
-
text: text
|
|
386
|
+
text: segmentAria.text,
|
|
398
387
|
}));
|
|
399
388
|
|
|
400
|
-
// Resolve render props
|
|
401
389
|
const renderProps = useRenderProps(
|
|
402
390
|
{
|
|
403
391
|
children: props.children,
|
|
404
392
|
class: props.class,
|
|
405
393
|
style: props.style,
|
|
406
|
-
defaultClassName:
|
|
394
|
+
defaultClassName: "solidaria-TimeSegment",
|
|
407
395
|
},
|
|
408
|
-
renderValues
|
|
396
|
+
renderValues,
|
|
409
397
|
);
|
|
410
398
|
|
|
411
399
|
// Determine children content - avoid Show for SSR hydration compatibility
|
|
412
400
|
const getChildren = () => {
|
|
413
|
-
if (typeof props.children ===
|
|
401
|
+
if (typeof props.children === "function") {
|
|
414
402
|
return renderProps.renderChildren();
|
|
415
403
|
}
|
|
416
|
-
return text
|
|
404
|
+
return segmentAria.text;
|
|
417
405
|
};
|
|
418
406
|
|
|
419
407
|
return (
|
|
420
408
|
<div
|
|
421
409
|
ref={setSegmentRef}
|
|
422
|
-
{...segmentProps
|
|
410
|
+
{...segmentAria.segmentProps}
|
|
423
411
|
class={renderProps.class()}
|
|
424
412
|
style={renderProps.style()}
|
|
425
|
-
data-focused={dataAttr(isFocused
|
|
426
|
-
data-editable={dataAttr(isEditable
|
|
427
|
-
data-placeholder={dataAttr(
|
|
413
|
+
data-focused={dataAttr(segmentAria.isFocused)}
|
|
414
|
+
data-editable={dataAttr(segmentAria.isEditable)}
|
|
415
|
+
data-placeholder={dataAttr(segmentAria.isPlaceholder)}
|
|
428
416
|
data-type={props.segment.type}
|
|
429
417
|
>
|
|
430
418
|
{getChildren()}
|
|
@@ -432,24 +420,46 @@ export function TimeSegment(props: TimeSegmentProps): JSX.Element {
|
|
|
432
420
|
);
|
|
433
421
|
}
|
|
434
422
|
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
423
|
+
export interface TimeFieldLabelProps {
|
|
424
|
+
children?: JSX.Element;
|
|
425
|
+
class?: string;
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
export function TimeFieldLabel(props: TimeFieldLabelProps): JSX.Element {
|
|
429
|
+
const { aria } = useTimeFieldContextValue();
|
|
430
|
+
return (
|
|
431
|
+
<span {...aria.labelProps} class={props.class}>
|
|
432
|
+
{props.children}
|
|
433
|
+
</span>
|
|
434
|
+
);
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
export interface TimeFieldDescriptionProps {
|
|
438
|
+
children?: JSX.Element;
|
|
439
|
+
class?: string;
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
export function TimeFieldDescription(props: TimeFieldDescriptionProps): JSX.Element {
|
|
443
|
+
const { aria } = useTimeFieldContextValue();
|
|
444
|
+
return (
|
|
445
|
+
<p {...aria.descriptionProps} class={props.class}>
|
|
446
|
+
{props.children}
|
|
447
|
+
</p>
|
|
448
|
+
);
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
export interface TimeFieldErrorMessageProps {
|
|
452
|
+
children?: JSX.Element;
|
|
453
|
+
class?: string;
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
export function TimeFieldErrorMessage(props: TimeFieldErrorMessageProps): JSX.Element {
|
|
457
|
+
const { aria } = useTimeFieldContextValue();
|
|
458
|
+
return (
|
|
459
|
+
<p {...aria.errorMessageProps} class={props.class}>
|
|
460
|
+
{props.children}
|
|
461
|
+
</p>
|
|
462
|
+
);
|
|
452
463
|
}
|
|
453
464
|
|
|
454
|
-
// Re-export types
|
|
455
465
|
export type { TimeFieldState, TimeSegmentType, TimeValue };
|