vueless 0.0.568 → 0.0.569
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/package.json +1 -1
- package/ui.form-calendar/UCalendar.vue +14 -25
- package/ui.form-calendar/config.ts +3 -0
- package/ui.form-calendar/constants.ts +0 -2
- package/ui.form-calendar/useAttrs.ts +1 -1
- package/ui.form-calendar/utilCalendar.ts +16 -9
- package/ui.form-calendar/utilFormatting.ts +63 -11
- package/ui.form-date-picker/UDatePicker.vue +109 -43
- package/ui.form-date-picker/config.ts +5 -5
- package/ui.form-date-picker-range/useAttrs.ts +1 -1
- package/ui.form-date-picker-range/useLocale.ts +1 -1
- package/ui.form-input/UInput.vue +20 -0
- package/web-types.json +11 -3
package/package.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<script setup lang="ts" generic="TModelValue extends DateValue">
|
|
2
|
-
import { computed, ref, watch, useTemplateRef } from "vue";
|
|
2
|
+
import { computed, ref, watch, useTemplateRef, onMounted } from "vue";
|
|
3
3
|
import { merge } from "lodash-es";
|
|
4
4
|
|
|
5
5
|
import UButton from "../ui.button/UButton.vue";
|
|
@@ -195,7 +195,7 @@ const userFormatLocale = computed(() => {
|
|
|
195
195
|
|
|
196
196
|
// formatted locale
|
|
197
197
|
return {
|
|
198
|
-
...currentLocale,
|
|
198
|
+
...currentLocale.value,
|
|
199
199
|
months: {
|
|
200
200
|
shorthand: getSortedLocale(months.shorthand, LocaleType.Month),
|
|
201
201
|
longhand: getSortedLocale(monthsLonghand, LocaleType.Month),
|
|
@@ -333,31 +333,19 @@ watch(
|
|
|
333
333
|
},
|
|
334
334
|
);
|
|
335
335
|
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
if (isInit) unwatchInit();
|
|
342
|
-
|
|
343
|
-
if (selectedDate.value && isTimepickerEnabled.value && isInputRefs.value && props.timepicker) {
|
|
344
|
-
hoursRef.value!.value = String(selectedDate.value.getHours()).padStart(2, "0");
|
|
345
|
-
minutesRef.value!.value = String(selectedDate.value.getMinutes()).padStart(2, "0");
|
|
346
|
-
secondsRef.value!.value = String(selectedDate.value.getSeconds()).padStart(2, "0");
|
|
336
|
+
onMounted(() => {
|
|
337
|
+
if (selectedDate.value && isTimepickerEnabled.value && isInputRefs.value && props.timepicker) {
|
|
338
|
+
hoursRef.value!.value = String(selectedDate.value.getHours()).padStart(2, "0");
|
|
339
|
+
minutesRef.value!.value = String(selectedDate.value.getMinutes()).padStart(2, "0");
|
|
340
|
+
secondsRef.value!.value = String(selectedDate.value.getSeconds()).padStart(2, "0");
|
|
347
341
|
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
isInit = true;
|
|
351
|
-
}
|
|
352
|
-
|
|
353
|
-
if (selectedDate.value) {
|
|
354
|
-
emit("userDateChange", userFormattedDate.value);
|
|
342
|
+
emit("userDateChange", userFormattedDate.value);
|
|
343
|
+
}
|
|
355
344
|
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
}
|
|
359
|
-
|
|
360
|
-
);
|
|
345
|
+
if (selectedDate.value) {
|
|
346
|
+
emit("userDateChange", userFormattedDate.value);
|
|
347
|
+
}
|
|
348
|
+
});
|
|
361
349
|
|
|
362
350
|
function getCurrentValueType(value: DateValue): DateValue {
|
|
363
351
|
if (props.range && value === null) {
|
|
@@ -543,6 +531,7 @@ function enterKeyHandler() {
|
|
|
543
531
|
activeMonth.value = null;
|
|
544
532
|
|
|
545
533
|
emit("input", localValue.value);
|
|
534
|
+
emit("submit");
|
|
546
535
|
}
|
|
547
536
|
|
|
548
537
|
if (isCurrentView.value.month) currentView.value = View.Day;
|
|
@@ -70,6 +70,9 @@ export default /*tw*/ {
|
|
|
70
70
|
timepickerInputSeconds: "{>timepickerInput} rounded-r-dynamic",
|
|
71
71
|
timepickerSubmitButton: "{UButton} py-2 border-0",
|
|
72
72
|
i18n: {
|
|
73
|
+
today: "Today,",
|
|
74
|
+
yesterday: "Yesterday,",
|
|
75
|
+
tomorrow: "Tomorrow,",
|
|
73
76
|
weekdays: {
|
|
74
77
|
shorthand: {
|
|
75
78
|
sunday: "Sun",
|
|
@@ -49,7 +49,7 @@ export function isNumeric(char: string | number) {
|
|
|
49
49
|
return /^\d+$/.test(String(char));
|
|
50
50
|
}
|
|
51
51
|
|
|
52
|
-
export function parseDate<TLocale>(
|
|
52
|
+
export function parseDate<TLocale extends DateLocale>(
|
|
53
53
|
date: Date | string | null,
|
|
54
54
|
format: string = "Y-m-d H:i:S",
|
|
55
55
|
locale: TLocale,
|
|
@@ -96,7 +96,7 @@ export function parseDate<TLocale>(
|
|
|
96
96
|
return parsedDate;
|
|
97
97
|
}
|
|
98
98
|
|
|
99
|
-
export function parseStringDate<TLocale>(
|
|
99
|
+
export function parseStringDate<TLocale extends DateLocale>(
|
|
100
100
|
dateString: string,
|
|
101
101
|
format = "Y-m-d H:i:S",
|
|
102
102
|
locale: TLocale,
|
|
@@ -108,6 +108,14 @@ export function parseStringDate<TLocale>(
|
|
|
108
108
|
} else {
|
|
109
109
|
let parsedDate = new Date(new Date().getFullYear(), 0, 1, 0, 0, 0, 0);
|
|
110
110
|
|
|
111
|
+
const isRelativeDay = [locale.tomorrow, locale.today, locale.tomorrow].some((word) => {
|
|
112
|
+
return dateString.toLowerCase().includes(word.toLowerCase());
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
if (!isRelativeDay) {
|
|
116
|
+
format = format.replaceAll("r", "").trim();
|
|
117
|
+
}
|
|
118
|
+
|
|
111
119
|
let matched;
|
|
112
120
|
const operations: Operation[] = [];
|
|
113
121
|
|
|
@@ -130,20 +138,19 @@ export function parseStringDate<TLocale>(
|
|
|
130
138
|
} else if (!isBackSlash) {
|
|
131
139
|
regexStr += ".";
|
|
132
140
|
}
|
|
141
|
+
}
|
|
133
142
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
const { val } = op;
|
|
143
|
+
operations.forEach((operation) => {
|
|
144
|
+
const { fn, val } = operation;
|
|
137
145
|
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
}
|
|
146
|
+
parsedDate = (fn(parsedDate, String(val), locale as DateLocale) || parsedDate) as Date;
|
|
147
|
+
});
|
|
141
148
|
|
|
142
149
|
return matched ? parsedDate : undefined;
|
|
143
150
|
}
|
|
144
151
|
}
|
|
145
152
|
|
|
146
|
-
export function dateIsOutOfRange<TLocale>(
|
|
153
|
+
export function dateIsOutOfRange<TLocale extends DateLocale>(
|
|
147
154
|
date: Date,
|
|
148
155
|
min: Date | string | undefined,
|
|
149
156
|
max: Date | string | undefined,
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { addDays, isSameDay } from "./utilDate";
|
|
2
|
+
|
|
1
3
|
export interface DateLocale {
|
|
2
4
|
weekdays: {
|
|
3
5
|
shorthand: string[];
|
|
@@ -9,6 +11,9 @@ export interface DateLocale {
|
|
|
9
11
|
longhand: string[];
|
|
10
12
|
userFormat?: unknown;
|
|
11
13
|
};
|
|
14
|
+
today: string;
|
|
15
|
+
tomorrow: string;
|
|
16
|
+
yesterday: string;
|
|
12
17
|
}
|
|
13
18
|
|
|
14
19
|
const pad = (number: number, length = 2) => `000${number}`.slice(length * -1);
|
|
@@ -21,27 +26,41 @@ export const monthToStr = (monthNumber: number, shorthand: boolean, locale: Date
|
|
|
21
26
|
|
|
22
27
|
export const revFormat = {
|
|
23
28
|
D: doNothing,
|
|
24
|
-
|
|
25
|
-
|
|
29
|
+
|
|
30
|
+
F: (dateObj: Date, monthName: string, locale: DateLocale) => {
|
|
31
|
+
const monthIndex = locale.months.longhand.findIndex((longMonth) => {
|
|
32
|
+
return longMonth.toLowerCase().trim() === monthName.toLowerCase().trim();
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
dateObj.setMonth(monthIndex);
|
|
26
36
|
},
|
|
37
|
+
|
|
27
38
|
G: (dateObj: Date, hour: number | string) => {
|
|
28
39
|
dateObj.setHours(parseFloat(String(hour)));
|
|
29
40
|
},
|
|
41
|
+
|
|
30
42
|
H: (dateObj: Date, hour: number | string) => {
|
|
31
43
|
dateObj.setHours(parseFloat(String(hour)));
|
|
32
44
|
},
|
|
45
|
+
|
|
33
46
|
J: (dateObj: Date, day: number | string) => {
|
|
34
47
|
dateObj.setDate(parseFloat(String(day)));
|
|
35
48
|
},
|
|
36
|
-
|
|
37
|
-
|
|
49
|
+
|
|
50
|
+
M: (dateObj: Date, monthName: string, locale: DateLocale) => {
|
|
51
|
+
const monthIndex = locale.months.shorthand.findIndex((shortMonth) => {
|
|
52
|
+
return shortMonth.toLowerCase().trim() === monthName.toLowerCase().trim();
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
dateObj.setMonth(monthIndex);
|
|
38
56
|
},
|
|
39
57
|
S: (dateObj: Date, seconds: number | string) => {
|
|
40
58
|
dateObj.setSeconds(parseFloat(String(seconds)));
|
|
41
59
|
},
|
|
60
|
+
|
|
42
61
|
U: (_: unknown, unixSeconds: string | number) => new Date(parseFloat(String(unixSeconds)) * 1000),
|
|
43
62
|
|
|
44
|
-
W(dateObj: Date, weekNum: number | string) {
|
|
63
|
+
W: (dateObj: Date, weekNum: number | string) => {
|
|
45
64
|
const weekNumber = parseInt(String(weekNum), 10);
|
|
46
65
|
const date = new Date(dateObj.getFullYear(), 0, 2 + (weekNumber - 1) * 7, 0, 0, 0, 0);
|
|
47
66
|
|
|
@@ -49,6 +68,7 @@ export const revFormat = {
|
|
|
49
68
|
|
|
50
69
|
return date;
|
|
51
70
|
},
|
|
71
|
+
|
|
52
72
|
Y: (dateObj: Date, year: number | string) => {
|
|
53
73
|
dateObj.setFullYear(parseFloat(String(year)));
|
|
54
74
|
},
|
|
@@ -57,31 +77,42 @@ export const revFormat = {
|
|
|
57
77
|
d: (dateObj: Date, day: number | string) => {
|
|
58
78
|
dateObj.setDate(parseFloat(String(day)));
|
|
59
79
|
},
|
|
80
|
+
|
|
60
81
|
h: (dateObj: Date, hour: number | string) => {
|
|
61
82
|
dateObj.setHours(parseFloat(String(hour)));
|
|
62
83
|
},
|
|
84
|
+
|
|
63
85
|
i: (dateObj: Date, minutes: number | string) => {
|
|
64
86
|
dateObj.setMinutes(parseFloat(String(minutes)));
|
|
65
87
|
},
|
|
88
|
+
|
|
66
89
|
j: (dateObj: Date, day: number | string) => {
|
|
67
90
|
dateObj.setDate(parseFloat(String(day)));
|
|
68
91
|
},
|
|
92
|
+
|
|
69
93
|
l: doNothing,
|
|
94
|
+
|
|
70
95
|
m: (dateObj: Date, month: number | string) => {
|
|
71
96
|
dateObj.setMonth(parseFloat(String(month)) - 1);
|
|
72
97
|
},
|
|
98
|
+
|
|
73
99
|
n: (dateObj: Date, month: number | string) => {
|
|
74
100
|
dateObj.setMonth(parseFloat(String(month)) - 1);
|
|
75
101
|
},
|
|
102
|
+
|
|
76
103
|
s: (dateObj: Date, seconds: number | string) => {
|
|
77
104
|
dateObj.setSeconds(parseFloat(String(seconds)));
|
|
78
105
|
},
|
|
106
|
+
|
|
79
107
|
u: (_: unknown, unixMillSeconds: number | string) =>
|
|
80
108
|
new Date(parseFloat(String(unixMillSeconds))),
|
|
81
109
|
w: doNothing,
|
|
110
|
+
|
|
82
111
|
y: (dateObj: Date, year: number | string) => {
|
|
83
112
|
dateObj.setFullYear(2000 + parseFloat(String(year)));
|
|
84
113
|
},
|
|
114
|
+
|
|
115
|
+
r: doNothing,
|
|
85
116
|
};
|
|
86
117
|
|
|
87
118
|
export const formats = {
|
|
@@ -89,17 +120,17 @@ export const formats = {
|
|
|
89
120
|
Z: (date: Date) => date.toISOString(),
|
|
90
121
|
|
|
91
122
|
// weekday name, short, e.g. Thu
|
|
92
|
-
D(date: Date, locale: DateLocale) {
|
|
123
|
+
D: (date: Date, locale: DateLocale) => {
|
|
93
124
|
return locale.weekdays.shorthand[formats.w(date)];
|
|
94
125
|
},
|
|
95
126
|
|
|
96
127
|
// full month name e.g. January
|
|
97
|
-
F(date: Date, locale: DateLocale) {
|
|
128
|
+
F: (date: Date, locale: DateLocale) => {
|
|
98
129
|
return monthToStr(formats.n(date) - 1, false, locale);
|
|
99
130
|
},
|
|
100
131
|
|
|
101
132
|
// padded hour 1-12
|
|
102
|
-
G(date: Date) {
|
|
133
|
+
G: (date: Date) => {
|
|
103
134
|
return pad(formats.h(date));
|
|
104
135
|
},
|
|
105
136
|
|
|
@@ -107,7 +138,7 @@ export const formats = {
|
|
|
107
138
|
H: (date: Date) => pad(date.getHours()),
|
|
108
139
|
|
|
109
140
|
// shorthand month e.g. Jan, Sep, Oct, etc
|
|
110
|
-
M(date: Date, locale: DateLocale) {
|
|
141
|
+
M: (date: Date, locale: DateLocale) => {
|
|
111
142
|
return monthToStr(date.getMonth(), true, locale);
|
|
112
143
|
},
|
|
113
144
|
|
|
@@ -117,7 +148,7 @@ export const formats = {
|
|
|
117
148
|
// unix timestamp
|
|
118
149
|
U: (date: Date) => date.getTime() / 1000,
|
|
119
150
|
|
|
120
|
-
W(date: Date) {
|
|
151
|
+
W: (date: Date) => {
|
|
121
152
|
// return options.getWeek(date);
|
|
122
153
|
const localDate = new Date(date.getTime());
|
|
123
154
|
|
|
@@ -154,7 +185,7 @@ export const formats = {
|
|
|
154
185
|
j: (date: Date) => date.getDate(),
|
|
155
186
|
|
|
156
187
|
// weekday name, full, e.g. Thursday
|
|
157
|
-
l(date: Date, locale: DateLocale) {
|
|
188
|
+
l: (date: Date, locale: DateLocale) => {
|
|
158
189
|
return locale.weekdays.longhand[date.getDay()];
|
|
159
190
|
},
|
|
160
191
|
|
|
@@ -175,4 +206,25 @@ export const formats = {
|
|
|
175
206
|
|
|
176
207
|
// last two digits of year e.g. 16 for 2016
|
|
177
208
|
y: (date: Date) => String(date.getFullYear()).substring(2),
|
|
209
|
+
|
|
210
|
+
r: (date: Date, locale: DateLocale) => {
|
|
211
|
+
const today = new Date();
|
|
212
|
+
const isToday = isSameDay(today, date);
|
|
213
|
+
const isYesterday = isSameDay(addDays(today, -1), date);
|
|
214
|
+
const isTomorrow = isSameDay(addDays(today, 1), date);
|
|
215
|
+
|
|
216
|
+
if (isToday) {
|
|
217
|
+
return `${locale.today}`;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
if (isYesterday) {
|
|
221
|
+
return `${locale.yesterday}`;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
if (isTomorrow) {
|
|
225
|
+
return `${locale.tomorrow}`;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
return "";
|
|
229
|
+
},
|
|
178
230
|
};
|
|
@@ -5,22 +5,25 @@ import { merge } from "lodash-es";
|
|
|
5
5
|
import UIcon from "../ui.image-icon/UIcon.vue";
|
|
6
6
|
import UInput from "../ui.form-input/UInput.vue";
|
|
7
7
|
import UCalendar from "../ui.form-calendar/UCalendar.vue";
|
|
8
|
-
import { View,
|
|
8
|
+
import { View, LocaleType, ARROW_KEYS, TOKEN_REG_EXP } from "../ui.form-calendar/constants.ts";
|
|
9
9
|
|
|
10
10
|
import { getDefault } from "../utils/ui.ts";
|
|
11
11
|
|
|
12
|
-
import {
|
|
13
|
-
import { parseDate } from "../ui.form-calendar/utilCalendar.ts";
|
|
12
|
+
import { getSortedLocale } from "../ui.form-calendar/utilDate.ts";
|
|
13
|
+
import { formatDate, parseDate } from "../ui.form-calendar/utilCalendar.ts";
|
|
14
14
|
|
|
15
15
|
import useAttrs from "./useAttrs.js";
|
|
16
16
|
import { useLocale } from "../composables/useLocale.ts";
|
|
17
17
|
import { useAutoPosition } from "../composables/useAutoPosition.ts";
|
|
18
18
|
|
|
19
|
-
import defaultConfig from "./config.
|
|
20
|
-
import { UDatePicker } from "./constants.
|
|
19
|
+
import defaultConfig from "./config.ts";
|
|
20
|
+
import { UDatePicker } from "./constants.ts";
|
|
21
|
+
|
|
22
|
+
import { vClickOutside } from "../directives";
|
|
21
23
|
|
|
22
24
|
import type { UDatePickerProps } from "./types.ts";
|
|
23
25
|
import type { ComponentExposed } from "../types.ts";
|
|
26
|
+
import type { DateLocale } from "../ui.form-calendar/utilFormatting.ts";
|
|
24
27
|
|
|
25
28
|
defineOptions({ inheritAttrs: false });
|
|
26
29
|
|
|
@@ -65,6 +68,7 @@ const userFormatDate = ref("");
|
|
|
65
68
|
const formattedDate = ref("");
|
|
66
69
|
const customView = ref(View.Day);
|
|
67
70
|
|
|
71
|
+
const datepickerInputRef = useTemplateRef<typeof UInput>("input");
|
|
68
72
|
const wrapperRef = useTemplateRef<HTMLDivElement>("wrapper");
|
|
69
73
|
const calendarRef = useTemplateRef<ComponentExposed<typeof UCalendar>>("calendar");
|
|
70
74
|
|
|
@@ -84,6 +88,25 @@ const localValue = computed({
|
|
|
84
88
|
|
|
85
89
|
const currentLocale = computed(() => merge(defaultConfig.i18n, i18nGlobal, props.config.i18n));
|
|
86
90
|
|
|
91
|
+
const clickOutsideOptions = computed(() => ({ ignore: [datepickerInputRef.value?.inputRef] }));
|
|
92
|
+
|
|
93
|
+
const locale = computed(() => {
|
|
94
|
+
const { months, weekdays } = currentLocale.value;
|
|
95
|
+
|
|
96
|
+
// formatted locale
|
|
97
|
+
return {
|
|
98
|
+
...currentLocale.value,
|
|
99
|
+
months: {
|
|
100
|
+
shorthand: getSortedLocale(months.shorthand, LocaleType.Month),
|
|
101
|
+
longhand: getSortedLocale(months.longhand, LocaleType.Month),
|
|
102
|
+
},
|
|
103
|
+
weekdays: {
|
|
104
|
+
shorthand: getSortedLocale(weekdays.shorthand, LocaleType.Day),
|
|
105
|
+
longhand: getSortedLocale(weekdays.longhand, LocaleType.Day),
|
|
106
|
+
},
|
|
107
|
+
} as DateLocale;
|
|
108
|
+
});
|
|
109
|
+
|
|
87
110
|
const elementId = props.id || useId();
|
|
88
111
|
|
|
89
112
|
const { config, datepickerInputAttrs, datepickerInputActiveAttrs, calendarAttrs, wrapperAttrs } =
|
|
@@ -98,8 +121,6 @@ function activate() {
|
|
|
98
121
|
nextTick(() => {
|
|
99
122
|
adjustPositionY();
|
|
100
123
|
adjustPositionX();
|
|
101
|
-
|
|
102
|
-
calendarRef.value?.wrapperRef?.focus();
|
|
103
124
|
});
|
|
104
125
|
}
|
|
105
126
|
|
|
@@ -110,53 +131,93 @@ function deactivate() {
|
|
|
110
131
|
}
|
|
111
132
|
|
|
112
133
|
function onUserFormatDateChange(value: string) {
|
|
113
|
-
userFormatDate.value =
|
|
134
|
+
userFormatDate.value = value.trim();
|
|
114
135
|
}
|
|
115
136
|
|
|
116
137
|
function onSubmit() {
|
|
117
138
|
deactivate();
|
|
118
139
|
}
|
|
119
140
|
|
|
120
|
-
function
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
141
|
+
function onInput() {
|
|
142
|
+
nextTick(() => {
|
|
143
|
+
deactivate();
|
|
144
|
+
emit("input", localValue.value);
|
|
145
|
+
});
|
|
124
146
|
}
|
|
125
147
|
|
|
126
|
-
function
|
|
127
|
-
if (
|
|
128
|
-
|
|
129
|
-
let prefix = "";
|
|
130
|
-
const formattedDate = data.charAt(0).toUpperCase() + data.toLowerCase().slice(1);
|
|
131
|
-
const formattedDateWithoutDay = formattedDate.split(",").slice(1).join("").trim();
|
|
132
|
-
|
|
133
|
-
const today = new Date();
|
|
134
|
-
|
|
135
|
-
const parsedLocalDate = parseDate(localValue.value, props.dateFormat, currentLocale.value);
|
|
136
|
-
const isToday = parsedLocalDate && isSameDay(today, parsedLocalDate);
|
|
137
|
-
const isYesterday = parsedLocalDate && isSameDay(addDays(today, -1), parsedLocalDate);
|
|
138
|
-
const isTomorrow = parsedLocalDate && isSameDay(addDays(today, 1), parsedLocalDate);
|
|
139
|
-
|
|
140
|
-
if (isToday) {
|
|
141
|
-
prefix = currentLocale.value.today;
|
|
148
|
+
function onTextInput() {
|
|
149
|
+
if (datepickerInputRef.value?.inputRef) {
|
|
150
|
+
datepickerInputRef.value.inputRef.value = userFormatDate.value;
|
|
142
151
|
}
|
|
152
|
+
}
|
|
143
153
|
|
|
144
|
-
|
|
145
|
-
|
|
154
|
+
function onPaste(event: ClipboardEvent) {
|
|
155
|
+
try {
|
|
156
|
+
const pasteContent = event.clipboardData ? event.clipboardData.getData("text/plain") : "";
|
|
157
|
+
const userFormat = props.timepicker ? props.userDateTimeFormat : props.userDateFormat;
|
|
158
|
+
const relativeTokensAmount = Number(userFormat.match(/(?<!\\)r/g)?.length);
|
|
159
|
+
|
|
160
|
+
// Amount of tokens used in format string without decimeters.
|
|
161
|
+
const tokensAmount = userFormat
|
|
162
|
+
.split("")
|
|
163
|
+
.filter((char) => Object.keys(TOKEN_REG_EXP).includes(char)).length;
|
|
164
|
+
|
|
165
|
+
// Amount of substring that satisfies format tokens.
|
|
166
|
+
let pastedTokensAmount = pasteContent
|
|
167
|
+
.replace(/[^a-zA-Z0-9]/g, " ")
|
|
168
|
+
.replace(/\s+/g, " ")
|
|
169
|
+
.trim()
|
|
170
|
+
.split(" ").length;
|
|
171
|
+
|
|
172
|
+
const isPastedRelativeDay = [
|
|
173
|
+
locale.value.tomorrow,
|
|
174
|
+
locale.value.today,
|
|
175
|
+
locale.value.tomorrow,
|
|
176
|
+
].some((word) => {
|
|
177
|
+
return pasteContent.includes(word);
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
if (isPastedRelativeDay) {
|
|
181
|
+
pastedTokensAmount -= relativeTokensAmount;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
if (pastedTokensAmount !== tokensAmount) return;
|
|
185
|
+
|
|
186
|
+
const parsedDate = parseDate(pasteContent, userFormat, locale.value);
|
|
187
|
+
|
|
188
|
+
if (parsedDate) {
|
|
189
|
+
localValue.value = (
|
|
190
|
+
props.dateFormat ? formatDate(parsedDate, props.dateFormat, locale.value) : parsedDate
|
|
191
|
+
) as TModelValue;
|
|
192
|
+
}
|
|
193
|
+
} catch (error) {
|
|
194
|
+
// eslint-disable-next-line no-console
|
|
195
|
+
console.log(error);
|
|
146
196
|
}
|
|
197
|
+
}
|
|
147
198
|
|
|
148
|
-
|
|
149
|
-
|
|
199
|
+
function onCopy(event: ClipboardEvent) {
|
|
200
|
+
const target = event.target as HTMLInputElement;
|
|
201
|
+
|
|
202
|
+
const cursorStart = target.selectionStart || 0;
|
|
203
|
+
const cursorEnd = target.selectionEnd || 0;
|
|
204
|
+
|
|
205
|
+
try {
|
|
206
|
+
if (cursorStart !== cursorEnd) {
|
|
207
|
+
navigator.clipboard.writeText(target.value.substring(cursorStart, cursorEnd));
|
|
208
|
+
} else {
|
|
209
|
+
navigator.clipboard.writeText(target.value);
|
|
210
|
+
}
|
|
211
|
+
} catch (error) {
|
|
212
|
+
// eslint-disable-next-line no-console
|
|
213
|
+
console.error(error);
|
|
150
214
|
}
|
|
151
|
-
|
|
152
|
-
return prefix ? `${prefix}, ${formattedDateWithoutDay}` : formattedDate;
|
|
153
215
|
}
|
|
154
216
|
|
|
155
|
-
function
|
|
156
|
-
|
|
157
|
-
calendarRef.value?.wrapperRef?.
|
|
158
|
-
|
|
159
|
-
});
|
|
217
|
+
function onTextInputKeyDown(event: KeyboardEvent) {
|
|
218
|
+
if (ARROW_KEYS.includes(event.code)) {
|
|
219
|
+
calendarRef.value?.wrapperRef?.focus();
|
|
220
|
+
}
|
|
160
221
|
}
|
|
161
222
|
|
|
162
223
|
defineExpose({
|
|
@@ -184,20 +245,25 @@ defineExpose({
|
|
|
184
245
|
<div v-bind="wrapperAttrs" ref="wrapper">
|
|
185
246
|
<UInput
|
|
186
247
|
:id="elementId"
|
|
187
|
-
:key="String(
|
|
188
|
-
|
|
248
|
+
:key="String(localValue)"
|
|
249
|
+
ref="input"
|
|
250
|
+
:model-value="userFormatDate"
|
|
189
251
|
:label-align="labelAlign"
|
|
190
252
|
:label="label"
|
|
191
253
|
:placeholder="placeholder"
|
|
192
254
|
:error="error"
|
|
193
255
|
:description="description"
|
|
194
|
-
readonly
|
|
195
256
|
:disabled="disabled"
|
|
196
257
|
:size="size"
|
|
197
258
|
:left-icon="leftIcon"
|
|
198
259
|
:right-icon="rightIcon"
|
|
199
260
|
v-bind="isShownCalendar ? datepickerInputActiveAttrs : datepickerInputAttrs"
|
|
261
|
+
@input="onTextInput"
|
|
200
262
|
@focus="activate"
|
|
263
|
+
@paste="onPaste"
|
|
264
|
+
@copy="onCopy"
|
|
265
|
+
@keydown.esc="deactivate"
|
|
266
|
+
@keydown="onTextInputKeyDown"
|
|
201
267
|
>
|
|
202
268
|
<template #left>
|
|
203
269
|
<!-- @slot Use it add something before the date. -->
|
|
@@ -236,6 +302,7 @@ defineExpose({
|
|
|
236
302
|
ref="calendar"
|
|
237
303
|
v-model="localValue"
|
|
238
304
|
v-model:view="customView"
|
|
305
|
+
v-click-outside="[deactivate, clickOutsideOptions]"
|
|
239
306
|
:tabindex="-1"
|
|
240
307
|
:timepicker="timepicker"
|
|
241
308
|
:date-format="dateFormat"
|
|
@@ -248,7 +315,6 @@ defineExpose({
|
|
|
248
315
|
@keydown.esc="deactivate"
|
|
249
316
|
@user-date-change="onUserFormatDateChange"
|
|
250
317
|
@input="onInput"
|
|
251
|
-
@blur="onBlur"
|
|
252
318
|
@submit="onSubmit"
|
|
253
319
|
/>
|
|
254
320
|
</Transition>
|
|
@@ -37,9 +37,9 @@ export default /*tw*/ {
|
|
|
37
37
|
leaveToClass: "opacity-0 scale-95",
|
|
38
38
|
},
|
|
39
39
|
i18n: {
|
|
40
|
-
today: "Today",
|
|
41
|
-
yesterday: "Yesterday",
|
|
42
|
-
tomorrow: "Tomorrow",
|
|
40
|
+
today: "Today,",
|
|
41
|
+
yesterday: "Yesterday,",
|
|
42
|
+
tomorrow: "Tomorrow,",
|
|
43
43
|
weekdays: {
|
|
44
44
|
shorthand: {
|
|
45
45
|
sunday: "Sun",
|
|
@@ -117,8 +117,8 @@ export default /*tw*/ {
|
|
|
117
117
|
okLabel: "Ok",
|
|
118
118
|
},
|
|
119
119
|
defaults: {
|
|
120
|
-
userDateFormat: "j F, Y",
|
|
121
|
-
userDateTimeFormat: "j F, Y - H:i:S",
|
|
120
|
+
userDateFormat: "r j F, Y",
|
|
121
|
+
userDateTimeFormat: "r j F, Y - H:i:S",
|
|
122
122
|
size: "md",
|
|
123
123
|
openDirectionX: "auto",
|
|
124
124
|
openDirectionY: "auto",
|
|
@@ -3,7 +3,7 @@ import { merge } from "lodash-es";
|
|
|
3
3
|
|
|
4
4
|
import useUI from "../composables/useUI.ts";
|
|
5
5
|
|
|
6
|
-
import defaultConfig from "./config.
|
|
6
|
+
import defaultConfig from "./config.ts";
|
|
7
7
|
import { Direction } from "../composables/useAutoPosition.ts";
|
|
8
8
|
|
|
9
9
|
import type { Ref } from "vue";
|
|
@@ -4,7 +4,7 @@ import { useLocale as useGlobalLocale } from "../composables/useLocale.ts";
|
|
|
4
4
|
|
|
5
5
|
import { getSortedLocale } from "../ui.form-calendar/utilDate.ts";
|
|
6
6
|
import { LocaleType } from "../ui.form-calendar/constants.ts";
|
|
7
|
-
import { UDatePickerRange } from "./constants.
|
|
7
|
+
import { UDatePickerRange } from "./constants.ts";
|
|
8
8
|
|
|
9
9
|
import defaultConfig from "./config.ts";
|
|
10
10
|
|
package/ui.form-input/UInput.vue
CHANGED
|
@@ -56,6 +56,8 @@
|
|
|
56
56
|
@change="onChange"
|
|
57
57
|
@mousedown="onMousedown"
|
|
58
58
|
@click="onClick"
|
|
59
|
+
@paste="onPaste"
|
|
60
|
+
@copy="onCopy"
|
|
59
61
|
/>
|
|
60
62
|
|
|
61
63
|
<label v-if="isTypePassword" v-bind="rightIconWrapperAttrs" :for="elementId">
|
|
@@ -158,6 +160,16 @@ const emit = defineEmits([
|
|
|
158
160
|
*/
|
|
159
161
|
"blur",
|
|
160
162
|
|
|
163
|
+
/**
|
|
164
|
+
* Triggers when content pasted to the input.
|
|
165
|
+
*/
|
|
166
|
+
"paste",
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* Triggers when content copied from the input.
|
|
170
|
+
*/
|
|
171
|
+
"copy",
|
|
172
|
+
|
|
161
173
|
/**
|
|
162
174
|
* Triggers when the input value is changes.
|
|
163
175
|
* @property {string} modelValue
|
|
@@ -424,6 +436,14 @@ function onMousedown(event) {
|
|
|
424
436
|
emit("mousedown", event);
|
|
425
437
|
}
|
|
426
438
|
|
|
439
|
+
function onPaste(event) {
|
|
440
|
+
emit("paste", event);
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
function onCopy(event) {
|
|
444
|
+
emit("copy", event);
|
|
445
|
+
}
|
|
446
|
+
|
|
427
447
|
function onClickShowPassword() {
|
|
428
448
|
isShownPassword.value = !isShownPassword.value;
|
|
429
449
|
}
|
package/web-types.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"framework": "vue",
|
|
3
3
|
"name": "vueless",
|
|
4
|
-
"version": "0.0.
|
|
4
|
+
"version": "0.0.569",
|
|
5
5
|
"contributions": {
|
|
6
6
|
"html": {
|
|
7
7
|
"description-markup": "markdown",
|
|
@@ -3058,7 +3058,7 @@
|
|
|
3058
3058
|
"kind": "expression",
|
|
3059
3059
|
"type": "string"
|
|
3060
3060
|
},
|
|
3061
|
-
"default": "j F, Y"
|
|
3061
|
+
"default": "r j F, Y"
|
|
3062
3062
|
},
|
|
3063
3063
|
{
|
|
3064
3064
|
"name": "userDateTimeFormat",
|
|
@@ -3068,7 +3068,7 @@
|
|
|
3068
3068
|
"kind": "expression",
|
|
3069
3069
|
"type": "string"
|
|
3070
3070
|
},
|
|
3071
|
-
"default": "j F, Y - H:i:S"
|
|
3071
|
+
"default": "r j F, Y - H:i:S"
|
|
3072
3072
|
},
|
|
3073
3073
|
{
|
|
3074
3074
|
"name": "minDate",
|
|
@@ -5988,6 +5988,14 @@
|
|
|
5988
5988
|
"name": "blur",
|
|
5989
5989
|
"description": "Triggers when the input loses focus."
|
|
5990
5990
|
},
|
|
5991
|
+
{
|
|
5992
|
+
"name": "paste",
|
|
5993
|
+
"description": "Triggers when content pasted to the input."
|
|
5994
|
+
},
|
|
5995
|
+
{
|
|
5996
|
+
"name": "copy",
|
|
5997
|
+
"description": "Triggers when content copied from the input."
|
|
5998
|
+
},
|
|
5991
5999
|
{
|
|
5992
6000
|
"name": "input",
|
|
5993
6001
|
"description": "Triggers when the input value is changes.",
|