@rotki/ui-library 2.9.1 → 2.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/accordions/accordion/RuiAccordion.vue.d.ts +3 -3
- package/dist/components/accordions/accordion/RuiAccordion.vue.js +87 -8
- package/dist/components/accordions/accordion/RuiAccordion.vue.js.map +1 -1
- package/dist/components/accordions/accordion/RuiAccordion.vue2.js +1 -62
- package/dist/components/accordions/accordion/RuiAccordion.vue2.js.map +1 -1
- package/dist/components/alerts/RuiAlert.vue.d.ts +3 -3
- package/dist/components/buttons/button/RuiButton.vue.d.ts +9 -5
- package/dist/components/buttons/button-group/RuiButtonGroup.vue.d.ts +9 -5
- package/dist/components/calendar/RuiCalendar.vue.js +12 -0
- package/dist/components/calendar/RuiCalendar.vue.js.map +1 -1
- package/dist/components/calendar/RuiCalendarMenu.vue.js +1 -1
- package/dist/components/calendar/RuiCalendarMenu.vue2.js +2 -2
- package/dist/components/calendar/RuiCalendarMenu.vue2.js.map +1 -1
- package/dist/components/calendar/state.js +1 -1
- package/dist/components/calendar/state.js.map +1 -1
- package/dist/components/cards/RuiCard.vue.d.ts +6 -6
- package/dist/components/date-time-picker/RuiDateTimePicker.vue.d.ts +3 -4
- package/dist/components/date-time-picker/RuiDateTimePicker.vue2.js +70 -251
- package/dist/components/date-time-picker/RuiDateTimePicker.vue2.js.map +1 -1
- package/dist/components/date-time-picker/use-date-time-selection.d.ts +38 -0
- package/dist/components/date-time-picker/use-date-time-selection.js +286 -0
- package/dist/components/date-time-picker/use-date-time-selection.js.map +1 -0
- package/dist/components/date-time-picker/use-keyboard-handler.d.ts +2 -0
- package/dist/components/date-time-picker/use-keyboard-handler.js +71 -60
- package/dist/components/date-time-picker/use-keyboard-handler.js.map +1 -1
- package/dist/components/forms/auto-complete/RuiAutoComplete.vue.d.ts +29 -25
- package/dist/components/forms/auto-complete/RuiAutoComplete.vue2.js +5 -3
- package/dist/components/forms/auto-complete/RuiAutoComplete.vue2.js.map +1 -1
- package/dist/components/forms/checkbox/RuiCheckbox.vue.d.ts +2 -2
- package/dist/components/forms/checkbox/RuiCheckbox.vue2.js +13 -8
- package/dist/components/forms/checkbox/RuiCheckbox.vue2.js.map +1 -1
- package/dist/components/forms/radio-button/radio/RuiRadio.vue.d.ts +9 -5
- package/dist/components/forms/radio-button/radio/RuiRadio.vue2.js +12 -8
- package/dist/components/forms/radio-button/radio/RuiRadio.vue2.js.map +1 -1
- package/dist/components/forms/radio-button/radio-group/RuiRadioGroup.vue.d.ts +9 -5
- package/dist/components/forms/revealable-text-field/RuiRevealableTextField.vue.d.ts +4 -4
- package/dist/components/forms/select/RuiMenuSelect.vue.d.ts +29 -25
- package/dist/components/forms/select/RuiMenuSelect.vue2.js +4 -2
- package/dist/components/forms/select/RuiMenuSelect.vue2.js.map +1 -1
- package/dist/components/forms/slider/RuiSlider.vue2.js +14 -11
- package/dist/components/forms/slider/RuiSlider.vue2.js.map +1 -1
- package/dist/components/forms/switch/RuiSwitch.vue2.js +10 -7
- package/dist/components/forms/switch/RuiSwitch.vue2.js.map +1 -1
- package/dist/components/forms/text-area/RuiTextArea.vue.d.ts +3 -3
- package/dist/components/forms/text-area/RuiTextArea.vue2.js +15 -12
- package/dist/components/forms/text-area/RuiTextArea.vue2.js.map +1 -1
- package/dist/components/forms/text-field/RuiTextField.vue.d.ts +3 -3
- package/dist/components/forms/text-field/RuiTextField.vue2.js +13 -10
- package/dist/components/forms/text-field/RuiTextField.vue2.js.map +1 -1
- package/dist/components/icons/IconBrowser.vue.d.ts +3 -0
- package/dist/components/icons/LazyIcon.vue.d.ts +10 -0
- package/dist/components/overlays/badge/RuiBadge.vue.d.ts +3 -3
- package/dist/components/overlays/bottom-sheet/RuiBottomSheet.vue.d.ts +2 -2
- package/dist/components/overlays/dialog/RuiDialog.vue.d.ts +2 -2
- package/dist/components/overlays/menu/RuiMenu.vue.d.ts +2 -2
- package/dist/components/overlays/navigation-drawer/RuiNavigationDrawer.vue.d.ts +2 -2
- package/dist/components/overlays/notification/RuiNotification.vue.d.ts +2 -2
- package/dist/components/overlays/tooltip/RuiTooltip.vue.d.ts +2 -2
- package/dist/components/tables/RuiDataTable.vue.d.ts +9 -5
- package/dist/components/tables/RuiExpandButton.vue.d.ts +2 -2
- package/dist/components/tables/RuiTableHead.vue.d.ts +9 -5
- package/dist/components/tabs/tab/RuiTab.vue.d.ts +1 -1
- package/dist/components/tabs/tab-item/RuiTabItem.vue.d.ts +3 -3
- package/dist/components/tabs/tab-items/RuiTabItems.vue.d.ts +9 -5
- package/dist/components/time-picker/RuiTimePicker.vue2.js +0 -1
- package/dist/components/time-picker/RuiTimePicker.vue2.js.map +1 -1
- package/dist/composables/defaults/table.js +1 -1
- package/dist/composables/defaults/table.js.map +1 -1
- package/dist/composables/icons.js +1 -1
- package/dist/composables/icons.js.map +1 -1
- package/dist/composables/use-rui-i18n.js +1 -1
- package/dist/composables/use-rui-i18n.js.map +1 -1
- package/dist/style.css +98 -61
- package/dist/web-types.json +116 -72
- package/package.json +31 -40
- package/dist/components/accordions/accordion/RuiAccordion.vue3.js +0 -18
- package/dist/components/accordions/accordion/RuiAccordion.vue3.js.map +0 -1
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { ComputedRef, Ref, WritableComputedRef } from 'vue';
|
|
2
|
+
import type { SegmentData } from '../../components/date-time-picker/types.js';
|
|
3
|
+
import type { TimeAccuracy } from '../../consts/time-accuracy.js';
|
|
4
|
+
import { type Dayjs } from 'dayjs';
|
|
5
|
+
type DateTimeModelType = 'date' | 'epoch-ms' | 'epoch';
|
|
6
|
+
type ModelValueType<T extends DateTimeModelType> = T extends 'date' ? Date | undefined : T extends 'epoch-ms' ? number | undefined : T extends 'epoch' ? number | undefined : Date | number | undefined;
|
|
7
|
+
interface DateTimeSelectionOptions<T extends DateTimeModelType> {
|
|
8
|
+
modelValue: Ref<ModelValueType<T>>;
|
|
9
|
+
type: T;
|
|
10
|
+
accuracy: TimeAccuracy;
|
|
11
|
+
minDate: Date | number | undefined;
|
|
12
|
+
maxDate: Date | number | 'now' | undefined;
|
|
13
|
+
allowEmpty: boolean;
|
|
14
|
+
}
|
|
15
|
+
interface DateTimeSelectionReturn {
|
|
16
|
+
selectedYear: Ref<number | undefined>;
|
|
17
|
+
selectedMonth: Ref<number | undefined>;
|
|
18
|
+
selectedDay: Ref<number | undefined>;
|
|
19
|
+
selectedHour: Ref<number | undefined>;
|
|
20
|
+
selectedMinute: Ref<number | undefined>;
|
|
21
|
+
selectedSecond: Ref<number | undefined>;
|
|
22
|
+
selectedMillisecond: Ref<number | undefined>;
|
|
23
|
+
selectedTimezone: Ref<string | undefined>;
|
|
24
|
+
selectedDate: WritableComputedRef<Date | undefined>;
|
|
25
|
+
selectedTime: WritableComputedRef<Date | undefined>;
|
|
26
|
+
valueSet: ComputedRef<boolean>;
|
|
27
|
+
internalErrorMessages: Ref<string[]>;
|
|
28
|
+
now: Ref<Dayjs>;
|
|
29
|
+
segmentData: SegmentData;
|
|
30
|
+
minAllowedDate: ComputedRef<Date>;
|
|
31
|
+
maxAllowedDate: ComputedRef<Date | undefined>;
|
|
32
|
+
getDateTime: () => Dayjs;
|
|
33
|
+
setNow: () => void;
|
|
34
|
+
clear: () => void;
|
|
35
|
+
isDateValid: (date: Dayjs) => boolean;
|
|
36
|
+
}
|
|
37
|
+
export declare function useDateTimeSelection<T extends DateTimeModelType>(options: DateTimeSelectionOptions<T>): DateTimeSelectionReturn;
|
|
38
|
+
export {};
|
|
@@ -0,0 +1,286 @@
|
|
|
1
|
+
import dayjs from "dayjs";
|
|
2
|
+
import { guessTimezone, includeSeconds, includeMilliseconds } from "./utils.js";
|
|
3
|
+
import { useRuiI8n } from "../../composables/use-rui-i18n.js";
|
|
4
|
+
import { RUI_I18N_KEYS } from "../../i18n/keys.js";
|
|
5
|
+
import { ref, computed, watch, onMounted, nextTick } from "vue";
|
|
6
|
+
import { get, set } from "@vueuse/shared";
|
|
7
|
+
import { isDefined, watchIgnorable } from "@vueuse/core";
|
|
8
|
+
const MILLISECONDS = 1e3;
|
|
9
|
+
function useDateTimeSelection(options) {
|
|
10
|
+
const {
|
|
11
|
+
accuracy,
|
|
12
|
+
allowEmpty,
|
|
13
|
+
maxDate,
|
|
14
|
+
minDate,
|
|
15
|
+
modelValue,
|
|
16
|
+
type
|
|
17
|
+
} = options;
|
|
18
|
+
const { t } = useRuiI8n();
|
|
19
|
+
const selectedYear = ref();
|
|
20
|
+
const selectedMonth = ref();
|
|
21
|
+
const selectedDay = ref();
|
|
22
|
+
const selectedHour = ref();
|
|
23
|
+
const selectedMinute = ref();
|
|
24
|
+
const selectedSecond = ref();
|
|
25
|
+
const selectedMillisecond = ref();
|
|
26
|
+
const selectedTimezone = ref(guessTimezone());
|
|
27
|
+
const internalErrorMessages = ref([]);
|
|
28
|
+
const now = ref(dayjs.tz(void 0, guessTimezone()));
|
|
29
|
+
const minAllowedDate = computed(() => {
|
|
30
|
+
if (minDate === void 0) {
|
|
31
|
+
return new Date(1970, 0, 1);
|
|
32
|
+
}
|
|
33
|
+
if (type === "epoch" && typeof minDate === "number") {
|
|
34
|
+
return new Date(minDate * MILLISECONDS);
|
|
35
|
+
}
|
|
36
|
+
return new Date(minDate);
|
|
37
|
+
});
|
|
38
|
+
const maxAllowedDate = computed(() => {
|
|
39
|
+
if (maxDate === void 0) {
|
|
40
|
+
return void 0;
|
|
41
|
+
}
|
|
42
|
+
if (maxDate === "now") {
|
|
43
|
+
return get(now).toDate();
|
|
44
|
+
}
|
|
45
|
+
if (type === "epoch" && typeof maxDate === "number") {
|
|
46
|
+
return new Date(maxDate * MILLISECONDS);
|
|
47
|
+
}
|
|
48
|
+
return new Date(maxDate);
|
|
49
|
+
});
|
|
50
|
+
const segmentData = {
|
|
51
|
+
DD: selectedDay,
|
|
52
|
+
HH: selectedHour,
|
|
53
|
+
MM: selectedMonth,
|
|
54
|
+
SSS: selectedMillisecond,
|
|
55
|
+
YYYY: selectedYear,
|
|
56
|
+
mm: selectedMinute,
|
|
57
|
+
ss: selectedSecond
|
|
58
|
+
};
|
|
59
|
+
const selectedDate = computed({
|
|
60
|
+
get() {
|
|
61
|
+
if (!(isDefined(selectedYear) && isDefined(selectedMonth) && isDefined(selectedDay))) {
|
|
62
|
+
return void 0;
|
|
63
|
+
}
|
|
64
|
+
const date = /* @__PURE__ */ new Date();
|
|
65
|
+
date.setFullYear(get(selectedYear));
|
|
66
|
+
date.setDate(1);
|
|
67
|
+
date.setMonth(get(selectedMonth) - 1);
|
|
68
|
+
date.setDate(get(selectedDay));
|
|
69
|
+
return date;
|
|
70
|
+
},
|
|
71
|
+
set(value) {
|
|
72
|
+
set(selectedYear, value?.getFullYear());
|
|
73
|
+
set(selectedMonth, value ? value.getMonth() + 1 : void 0);
|
|
74
|
+
set(selectedDay, value?.getDate());
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
const selectedTime = computed({
|
|
78
|
+
get() {
|
|
79
|
+
if (!(isDefined(selectedHour) && isDefined(selectedMinute))) {
|
|
80
|
+
return void 0;
|
|
81
|
+
}
|
|
82
|
+
const date = /* @__PURE__ */ new Date();
|
|
83
|
+
date.setHours(
|
|
84
|
+
get(selectedHour),
|
|
85
|
+
get(selectedMinute),
|
|
86
|
+
get(selectedSecond) ?? 0,
|
|
87
|
+
get(selectedMillisecond) ?? 0
|
|
88
|
+
);
|
|
89
|
+
return date;
|
|
90
|
+
},
|
|
91
|
+
set(value) {
|
|
92
|
+
set(selectedHour, value?.getHours());
|
|
93
|
+
set(selectedMinute, value?.getMinutes());
|
|
94
|
+
set(selectedSecond, value?.getSeconds());
|
|
95
|
+
set(selectedMillisecond, value?.getMilliseconds());
|
|
96
|
+
}
|
|
97
|
+
});
|
|
98
|
+
const valueSet = computed(() => isDefined(selectedDate) && isDefined(selectedTime));
|
|
99
|
+
function getDateTime() {
|
|
100
|
+
let dateTime = dayjs();
|
|
101
|
+
if (isDefined(selectedYear)) {
|
|
102
|
+
dateTime = dateTime.year(get(selectedYear));
|
|
103
|
+
}
|
|
104
|
+
if (isDefined(selectedMonth)) {
|
|
105
|
+
dateTime = dateTime.month(get(selectedMonth) - 1);
|
|
106
|
+
}
|
|
107
|
+
if (isDefined(selectedDay)) {
|
|
108
|
+
const daysInMonth = dateTime.daysInMonth();
|
|
109
|
+
const day = Math.min(get(selectedDay), daysInMonth);
|
|
110
|
+
dateTime = dateTime.date(day);
|
|
111
|
+
}
|
|
112
|
+
if (isDefined(selectedHour)) {
|
|
113
|
+
dateTime = dateTime.hour(get(selectedHour));
|
|
114
|
+
}
|
|
115
|
+
if (isDefined(selectedMinute)) {
|
|
116
|
+
dateTime = dateTime.minute(get(selectedMinute));
|
|
117
|
+
}
|
|
118
|
+
if (isDefined(selectedSecond)) {
|
|
119
|
+
dateTime = dateTime.second(get(selectedSecond));
|
|
120
|
+
}
|
|
121
|
+
if (isDefined(selectedMillisecond)) {
|
|
122
|
+
dateTime = dateTime.millisecond(get(selectedMillisecond));
|
|
123
|
+
}
|
|
124
|
+
return dateTime;
|
|
125
|
+
}
|
|
126
|
+
function isDateValid(date) {
|
|
127
|
+
const min = get(minAllowedDate);
|
|
128
|
+
const max = get(maxAllowedDate);
|
|
129
|
+
set(internalErrorMessages, []);
|
|
130
|
+
if (min && date.isBefore(min)) {
|
|
131
|
+
const errorMessage = t(RUI_I18N_KEYS.dateTimePicker.dateBeforeMin, {
|
|
132
|
+
date: min.toLocaleDateString()
|
|
133
|
+
}, `Date cannot be before ${min.toLocaleDateString()}`);
|
|
134
|
+
set(internalErrorMessages, [...get(internalErrorMessages), errorMessage]);
|
|
135
|
+
return false;
|
|
136
|
+
}
|
|
137
|
+
if (max && date.isAfter(max)) {
|
|
138
|
+
const nowError = t(RUI_I18N_KEYS.dateTimePicker.dateInFuture, "The selected date cannot be in the future");
|
|
139
|
+
const maxError = t(RUI_I18N_KEYS.dateTimePicker.dateAfterMax, { date: max.toLocaleDateString() }, `Date cannot be after ${max.toLocaleDateString()}`);
|
|
140
|
+
const errorMessage = maxDate === "now" ? nowError : maxError;
|
|
141
|
+
set(internalErrorMessages, [...get(internalErrorMessages), errorMessage]);
|
|
142
|
+
return false;
|
|
143
|
+
}
|
|
144
|
+
return true;
|
|
145
|
+
}
|
|
146
|
+
function emitUpdate(updatedModel) {
|
|
147
|
+
const typeMap = {
|
|
148
|
+
"date": () => updatedModel.toDate(),
|
|
149
|
+
"epoch": () => updatedModel.valueOf() / MILLISECONDS,
|
|
150
|
+
"epoch-ms": () => updatedModel.valueOf()
|
|
151
|
+
};
|
|
152
|
+
set(modelValue, typeMap[type]());
|
|
153
|
+
}
|
|
154
|
+
function updateModelValue() {
|
|
155
|
+
if (!isDefined(selectedDate) || !isDefined(selectedTime)) {
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
158
|
+
if (!(isDefined(selectedDate) && isDefined(selectedTime))) {
|
|
159
|
+
set(modelValue, void 0);
|
|
160
|
+
} else {
|
|
161
|
+
const date = get(selectedDate);
|
|
162
|
+
const time = get(selectedTime);
|
|
163
|
+
const updatedModel = dayjs.tz(isDefined(modelValue) ? get(modelValue) : void 0, get(selectedTimezone)).year(date.getFullYear()).month(date.getMonth()).date(date.getDate()).hour(time.getHours()).minute(time.getMinutes()).second(includeSeconds(accuracy) ? time.getSeconds() : 0).millisecond(includeMilliseconds(accuracy) ? time.getMilliseconds() : 0);
|
|
164
|
+
if (!isDateValid(updatedModel)) {
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
emitUpdate(updatedModel);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
function clear() {
|
|
171
|
+
set(internalErrorMessages, []);
|
|
172
|
+
set(selectedYear, void 0);
|
|
173
|
+
set(selectedMonth, void 0);
|
|
174
|
+
set(selectedDay, void 0);
|
|
175
|
+
set(selectedHour, void 0);
|
|
176
|
+
set(selectedMinute, void 0);
|
|
177
|
+
set(selectedSecond, void 0);
|
|
178
|
+
set(selectedMillisecond, void 0);
|
|
179
|
+
set(modelValue, void 0);
|
|
180
|
+
}
|
|
181
|
+
function setNow() {
|
|
182
|
+
set(internalErrorMessages, []);
|
|
183
|
+
const date = dayjs();
|
|
184
|
+
set(now, date);
|
|
185
|
+
set(selectedYear, date.year());
|
|
186
|
+
set(selectedMonth, date.month() + 1);
|
|
187
|
+
set(selectedDay, date.date());
|
|
188
|
+
set(selectedHour, date.hour());
|
|
189
|
+
set(selectedMinute, date.minute());
|
|
190
|
+
set(selectedSecond, includeSeconds(accuracy) ? date.second() : 0);
|
|
191
|
+
set(selectedMillisecond, includeMilliseconds(accuracy) ? date.millisecond() : 0);
|
|
192
|
+
nextTick(() => {
|
|
193
|
+
updateModelValue();
|
|
194
|
+
});
|
|
195
|
+
}
|
|
196
|
+
function updateSegments(date) {
|
|
197
|
+
const year = date.year();
|
|
198
|
+
const month = date.month() + 1;
|
|
199
|
+
const day = date.date();
|
|
200
|
+
const hour = date.hour();
|
|
201
|
+
const minute = date.minute();
|
|
202
|
+
const second = includeSeconds(accuracy) ? date.second() : void 0;
|
|
203
|
+
const millisecond = includeMilliseconds(accuracy) ? date.millisecond() : void 0;
|
|
204
|
+
if (get(selectedYear) !== year)
|
|
205
|
+
set(selectedYear, year);
|
|
206
|
+
if (get(selectedMonth) !== month)
|
|
207
|
+
set(selectedMonth, month);
|
|
208
|
+
if (get(selectedDay) !== day)
|
|
209
|
+
set(selectedDay, day);
|
|
210
|
+
if (get(selectedHour) !== hour)
|
|
211
|
+
set(selectedHour, hour);
|
|
212
|
+
if (get(selectedMinute) !== minute)
|
|
213
|
+
set(selectedMinute, minute);
|
|
214
|
+
if (get(selectedSecond) !== second)
|
|
215
|
+
set(selectedSecond, second);
|
|
216
|
+
if (get(selectedMillisecond) !== millisecond)
|
|
217
|
+
set(selectedMillisecond, millisecond);
|
|
218
|
+
}
|
|
219
|
+
const { ignoreUpdates } = watchIgnorable([selectedDate, selectedTime], ([newSelectedDate, newSelectedTime], [prevSelectedDate, prevSelectedTime]) => {
|
|
220
|
+
const currentTimezone = get(selectedTimezone);
|
|
221
|
+
const newDate = dayjs.tz(newSelectedDate, currentTimezone);
|
|
222
|
+
const oldDate = dayjs.tz(prevSelectedDate, currentTimezone);
|
|
223
|
+
const newTime = dayjs.tz(newSelectedTime, currentTimezone);
|
|
224
|
+
const oldTime = dayjs.tz(prevSelectedTime, currentTimezone);
|
|
225
|
+
if (newDate.isSame(oldDate) && newTime.isSame(oldTime)) {
|
|
226
|
+
return;
|
|
227
|
+
}
|
|
228
|
+
set(now, dayjs());
|
|
229
|
+
updateModelValue();
|
|
230
|
+
});
|
|
231
|
+
function updateInternalModel(value) {
|
|
232
|
+
ignoreUpdates(() => {
|
|
233
|
+
const updatedValue = type === "epoch" && typeof value === "number" ? value * MILLISECONDS : value;
|
|
234
|
+
const date = dayjs.tz(updatedValue, get(selectedTimezone));
|
|
235
|
+
isDateValid(date);
|
|
236
|
+
updateSegments(date);
|
|
237
|
+
});
|
|
238
|
+
}
|
|
239
|
+
watch(selectedTimezone, (newTimezone) => {
|
|
240
|
+
if (newTimezone && isDefined(selectedDate) && isDefined(selectedTime)) {
|
|
241
|
+
set(now, dayjs());
|
|
242
|
+
updateModelValue();
|
|
243
|
+
}
|
|
244
|
+
});
|
|
245
|
+
watch(modelValue, (value) => {
|
|
246
|
+
set(now, dayjs());
|
|
247
|
+
if (value === void 0) {
|
|
248
|
+
clear();
|
|
249
|
+
} else {
|
|
250
|
+
updateInternalModel(value);
|
|
251
|
+
}
|
|
252
|
+
});
|
|
253
|
+
onMounted(() => {
|
|
254
|
+
if (isDefined(modelValue)) {
|
|
255
|
+
updateInternalModel(get(modelValue));
|
|
256
|
+
} else if (!allowEmpty) {
|
|
257
|
+
setNow();
|
|
258
|
+
}
|
|
259
|
+
});
|
|
260
|
+
return {
|
|
261
|
+
clear,
|
|
262
|
+
getDateTime,
|
|
263
|
+
internalErrorMessages,
|
|
264
|
+
isDateValid,
|
|
265
|
+
maxAllowedDate,
|
|
266
|
+
minAllowedDate,
|
|
267
|
+
now,
|
|
268
|
+
segmentData,
|
|
269
|
+
selectedDate,
|
|
270
|
+
selectedDay,
|
|
271
|
+
selectedHour,
|
|
272
|
+
selectedMillisecond,
|
|
273
|
+
selectedMinute,
|
|
274
|
+
selectedMonth,
|
|
275
|
+
selectedSecond,
|
|
276
|
+
selectedTime,
|
|
277
|
+
selectedTimezone,
|
|
278
|
+
selectedYear,
|
|
279
|
+
setNow,
|
|
280
|
+
valueSet
|
|
281
|
+
};
|
|
282
|
+
}
|
|
283
|
+
export {
|
|
284
|
+
useDateTimeSelection
|
|
285
|
+
};
|
|
286
|
+
//# sourceMappingURL=use-date-time-selection.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-date-time-selection.js","sources":["../../../src/components/date-time-picker/use-date-time-selection.ts"],"sourcesContent":["import type { ComputedRef, Ref, WritableComputedRef } from 'vue';\nimport type { SegmentData } from '@/components/date-time-picker/types';\nimport type { TimeAccuracy } from '@/consts/time-accuracy';\nimport dayjs, { type Dayjs } from 'dayjs';\nimport { guessTimezone, includeMilliseconds, includeSeconds } from '@/components/date-time-picker/utils';\nimport { useRuiI8n } from '@/composables/use-rui-i18n';\nimport { RUI_I18N_KEYS } from '@/i18n/keys';\n\ntype DateTimeModelType = 'date' | 'epoch-ms' | 'epoch';\n\ntype ModelValueType<T extends DateTimeModelType> =\n T extends 'date' ? Date | undefined :\n T extends 'epoch-ms' ? number | undefined :\n T extends 'epoch' ? number | undefined :\n Date | number | undefined;\n\ninterface DateTimeSelectionOptions<T extends DateTimeModelType> {\n modelValue: Ref<ModelValueType<T>>;\n type: T;\n accuracy: TimeAccuracy;\n minDate: Date | number | undefined;\n maxDate: Date | number | 'now' | undefined;\n allowEmpty: boolean;\n}\n\ninterface DateTimeSelectionReturn {\n selectedYear: Ref<number | undefined>;\n selectedMonth: Ref<number | undefined>;\n selectedDay: Ref<number | undefined>;\n selectedHour: Ref<number | undefined>;\n selectedMinute: Ref<number | undefined>;\n selectedSecond: Ref<number | undefined>;\n selectedMillisecond: Ref<number | undefined>;\n selectedTimezone: Ref<string | undefined>;\n selectedDate: WritableComputedRef<Date | undefined>;\n selectedTime: WritableComputedRef<Date | undefined>;\n valueSet: ComputedRef<boolean>;\n internalErrorMessages: Ref<string[]>;\n now: Ref<Dayjs>;\n segmentData: SegmentData;\n minAllowedDate: ComputedRef<Date>;\n maxAllowedDate: ComputedRef<Date | undefined>;\n getDateTime: () => Dayjs;\n setNow: () => void;\n clear: () => void;\n isDateValid: (date: Dayjs) => boolean;\n}\n\nconst MILLISECONDS = 1000;\n\nexport function useDateTimeSelection<T extends DateTimeModelType>(\n options: DateTimeSelectionOptions<T>,\n): DateTimeSelectionReturn {\n const {\n accuracy,\n allowEmpty,\n maxDate,\n minDate,\n modelValue,\n type,\n } = options;\n\n const { t } = useRuiI8n();\n\n const selectedYear = ref<number | undefined>();\n const selectedMonth = ref<number | undefined>();\n const selectedDay = ref<number | undefined>();\n\n const selectedHour = ref<number | undefined>();\n const selectedMinute = ref<number | undefined>();\n const selectedSecond = ref<number | undefined>();\n const selectedMillisecond = ref<number | undefined>();\n const selectedTimezone = ref<string | undefined>(guessTimezone());\n\n const internalErrorMessages = ref<string[]>([]);\n const now = ref<Dayjs>(dayjs.tz(undefined, guessTimezone()));\n\n const minAllowedDate = computed<Date>(() => {\n if (minDate === undefined) {\n return new Date(1970, 0, 1);\n }\n\n if (type === 'epoch' && typeof minDate === 'number') {\n return new Date(minDate * MILLISECONDS);\n }\n\n return new Date(minDate);\n });\n\n const maxAllowedDate = computed<Date | undefined>(() => {\n if (maxDate === undefined) {\n return undefined;\n }\n if (maxDate === 'now') {\n return get(now).toDate();\n }\n if (type === 'epoch' && typeof maxDate === 'number') {\n return new Date(maxDate * MILLISECONDS);\n }\n return new Date(maxDate);\n });\n\n const segmentData: SegmentData = {\n DD: selectedDay,\n HH: selectedHour,\n MM: selectedMonth,\n SSS: selectedMillisecond,\n YYYY: selectedYear,\n mm: selectedMinute,\n ss: selectedSecond,\n };\n\n const selectedDate = computed<Date | undefined>({\n get() {\n if (!(isDefined(selectedYear) && isDefined(selectedMonth) && isDefined(selectedDay))) {\n return undefined;\n }\n const date = new Date();\n date.setFullYear(get(selectedYear));\n // Set day to 1 first to prevent month overflow when today's day > days in target month\n // e.g., if today is Dec 30 and we set month to Feb, day 30 would overflow to March\n date.setDate(1);\n date.setMonth(get(selectedMonth) - 1);\n date.setDate(get(selectedDay));\n return date;\n },\n set(value?: Date) {\n set(selectedYear, value?.getFullYear());\n set(selectedMonth, value ? value.getMonth() + 1 : undefined);\n set(selectedDay, value?.getDate());\n },\n });\n\n const selectedTime = computed<Date | undefined>({\n get() {\n if (!(isDefined(selectedHour) && isDefined(selectedMinute))) {\n return undefined;\n }\n const date = new Date();\n date.setHours(\n get(selectedHour),\n get(selectedMinute),\n get(selectedSecond) ?? 0,\n get(selectedMillisecond) ?? 0,\n );\n return date;\n },\n set(value?: Date) {\n set(selectedHour, value?.getHours());\n set(selectedMinute, value?.getMinutes());\n set(selectedSecond, value?.getSeconds());\n set(selectedMillisecond, value?.getMilliseconds());\n },\n });\n\n const valueSet = computed<boolean>(() => isDefined(selectedDate) && isDefined(selectedTime));\n\n function getDateTime(): Dayjs {\n let dateTime = dayjs();\n\n if (isDefined(selectedYear)) {\n dateTime = dateTime.year(get(selectedYear));\n }\n\n if (isDefined(selectedMonth)) {\n dateTime = dateTime.month(get(selectedMonth) - 1);\n }\n\n if (isDefined(selectedDay)) {\n const daysInMonth = dateTime.daysInMonth();\n const day = Math.min(get(selectedDay), daysInMonth);\n dateTime = dateTime.date(day);\n }\n\n if (isDefined(selectedHour)) {\n dateTime = dateTime.hour(get(selectedHour));\n }\n\n if (isDefined(selectedMinute)) {\n dateTime = dateTime.minute(get(selectedMinute));\n }\n\n if (isDefined(selectedSecond)) {\n dateTime = dateTime.second(get(selectedSecond));\n }\n\n if (isDefined(selectedMillisecond)) {\n dateTime = dateTime.millisecond(get(selectedMillisecond));\n }\n\n return dateTime;\n }\n\n function isDateValid(date: Dayjs): boolean {\n const min = get(minAllowedDate);\n const max = get(maxAllowedDate);\n\n set(internalErrorMessages, []);\n\n if (min && date.isBefore(min)) {\n const errorMessage = t(RUI_I18N_KEYS.dateTimePicker.dateBeforeMin, {\n date: min.toLocaleDateString(),\n }, `Date cannot be before ${min.toLocaleDateString()}`);\n set(internalErrorMessages, [...get(internalErrorMessages), errorMessage]);\n return false;\n }\n\n if (max && date.isAfter(max)) {\n const nowError = t(RUI_I18N_KEYS.dateTimePicker.dateInFuture, 'The selected date cannot be in the future');\n const maxError = t(RUI_I18N_KEYS.dateTimePicker.dateAfterMax, { date: max.toLocaleDateString() }, `Date cannot be after ${max.toLocaleDateString()}`);\n const errorMessage = maxDate === 'now' ? nowError : maxError;\n set(internalErrorMessages, [...get(internalErrorMessages), errorMessage]);\n return false;\n }\n\n return true;\n }\n\n function emitUpdate(updatedModel: Dayjs): void {\n const typeMap = {\n 'date': () => updatedModel.toDate(),\n 'epoch': () => updatedModel.valueOf() / MILLISECONDS,\n 'epoch-ms': () => updatedModel.valueOf(),\n } as const;\n\n set(modelValue, typeMap[type]() as ModelValueType<T>);\n }\n\n function updateModelValue(): void {\n if (!isDefined(selectedDate) || !isDefined(selectedTime)) {\n return;\n }\n\n if (!(isDefined(selectedDate) && isDefined(selectedTime))) {\n set(modelValue, undefined as ModelValueType<T>);\n }\n else {\n const date = get(selectedDate);\n const time = get(selectedTime);\n\n const updatedModel = dayjs.tz(isDefined(modelValue) ? get(modelValue) : undefined, get(selectedTimezone))\n .year(date.getFullYear())\n .month(date.getMonth())\n .date(date.getDate())\n .hour(time.getHours())\n .minute(time.getMinutes())\n .second(includeSeconds(accuracy) ? time.getSeconds() : 0)\n .millisecond(includeMilliseconds(accuracy) ? time.getMilliseconds() : 0);\n\n if (!isDateValid(updatedModel)) {\n return;\n }\n\n emitUpdate(updatedModel);\n }\n }\n\n function clear(): void {\n set(internalErrorMessages, []);\n set(selectedYear, undefined);\n set(selectedMonth, undefined);\n set(selectedDay, undefined);\n set(selectedHour, undefined);\n set(selectedMinute, undefined);\n set(selectedSecond, undefined);\n set(selectedMillisecond, undefined);\n set(modelValue, undefined as ModelValueType<T>);\n }\n\n function setNow(): void {\n set(internalErrorMessages, []);\n\n const date = dayjs();\n set(now, date);\n set(selectedYear, date.year());\n set(selectedMonth, date.month() + 1);\n set(selectedDay, date.date());\n set(selectedHour, date.hour());\n set(selectedMinute, date.minute());\n set(selectedSecond, includeSeconds(accuracy) ? date.second() : 0);\n set(selectedMillisecond, includeMilliseconds(accuracy) ? date.millisecond() : 0);\n\n nextTick(() => {\n updateModelValue();\n });\n }\n\n function updateSegments(date: Dayjs): void {\n const year = date.year();\n const month = date.month() + 1;\n const day = date.date();\n const hour = date.hour();\n const minute = date.minute();\n const second = includeSeconds(accuracy) ? date.second() : undefined;\n const millisecond = includeMilliseconds(accuracy) ? date.millisecond() : undefined;\n\n if (get(selectedYear) !== year)\n set(selectedYear, year);\n if (get(selectedMonth) !== month)\n set(selectedMonth, month);\n if (get(selectedDay) !== day)\n set(selectedDay, day);\n if (get(selectedHour) !== hour)\n set(selectedHour, hour);\n if (get(selectedMinute) !== minute)\n set(selectedMinute, minute);\n if (get(selectedSecond) !== second)\n set(selectedSecond, second);\n if (get(selectedMillisecond) !== millisecond)\n set(selectedMillisecond, millisecond);\n }\n\n const { ignoreUpdates } = watchIgnorable([selectedDate, selectedTime], ([newSelectedDate, newSelectedTime], [prevSelectedDate, prevSelectedTime]) => {\n const currentTimezone = get(selectedTimezone);\n const newDate = dayjs.tz(newSelectedDate, currentTimezone);\n const oldDate = dayjs.tz(prevSelectedDate, currentTimezone);\n const newTime = dayjs.tz(newSelectedTime, currentTimezone);\n const oldTime = dayjs.tz(prevSelectedTime, currentTimezone);\n\n if (newDate.isSame(oldDate) && newTime.isSame(oldTime)) {\n return;\n }\n\n set(now, dayjs());\n updateModelValue();\n });\n\n function updateInternalModel(value: ModelValueType<T>): void {\n ignoreUpdates(() => {\n const updatedValue = type === 'epoch' && typeof value === 'number'\n ? value * MILLISECONDS\n : value;\n const date = dayjs.tz(updatedValue, get(selectedTimezone));\n isDateValid(date);\n updateSegments(date);\n });\n }\n\n watch(selectedTimezone, (newTimezone: string | undefined) => {\n if (newTimezone && isDefined(selectedDate) && isDefined(selectedTime)) {\n set(now, dayjs());\n updateModelValue();\n }\n });\n\n watch(modelValue, (value) => {\n set(now, dayjs());\n if (value === undefined) {\n clear();\n }\n else {\n updateInternalModel(value);\n }\n });\n\n onMounted(() => {\n if (isDefined(modelValue)) {\n updateInternalModel(get(modelValue));\n }\n else if (!allowEmpty) {\n setNow();\n }\n });\n\n return {\n clear,\n getDateTime,\n internalErrorMessages,\n isDateValid,\n maxAllowedDate,\n minAllowedDate,\n now,\n segmentData,\n selectedDate,\n selectedDay,\n selectedHour,\n selectedMillisecond,\n selectedMinute,\n selectedMonth,\n selectedSecond,\n selectedTime,\n selectedTimezone,\n selectedYear,\n setNow,\n valueSet,\n };\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -22,11 +22,13 @@ interface KeyboardHandlerOptions {
|
|
|
22
22
|
export declare function useKeyboardHandler(options: KeyboardHandlerOptions): {
|
|
23
23
|
clear: (segmentType?: string) => void;
|
|
24
24
|
getCurrentSegment: (position?: number) => Segment | undefined;
|
|
25
|
+
handleBlur: () => void;
|
|
25
26
|
handleClick: (event: MouseEvent) => void;
|
|
26
27
|
handleFocus: () => void;
|
|
27
28
|
handleInput: (event: Event) => void;
|
|
28
29
|
handleInputSelection: (event: Event) => void;
|
|
29
30
|
handleKeyDown: (event: KeyboardEvent) => void;
|
|
31
|
+
handleMouseDown: (event: MouseEvent) => void;
|
|
30
32
|
handlePaste: (event: ClipboardEvent) => void;
|
|
31
33
|
setSegment: (segmentType: DateTimeSegmentType) => void;
|
|
32
34
|
};
|
|
@@ -5,6 +5,24 @@ import { assert } from "../../utils/assert.js";
|
|
|
5
5
|
import { computed, nextTick } from "vue";
|
|
6
6
|
import { get, set } from "@vueuse/shared";
|
|
7
7
|
import { isDefined } from "@vueuse/core";
|
|
8
|
+
const SEGMENT_METHODS = {
|
|
9
|
+
DD: "date",
|
|
10
|
+
HH: "hour",
|
|
11
|
+
MM: "month",
|
|
12
|
+
SSS: "millisecond",
|
|
13
|
+
YYYY: "year",
|
|
14
|
+
mm: "minute",
|
|
15
|
+
ss: "second"
|
|
16
|
+
};
|
|
17
|
+
const SEGMENT_CONFIG = {
|
|
18
|
+
DD: { maxValue: 31, minValue: 1 },
|
|
19
|
+
HH: { maxValue: 23, minValue: 0 },
|
|
20
|
+
MM: { maxValue: 12, minValue: 1 },
|
|
21
|
+
SSS: { maxValue: 999, minValue: 0 },
|
|
22
|
+
YYYY: { maxValue: 9999, minValue: 1 },
|
|
23
|
+
mm: { maxValue: 59, minValue: 0 },
|
|
24
|
+
ss: { maxValue: 59, minValue: 0 }
|
|
25
|
+
};
|
|
8
26
|
function useKeyboardHandler(options) {
|
|
9
27
|
const {
|
|
10
28
|
accuracy,
|
|
@@ -81,17 +99,8 @@ function useKeyboardHandler(options) {
|
|
|
81
99
|
const currentSegment = getCurrentSegment();
|
|
82
100
|
if (!currentSegment)
|
|
83
101
|
return;
|
|
84
|
-
const segmentMethods = {
|
|
85
|
-
DD: "date",
|
|
86
|
-
HH: "hour",
|
|
87
|
-
MM: "month",
|
|
88
|
-
mm: "minute",
|
|
89
|
-
ss: "second",
|
|
90
|
-
SSS: "millisecond",
|
|
91
|
-
YYYY: "year"
|
|
92
|
-
};
|
|
93
102
|
const segmentType = currentSegment.type;
|
|
94
|
-
const method =
|
|
103
|
+
const method = SEGMENT_METHODS[segmentType];
|
|
95
104
|
const selectedDate = getDateTime();
|
|
96
105
|
const updatedDate = selectedDate.set(method, selectedDate.get(method) + (increment ? 1 : -1));
|
|
97
106
|
if (updatedDate.year() >= 1970) {
|
|
@@ -127,57 +136,41 @@ function useKeyboardHandler(options) {
|
|
|
127
136
|
}
|
|
128
137
|
}
|
|
129
138
|
function handleDigitPressed(event, digit) {
|
|
130
|
-
if (!(event.target instanceof HTMLInputElement))
|
|
139
|
+
if (!(event.target instanceof HTMLInputElement))
|
|
131
140
|
return;
|
|
132
|
-
}
|
|
133
141
|
const position = event.target.selectionStart ?? 0;
|
|
134
142
|
const currentSegment = getCurrentSegment(position);
|
|
135
|
-
if (!currentSegment)
|
|
136
|
-
return;
|
|
137
|
-
const number = parseInt(digit);
|
|
138
|
-
if (isNaN(number))
|
|
143
|
+
if (!currentSegment || isNaN(parseInt(digit)))
|
|
139
144
|
return;
|
|
140
|
-
const segmentConfig = {
|
|
141
|
-
DD: { maxValue: 31, minValue: 1 },
|
|
142
|
-
HH: { maxValue: 23, minValue: 0 },
|
|
143
|
-
MM: { maxValue: 12, minValue: 1 },
|
|
144
|
-
mm: { maxValue: 59, minValue: 0 },
|
|
145
|
-
ss: { maxValue: 59, minValue: 0 },
|
|
146
|
-
SSS: { maxValue: 999, minValue: 0 },
|
|
147
|
-
YYYY: { maxValue: 9999, minValue: 1 }
|
|
148
|
-
};
|
|
149
145
|
const segmentType = currentSegment.type;
|
|
150
|
-
if (isDateTimeSegmentType(segmentType))
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
if (willExceedMax || reachedMaxLength) {
|
|
164
|
-
navigateSegments("ArrowRight");
|
|
165
|
-
}
|
|
146
|
+
if (!isDateTimeSegmentType(segmentType))
|
|
147
|
+
return;
|
|
148
|
+
const config = SEGMENT_CONFIG[segmentType];
|
|
149
|
+
const value = get(currentValue) ?? "";
|
|
150
|
+
const combinedStr = `${value}${digit}`;
|
|
151
|
+
const combinedValue = parseInt(combinedStr);
|
|
152
|
+
const maxLength = segmentType.length;
|
|
153
|
+
const minValue = config.minValue ?? 0;
|
|
154
|
+
if (combinedValue >= minValue && combinedValue <= config.maxValue) {
|
|
155
|
+
setValue(segmentType, combinedValue);
|
|
156
|
+
setCursorPosition(currentSegment);
|
|
157
|
+
} else if (combinedValue < minValue && combinedStr.length < maxLength) {
|
|
158
|
+
set(currentValue, combinedValue);
|
|
166
159
|
}
|
|
160
|
+
const willExceedMax = parseInt(`${combinedStr}0`) > config.maxValue;
|
|
161
|
+
if (willExceedMax || combinedStr.length >= maxLength)
|
|
162
|
+
navigateSegments("ArrowRight");
|
|
167
163
|
}
|
|
168
164
|
function handleKeyboardNavigation(event) {
|
|
169
|
-
if (event.key === "ArrowUp")
|
|
165
|
+
if (event.key === "ArrowUp")
|
|
170
166
|
changeSegmentValue(true);
|
|
171
|
-
|
|
167
|
+
else if (event.key === "ArrowDown")
|
|
172
168
|
changeSegmentValue(false);
|
|
173
|
-
}
|
|
174
169
|
}
|
|
175
170
|
function handleBackspace(event) {
|
|
176
|
-
if (!(event.target instanceof HTMLInputElement))
|
|
171
|
+
if (!(event.target instanceof HTMLInputElement))
|
|
177
172
|
return;
|
|
178
|
-
|
|
179
|
-
const position = event.target.selectionStart ?? 0;
|
|
180
|
-
const currentSegment = getCurrentSegment(position);
|
|
173
|
+
const currentSegment = getCurrentSegment(event.target.selectionStart ?? 0);
|
|
181
174
|
if (!currentSegment)
|
|
182
175
|
return;
|
|
183
176
|
const value = get(currentValue) ?? getCurrent(currentSegment.type) ?? "";
|
|
@@ -186,11 +179,9 @@ function useKeyboardHandler(options) {
|
|
|
186
179
|
setCursorPosition(currentSegment);
|
|
187
180
|
}
|
|
188
181
|
function onInputDeletePressed(event) {
|
|
189
|
-
if (!(event.target instanceof HTMLInputElement))
|
|
182
|
+
if (!(event.target instanceof HTMLInputElement))
|
|
190
183
|
return;
|
|
191
|
-
|
|
192
|
-
const selectionStart = event.target.selectionStart ?? 0;
|
|
193
|
-
const segment = getCurrentSegment(selectionStart);
|
|
184
|
+
const segment = getCurrentSegment(event.target.selectionStart ?? 0);
|
|
194
185
|
if (segment) {
|
|
195
186
|
clear(segment.type);
|
|
196
187
|
setCursorPosition(segment);
|
|
@@ -200,21 +191,19 @@ function useKeyboardHandler(options) {
|
|
|
200
191
|
if (disabled || readonly)
|
|
201
192
|
return;
|
|
202
193
|
const { key } = event;
|
|
203
|
-
if (
|
|
194
|
+
if (key === "Tab")
|
|
204
195
|
return;
|
|
205
|
-
}
|
|
206
196
|
event.preventDefault();
|
|
207
|
-
if (key === "ArrowRight" || key === "ArrowLeft")
|
|
197
|
+
if (key === "ArrowRight" || key === "ArrowLeft")
|
|
208
198
|
navigateSegments(key);
|
|
209
|
-
|
|
199
|
+
else if (key === "ArrowUp" || key === "ArrowDown")
|
|
210
200
|
handleKeyboardNavigation(event);
|
|
211
|
-
|
|
201
|
+
else if (key === "Backspace")
|
|
212
202
|
handleBackspace(event);
|
|
213
|
-
|
|
203
|
+
else if (key === "Delete")
|
|
214
204
|
onInputDeletePressed(event);
|
|
215
|
-
|
|
205
|
+
else if (/^\d$/.test(key))
|
|
216
206
|
handleDigitPressed(event, key);
|
|
217
|
-
}
|
|
218
207
|
}
|
|
219
208
|
function getClickPosition(event, input, useCaretPosition) {
|
|
220
209
|
const fallback = input.selectionStart ?? 0;
|
|
@@ -223,11 +212,21 @@ function useKeyboardHandler(options) {
|
|
|
223
212
|
return caretPos.offset;
|
|
224
213
|
return document.caretRangeFromPoint?.(event.clientX, event.clientY)?.startOffset ?? fallback;
|
|
225
214
|
}
|
|
215
|
+
let clickedSegment;
|
|
216
|
+
function handleMouseDown(event) {
|
|
217
|
+
if (disabled || readonly || !(event.target instanceof HTMLInputElement))
|
|
218
|
+
return;
|
|
219
|
+
const currentSegment = getCurrentSegment(getClickPosition(event, event.target));
|
|
220
|
+
if (currentSegment) {
|
|
221
|
+
clickedSegment = currentSegment;
|
|
222
|
+
}
|
|
223
|
+
}
|
|
226
224
|
function handleClick(event) {
|
|
227
225
|
if (disabled || readonly || !(event.target instanceof HTMLInputElement))
|
|
228
226
|
return;
|
|
229
227
|
const currentSegment = getCurrentSegment(getClickPosition(event, event.target));
|
|
230
228
|
if (currentSegment) {
|
|
229
|
+
clickedSegment = currentSegment;
|
|
231
230
|
set(cursorPosition, currentSegment.end);
|
|
232
231
|
event.target.setSelectionRange(currentSegment.start, currentSegment.end);
|
|
233
232
|
}
|
|
@@ -237,6 +236,11 @@ function useKeyboardHandler(options) {
|
|
|
237
236
|
set(cursorPosition, target.selectionStart ?? 0);
|
|
238
237
|
}
|
|
239
238
|
function handleFocus() {
|
|
239
|
+
if (clickedSegment) {
|
|
240
|
+
setCursorPosition(clickedSegment);
|
|
241
|
+
clickedSegment = void 0;
|
|
242
|
+
return;
|
|
243
|
+
}
|
|
240
244
|
const input = get(textInput);
|
|
241
245
|
if (input && input.selectionStart !== input.selectionEnd)
|
|
242
246
|
return;
|
|
@@ -244,6 +248,11 @@ function useKeyboardHandler(options) {
|
|
|
244
248
|
if (firstSegment)
|
|
245
249
|
setCursorPosition(firstSegment);
|
|
246
250
|
}
|
|
251
|
+
function handleBlur() {
|
|
252
|
+
set(cursorPosition, 0);
|
|
253
|
+
set(currentValue, void 0);
|
|
254
|
+
clickedSegment = void 0;
|
|
255
|
+
}
|
|
247
256
|
function parseAndSetDateValues(pastedText) {
|
|
248
257
|
try {
|
|
249
258
|
const parsedDate = dayjs(pastedText, get(dateFormat));
|
|
@@ -293,11 +302,13 @@ function useKeyboardHandler(options) {
|
|
|
293
302
|
return {
|
|
294
303
|
clear,
|
|
295
304
|
getCurrentSegment,
|
|
305
|
+
handleBlur,
|
|
296
306
|
handleClick,
|
|
297
307
|
handleFocus,
|
|
298
308
|
handleInput,
|
|
299
309
|
handleInputSelection,
|
|
300
310
|
handleKeyDown,
|
|
311
|
+
handleMouseDown,
|
|
301
312
|
handlePaste,
|
|
302
313
|
setSegment
|
|
303
314
|
};
|