@proyecto-viviana/solidaria-components 0.2.5 → 0.2.9
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/dist/ActionBar.d.ts +71 -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/Breadcrumbs.d.ts +10 -2
- package/dist/Breadcrumbs.d.ts.map +1 -1
- package/dist/Button.d.ts +4 -0
- package/dist/Button.d.ts.map +1 -1
- package/dist/Calendar.d.ts +13 -0
- package/dist/Calendar.d.ts.map +1 -1
- package/dist/Checkbox.d.ts +2 -2
- package/dist/Checkbox.d.ts.map +1 -1
- package/dist/Collection.d.ts +125 -0
- package/dist/Collection.d.ts.map +1 -0
- package/dist/Color.d.ts +114 -2
- 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 +64 -0
- 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 +27 -2
- package/dist/DateField.d.ts.map +1 -1
- package/dist/DatePicker.d.ts +67 -2
- package/dist/DatePicker.d.ts.map +1 -1
- package/dist/Dialog.d.ts.map +1 -1
- package/dist/Disclosure.d.ts +2 -0
- 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 +23 -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 +27 -0
- package/dist/Form.d.ts.map +1 -0
- package/dist/GridList.d.ts +40 -1
- package/dist/GridList.d.ts.map +1 -1
- 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/Link.d.ts.map +1 -1
- package/dist/ListBox.d.ts +43 -1
- 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 +20 -2
- package/dist/Menu.d.ts.map +1 -1
- package/dist/Meter.d.ts +2 -2
- package/dist/Meter.d.ts.map +1 -1
- package/dist/Modal.d.ts +2 -0
- package/dist/Modal.d.ts.map +1 -1
- package/dist/NumberField.d.ts +2 -0
- package/dist/NumberField.d.ts.map +1 -1
- package/dist/Popover.d.ts +4 -2
- 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 +2 -2
- package/dist/ProgressBar.d.ts.map +1 -1
- package/dist/RadioGroup.d.ts.map +1 -1
- package/dist/RangeCalendar.d.ts +5 -0
- 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 +2 -3
- package/dist/SearchField.d.ts.map +1 -1
- package/dist/Select.d.ts +11 -0
- 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/SharedElementTransition.d.ts +39 -0
- package/dist/SharedElementTransition.d.ts.map +1 -0
- package/dist/Slider.d.ts +6 -3
- package/dist/Slider.d.ts.map +1 -1
- package/dist/Table.d.ts +39 -0
- package/dist/Table.d.ts.map +1 -1
- package/dist/Tabs.d.ts +4 -3
- package/dist/Tabs.d.ts.map +1 -1
- package/dist/TagGroup.d.ts +12 -2
- 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 +4 -0
- package/dist/TextField.d.ts.map +1 -1
- package/dist/TimeField.d.ts +26 -1
- package/dist/TimeField.d.ts.map +1 -1
- package/dist/Toast.d.ts.map +1 -1
- package/dist/ToggleButton.d.ts +30 -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.map +1 -1
- package/dist/Tooltip.d.ts +9 -0
- package/dist/Tooltip.d.ts.map +1 -1
- package/dist/Tree.d.ts +44 -2
- 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 +3 -1
- package/dist/VisuallyHidden.d.ts.map +1 -1
- package/dist/contexts.d.ts +1 -0
- package/dist/contexts.d.ts.map +1 -1
- package/dist/index.d.ts +57 -25
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +13961 -5946
- package/dist/index.js.map +1 -7
- package/dist/index.ssr.js +9612 -2401
- package/dist/index.ssr.js.map +1 -7
- package/dist/useDragAndDrop.d.ts +93 -0
- package/dist/useDragAndDrop.d.ts.map +1 -0
- package/dist/utils.d.ts +7 -1
- 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 +8 -6
- package/src/ActionBar.tsx +248 -0
- package/src/ActionGroup.tsx +285 -0
- package/src/Alert.tsx +177 -0
- package/src/Autocomplete.tsx +1 -1
- package/src/Breadcrumbs.tsx +103 -17
- package/src/Button.tsx +65 -21
- package/src/Calendar.tsx +179 -53
- package/src/Checkbox.tsx +1 -2
- package/src/Collection.tsx +341 -0
- package/src/Color.tsx +652 -34
- package/src/ColorEditor.tsx +231 -0
- package/src/ComboBox.tsx +315 -81
- package/src/ContextualHelpTrigger.tsx +183 -0
- package/src/DateField.tsx +93 -19
- package/src/DatePicker.tsx +495 -25
- package/src/Dialog.tsx +40 -9
- package/src/Disclosure.tsx +33 -27
- package/src/DragAndDrop.tsx +334 -0
- package/src/DragPreview.tsx +45 -0
- package/src/DropZone.tsx +213 -0
- package/src/FieldError.tsx +67 -0
- package/src/FileTrigger.tsx +83 -0
- package/src/Focusable.tsx +106 -0
- package/src/Form.tsx +85 -0
- package/src/GridList.tsx +379 -41
- package/src/Icon.tsx +154 -0
- package/src/Keyboard.tsx +26 -0
- package/src/Link.tsx +14 -1
- package/src/ListBox.tsx +484 -33
- package/src/ListDropTargetDelegate.ts +282 -0
- package/src/Menu.tsx +388 -35
- package/src/Meter.tsx +7 -3
- package/src/Modal.tsx +32 -4
- package/src/NumberField.tsx +163 -43
- package/src/Popover.tsx +136 -180
- package/src/Pressable.tsx +108 -0
- package/src/ProgressBar.tsx +7 -3
- package/src/RadioGroup.tsx +35 -25
- package/src/RangeCalendar.tsx +100 -68
- package/src/RouterProvider.tsx +240 -0
- package/src/SearchField.tsx +142 -34
- package/src/Select.tsx +221 -73
- package/src/SelectionIndicator.tsx +105 -0
- package/src/SharedElementTransition.tsx +258 -0
- package/src/Slider.tsx +16 -6
- package/src/Table.tsx +417 -57
- package/src/Tabs.tsx +68 -35
- package/src/TagGroup.tsx +121 -36
- package/src/Text.tsx +18 -0
- package/src/TextField.tsx +25 -8
- package/src/TimeField.tsx +101 -151
- package/src/Toast.tsx +108 -14
- package/src/ToggleButton.tsx +159 -0
- package/src/ToggleButtonGroup.tsx +136 -0
- package/src/Toolbar.tsx +14 -8
- package/src/Tooltip.tsx +108 -19
- package/src/Tree.tsx +1143 -87
- package/src/Virtualizer.tsx +702 -0
- package/src/VirtualizerLayouts.ts +265 -0
- package/src/VisuallyHidden.tsx +15 -21
- package/src/contexts.ts +1 -0
- package/src/index.ts +1057 -620
- package/src/useDragAndDrop.ts +351 -0
- package/src/utils.tsx +37 -3
- package/src/virtualizer/Layout.ts +200 -0
package/src/DatePicker.tsx
CHANGED
|
@@ -8,25 +8,36 @@
|
|
|
8
8
|
import {
|
|
9
9
|
type JSX,
|
|
10
10
|
createContext,
|
|
11
|
+
createEffect,
|
|
11
12
|
createMemo,
|
|
12
13
|
createSignal,
|
|
13
14
|
splitProps,
|
|
14
15
|
useContext,
|
|
15
16
|
Show,
|
|
16
17
|
} from 'solid-js';
|
|
18
|
+
import { Portal } from 'solid-js/web';
|
|
17
19
|
import {
|
|
18
20
|
createDatePicker,
|
|
21
|
+
createDateRangePicker,
|
|
22
|
+
createPopover,
|
|
23
|
+
FocusScope,
|
|
24
|
+
useUNSAFE_PortalContext,
|
|
19
25
|
type AriaDatePickerProps,
|
|
26
|
+
type AriaDateRangePickerProps,
|
|
20
27
|
type DatePickerState as AriaDatePickerState,
|
|
21
28
|
} from '@proyecto-viviana/solidaria';
|
|
22
29
|
import {
|
|
23
30
|
createDateFieldState,
|
|
24
31
|
createCalendarState,
|
|
32
|
+
createRangeCalendarState,
|
|
25
33
|
type DateFieldState,
|
|
26
34
|
type CalendarState,
|
|
35
|
+
type RangeCalendarState,
|
|
27
36
|
type DateFieldStateProps,
|
|
28
37
|
type CalendarDate,
|
|
29
38
|
type DateValue,
|
|
39
|
+
type RangeCalendarStateProps,
|
|
40
|
+
type RangeValue,
|
|
30
41
|
} from '@proyecto-viviana/solid-stately';
|
|
31
42
|
import {
|
|
32
43
|
type RenderChildren,
|
|
@@ -38,6 +49,8 @@ import {
|
|
|
38
49
|
useIsHydrated,
|
|
39
50
|
} from './utils';
|
|
40
51
|
import { DateFieldContext } from './DateField';
|
|
52
|
+
import { CalendarContext } from './Calendar';
|
|
53
|
+
import { RangeCalendarContext } from './RangeCalendar';
|
|
41
54
|
|
|
42
55
|
// ============================================
|
|
43
56
|
// TYPES
|
|
@@ -56,6 +69,11 @@ export interface DatePickerRenderProps {
|
|
|
56
69
|
isOpen: boolean;
|
|
57
70
|
}
|
|
58
71
|
|
|
72
|
+
export interface DateRangePickerRenderProps
|
|
73
|
+
extends Omit<DatePickerRenderProps, 'isInvalid'> {
|
|
74
|
+
isInvalid: boolean;
|
|
75
|
+
}
|
|
76
|
+
|
|
59
77
|
export interface DatePickerContextValue {
|
|
60
78
|
fieldState: DateFieldState<DateValue>;
|
|
61
79
|
calendarState: CalendarState<DateValue>;
|
|
@@ -65,9 +83,24 @@ export interface DatePickerContextValue {
|
|
|
65
83
|
close: () => void;
|
|
66
84
|
toggle: () => void;
|
|
67
85
|
};
|
|
86
|
+
triggerRef: () => HTMLElement | null;
|
|
87
|
+
setTriggerRef: (element: HTMLElement | null) => void;
|
|
68
88
|
pickerAria: ReturnType<typeof createDatePicker>;
|
|
69
89
|
}
|
|
70
90
|
|
|
91
|
+
export interface DateRangePickerContextValue {
|
|
92
|
+
calendarState: RangeCalendarState<DateValue>;
|
|
93
|
+
overlayState: {
|
|
94
|
+
isOpen: boolean;
|
|
95
|
+
open: () => void;
|
|
96
|
+
close: () => void;
|
|
97
|
+
toggle: () => void;
|
|
98
|
+
};
|
|
99
|
+
triggerRef: () => HTMLElement | null;
|
|
100
|
+
setTriggerRef: (element: HTMLElement | null) => void;
|
|
101
|
+
pickerAria: ReturnType<typeof createDateRangePicker>;
|
|
102
|
+
}
|
|
103
|
+
|
|
71
104
|
export interface DatePickerProps<T extends DateValue = DateValue>
|
|
72
105
|
extends Omit<AriaDatePickerProps, 'id' | 'isDisabled' | 'isReadOnly' | 'isRequired'>,
|
|
73
106
|
Omit<DateFieldStateProps<T>, 'locale'>,
|
|
@@ -84,6 +117,17 @@ export interface DatePickerProps<T extends DateValue = DateValue>
|
|
|
84
117
|
shouldCloseOnSelect?: boolean;
|
|
85
118
|
}
|
|
86
119
|
|
|
120
|
+
export interface DateRangePickerProps<T extends DateValue = DateValue>
|
|
121
|
+
extends Omit<AriaDateRangePickerProps, 'id' | 'isDisabled' | 'isReadOnly'>,
|
|
122
|
+
Omit<RangeCalendarStateProps<T>, 'locale'>,
|
|
123
|
+
SlotProps {
|
|
124
|
+
children?: JSX.Element;
|
|
125
|
+
class?: ClassNameOrFunction<DateRangePickerRenderProps>;
|
|
126
|
+
style?: StyleOrFunction<DateRangePickerRenderProps>;
|
|
127
|
+
locale?: string;
|
|
128
|
+
shouldCloseOnSelect?: boolean;
|
|
129
|
+
}
|
|
130
|
+
|
|
87
131
|
export interface DatePickerButtonRenderProps {
|
|
88
132
|
/** Whether the button is disabled. */
|
|
89
133
|
isDisabled: boolean;
|
|
@@ -102,11 +146,16 @@ export interface DatePickerButtonProps extends SlotProps {
|
|
|
102
146
|
isDisabled?: boolean;
|
|
103
147
|
}
|
|
104
148
|
|
|
149
|
+
export interface DateRangePickerButtonProps extends DatePickerButtonProps {}
|
|
150
|
+
|
|
105
151
|
// ============================================
|
|
106
152
|
// CONTEXT
|
|
107
153
|
// ============================================
|
|
108
154
|
|
|
109
155
|
export const DatePickerContext = createContext<DatePickerContextValue | null>(null);
|
|
156
|
+
export const DateRangePickerContext = createContext<DateRangePickerContextValue | null>(null);
|
|
157
|
+
export const DatePickerStateContext = createContext<DateFieldState<DateValue> | null>(null);
|
|
158
|
+
export const DateRangePickerStateContext = createContext<RangeCalendarState<DateValue> | null>(null);
|
|
110
159
|
|
|
111
160
|
export function useDatePickerContext(): DatePickerContextValue {
|
|
112
161
|
const context = useContext(DatePickerContext);
|
|
@@ -116,6 +165,14 @@ export function useDatePickerContext(): DatePickerContextValue {
|
|
|
116
165
|
return context;
|
|
117
166
|
}
|
|
118
167
|
|
|
168
|
+
export function useDateRangePickerContext(): DateRangePickerContextValue {
|
|
169
|
+
const context = useContext(DateRangePickerContext);
|
|
170
|
+
if (!context) {
|
|
171
|
+
throw new Error('DateRangePicker components must be used within a DateRangePicker');
|
|
172
|
+
}
|
|
173
|
+
return context;
|
|
174
|
+
}
|
|
175
|
+
|
|
119
176
|
// ============================================
|
|
120
177
|
// DATE PICKER COMPONENT
|
|
121
178
|
// ============================================
|
|
@@ -192,6 +249,7 @@ function DatePickerInner<T extends DateValue = CalendarDate>(
|
|
|
192
249
|
|
|
193
250
|
// Create overlay trigger state
|
|
194
251
|
const [isOpen, setIsOpen] = createSignal(false);
|
|
252
|
+
let triggerRef: HTMLElement | null = null;
|
|
195
253
|
|
|
196
254
|
const overlayState = {
|
|
197
255
|
get isOpen() { return isOpen(); },
|
|
@@ -229,7 +287,11 @@ function DatePickerInner<T extends DateValue = CalendarDate>(
|
|
|
229
287
|
|
|
230
288
|
// Create date picker ARIA props
|
|
231
289
|
const pickerAria = createDatePicker(
|
|
232
|
-
|
|
290
|
+
() => ({
|
|
291
|
+
...(rest as Record<string, unknown>),
|
|
292
|
+
description: stateProps.description,
|
|
293
|
+
errorMessage: stateProps.errorMessage,
|
|
294
|
+
}),
|
|
233
295
|
fieldState as unknown as DateFieldState<DateValue>,
|
|
234
296
|
overlayState as AriaDatePickerState,
|
|
235
297
|
calendarState as unknown as CalendarState<DateValue>
|
|
@@ -240,15 +302,26 @@ function DatePickerInner<T extends DateValue = CalendarDate>(
|
|
|
240
302
|
fieldState: fieldState as unknown as DateFieldState<DateValue>,
|
|
241
303
|
calendarState: calendarState as unknown as CalendarState<DateValue>,
|
|
242
304
|
overlayState,
|
|
305
|
+
triggerRef: () => triggerRef,
|
|
306
|
+
setTriggerRef: (element) => {
|
|
307
|
+
if (!element) return;
|
|
308
|
+
if (!triggerRef || !triggerRef.isConnected) {
|
|
309
|
+
triggerRef = element;
|
|
310
|
+
}
|
|
311
|
+
},
|
|
243
312
|
pickerAria,
|
|
244
313
|
};
|
|
245
314
|
|
|
246
315
|
// Render props values
|
|
316
|
+
const isInvalid = createMemo(
|
|
317
|
+
() => fieldState.isInvalid() || Boolean((rest as { isInvalid?: boolean }).isInvalid)
|
|
318
|
+
);
|
|
319
|
+
|
|
247
320
|
const renderValues = createMemo<DatePickerRenderProps>(() => ({
|
|
248
321
|
isDisabled: fieldState.isDisabled(),
|
|
249
322
|
isReadOnly: fieldState.isReadOnly(),
|
|
250
323
|
isRequired: fieldState.isRequired(),
|
|
251
|
-
isInvalid:
|
|
324
|
+
isInvalid: isInvalid(),
|
|
252
325
|
isOpen: overlayState.isOpen,
|
|
253
326
|
}));
|
|
254
327
|
|
|
@@ -263,23 +336,163 @@ function DatePickerInner<T extends DateValue = CalendarDate>(
|
|
|
263
336
|
);
|
|
264
337
|
|
|
265
338
|
return (
|
|
266
|
-
<
|
|
267
|
-
{
|
|
268
|
-
|
|
269
|
-
<
|
|
270
|
-
{
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
339
|
+
<DatePickerStateContext.Provider value={fieldState as unknown as DateFieldState<DateValue>}>
|
|
340
|
+
<DatePickerContext.Provider value={contextValue}>
|
|
341
|
+
{/* Also provide DateFieldContext so DateInput/DateSegment work inside DatePicker */}
|
|
342
|
+
<DateFieldContext.Provider
|
|
343
|
+
value={{
|
|
344
|
+
state: fieldState as unknown as DateFieldState<DateValue>,
|
|
345
|
+
aria: {
|
|
346
|
+
labelProps: pickerAria.labelProps,
|
|
347
|
+
inputProps: pickerAria.fieldProps,
|
|
348
|
+
descriptionProps: pickerAria.descriptionProps,
|
|
349
|
+
errorMessageProps: pickerAria.errorMessageProps,
|
|
350
|
+
},
|
|
351
|
+
}}
|
|
278
352
|
>
|
|
279
|
-
{
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
353
|
+
<CalendarContext.Provider value={calendarState as unknown as CalendarState<DateValue>}>
|
|
354
|
+
<div
|
|
355
|
+
{...pickerAria.groupProps}
|
|
356
|
+
class={renderProps.class()}
|
|
357
|
+
style={renderProps.style()}
|
|
358
|
+
data-disabled={dataAttr(fieldState.isDisabled())}
|
|
359
|
+
data-readonly={dataAttr(fieldState.isReadOnly())}
|
|
360
|
+
data-required={dataAttr(fieldState.isRequired())}
|
|
361
|
+
data-invalid={dataAttr(isInvalid())}
|
|
362
|
+
data-open={dataAttr(overlayState.isOpen)}
|
|
363
|
+
>
|
|
364
|
+
{props.children}
|
|
365
|
+
</div>
|
|
366
|
+
</CalendarContext.Provider>
|
|
367
|
+
</DateFieldContext.Provider>
|
|
368
|
+
</DatePickerContext.Provider>
|
|
369
|
+
</DatePickerStateContext.Provider>
|
|
370
|
+
);
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
export function DateRangePicker<T extends DateValue = CalendarDate>(
|
|
374
|
+
props: DateRangePickerProps<T>
|
|
375
|
+
): JSX.Element {
|
|
376
|
+
const isHydrated = useIsHydrated();
|
|
377
|
+
return (
|
|
378
|
+
<Show
|
|
379
|
+
when={isHydrated()}
|
|
380
|
+
fallback={<div class="solidaria-DateRangePicker solidaria-DateRangePicker--placeholder" aria-hidden="true" />}
|
|
381
|
+
>
|
|
382
|
+
<DateRangePickerInner {...props} />
|
|
383
|
+
</Show>
|
|
384
|
+
);
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
function DateRangePickerInner<T extends DateValue = CalendarDate>(
|
|
388
|
+
props: DateRangePickerProps<T>
|
|
389
|
+
): JSX.Element {
|
|
390
|
+
const [local, stateProps, rest] = splitProps(
|
|
391
|
+
props,
|
|
392
|
+
['children', 'class', 'style', 'slot', 'shouldCloseOnSelect'],
|
|
393
|
+
[
|
|
394
|
+
'value',
|
|
395
|
+
'defaultValue',
|
|
396
|
+
'onChange',
|
|
397
|
+
'minValue',
|
|
398
|
+
'maxValue',
|
|
399
|
+
'isDisabled',
|
|
400
|
+
'isReadOnly',
|
|
401
|
+
'focusedValue',
|
|
402
|
+
'defaultFocusedValue',
|
|
403
|
+
'onFocusChange',
|
|
404
|
+
'locale',
|
|
405
|
+
'isDateUnavailable',
|
|
406
|
+
'visibleMonths',
|
|
407
|
+
'isDateDisabled',
|
|
408
|
+
'validationState',
|
|
409
|
+
'allowsNonContiguousRanges',
|
|
410
|
+
'firstDayOfWeek',
|
|
411
|
+
]
|
|
412
|
+
);
|
|
413
|
+
|
|
414
|
+
const [isOpen, setIsOpen] = createSignal(false);
|
|
415
|
+
let triggerRef: HTMLElement | null = null;
|
|
416
|
+
const overlayState = {
|
|
417
|
+
get isOpen() { return isOpen(); },
|
|
418
|
+
open: () => setIsOpen(true),
|
|
419
|
+
close: () => setIsOpen(false),
|
|
420
|
+
toggle: () => setIsOpen((prev) => !prev),
|
|
421
|
+
};
|
|
422
|
+
|
|
423
|
+
const calendarState = createRangeCalendarState({
|
|
424
|
+
...stateProps,
|
|
425
|
+
onChange: (value) => {
|
|
426
|
+
stateProps.onChange?.(value);
|
|
427
|
+
if (local.shouldCloseOnSelect !== false && value?.start && value?.end) {
|
|
428
|
+
overlayState.close();
|
|
429
|
+
}
|
|
430
|
+
},
|
|
431
|
+
});
|
|
432
|
+
const pickerAria = createDateRangePicker(
|
|
433
|
+
() => ({
|
|
434
|
+
...(rest as Record<string, unknown>),
|
|
435
|
+
description: (props as { description?: string }).description,
|
|
436
|
+
errorMessage: (props as { errorMessage?: string }).errorMessage,
|
|
437
|
+
}),
|
|
438
|
+
calendarState as unknown as RangeCalendarState<DateValue>,
|
|
439
|
+
overlayState as AriaDatePickerState
|
|
440
|
+
);
|
|
441
|
+
|
|
442
|
+
const isInvalid = createMemo(
|
|
443
|
+
() => Boolean((rest as { isInvalid?: boolean }).isInvalid) || calendarState.validationState() === 'invalid'
|
|
444
|
+
);
|
|
445
|
+
const isRequired = createMemo(
|
|
446
|
+
() => Boolean((rest as { isRequired?: boolean }).isRequired)
|
|
447
|
+
);
|
|
448
|
+
|
|
449
|
+
const contextValue: DateRangePickerContextValue = {
|
|
450
|
+
calendarState: calendarState as unknown as RangeCalendarState<DateValue>,
|
|
451
|
+
overlayState,
|
|
452
|
+
triggerRef: () => triggerRef,
|
|
453
|
+
setTriggerRef: (element) => {
|
|
454
|
+
if (!element) return;
|
|
455
|
+
if (!triggerRef || !triggerRef.isConnected) triggerRef = element;
|
|
456
|
+
},
|
|
457
|
+
pickerAria,
|
|
458
|
+
};
|
|
459
|
+
|
|
460
|
+
const renderValues = createMemo<DateRangePickerRenderProps>(() => ({
|
|
461
|
+
isDisabled: calendarState.isDisabled(),
|
|
462
|
+
isReadOnly: calendarState.isReadOnly(),
|
|
463
|
+
isRequired: isRequired(),
|
|
464
|
+
isInvalid: isInvalid(),
|
|
465
|
+
isOpen: overlayState.isOpen,
|
|
466
|
+
}));
|
|
467
|
+
|
|
468
|
+
const renderProps = useRenderProps(
|
|
469
|
+
{
|
|
470
|
+
class: local.class,
|
|
471
|
+
style: local.style,
|
|
472
|
+
defaultClassName: 'solidaria-DateRangePicker',
|
|
473
|
+
},
|
|
474
|
+
renderValues
|
|
475
|
+
);
|
|
476
|
+
|
|
477
|
+
return (
|
|
478
|
+
<DateRangePickerStateContext.Provider value={calendarState as unknown as RangeCalendarState<DateValue>}>
|
|
479
|
+
<DateRangePickerContext.Provider value={contextValue}>
|
|
480
|
+
<RangeCalendarContext.Provider value={calendarState as unknown as RangeCalendarState<DateValue>}>
|
|
481
|
+
<div
|
|
482
|
+
{...pickerAria.groupProps}
|
|
483
|
+
class={renderProps.class()}
|
|
484
|
+
style={renderProps.style()}
|
|
485
|
+
data-disabled={dataAttr(calendarState.isDisabled())}
|
|
486
|
+
data-readonly={dataAttr(calendarState.isReadOnly())}
|
|
487
|
+
data-required={dataAttr(isRequired())}
|
|
488
|
+
data-invalid={dataAttr(isInvalid())}
|
|
489
|
+
data-open={dataAttr(overlayState.isOpen)}
|
|
490
|
+
>
|
|
491
|
+
{props.children}
|
|
492
|
+
</div>
|
|
493
|
+
</RangeCalendarContext.Provider>
|
|
494
|
+
</DateRangePickerContext.Provider>
|
|
495
|
+
</DateRangePickerStateContext.Provider>
|
|
283
496
|
);
|
|
284
497
|
}
|
|
285
498
|
|
|
@@ -292,6 +505,7 @@ function DatePickerInner<T extends DateValue = CalendarDate>(
|
|
|
292
505
|
*/
|
|
293
506
|
export function DatePickerButton(props: DatePickerButtonProps): JSX.Element {
|
|
294
507
|
const context = useDatePickerContext();
|
|
508
|
+
let buttonRef: HTMLButtonElement | undefined;
|
|
295
509
|
|
|
296
510
|
// Render props values
|
|
297
511
|
const renderValues = createMemo<DatePickerButtonRenderProps>(() => ({
|
|
@@ -320,6 +534,10 @@ export function DatePickerButton(props: DatePickerButtonProps): JSX.Element {
|
|
|
320
534
|
|
|
321
535
|
return (
|
|
322
536
|
<button
|
|
537
|
+
ref={(el) => {
|
|
538
|
+
buttonRef = el;
|
|
539
|
+
context.setTriggerRef(el);
|
|
540
|
+
}}
|
|
323
541
|
{...context.pickerAria.buttonProps}
|
|
324
542
|
class={renderProps.class()}
|
|
325
543
|
style={renderProps.style()}
|
|
@@ -332,6 +550,46 @@ export function DatePickerButton(props: DatePickerButtonProps): JSX.Element {
|
|
|
332
550
|
);
|
|
333
551
|
}
|
|
334
552
|
|
|
553
|
+
export function DateRangePickerButton(props: DateRangePickerButtonProps): JSX.Element {
|
|
554
|
+
const context = useDateRangePickerContext();
|
|
555
|
+
|
|
556
|
+
const renderValues = createMemo<DatePickerButtonRenderProps>(() => ({
|
|
557
|
+
isDisabled: context.calendarState.isDisabled() || (props.isDisabled ?? false),
|
|
558
|
+
isOpen: context.overlayState.isOpen,
|
|
559
|
+
}));
|
|
560
|
+
|
|
561
|
+
const renderProps = useRenderProps(
|
|
562
|
+
{
|
|
563
|
+
children: props.children,
|
|
564
|
+
class: props.class,
|
|
565
|
+
style: props.style,
|
|
566
|
+
defaultClassName: 'solidaria-DateRangePickerButton',
|
|
567
|
+
},
|
|
568
|
+
renderValues
|
|
569
|
+
);
|
|
570
|
+
|
|
571
|
+
const getChildren = () => {
|
|
572
|
+
if (typeof props.children === 'function') {
|
|
573
|
+
return renderProps.renderChildren();
|
|
574
|
+
}
|
|
575
|
+
return props.children ?? '📅';
|
|
576
|
+
};
|
|
577
|
+
|
|
578
|
+
return (
|
|
579
|
+
<button
|
|
580
|
+
ref={(el) => context.setTriggerRef(el)}
|
|
581
|
+
{...context.pickerAria.buttonProps}
|
|
582
|
+
class={renderProps.class()}
|
|
583
|
+
style={renderProps.style()}
|
|
584
|
+
disabled={context.calendarState.isDisabled() || props.isDisabled}
|
|
585
|
+
data-disabled={dataAttr(context.calendarState.isDisabled() || props.isDisabled)}
|
|
586
|
+
data-open={dataAttr(context.overlayState.isOpen)}
|
|
587
|
+
>
|
|
588
|
+
{getChildren()}
|
|
589
|
+
</button>
|
|
590
|
+
);
|
|
591
|
+
}
|
|
592
|
+
|
|
335
593
|
// ============================================
|
|
336
594
|
// DATE PICKER CONTENT COMPONENT
|
|
337
595
|
// ============================================
|
|
@@ -345,21 +603,233 @@ export interface DatePickerContentProps extends SlotProps {
|
|
|
345
603
|
style?: JSX.CSSProperties;
|
|
346
604
|
}
|
|
347
605
|
|
|
606
|
+
export interface DateRangePickerContentProps extends DatePickerContentProps {}
|
|
607
|
+
|
|
608
|
+
export interface DatePickerLabelProps {
|
|
609
|
+
children?: JSX.Element;
|
|
610
|
+
class?: string;
|
|
611
|
+
}
|
|
612
|
+
|
|
613
|
+
export function DatePickerLabel(props: DatePickerLabelProps): JSX.Element {
|
|
614
|
+
const context = useDatePickerContext();
|
|
615
|
+
return (
|
|
616
|
+
<span {...context.pickerAria.labelProps} class={props.class}>
|
|
617
|
+
{props.children}
|
|
618
|
+
</span>
|
|
619
|
+
);
|
|
620
|
+
}
|
|
621
|
+
|
|
622
|
+
export interface DatePickerDescriptionProps {
|
|
623
|
+
children?: JSX.Element;
|
|
624
|
+
class?: string;
|
|
625
|
+
}
|
|
626
|
+
|
|
627
|
+
export function DatePickerDescription(props: DatePickerDescriptionProps): JSX.Element {
|
|
628
|
+
const context = useDatePickerContext();
|
|
629
|
+
return (
|
|
630
|
+
<p {...context.pickerAria.descriptionProps} class={props.class}>
|
|
631
|
+
{props.children}
|
|
632
|
+
</p>
|
|
633
|
+
);
|
|
634
|
+
}
|
|
635
|
+
|
|
636
|
+
export interface DatePickerErrorMessageProps {
|
|
637
|
+
children?: JSX.Element;
|
|
638
|
+
class?: string;
|
|
639
|
+
}
|
|
640
|
+
|
|
641
|
+
export function DatePickerErrorMessage(props: DatePickerErrorMessageProps): JSX.Element {
|
|
642
|
+
const context = useDatePickerContext();
|
|
643
|
+
return (
|
|
644
|
+
<p {...context.pickerAria.errorMessageProps} class={props.class}>
|
|
645
|
+
{props.children}
|
|
646
|
+
</p>
|
|
647
|
+
);
|
|
648
|
+
}
|
|
649
|
+
|
|
650
|
+
export interface DateRangePickerLabelProps {
|
|
651
|
+
children?: JSX.Element;
|
|
652
|
+
class?: string;
|
|
653
|
+
}
|
|
654
|
+
|
|
655
|
+
export function DateRangePickerLabel(props: DateRangePickerLabelProps): JSX.Element {
|
|
656
|
+
const context = useDateRangePickerContext();
|
|
657
|
+
return (
|
|
658
|
+
<span {...context.pickerAria.labelProps} class={props.class}>
|
|
659
|
+
{props.children}
|
|
660
|
+
</span>
|
|
661
|
+
);
|
|
662
|
+
}
|
|
663
|
+
|
|
664
|
+
export interface DateRangePickerDescriptionProps {
|
|
665
|
+
children?: JSX.Element;
|
|
666
|
+
class?: string;
|
|
667
|
+
}
|
|
668
|
+
|
|
669
|
+
export function DateRangePickerDescription(props: DateRangePickerDescriptionProps): JSX.Element {
|
|
670
|
+
const context = useDateRangePickerContext();
|
|
671
|
+
return (
|
|
672
|
+
<p {...context.pickerAria.descriptionProps} class={props.class}>
|
|
673
|
+
{props.children}
|
|
674
|
+
</p>
|
|
675
|
+
);
|
|
676
|
+
}
|
|
677
|
+
|
|
678
|
+
export interface DateRangePickerErrorMessageProps {
|
|
679
|
+
children?: JSX.Element;
|
|
680
|
+
class?: string;
|
|
681
|
+
}
|
|
682
|
+
|
|
683
|
+
export function DateRangePickerErrorMessage(props: DateRangePickerErrorMessageProps): JSX.Element {
|
|
684
|
+
const context = useDateRangePickerContext();
|
|
685
|
+
return (
|
|
686
|
+
<p {...context.pickerAria.errorMessageProps} class={props.class}>
|
|
687
|
+
{props.children}
|
|
688
|
+
</p>
|
|
689
|
+
);
|
|
690
|
+
}
|
|
691
|
+
|
|
348
692
|
/**
|
|
349
693
|
* The content area of the date picker (typically contains a Calendar).
|
|
350
694
|
*/
|
|
351
695
|
export function DatePickerContent(props: DatePickerContentProps): JSX.Element {
|
|
352
696
|
const context = useDatePickerContext();
|
|
697
|
+
const portalContext = useUNSAFE_PortalContext();
|
|
698
|
+
let contentRef: HTMLDivElement | undefined;
|
|
699
|
+
const portalContainer = () => portalContext.getContainer?.() ?? undefined;
|
|
700
|
+
|
|
701
|
+
const popoverAria = createPopover(
|
|
702
|
+
{
|
|
703
|
+
triggerRef: context.triggerRef,
|
|
704
|
+
popoverRef: () => contentRef ?? null,
|
|
705
|
+
placement: 'bottom start',
|
|
706
|
+
offset: 8,
|
|
707
|
+
isNonModal: false,
|
|
708
|
+
isKeyboardDismissDisabled: false,
|
|
709
|
+
},
|
|
710
|
+
{
|
|
711
|
+
isOpen: () => context.overlayState.isOpen,
|
|
712
|
+
open: context.overlayState.open,
|
|
713
|
+
close: context.overlayState.close,
|
|
714
|
+
toggle: context.overlayState.toggle,
|
|
715
|
+
}
|
|
716
|
+
);
|
|
717
|
+
|
|
718
|
+
const cleanPopoverProps = () => {
|
|
719
|
+
const { style: _style, ref: _ref, ...rest } = popoverAria.popoverProps as Record<string, unknown>;
|
|
720
|
+
return rest;
|
|
721
|
+
};
|
|
722
|
+
|
|
723
|
+
const mergedStyle = (): JSX.CSSProperties => {
|
|
724
|
+
const popoverStyle = (popoverAria.popoverProps as Record<string, unknown>).style as JSX.CSSProperties | undefined;
|
|
725
|
+
return {
|
|
726
|
+
...(popoverStyle ?? {}),
|
|
727
|
+
...(props.style ?? {}),
|
|
728
|
+
};
|
|
729
|
+
};
|
|
730
|
+
|
|
731
|
+
createEffect(() => {
|
|
732
|
+
if (!context.overlayState.isOpen || !contentRef) return;
|
|
733
|
+
if (document.activeElement !== contentRef) {
|
|
734
|
+
contentRef.focus();
|
|
735
|
+
}
|
|
736
|
+
});
|
|
737
|
+
|
|
738
|
+
return (
|
|
739
|
+
<Show when={context.overlayState.isOpen}>
|
|
740
|
+
<Portal mount={portalContainer()}>
|
|
741
|
+
<FocusScope contain restoreFocus autoFocus>
|
|
742
|
+
<div
|
|
743
|
+
ref={contentRef}
|
|
744
|
+
{...cleanPopoverProps()}
|
|
745
|
+
{...context.pickerAria.dialogProps}
|
|
746
|
+
tabIndex={-1}
|
|
747
|
+
class={props.class ?? 'solidaria-DatePickerContent'}
|
|
748
|
+
style={mergedStyle()}
|
|
749
|
+
data-placement={popoverAria.placement() ?? undefined}
|
|
750
|
+
onKeyDown={(event) => {
|
|
751
|
+
if (event.key === 'Escape') {
|
|
752
|
+
event.preventDefault();
|
|
753
|
+
event.stopPropagation();
|
|
754
|
+
context.overlayState.close();
|
|
755
|
+
}
|
|
756
|
+
}}
|
|
757
|
+
>
|
|
758
|
+
{props.children}
|
|
759
|
+
</div>
|
|
760
|
+
</FocusScope>
|
|
761
|
+
</Portal>
|
|
762
|
+
</Show>
|
|
763
|
+
);
|
|
764
|
+
}
|
|
765
|
+
|
|
766
|
+
export function DateRangePickerContent(props: DateRangePickerContentProps): JSX.Element {
|
|
767
|
+
const context = useDateRangePickerContext();
|
|
768
|
+
const portalContext = useUNSAFE_PortalContext();
|
|
769
|
+
let contentRef: HTMLDivElement | undefined;
|
|
770
|
+
const portalContainer = () => portalContext.getContainer?.() ?? undefined;
|
|
771
|
+
|
|
772
|
+
const popoverAria = createPopover(
|
|
773
|
+
{
|
|
774
|
+
triggerRef: context.triggerRef,
|
|
775
|
+
popoverRef: () => contentRef ?? null,
|
|
776
|
+
placement: 'bottom start',
|
|
777
|
+
offset: 8,
|
|
778
|
+
isNonModal: false,
|
|
779
|
+
isKeyboardDismissDisabled: false,
|
|
780
|
+
},
|
|
781
|
+
{
|
|
782
|
+
isOpen: () => context.overlayState.isOpen,
|
|
783
|
+
open: context.overlayState.open,
|
|
784
|
+
close: context.overlayState.close,
|
|
785
|
+
toggle: context.overlayState.toggle,
|
|
786
|
+
}
|
|
787
|
+
);
|
|
788
|
+
|
|
789
|
+
const cleanPopoverProps = () => {
|
|
790
|
+
const { style: _style, ref: _ref, ...rest } = popoverAria.popoverProps as Record<string, unknown>;
|
|
791
|
+
return rest;
|
|
792
|
+
};
|
|
793
|
+
|
|
794
|
+
const mergedStyle = (): JSX.CSSProperties => {
|
|
795
|
+
const popoverStyle = (popoverAria.popoverProps as Record<string, unknown>).style as JSX.CSSProperties | undefined;
|
|
796
|
+
return {
|
|
797
|
+
...(popoverStyle ?? {}),
|
|
798
|
+
...(props.style ?? {}),
|
|
799
|
+
};
|
|
800
|
+
};
|
|
801
|
+
|
|
802
|
+
createEffect(() => {
|
|
803
|
+
if (!context.overlayState.isOpen || !contentRef) return;
|
|
804
|
+
if (document.activeElement !== contentRef) {
|
|
805
|
+
contentRef.focus();
|
|
806
|
+
}
|
|
807
|
+
});
|
|
353
808
|
|
|
354
809
|
return (
|
|
355
810
|
<Show when={context.overlayState.isOpen}>
|
|
356
|
-
<
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
811
|
+
<Portal mount={portalContainer()}>
|
|
812
|
+
<FocusScope contain restoreFocus autoFocus>
|
|
813
|
+
<div
|
|
814
|
+
ref={contentRef}
|
|
815
|
+
{...cleanPopoverProps()}
|
|
816
|
+
{...context.pickerAria.dialogProps}
|
|
817
|
+
tabIndex={-1}
|
|
818
|
+
class={props.class ?? 'solidaria-DateRangePickerContent'}
|
|
819
|
+
style={mergedStyle()}
|
|
820
|
+
data-placement={popoverAria.placement() ?? undefined}
|
|
821
|
+
onKeyDown={(event) => {
|
|
822
|
+
if (event.key === 'Escape') {
|
|
823
|
+
event.preventDefault();
|
|
824
|
+
event.stopPropagation();
|
|
825
|
+
context.overlayState.close();
|
|
826
|
+
}
|
|
827
|
+
}}
|
|
828
|
+
>
|
|
829
|
+
{props.children}
|
|
830
|
+
</div>
|
|
831
|
+
</FocusScope>
|
|
832
|
+
</Portal>
|
|
363
833
|
</Show>
|
|
364
834
|
);
|
|
365
835
|
}
|