@proyecto-viviana/solid-stately 0.2.4 → 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 +30 -283
- package/dist/autocomplete/createAutocompleteState.d.ts +3 -2
- package/dist/autocomplete/index.d.ts +1 -1
- package/dist/calendar/createCalendarState.d.ts +22 -7
- package/dist/calendar/createDateFieldState.d.ts +30 -7
- package/dist/calendar/createDatePickerState.d.ts +60 -0
- package/dist/calendar/createRangeCalendarState.d.ts +27 -8
- package/dist/calendar/createTimeFieldState.d.ts +34 -7
- package/dist/calendar/index.d.ts +7 -6
- package/dist/checkbox/createCheckboxGroupState.d.ts +12 -3
- package/dist/checkbox/index.d.ts +1 -1
- package/dist/collections/ListCollection.d.ts +1 -1
- package/dist/collections/createListState.d.ts +8 -8
- package/dist/collections/createMenuState.d.ts +7 -7
- package/dist/collections/createSelectionState.d.ts +5 -5
- package/dist/collections/index.d.ts +5 -5
- package/dist/collections/types.d.ts +23 -12
- package/dist/color/Color.d.ts +1 -1
- package/dist/color/createColorAreaState.d.ts +4 -2
- package/dist/color/createColorFieldState.d.ts +38 -12
- package/dist/color/createColorSliderState.d.ts +9 -2
- package/dist/color/createColorWheelState.d.ts +13 -2
- package/dist/color/getColorChannels.d.ts +20 -0
- package/dist/color/index.d.ts +6 -6
- package/dist/color/types.d.ts +4 -4
- package/dist/combobox/createComboBoxState.d.ts +27 -13
- package/dist/combobox/index.d.ts +1 -1
- package/dist/data/createAsyncList.d.ts +111 -0
- package/dist/data/createListData.d.ts +65 -0
- package/dist/data/createTreeData.d.ts +65 -0
- package/dist/data/index.d.ts +3 -0
- package/dist/datepicker/index.d.ts +8 -0
- package/dist/disclosure/createDisclosureState.d.ts +2 -2
- package/dist/disclosure/index.d.ts +1 -1
- package/dist/dnd/createDragState.d.ts +2 -2
- package/dist/dnd/createDraggableCollectionState.d.ts +2 -2
- package/dist/dnd/createDropState.d.ts +2 -2
- package/dist/dnd/createDroppableCollectionState.d.ts +3 -3
- package/dist/dnd/index.d.ts +5 -5
- package/dist/dnd/types.d.ts +16 -16
- package/dist/form/createFormValidationState.d.ts +3 -3
- package/dist/form/index.d.ts +1 -1
- package/dist/grid/createGridState.d.ts +2 -2
- package/dist/grid/index.d.ts +2 -2
- package/dist/grid/types.d.ts +17 -11
- package/dist/index.d.ts +31 -25
- package/dist/index.js +7990 -6264
- package/dist/index.js.map +1 -7
- package/dist/menu/index.d.ts +8 -0
- package/dist/numberfield/createNumberFieldState.d.ts +2 -2
- package/dist/numberfield/index.d.ts +1 -1
- package/dist/overlays/createOverlayTriggerState.d.ts +2 -2
- package/dist/overlays/index.d.ts +1 -1
- package/dist/radio/createRadioGroupState.d.ts +13 -4
- package/dist/radio/index.d.ts +1 -1
- package/dist/searchfield/createSearchFieldState.d.ts +2 -2
- package/dist/searchfield/index.d.ts +2 -2
- package/dist/select/createSelectState.d.ts +20 -3
- package/dist/select/index.d.ts +1 -1
- package/dist/selection/index.d.ts +11 -0
- package/dist/slider/createSliderState.d.ts +3 -3
- package/dist/slider/index.d.ts +2 -2
- package/dist/steplist/createStepListState.d.ts +48 -0
- package/dist/steplist/index.d.ts +1 -0
- package/dist/table/TableCollection.d.ts +3 -3
- package/dist/table/createTableColumnResizeState.d.ts +54 -0
- package/dist/table/createTableState.d.ts +2 -2
- package/dist/table/index.d.ts +5 -3
- package/dist/table/types.d.ts +10 -10
- package/dist/tabs/createTabListState.d.ts +5 -5
- package/dist/tabs/index.d.ts +1 -1
- package/dist/textfield/createTextFieldState.d.ts +2 -2
- package/dist/textfield/index.d.ts +1 -1
- package/dist/toast/createToastState.d.ts +15 -3
- package/dist/toast/index.d.ts +1 -1
- package/dist/toggle/createToggleGroupState.d.ts +45 -0
- package/dist/toggle/createToggleState.d.ts +2 -2
- package/dist/toggle/index.d.ts +2 -1
- package/dist/tooltip/createTooltipTriggerState.d.ts +2 -2
- package/dist/tooltip/index.d.ts +1 -1
- package/dist/tree/TreeCollection.d.ts +5 -4
- package/dist/tree/createTreeState.d.ts +2 -2
- package/dist/tree/index.d.ts +3 -3
- package/dist/tree/types.d.ts +19 -13
- package/dist/utils/index.d.ts +1 -1
- package/dist/utils/reactivity.d.ts +1 -1
- package/package.json +30 -30
- package/src/autocomplete/createAutocompleteState.d.ts +19 -17
- package/src/autocomplete/createAutocompleteState.ts +25 -32
- package/src/autocomplete/index.d.ts +6 -2
- package/src/autocomplete/index.ts +1 -1
- package/src/calendar/createCalendarState.d.ts +139 -117
- package/src/calendar/createCalendarState.ts +221 -74
- package/src/calendar/createDateFieldState.d.ts +130 -95
- package/src/calendar/createDateFieldState.ts +286 -151
- package/src/calendar/createDatePickerState.ts +347 -0
- package/src/calendar/createRangeCalendarState.d.ts +154 -129
- package/src/calendar/createRangeCalendarState.ts +293 -79
- package/src/calendar/createTimeFieldState.d.ts +81 -79
- package/src/calendar/createTimeFieldState.ts +187 -108
- package/src/calendar/index.d.ts +80 -7
- package/src/calendar/index.ts +21 -12
- package/src/checkbox/createCheckboxGroupState.d.ts +57 -55
- package/src/checkbox/createCheckboxGroupState.ts +57 -30
- package/src/checkbox/index.d.ts +6 -2
- package/src/checkbox/index.ts +1 -1
- package/src/collections/ListCollection.d.ts +25 -22
- package/src/collections/ListCollection.ts +152 -146
- package/src/collections/createListState.d.ts +73 -58
- package/src/collections/createListState.ts +267 -264
- package/src/collections/createMenuState.d.ts +36 -31
- package/src/collections/createMenuState.ts +112 -106
- package/src/collections/createSelectionState.d.ts +78 -65
- package/src/collections/createSelectionState.ts +340 -336
- package/src/collections/index.d.ts +38 -6
- package/src/collections/index.ts +41 -46
- package/src/collections/types.d.ts +101 -101
- package/src/collections/types.ts +181 -169
- package/src/color/Color.d.ts +20 -5
- package/src/color/Color.ts +1054 -951
- package/src/color/createColorAreaState.d.ts +67 -65
- package/src/color/createColorAreaState.ts +301 -293
- package/src/color/createColorFieldState.d.ts +46 -44
- package/src/color/createColorFieldState.ts +428 -292
- package/src/color/createColorSliderState.d.ts +58 -56
- package/src/color/createColorSliderState.ts +272 -241
- package/src/color/createColorWheelState.d.ts +42 -40
- package/src/color/createColorWheelState.ts +248 -211
- package/src/color/getColorChannels.ts +36 -0
- package/src/color/index.d.ts +36 -7
- package/src/color/index.ts +44 -47
- package/src/color/types.d.ts +68 -63
- package/src/color/types.ts +119 -127
- package/src/combobox/createComboBoxState.d.ts +107 -105
- package/src/combobox/createComboBoxState.ts +790 -703
- package/src/combobox/index.d.ts +10 -2
- package/src/combobox/index.ts +13 -13
- package/src/data/createAsyncList.ts +403 -0
- package/src/data/createListData.ts +298 -0
- package/src/data/createTreeData.ts +646 -0
- package/src/data/index.ts +25 -0
- package/src/datepicker/index.ts +32 -0
- package/src/disclosure/createDisclosureState.d.ts +47 -43
- package/src/disclosure/createDisclosureState.ts +9 -23
- package/src/disclosure/index.d.ts +10 -2
- package/src/disclosure/index.ts +1 -1
- package/src/dnd/createDragState.d.ts +51 -42
- package/src/dnd/createDragState.ts +151 -153
- package/src/dnd/createDraggableCollectionState.d.ts +52 -41
- package/src/dnd/createDraggableCollectionState.ts +158 -165
- package/src/dnd/createDropState.d.ts +64 -45
- package/src/dnd/createDropState.ts +202 -212
- package/src/dnd/createDroppableCollectionState.d.ts +88 -59
- package/src/dnd/createDroppableCollectionState.ts +354 -357
- package/src/dnd/index.d.ts +54 -6
- package/src/dnd/index.ts +63 -76
- package/src/dnd/types.d.ts +167 -156
- package/src/dnd/types.ts +316 -317
- package/src/form/createFormValidationState.d.ts +47 -45
- package/src/form/createFormValidationState.ts +356 -389
- package/src/form/index.d.ts +16 -2
- package/src/form/index.ts +15 -15
- package/src/grid/createGridState.d.ts +7 -4
- package/src/grid/createGridState.ts +44 -51
- package/src/grid/index.d.ts +3 -3
- package/src/grid/index.ts +2 -8
- package/src/grid/types.d.ts +136 -129
- package/src/grid/types.ts +24 -17
- package/src/index.d.ts +310 -26
- package/src/index.ts +87 -79
- package/src/menu/index.ts +17 -0
- package/src/numberfield/createNumberFieldState.d.ts +56 -54
- package/src/numberfield/createNumberFieldState.ts +422 -383
- package/src/numberfield/index.d.ts +6 -2
- package/src/numberfield/index.ts +5 -5
- package/src/overlays/createOverlayTriggerState.d.ts +22 -20
- package/src/overlays/createOverlayTriggerState.ts +66 -67
- package/src/overlays/index.d.ts +6 -2
- package/src/overlays/index.ts +5 -5
- package/src/radio/createRadioGroupState.d.ts +54 -52
- package/src/radio/createRadioGroupState.ts +66 -30
- package/src/radio/index.d.ts +7 -2
- package/src/radio/index.ts +1 -1
- package/src/searchfield/createSearchFieldState.d.ts +16 -14
- package/src/searchfield/createSearchFieldState.ts +56 -62
- package/src/searchfield/index.d.ts +3 -3
- package/src/searchfield/index.ts +2 -5
- package/src/select/createSelectState.d.ts +63 -61
- package/src/select/createSelectState.ts +290 -181
- package/src/select/index.d.ts +2 -2
- package/src/select/index.ts +1 -5
- package/src/selection/index.ts +27 -0
- package/src/slider/createSliderState.d.ts +60 -60
- package/src/slider/createSliderState.ts +233 -211
- package/src/slider/index.d.ts +3 -3
- package/src/slider/index.ts +2 -6
- package/src/ssr/index.d.ts +1 -1
- package/src/ssr/index.ts +2 -2
- package/src/steplist/createStepListState.ts +191 -0
- package/src/steplist/index.ts +5 -0
- package/src/table/TableCollection.d.ts +42 -40
- package/src/table/TableCollection.ts +61 -64
- package/src/table/createTableColumnResizeState.ts +242 -0
- package/src/table/createTableState.d.ts +7 -4
- package/src/table/createTableState.ts +10 -7
- package/src/table/index.d.ts +14 -4
- package/src/table/index.ts +10 -3
- package/src/table/types.d.ts +98 -92
- package/src/table/types.ts +17 -13
- package/src/tabs/createTabListState.d.ts +59 -57
- package/src/tabs/createTabListState.ts +58 -39
- package/src/tabs/index.d.ts +8 -2
- package/src/tabs/index.ts +1 -1
- package/src/textfield/createTextFieldState.d.ts +16 -14
- package/src/textfield/createTextFieldState.ts +7 -18
- package/src/textfield/index.d.ts +6 -2
- package/src/textfield/index.ts +1 -1
- package/src/toast/createToastState.d.ts +92 -81
- package/src/toast/createToastState.ts +56 -44
- package/src/toast/index.d.ts +12 -2
- package/src/toast/index.ts +1 -1
- package/src/toggle/createToggleGroupState.ts +117 -0
- package/src/toggle/createToggleState.d.ts +19 -19
- package/src/toggle/createToggleState.ts +2 -16
- package/src/toggle/index.d.ts +2 -2
- package/src/toggle/index.ts +6 -4
- package/src/tooltip/createTooltipTriggerState.d.ts +17 -17
- package/src/tooltip/createTooltipTriggerState.ts +184 -183
- package/src/tooltip/index.d.ts +7 -2
- package/src/tooltip/index.ts +6 -6
- package/src/tree/TreeCollection.d.ts +26 -23
- package/src/tree/TreeCollection.ts +215 -175
- package/src/tree/createTreeState.d.ts +7 -4
- package/src/tree/createTreeState.ts +390 -392
- package/src/tree/index.d.ts +10 -4
- package/src/tree/index.ts +13 -13
- package/src/tree/types.d.ts +131 -126
- package/src/tree/types.ts +183 -174
- package/src/utils/index.d.ts +2 -2
- package/src/utils/index.ts +1 -1
- package/src/utils/reactivity.d.ts +2 -2
- package/src/utils/reactivity.ts +3 -3
|
@@ -5,28 +5,33 @@
|
|
|
5
5
|
* Based on @react-stately/calendar useRangeCalendarState
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
import { createSignal, createMemo, type Accessor } from
|
|
8
|
+
import { createSignal, createMemo, createEffect, type Accessor } from "solid-js";
|
|
9
9
|
import {
|
|
10
|
+
type Calendar as InternationalizedCalendar,
|
|
10
11
|
type CalendarDate,
|
|
12
|
+
type CalendarIdentifier,
|
|
11
13
|
type DateValue,
|
|
14
|
+
GregorianCalendar,
|
|
12
15
|
today,
|
|
13
16
|
getLocalTimeZone,
|
|
17
|
+
isEqualCalendar,
|
|
14
18
|
isSameDay,
|
|
15
19
|
isSameMonth,
|
|
16
20
|
startOfMonth,
|
|
17
21
|
endOfMonth,
|
|
18
22
|
startOfWeek,
|
|
19
23
|
getWeeksInMonth,
|
|
20
|
-
getDayOfWeek,
|
|
21
24
|
DateFormatter,
|
|
25
|
+
createCalendar as intlCreateCalendar,
|
|
26
|
+
toCalendar as intlToCalendar,
|
|
22
27
|
toCalendarDate as intlToCalendarDate,
|
|
23
|
-
} from
|
|
24
|
-
import { access, type MaybeAccessor } from
|
|
25
|
-
import type { ValidationState } from
|
|
28
|
+
} from "@internationalized/date";
|
|
29
|
+
import { access, type MaybeAccessor } from "../utils";
|
|
30
|
+
import type { CalendarDayOfWeek, ValidationState } from "./createCalendarState";
|
|
26
31
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
32
|
+
const dayOfWeekNames: CalendarDayOfWeek[] = ["sun", "mon", "tue", "wed", "thu", "fri", "sat"];
|
|
33
|
+
type RangeCalendarSelectionAlignment = "start" | "center" | "end";
|
|
34
|
+
type RangeCalendarPageBehavior = "single" | "visible";
|
|
30
35
|
|
|
31
36
|
export interface DateRange {
|
|
32
37
|
start: CalendarDate;
|
|
@@ -44,7 +49,7 @@ export interface RangeCalendarStateProps<T extends DateValue = DateValue> {
|
|
|
44
49
|
/** The default value (uncontrolled). */
|
|
45
50
|
defaultValue?: RangeValue<T> | null;
|
|
46
51
|
/** Handler called when the value changes. */
|
|
47
|
-
onChange?: (value: RangeValue<T>) => void;
|
|
52
|
+
onChange?: (value: RangeValue<T> | null) => void;
|
|
48
53
|
/** The minimum allowed date. */
|
|
49
54
|
minValue?: MaybeAccessor<DateValue | undefined>;
|
|
50
55
|
/** The maximum allowed date. */
|
|
@@ -54,17 +59,23 @@ export interface RangeCalendarStateProps<T extends DateValue = DateValue> {
|
|
|
54
59
|
/** Whether the calendar is read-only. */
|
|
55
60
|
isReadOnly?: MaybeAccessor<boolean>;
|
|
56
61
|
/** The date that is focused when the calendar first mounts. */
|
|
57
|
-
focusedValue?: MaybeAccessor<DateValue | undefined>;
|
|
62
|
+
focusedValue?: MaybeAccessor<DateValue | null | undefined>;
|
|
58
63
|
/** The default focused date (uncontrolled). */
|
|
59
64
|
defaultFocusedValue?: DateValue;
|
|
60
65
|
/** Handler called when the focused date changes. */
|
|
61
66
|
onFocusChange?: (date: CalendarDate) => void;
|
|
62
67
|
/** The locale to use for formatting. */
|
|
63
|
-
locale?: string
|
|
68
|
+
locale?: MaybeAccessor<string | undefined>;
|
|
69
|
+
/** Creates a calendar object for a locale calendar identifier. */
|
|
70
|
+
createCalendar?: (identifier: CalendarIdentifier) => InternationalizedCalendar;
|
|
64
71
|
/** Callback to determine if a date is unavailable. */
|
|
65
72
|
isDateUnavailable?: (date: DateValue) => boolean;
|
|
66
73
|
/** The number of months to display at once. */
|
|
67
|
-
visibleMonths?: number
|
|
74
|
+
visibleMonths?: MaybeAccessor<number | undefined>;
|
|
75
|
+
/** Controls how the initial visible months are aligned around the current value. */
|
|
76
|
+
selectionAlignment?: MaybeAccessor<RangeCalendarSelectionAlignment | undefined>;
|
|
77
|
+
/** Controls whether pagination moves by one month or the visible month count. */
|
|
78
|
+
pageBehavior?: MaybeAccessor<RangeCalendarPageBehavior | undefined>;
|
|
68
79
|
/** Controls which days are disabled. */
|
|
69
80
|
isDateDisabled?: (date: DateValue) => boolean;
|
|
70
81
|
/** Validation state. */
|
|
@@ -98,8 +109,14 @@ export interface RangeCalendarState<T extends DateValue = DateValue> {
|
|
|
98
109
|
visibleRange: Accessor<{ start: CalendarDate; end: CalendarDate }>;
|
|
99
110
|
/** The timezone used for date calculations. */
|
|
100
111
|
timeZone: string;
|
|
112
|
+
/** The locale used for formatting and locale-specific week starts. */
|
|
113
|
+
locale: Accessor<string>;
|
|
114
|
+
/** The explicitly requested first weekday, or undefined for the locale default. */
|
|
115
|
+
firstDayOfWeek: Accessor<CalendarDayOfWeek | undefined>;
|
|
101
116
|
/** The validation state. */
|
|
102
117
|
validationState: Accessor<ValidationState | undefined>;
|
|
118
|
+
/** Whether the current value is invalid according to validation state. */
|
|
119
|
+
isValueInvalid: Accessor<boolean>;
|
|
103
120
|
/** Whether a date is within the selected range. */
|
|
104
121
|
isSelected: (date: DateValue) => boolean;
|
|
105
122
|
/** Whether a date is the start of the selection. */
|
|
@@ -124,6 +141,10 @@ export interface RangeCalendarState<T extends DateValue = DateValue> {
|
|
|
124
141
|
focusPreviousSection: () => void;
|
|
125
142
|
/** Moves focus to the next section (year). */
|
|
126
143
|
focusNextSection: () => void;
|
|
144
|
+
/** Whether the previous visible range would be outside the allowed date range. */
|
|
145
|
+
isPreviousVisibleRangeInvalid: () => boolean;
|
|
146
|
+
/** Whether the next visible range would be outside the allowed date range. */
|
|
147
|
+
isNextVisibleRangeInvalid: () => boolean;
|
|
127
148
|
/** Moves focus to the previous day. */
|
|
128
149
|
focusPreviousDay: () => void;
|
|
129
150
|
/** Moves focus to the next day. */
|
|
@@ -160,60 +181,170 @@ export interface RangeCalendarState<T extends DateValue = DateValue> {
|
|
|
160
181
|
setDragging: (dragging: boolean) => void;
|
|
161
182
|
}
|
|
162
183
|
|
|
163
|
-
// ============================================
|
|
164
|
-
// IMPLEMENTATION
|
|
165
|
-
// ============================================
|
|
166
|
-
|
|
167
184
|
/**
|
|
168
185
|
* Provides state management for a range calendar component.
|
|
169
186
|
*/
|
|
170
187
|
export function createRangeCalendarState<T extends DateValue = CalendarDate>(
|
|
171
|
-
props: RangeCalendarStateProps<T> = {}
|
|
188
|
+
props: RangeCalendarStateProps<T> = {},
|
|
172
189
|
): RangeCalendarState<T> {
|
|
173
190
|
const timeZone = getLocalTimeZone();
|
|
174
|
-
const locale = props.locale ??
|
|
175
|
-
const
|
|
191
|
+
const locale = createMemo(() => access(props.locale) ?? "en-US");
|
|
192
|
+
const resolvedOptions = createMemo(() => new DateFormatter(locale()).resolvedOptions());
|
|
193
|
+
const calendar = createMemo(() =>
|
|
194
|
+
(props.createCalendar ?? intlCreateCalendar)(resolvedOptions().calendar as CalendarIdentifier),
|
|
195
|
+
);
|
|
196
|
+
const visibleMonths = Math.max(1, Number(access(props.visibleMonths) ?? 1));
|
|
197
|
+
const firstDayOfWeekName = (): CalendarDayOfWeek | undefined =>
|
|
198
|
+
props.firstDayOfWeek == null ? undefined : dayOfWeekNames[props.firstDayOfWeek];
|
|
199
|
+
|
|
200
|
+
const toDisplayCalendarDate = (date: DateValue): CalendarDate =>
|
|
201
|
+
intlToCalendar(toCalendarDate(date), calendar());
|
|
202
|
+
|
|
203
|
+
const constrainDate = (date: CalendarDate): CalendarDate => {
|
|
204
|
+
const minValue = access(props.minValue);
|
|
205
|
+
const maxValue = access(props.maxValue);
|
|
206
|
+
|
|
207
|
+
let constrained = date;
|
|
208
|
+
|
|
209
|
+
if (minValue && constrained.compare(toDisplayCalendarDate(minValue)) < 0) {
|
|
210
|
+
constrained = toDisplayCalendarDate(minValue);
|
|
211
|
+
}
|
|
212
|
+
if (maxValue && constrained.compare(toDisplayCalendarDate(maxValue)) > 0) {
|
|
213
|
+
constrained = toDisplayCalendarDate(maxValue);
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
return constrained;
|
|
217
|
+
};
|
|
218
|
+
|
|
219
|
+
const visibleRangeEndFromStart = (start: CalendarDate): CalendarDate => {
|
|
220
|
+
let end = endOfMonth(start);
|
|
221
|
+
|
|
222
|
+
for (let i = 1; i < visibleMonths; i++) {
|
|
223
|
+
end = endOfMonth(end.add({ months: 1 }));
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
return end;
|
|
227
|
+
};
|
|
228
|
+
|
|
229
|
+
const rawAlignStart = (date: CalendarDate): CalendarDate => startOfMonth(date);
|
|
230
|
+
|
|
231
|
+
const rawAlignEnd = (date: CalendarDate): CalendarDate =>
|
|
232
|
+
startOfMonth(date).subtract({ months: Math.max(visibleMonths - 1, 0) });
|
|
233
|
+
|
|
234
|
+
const constrainVisibleRangeStart = (date: CalendarDate, aligned: CalendarDate): CalendarDate => {
|
|
235
|
+
const minValue = access(props.minValue);
|
|
236
|
+
const maxValue = access(props.maxValue);
|
|
237
|
+
let constrained = aligned;
|
|
238
|
+
|
|
239
|
+
if (minValue && date.compare(toDisplayCalendarDate(minValue)) >= 0) {
|
|
240
|
+
const minStart = rawAlignStart(toDisplayCalendarDate(minValue));
|
|
241
|
+
if (minStart.compare(constrained) > 0) {
|
|
242
|
+
constrained = minStart;
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
if (maxValue && date.compare(toDisplayCalendarDate(maxValue)) <= 0) {
|
|
247
|
+
const maxStart = rawAlignEnd(toDisplayCalendarDate(maxValue));
|
|
248
|
+
if (maxStart.compare(constrained) < 0) {
|
|
249
|
+
constrained = maxStart;
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
return constrained;
|
|
254
|
+
};
|
|
255
|
+
|
|
256
|
+
const alignStart = (date: CalendarDate): CalendarDate =>
|
|
257
|
+
constrainVisibleRangeStart(date, rawAlignStart(date));
|
|
258
|
+
|
|
259
|
+
const alignEnd = (date: CalendarDate): CalendarDate =>
|
|
260
|
+
constrainVisibleRangeStart(date, rawAlignEnd(date));
|
|
261
|
+
|
|
262
|
+
const alignCenter = (date: CalendarDate): CalendarDate => {
|
|
263
|
+
let offset = Math.floor(visibleMonths / 2);
|
|
264
|
+
if (offset > 0 && visibleMonths % 2 === 0) {
|
|
265
|
+
offset--;
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
return constrainVisibleRangeStart(date, rawAlignStart(date).subtract({ months: offset }));
|
|
269
|
+
};
|
|
270
|
+
|
|
271
|
+
const defaultSelectionAlignment = (): RangeCalendarSelectionAlignment => {
|
|
272
|
+
const currentValue = access(props.value) ?? props.defaultValue;
|
|
273
|
+
if (!currentValue?.start || !currentValue?.end) {
|
|
274
|
+
return "center";
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
const start = alignCenter(toDisplayCalendarDate(currentValue.start));
|
|
278
|
+
const end = visibleRangeEndFromStart(start);
|
|
279
|
+
return toDisplayCalendarDate(currentValue.end).compare(end) > 0 ? "start" : "center";
|
|
280
|
+
};
|
|
281
|
+
|
|
282
|
+
const alignVisibleRangeStart = (date: CalendarDate): CalendarDate => {
|
|
283
|
+
switch (access(props.selectionAlignment) ?? defaultSelectionAlignment()) {
|
|
284
|
+
case "start":
|
|
285
|
+
return alignStart(date);
|
|
286
|
+
case "end":
|
|
287
|
+
return alignEnd(date);
|
|
288
|
+
case "center":
|
|
289
|
+
default:
|
|
290
|
+
return alignCenter(date);
|
|
291
|
+
}
|
|
292
|
+
};
|
|
176
293
|
|
|
177
294
|
// Determine the initially focused date
|
|
178
295
|
const getInitialFocusedDate = (): CalendarDate => {
|
|
179
296
|
const controlledFocused = access(props.focusedValue);
|
|
180
297
|
if (controlledFocused) {
|
|
181
|
-
return
|
|
298
|
+
return toDisplayCalendarDate(controlledFocused);
|
|
182
299
|
}
|
|
183
300
|
if (props.defaultFocusedValue) {
|
|
184
|
-
return
|
|
301
|
+
return toDisplayCalendarDate(props.defaultFocusedValue);
|
|
185
302
|
}
|
|
186
303
|
const controlledValue = access(props.value);
|
|
187
304
|
if (controlledValue?.start) {
|
|
188
|
-
return
|
|
305
|
+
return toDisplayCalendarDate(controlledValue.start);
|
|
189
306
|
}
|
|
190
307
|
if (props.defaultValue?.start) {
|
|
191
|
-
return
|
|
308
|
+
return toDisplayCalendarDate(props.defaultValue.start);
|
|
192
309
|
}
|
|
193
|
-
return today(timeZone);
|
|
310
|
+
return intlToCalendar(today(timeZone), calendar());
|
|
194
311
|
};
|
|
195
312
|
|
|
196
313
|
// State signals
|
|
197
314
|
const [internalValue, setInternalValue] = createSignal<RangeValue<T> | null>(
|
|
198
|
-
props.defaultValue ?? null
|
|
315
|
+
props.defaultValue ?? null,
|
|
199
316
|
);
|
|
200
|
-
const
|
|
201
|
-
|
|
317
|
+
const initialFocusedDate = constrainDate(getInitialFocusedDate());
|
|
318
|
+
const [focusedDate, setFocusedDateInternal] = createSignal<CalendarDate>(initialFocusedDate);
|
|
319
|
+
const [visibleRangeStart, setVisibleRangeStart] = createSignal<CalendarDate>(
|
|
320
|
+
alignVisibleRangeStart(initialFocusedDate),
|
|
202
321
|
);
|
|
203
322
|
const [anchorDate, setAnchorDate] = createSignal<CalendarDate | null>(null);
|
|
204
323
|
const [isFocused, setFocused] = createSignal(false);
|
|
205
324
|
const [isDragging, setDragging] = createSignal(false);
|
|
206
325
|
|
|
207
326
|
// Controlled vs uncontrolled value
|
|
208
|
-
const
|
|
327
|
+
const sourceValue = createMemo<RangeValue<T> | null>(() => {
|
|
209
328
|
const controlled = access(props.value);
|
|
210
329
|
return controlled !== undefined ? controlled : internalValue();
|
|
211
330
|
});
|
|
331
|
+
const value = createMemo<RangeValue<T> | null>(() => {
|
|
332
|
+
const currentValue = sourceValue();
|
|
333
|
+
if (!currentValue) {
|
|
334
|
+
return null;
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
return {
|
|
338
|
+
start: toDisplayCalendarDate(currentValue.start) as unknown as T,
|
|
339
|
+
end: toDisplayCalendarDate(currentValue.end) as unknown as T,
|
|
340
|
+
};
|
|
341
|
+
});
|
|
212
342
|
|
|
213
343
|
// Derived states
|
|
214
344
|
const isDisabled = createMemo(() => access(props.isDisabled) ?? false);
|
|
215
345
|
const isReadOnly = createMemo(() => access(props.isReadOnly) ?? false);
|
|
216
346
|
const validationState = createMemo(() => access(props.validationState));
|
|
347
|
+
const isValueInvalid = createMemo(() => validationState() === "invalid");
|
|
217
348
|
|
|
218
349
|
// Highlighted range during selection
|
|
219
350
|
const highlightedRange = createMemo<RangeValue<CalendarDate> | null>(() => {
|
|
@@ -222,8 +353,8 @@ export function createRangeCalendarState<T extends DateValue = CalendarDate>(
|
|
|
222
353
|
const v = value();
|
|
223
354
|
if (v) {
|
|
224
355
|
return {
|
|
225
|
-
start:
|
|
226
|
-
end:
|
|
356
|
+
start: toDisplayCalendarDate(v.start),
|
|
357
|
+
end: toDisplayCalendarDate(v.end),
|
|
227
358
|
};
|
|
228
359
|
}
|
|
229
360
|
return null;
|
|
@@ -236,28 +367,68 @@ export function createRangeCalendarState<T extends DateValue = CalendarDate>(
|
|
|
236
367
|
return { start: focused, end: anchor };
|
|
237
368
|
});
|
|
238
369
|
|
|
239
|
-
// Visible range based on
|
|
370
|
+
// Visible range based on React Stately's selection alignment rules.
|
|
240
371
|
const visibleRange = createMemo(() => {
|
|
241
|
-
const
|
|
242
|
-
|
|
243
|
-
|
|
372
|
+
const start = visibleRangeStart();
|
|
373
|
+
return { start, end: visibleRangeEndFromStart(start) };
|
|
374
|
+
});
|
|
244
375
|
|
|
245
|
-
|
|
246
|
-
|
|
376
|
+
createEffect(() => {
|
|
377
|
+
const controlledFocused = access(props.focusedValue);
|
|
378
|
+
if (!controlledFocused) {
|
|
379
|
+
return;
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
const nextFocusedDate = constrainDate(toDisplayCalendarDate(controlledFocused));
|
|
383
|
+
const currentFocusedDate = focusedDate();
|
|
384
|
+
|
|
385
|
+
if (
|
|
386
|
+
nextFocusedDate.compare(currentFocusedDate) !== 0 ||
|
|
387
|
+
!isEqualCalendar(nextFocusedDate.calendar, currentFocusedDate.calendar)
|
|
388
|
+
) {
|
|
389
|
+
setFocusedDateInternal(nextFocusedDate);
|
|
390
|
+
setVisibleRangeStart(alignVisibleRangeStart(nextFocusedDate));
|
|
391
|
+
}
|
|
392
|
+
});
|
|
393
|
+
|
|
394
|
+
createEffect(() => {
|
|
395
|
+
const controlledFocused = access(props.focusedValue);
|
|
396
|
+
if (controlledFocused) {
|
|
397
|
+
return;
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
const currentFocusedDate = focusedDate();
|
|
401
|
+
const nextFocusedDate = constrainDate(currentFocusedDate);
|
|
402
|
+
|
|
403
|
+
if (
|
|
404
|
+
nextFocusedDate.compare(currentFocusedDate) === 0 &&
|
|
405
|
+
isEqualCalendar(nextFocusedDate.calendar, currentFocusedDate.calendar)
|
|
406
|
+
) {
|
|
407
|
+
return;
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
setFocusedDateInternal(nextFocusedDate);
|
|
411
|
+
setVisibleRangeStart(alignVisibleRangeStart(nextFocusedDate));
|
|
412
|
+
props.onFocusChange?.(nextFocusedDate);
|
|
413
|
+
});
|
|
414
|
+
|
|
415
|
+
createEffect(() => {
|
|
416
|
+
const currentFocusedDate = focusedDate();
|
|
417
|
+
const nextFocusedDate = toDisplayCalendarDate(currentFocusedDate);
|
|
418
|
+
|
|
419
|
+
if (isEqualCalendar(currentFocusedDate.calendar, nextFocusedDate.calendar)) {
|
|
420
|
+
return;
|
|
247
421
|
}
|
|
248
422
|
|
|
249
|
-
|
|
423
|
+
setFocusedDateInternal(nextFocusedDate);
|
|
424
|
+
setVisibleRangeStart(alignVisibleRangeStart(nextFocusedDate));
|
|
250
425
|
});
|
|
251
426
|
|
|
252
427
|
// Format week days for headers
|
|
253
428
|
const weekDays = createMemo(() => {
|
|
254
|
-
const formatter = new DateFormatter(locale, { weekday:
|
|
255
|
-
const startDay = props.firstDayOfWeek ?? 0;
|
|
429
|
+
const formatter = new DateFormatter(locale(), { weekday: "narrow" });
|
|
256
430
|
const days: string[] = [];
|
|
257
|
-
const
|
|
258
|
-
|
|
259
|
-
const dayOfWeek = getDayOfWeek(base, locale);
|
|
260
|
-
const weekStart = base.subtract({ days: (dayOfWeek - startDay + 7) % 7 });
|
|
431
|
+
const weekStart = startOfWeek(today(timeZone), locale(), firstDayOfWeekName());
|
|
261
432
|
|
|
262
433
|
for (let i = 0; i < 7; i++) {
|
|
263
434
|
const day = weekStart.add({ days: i });
|
|
@@ -269,42 +440,51 @@ export function createRangeCalendarState<T extends DateValue = CalendarDate>(
|
|
|
269
440
|
|
|
270
441
|
// Title (formatted month/year)
|
|
271
442
|
const title = createMemo(() => {
|
|
272
|
-
const formatter = new DateFormatter(locale, {
|
|
273
|
-
month:
|
|
274
|
-
year:
|
|
443
|
+
const formatter = new DateFormatter(locale(), {
|
|
444
|
+
month: "long",
|
|
445
|
+
year: "numeric",
|
|
446
|
+
calendar: focusedDate().calendar.identifier,
|
|
275
447
|
});
|
|
276
|
-
|
|
448
|
+
const date = focusedDate();
|
|
449
|
+
const formattableMonth = date.calendar.getFormattableMonth?.(date) ?? date;
|
|
450
|
+
return formatter.format(formattableMonth.toDate(timeZone));
|
|
277
451
|
});
|
|
278
452
|
|
|
279
453
|
// Set value with onChange callback
|
|
280
454
|
const setValue = (newValue: RangeValue<T> | null) => {
|
|
281
455
|
if (isDisabled() || isReadOnly()) return;
|
|
282
456
|
|
|
457
|
+
const oldValue = sourceValue();
|
|
458
|
+
const nextValue = newValue
|
|
459
|
+
? {
|
|
460
|
+
start: convertValue(
|
|
461
|
+
constrainDate(toDisplayCalendarDate(newValue.start)),
|
|
462
|
+
oldValue?.start,
|
|
463
|
+
) as T,
|
|
464
|
+
end: convertValue(constrainDate(toDisplayCalendarDate(newValue.end)), oldValue?.end) as T,
|
|
465
|
+
}
|
|
466
|
+
: null;
|
|
467
|
+
|
|
283
468
|
const controlled = access(props.value);
|
|
284
469
|
if (controlled === undefined) {
|
|
285
|
-
setInternalValue(() =>
|
|
470
|
+
setInternalValue(() => nextValue);
|
|
286
471
|
}
|
|
287
472
|
|
|
288
|
-
if (
|
|
289
|
-
props.onChange(
|
|
473
|
+
if (!Object.is(oldValue, nextValue) && props.onChange) {
|
|
474
|
+
props.onChange(nextValue);
|
|
290
475
|
}
|
|
291
476
|
};
|
|
292
477
|
|
|
293
478
|
// Set focused date with constraints
|
|
294
479
|
const setFocusedDate = (date: CalendarDate) => {
|
|
295
|
-
const
|
|
296
|
-
const maxValue = access(props.maxValue);
|
|
297
|
-
|
|
298
|
-
let constrained = date;
|
|
480
|
+
const constrained = constrainDate(date);
|
|
299
481
|
|
|
300
|
-
if (
|
|
301
|
-
|
|
302
|
-
}
|
|
303
|
-
if (maxValue && date.compare(toCalendarDate(maxValue)) > 0) {
|
|
304
|
-
constrained = toCalendarDate(maxValue);
|
|
482
|
+
if (Object.is(constrained, focusedDate())) {
|
|
483
|
+
return;
|
|
305
484
|
}
|
|
306
485
|
|
|
307
486
|
setFocusedDateInternal(constrained);
|
|
487
|
+
setVisibleRangeStart(alignVisibleRangeStart(constrained));
|
|
308
488
|
props.onFocusChange?.(constrained);
|
|
309
489
|
};
|
|
310
490
|
|
|
@@ -313,29 +493,27 @@ export function createRangeCalendarState<T extends DateValue = CalendarDate>(
|
|
|
313
493
|
const range = highlightedRange();
|
|
314
494
|
if (!range) return false;
|
|
315
495
|
|
|
316
|
-
const calDate =
|
|
317
|
-
return (
|
|
318
|
-
calDate.compare(range.start) >= 0 && calDate.compare(range.end) <= 0
|
|
319
|
-
);
|
|
496
|
+
const calDate = toDisplayCalendarDate(date);
|
|
497
|
+
return calDate.compare(range.start) >= 0 && calDate.compare(range.end) <= 0;
|
|
320
498
|
};
|
|
321
499
|
|
|
322
500
|
// Check if a date is the start of the selection
|
|
323
501
|
const isSelectionStart = (date: DateValue): boolean => {
|
|
324
502
|
const range = highlightedRange();
|
|
325
503
|
if (!range) return false;
|
|
326
|
-
return isSameDay(
|
|
504
|
+
return isSameDay(toDisplayCalendarDate(date), range.start);
|
|
327
505
|
};
|
|
328
506
|
|
|
329
507
|
// Check if a date is the end of the selection
|
|
330
508
|
const isSelectionEnd = (date: DateValue): boolean => {
|
|
331
509
|
const range = highlightedRange();
|
|
332
510
|
if (!range) return false;
|
|
333
|
-
return isSameDay(
|
|
511
|
+
return isSameDay(toDisplayCalendarDate(date), range.end);
|
|
334
512
|
};
|
|
335
513
|
|
|
336
514
|
// Check if a date is focused
|
|
337
515
|
const isCellFocused = (date: DateValue): boolean => {
|
|
338
|
-
return isSameDay(
|
|
516
|
+
return isSameDay(toDisplayCalendarDate(date), focusedDate());
|
|
339
517
|
};
|
|
340
518
|
|
|
341
519
|
// Check if a date is unavailable
|
|
@@ -350,10 +528,21 @@ export function createRangeCalendarState<T extends DateValue = CalendarDate>(
|
|
|
350
528
|
|
|
351
529
|
const minValue = access(props.minValue);
|
|
352
530
|
const maxValue = access(props.maxValue);
|
|
353
|
-
const calDate =
|
|
531
|
+
const calDate = toDisplayCalendarDate(date);
|
|
532
|
+
|
|
533
|
+
if (minValue && calDate.compare(toDisplayCalendarDate(minValue)) < 0) return true;
|
|
534
|
+
if (maxValue && calDate.compare(toDisplayCalendarDate(maxValue)) > 0) return true;
|
|
535
|
+
|
|
536
|
+
return false;
|
|
537
|
+
};
|
|
538
|
+
|
|
539
|
+
const isDateOutsideAllowedRange = (date: DateValue): boolean => {
|
|
540
|
+
const minValue = access(props.minValue);
|
|
541
|
+
const maxValue = access(props.maxValue);
|
|
542
|
+
const calDate = toDisplayCalendarDate(date);
|
|
354
543
|
|
|
355
|
-
if (minValue && calDate.compare(
|
|
356
|
-
if (maxValue && calDate.compare(
|
|
544
|
+
if (minValue && calDate.compare(toDisplayCalendarDate(minValue)) < 0) return true;
|
|
545
|
+
if (maxValue && calDate.compare(toDisplayCalendarDate(maxValue)) > 0) return true;
|
|
357
546
|
|
|
358
547
|
return false;
|
|
359
548
|
};
|
|
@@ -361,7 +550,7 @@ export function createRangeCalendarState<T extends DateValue = CalendarDate>(
|
|
|
361
550
|
// Check if a date is outside the visible range
|
|
362
551
|
const isOutsideVisibleRange = (date: DateValue): boolean => {
|
|
363
552
|
const range = visibleRange();
|
|
364
|
-
const calDate =
|
|
553
|
+
const calDate = toDisplayCalendarDate(date);
|
|
365
554
|
return !isSameMonth(calDate, range.start) && !isSameMonth(calDate, range.end);
|
|
366
555
|
};
|
|
367
556
|
|
|
@@ -372,11 +561,13 @@ export function createRangeCalendarState<T extends DateValue = CalendarDate>(
|
|
|
372
561
|
|
|
373
562
|
// Navigation methods
|
|
374
563
|
const focusPreviousPage = () => {
|
|
375
|
-
|
|
564
|
+
const pageMonths = access(props.pageBehavior) === "single" ? 1 : visibleMonths;
|
|
565
|
+
setFocusedDate(focusedDate().subtract({ months: pageMonths }));
|
|
376
566
|
};
|
|
377
567
|
|
|
378
568
|
const focusNextPage = () => {
|
|
379
|
-
|
|
569
|
+
const pageMonths = access(props.pageBehavior) === "single" ? 1 : visibleMonths;
|
|
570
|
+
setFocusedDate(focusedDate().add({ months: pageMonths }));
|
|
380
571
|
};
|
|
381
572
|
|
|
382
573
|
const focusPreviousSection = () => {
|
|
@@ -387,6 +578,18 @@ export function createRangeCalendarState<T extends DateValue = CalendarDate>(
|
|
|
387
578
|
setFocusedDate(focusedDate().add({ years: 1 }));
|
|
388
579
|
};
|
|
389
580
|
|
|
581
|
+
const isPreviousVisibleRangeInvalid = () => {
|
|
582
|
+
const start = visibleRange().start;
|
|
583
|
+
const previous = start.subtract({ days: 1 });
|
|
584
|
+
return isSameDay(previous, start) || isDateOutsideAllowedRange(previous);
|
|
585
|
+
};
|
|
586
|
+
|
|
587
|
+
const isNextVisibleRangeInvalid = () => {
|
|
588
|
+
const end = visibleRange().end;
|
|
589
|
+
const next = end.add({ days: 1 });
|
|
590
|
+
return isSameDay(next, end) || isDateOutsideAllowedRange(next);
|
|
591
|
+
};
|
|
592
|
+
|
|
390
593
|
const focusPreviousDay = () => {
|
|
391
594
|
setFocusedDate(focusedDate().subtract({ days: 1 }));
|
|
392
595
|
};
|
|
@@ -454,12 +657,12 @@ export function createRangeCalendarState<T extends DateValue = CalendarDate>(
|
|
|
454
657
|
// Get dates in a specific week
|
|
455
658
|
const getDatesInWeek = (
|
|
456
659
|
weekIndex: number,
|
|
457
|
-
monthStartDate?: CalendarDate
|
|
660
|
+
monthStartDate?: CalendarDate,
|
|
458
661
|
): (CalendarDate | null)[] => {
|
|
459
662
|
const startDate = monthStartDate ?? visibleRange().start;
|
|
460
663
|
|
|
461
664
|
const monthStart = startOfMonth(startDate);
|
|
462
|
-
const weekStart = startOfWeek(monthStart, locale);
|
|
665
|
+
const weekStart = startOfWeek(monthStart, locale(), firstDayOfWeekName());
|
|
463
666
|
|
|
464
667
|
const week: (CalendarDate | null)[] = [];
|
|
465
668
|
const firstDayOfWeek = weekStart.add({ weeks: weekIndex });
|
|
@@ -475,7 +678,7 @@ export function createRangeCalendarState<T extends DateValue = CalendarDate>(
|
|
|
475
678
|
// Get number of weeks in a month
|
|
476
679
|
const getWeeksInMonthFn = (date?: CalendarDate): number => {
|
|
477
680
|
const monthDate = date ?? focusedDate();
|
|
478
|
-
return getWeeksInMonth(monthDate, locale);
|
|
681
|
+
return getWeeksInMonth(monthDate, locale(), firstDayOfWeekName());
|
|
479
682
|
};
|
|
480
683
|
|
|
481
684
|
return {
|
|
@@ -490,7 +693,10 @@ export function createRangeCalendarState<T extends DateValue = CalendarDate>(
|
|
|
490
693
|
isReadOnly,
|
|
491
694
|
visibleRange,
|
|
492
695
|
timeZone,
|
|
696
|
+
locale,
|
|
697
|
+
firstDayOfWeek: firstDayOfWeekName,
|
|
493
698
|
validationState,
|
|
699
|
+
isValueInvalid,
|
|
494
700
|
isSelected,
|
|
495
701
|
isSelectionStart,
|
|
496
702
|
isSelectionEnd,
|
|
@@ -503,6 +709,8 @@ export function createRangeCalendarState<T extends DateValue = CalendarDate>(
|
|
|
503
709
|
focusNextPage,
|
|
504
710
|
focusPreviousSection,
|
|
505
711
|
focusNextSection,
|
|
712
|
+
isPreviousVisibleRangeInvalid,
|
|
713
|
+
isNextVisibleRangeInvalid,
|
|
506
714
|
focusPreviousDay,
|
|
507
715
|
focusNextDay,
|
|
508
716
|
focusPreviousWeek,
|
|
@@ -523,13 +731,19 @@ export function createRangeCalendarState<T extends DateValue = CalendarDate>(
|
|
|
523
731
|
};
|
|
524
732
|
}
|
|
525
733
|
|
|
526
|
-
// ============================================
|
|
527
|
-
// HELPER FUNCTIONS
|
|
528
|
-
// ============================================
|
|
529
|
-
|
|
530
734
|
/**
|
|
531
735
|
* Converts a DateValue to a CalendarDate.
|
|
532
736
|
*/
|
|
533
737
|
function toCalendarDate(date: DateValue): CalendarDate {
|
|
534
738
|
return intlToCalendarDate(date);
|
|
535
739
|
}
|
|
740
|
+
|
|
741
|
+
function convertValue(newValue: CalendarDate, oldValue?: DateValue | null): DateValue {
|
|
742
|
+
const localValue = intlToCalendar(newValue, oldValue?.calendar ?? new GregorianCalendar());
|
|
743
|
+
|
|
744
|
+
if (oldValue && "hour" in oldValue) {
|
|
745
|
+
return oldValue.set(localValue);
|
|
746
|
+
}
|
|
747
|
+
|
|
748
|
+
return localValue;
|
|
749
|
+
}
|