@vkontakte/vkui 7.3.0 → 7.3.1
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/Calendar/Calendar.d.ts.map +1 -1
- package/dist/components/Calendar/Calendar.js +7 -14
- package/dist/components/Calendar/Calendar.js.map +1 -1
- package/dist/components/CalendarRange/CalendarRange.d.ts.map +1 -1
- package/dist/components/CalendarRange/CalendarRange.js +6 -13
- package/dist/components/CalendarRange/CalendarRange.js.map +1 -1
- package/dist/components/DateInput/DateInput.d.ts +1 -3
- package/dist/components/DateInput/DateInput.d.ts.map +1 -1
- package/dist/components/DateInput/DateInput.js +2 -2
- package/dist/components/DateInput/DateInput.js.map +1 -1
- package/dist/cssm/components/Calendar/Calendar.js +7 -14
- package/dist/cssm/components/Calendar/Calendar.js.map +1 -1
- package/dist/cssm/components/CalendarRange/CalendarRange.js +6 -13
- package/dist/cssm/components/CalendarRange/CalendarRange.js.map +1 -1
- package/dist/cssm/components/DateInput/DateInput.js +2 -2
- package/dist/cssm/components/DateInput/DateInput.js.map +1 -1
- package/dist/cssm/hooks/useDateInput.js +18 -5
- package/dist/cssm/hooks/useDateInput.js.map +1 -1
- package/dist/cssm/lib/calendar.js +19 -8
- package/dist/cssm/lib/calendar.js.map +1 -1
- package/dist/hooks/useDateInput.d.ts +1 -0
- package/dist/hooks/useDateInput.d.ts.map +1 -1
- package/dist/hooks/useDateInput.js +19 -6
- package/dist/hooks/useDateInput.js.map +1 -1
- package/dist/lib/calendar.d.ts +3 -1
- package/dist/lib/calendar.d.ts.map +1 -1
- package/dist/lib/calendar.js +19 -8
- package/dist/lib/calendar.js.map +1 -1
- package/package.json +1 -1
- package/src/components/Calendar/Calendar.tsx +14 -16
- package/src/components/CalendarRange/CalendarRange.tsx +7 -15
- package/src/components/DateInput/DateInput.tsx +4 -5
- package/src/hooks/useDateInput.ts +18 -4
- package/src/lib/calendar.ts +21 -9
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { addDays, addMonths, addWeeks, eachDayOfInterval, endOfMonth, endOfWeek, isAfter, isBefore, isFirstDayOfMonth, isLastDayOfMonth, isSameDay, startOfMonth, startOfWeek, subDays, subMonths, subWeeks } from "date-fns";
|
|
2
2
|
import { clamp as clampNumber } from "../helpers/math.js";
|
|
3
|
+
import { Keys } from "./accessibility.js";
|
|
3
4
|
export const DEFAULT_MAX_YEAR = 9999;
|
|
4
5
|
// 100 - из-за ограничений dayjs https://github.com/iamkun/dayjs/issues/2591
|
|
5
6
|
export const DEFAULT_MIN_YEAR = 100;
|
|
@@ -47,35 +48,45 @@ export const getDaysNames = (now, weekStartsOn, locale)=>{
|
|
|
47
48
|
long: longFormatter.format(day)
|
|
48
49
|
}));
|
|
49
50
|
};
|
|
51
|
+
export const NAVIGATION_KEYS = [
|
|
52
|
+
Keys.ARROW_UP,
|
|
53
|
+
Keys.ARROW_DOWN,
|
|
54
|
+
Keys.ARROW_LEFT,
|
|
55
|
+
Keys.ARROW_RIGHT,
|
|
56
|
+
Keys.HOME,
|
|
57
|
+
Keys.END,
|
|
58
|
+
Keys.PAGE_UP,
|
|
59
|
+
Keys.PAGE_DOWN
|
|
60
|
+
];
|
|
50
61
|
export const navigateDate = (date, key)=>{
|
|
51
62
|
let newDate = date ?? new Date();
|
|
52
63
|
switch(key){
|
|
53
|
-
case
|
|
64
|
+
case Keys.ARROW_RIGHT:
|
|
54
65
|
newDate = addDays(newDate, 1);
|
|
55
66
|
break;
|
|
56
|
-
case
|
|
67
|
+
case Keys.ARROW_LEFT:
|
|
57
68
|
newDate = subDays(newDate, 1);
|
|
58
69
|
break;
|
|
59
|
-
case
|
|
70
|
+
case Keys.ARROW_UP:
|
|
60
71
|
newDate = subWeeks(newDate, 1);
|
|
61
72
|
break;
|
|
62
|
-
case
|
|
73
|
+
case Keys.ARROW_DOWN:
|
|
63
74
|
newDate = addWeeks(newDate, 1);
|
|
64
75
|
break;
|
|
65
|
-
case
|
|
76
|
+
case Keys.HOME:
|
|
66
77
|
newDate = startOfWeek(newDate, {
|
|
67
78
|
weekStartsOn: 1
|
|
68
79
|
});
|
|
69
80
|
break;
|
|
70
|
-
case
|
|
81
|
+
case Keys.END:
|
|
71
82
|
newDate = endOfWeek(newDate, {
|
|
72
83
|
weekStartsOn: 1
|
|
73
84
|
});
|
|
74
85
|
break;
|
|
75
|
-
case
|
|
86
|
+
case Keys.PAGE_UP:
|
|
76
87
|
newDate = subMonths(newDate, 1);
|
|
77
88
|
break;
|
|
78
|
-
case
|
|
89
|
+
case Keys.PAGE_DOWN:
|
|
79
90
|
newDate = addMonths(newDate, 1);
|
|
80
91
|
break;
|
|
81
92
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/lib/calendar.ts"],"sourcesContent":["import {\n addDays,\n addMonths,\n addWeeks,\n eachDayOfInterval,\n endOfMonth,\n endOfWeek,\n isAfter,\n isBefore,\n isFirstDayOfMonth,\n isLastDayOfMonth,\n isSameDay,\n startOfMonth,\n startOfWeek,\n subDays,\n subMonths,\n subWeeks,\n} from 'date-fns';\nimport { clamp as clampNumber } from '../helpers/math';\n\nexport const DEFAULT_MAX_YEAR = 9999;\n// 100 - из-за ограничений dayjs https://github.com/iamkun/dayjs/issues/2591\nexport const DEFAULT_MIN_YEAR = 100;\n\nexport const getYears = (\n currentYear: number,\n range: number,\n): Array<{\n value: number;\n label: string;\n}> => {\n const years: Array<{\n value: number;\n label: string;\n }> = [];\n\n const minYear = clampNumber(currentYear - range, DEFAULT_MIN_YEAR, DEFAULT_MAX_YEAR);\n const maxYear = clampNumber(currentYear + range, DEFAULT_MIN_YEAR, DEFAULT_MAX_YEAR);\n\n for (let i = minYear; i <= maxYear; i++) {\n years.push({ label: String(i).padStart(4, '0'), value: i });\n }\n\n return years;\n};\n\nexport const getMonths = (\n locale?: string,\n): Array<{\n value: number;\n label: string;\n}> => {\n const months: Array<{\n value: number;\n label: string;\n }> = [];\n const formatter = new Intl.DateTimeFormat(locale, {\n month: 'long',\n });\n\n for (let i = 0; i < 12; i++) {\n months.push({\n label: formatter.format(new Date('1970-01-01').setMonth(i)),\n value: i,\n });\n }\n\n return months;\n};\n\nexport const getDaysNames = (\n now: Date,\n weekStartsOn: 0 | 1 | 2 | 3 | 4 | 5 | 6,\n locale?: string,\n): Array<{ short: string; long: string }> => {\n const shortFormatter = new Intl.DateTimeFormat(locale, {\n weekday: 'short',\n });\n const longFormatter = new Intl.DateTimeFormat(locale, {\n weekday: 'long',\n });\n return eachDayOfInterval({\n start: startOfWeek(now, { weekStartsOn }),\n end: endOfWeek(now, { weekStartsOn }),\n }).map((day) => ({ short: shortFormatter.format(day), long: longFormatter.format(day) }));\n};\n\nexport const navigateDate = (date?: Date | null, key?:
|
|
1
|
+
{"version":3,"sources":["../../../src/lib/calendar.ts"],"sourcesContent":["import {\n addDays,\n addMonths,\n addWeeks,\n eachDayOfInterval,\n endOfMonth,\n endOfWeek,\n isAfter,\n isBefore,\n isFirstDayOfMonth,\n isLastDayOfMonth,\n isSameDay,\n startOfMonth,\n startOfWeek,\n subDays,\n subMonths,\n subWeeks,\n} from 'date-fns';\nimport { clamp as clampNumber } from '../helpers/math';\nimport { Keys, type KeysValues } from './accessibility';\n\nexport const DEFAULT_MAX_YEAR = 9999;\n// 100 - из-за ограничений dayjs https://github.com/iamkun/dayjs/issues/2591\nexport const DEFAULT_MIN_YEAR = 100;\n\nexport const getYears = (\n currentYear: number,\n range: number,\n): Array<{\n value: number;\n label: string;\n}> => {\n const years: Array<{\n value: number;\n label: string;\n }> = [];\n\n const minYear = clampNumber(currentYear - range, DEFAULT_MIN_YEAR, DEFAULT_MAX_YEAR);\n const maxYear = clampNumber(currentYear + range, DEFAULT_MIN_YEAR, DEFAULT_MAX_YEAR);\n\n for (let i = minYear; i <= maxYear; i++) {\n years.push({ label: String(i).padStart(4, '0'), value: i });\n }\n\n return years;\n};\n\nexport const getMonths = (\n locale?: string,\n): Array<{\n value: number;\n label: string;\n}> => {\n const months: Array<{\n value: number;\n label: string;\n }> = [];\n const formatter = new Intl.DateTimeFormat(locale, {\n month: 'long',\n });\n\n for (let i = 0; i < 12; i++) {\n months.push({\n label: formatter.format(new Date('1970-01-01').setMonth(i)),\n value: i,\n });\n }\n\n return months;\n};\n\nexport const getDaysNames = (\n now: Date,\n weekStartsOn: 0 | 1 | 2 | 3 | 4 | 5 | 6,\n locale?: string,\n): Array<{ short: string; long: string }> => {\n const shortFormatter = new Intl.DateTimeFormat(locale, {\n weekday: 'short',\n });\n const longFormatter = new Intl.DateTimeFormat(locale, {\n weekday: 'long',\n });\n return eachDayOfInterval({\n start: startOfWeek(now, { weekStartsOn }),\n end: endOfWeek(now, { weekStartsOn }),\n }).map((day) => ({ short: shortFormatter.format(day), long: longFormatter.format(day) }));\n};\n\nexport const NAVIGATION_KEYS: KeysValues[] = [\n Keys.ARROW_UP,\n Keys.ARROW_DOWN,\n Keys.ARROW_LEFT,\n Keys.ARROW_RIGHT,\n Keys.HOME,\n Keys.END,\n Keys.PAGE_UP,\n Keys.PAGE_DOWN,\n];\n\nexport const navigateDate = (date?: Date | null, key?: (typeof NAVIGATION_KEYS)[number]): Date => {\n let newDate = date ?? new Date();\n\n switch (key) {\n case Keys.ARROW_RIGHT:\n newDate = addDays(newDate, 1);\n break;\n case Keys.ARROW_LEFT:\n newDate = subDays(newDate, 1);\n break;\n case Keys.ARROW_UP:\n newDate = subWeeks(newDate, 1);\n break;\n case Keys.ARROW_DOWN:\n newDate = addWeeks(newDate, 1);\n break;\n case Keys.HOME:\n newDate = startOfWeek(newDate, { weekStartsOn: 1 });\n break;\n case Keys.END:\n newDate = endOfWeek(newDate, { weekStartsOn: 1 });\n break;\n case Keys.PAGE_UP:\n newDate = subMonths(newDate, 1);\n break;\n case Keys.PAGE_DOWN:\n newDate = addMonths(newDate, 1);\n break;\n }\n\n return newDate;\n};\n\nexport const getWeeks = (viewDate: Date, weekStartsOn: 0 | 1 | 2 | 3 | 4 | 5 | 6): Date[][] => {\n const start = startOfWeek(startOfMonth(viewDate), { weekStartsOn });\n const end = endOfWeek(endOfMonth(viewDate), { weekStartsOn });\n\n let count = 0;\n let current = start;\n const nestedWeeks: Date[][] = [];\n let lastDay = null;\n while (isBefore(current, end)) {\n const weekNumber = Math.floor(count / 7);\n nestedWeeks[weekNumber] = nestedWeeks[weekNumber] || [];\n const day = current.getDay();\n if (lastDay !== day) {\n lastDay = day;\n nestedWeeks[weekNumber].push(current);\n count += 1;\n }\n current = addDays(current, 1);\n }\n return nestedWeeks;\n};\n\nexport const setTimeEqual = (to: Date, from?: Date | null): Date => {\n if (from) {\n to.setHours(from.getHours());\n to.setMinutes(from.getMinutes());\n to.setSeconds(from.getSeconds());\n to.setMilliseconds(from.getMilliseconds());\n }\n\n return to;\n};\n\nexport const isFirstDay = (day: Date, dayOfWeek: number): boolean =>\n dayOfWeek === 0 || isFirstDayOfMonth(day);\n\nexport const isLastDay = (day: Date, dayOfWeek: number): boolean =>\n dayOfWeek === 6 || isLastDayOfMonth(day);\n\n/**\n * Возвращает дату, ограниченную `min` и/или `max` значениями\n */\nexport function clamp(day: Date, options: { min?: Date; max?: Date } = {}): Date {\n const { min, max } = options;\n if (min && isBefore(day, min)) {\n return min;\n }\n if (max && isAfter(day, max)) {\n return max;\n }\n return day;\n}\n\n/**\n * Позволяет определить удовлетворяет ли исходная дата заданным ограничения `min` и/или `max`\n */\nexport function isDayMinMaxRestricted(\n day: Date,\n options: { min?: Date; max?: Date; withTime?: boolean } = {},\n): boolean {\n const { min, max, withTime = false } = options;\n if (!withTime && ((min && isSameDay(day, min)) || (max && isSameDay(day, max)))) {\n return false;\n }\n return Boolean((min && isBefore(day, min)) || (max && isAfter(day, max)));\n}\n"],"names":["addDays","addMonths","addWeeks","eachDayOfInterval","endOfMonth","endOfWeek","isAfter","isBefore","isFirstDayOfMonth","isLastDayOfMonth","isSameDay","startOfMonth","startOfWeek","subDays","subMonths","subWeeks","clamp","clampNumber","Keys","DEFAULT_MAX_YEAR","DEFAULT_MIN_YEAR","getYears","currentYear","range","years","minYear","maxYear","i","push","label","String","padStart","value","getMonths","locale","months","formatter","Intl","DateTimeFormat","month","format","Date","setMonth","getDaysNames","now","weekStartsOn","shortFormatter","weekday","longFormatter","start","end","map","day","short","long","NAVIGATION_KEYS","ARROW_UP","ARROW_DOWN","ARROW_LEFT","ARROW_RIGHT","HOME","END","PAGE_UP","PAGE_DOWN","navigateDate","date","key","newDate","getWeeks","viewDate","count","current","nestedWeeks","lastDay","weekNumber","Math","floor","getDay","setTimeEqual","to","from","setHours","getHours","setMinutes","getMinutes","setSeconds","getSeconds","setMilliseconds","getMilliseconds","isFirstDay","dayOfWeek","isLastDay","options","min","max","isDayMinMaxRestricted","withTime","Boolean"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useDateInput.d.ts","sourceRoot":"","sources":["../../src/hooks/useDateInput.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAK/B,MAAM,WAAW,wBAAwB,CAAC,CAAC,EAAE,CAAC;IAC5C,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,KAAK,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC;IACvC,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,KAAK,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC;IACjB,cAAc,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK;QACjC,MAAM,EAAE,MAAM,CAAC;QACf,GAAG,EAAE,MAAM,CAAC;QACZ,GAAG,EAAE,MAAM,CAAC;KACb,CAAC;IACF,qBAAqB,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;IACjD,gBAAgB,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,GAAG,IAAI,GAAG,SAAS,KAAK,MAAM,EAAE,CAAC;IAC7D,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,qBAAqB,CAAC,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,IAAI,CAAC;IAClD,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,wBAAgB,YAAY,CAAC,CAAC,SAAS,WAAW,EAAE,CAAC,EAAE,EACrD,UAAU,EACV,IAAI,EACJ,SAAS,EACT,QAAQ,EACR,cAAc,EACd,OAAO,EACP,qBAAqB,EACrB,gBAAgB,EAChB,KAAK,EACL,qBAAqB,EACrB,UAAU,GACX,EAAE,wBAAwB,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG;IAClC,OAAO,EAAE,KAAK,CAAC,SAAS,CAAC,cAAc,GAAG,IAAI,CAAC,CAAC;IAChD,WAAW,EAAE,KAAK,CAAC,SAAS,CAAC,cAAc,GAAG,IAAI,CAAC,CAAC;IACpD,IAAI,EAAE,OAAO,CAAC;IACd,YAAY,EAAE,MAAM,IAAI,CAAC;IACzB,aAAa,EAAE,MAAM,IAAI,CAAC;IAC1B,cAAc,EAAE,MAAM,IAAI,CAAC;IAC3B,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,iBAAiB,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC,CAAC;IACvE,aAAa,EAAE,CAAC,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC,eAAe,CAAC,KAAK,IAAI,CAAC;IACjE,KAAK,EAAE,MAAM,IAAI,CAAC;IAClB,gBAAgB,EAAE,MAAM,IAAI,CAAC;IAC7B,oBAAoB,EAAE,MAAM,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"useDateInput.d.ts","sourceRoot":"","sources":["../../src/hooks/useDateInput.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAK/B,MAAM,WAAW,wBAAwB,CAAC,CAAC,EAAE,CAAC;IAC5C,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,KAAK,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC;IACvC,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,KAAK,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC;IACjB,cAAc,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK;QACjC,MAAM,EAAE,MAAM,CAAC;QACf,GAAG,EAAE,MAAM,CAAC;QACZ,GAAG,EAAE,MAAM,CAAC;KACb,CAAC;IACF,qBAAqB,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;IACjD,gBAAgB,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,GAAG,IAAI,GAAG,SAAS,KAAK,MAAM,EAAE,CAAC;IAC7D,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,qBAAqB,CAAC,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,IAAI,CAAC;IAClD,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,wBAAgB,YAAY,CAAC,CAAC,SAAS,WAAW,EAAE,CAAC,EAAE,EACrD,UAAU,EACV,IAAI,EACJ,SAAS,EACT,QAAQ,EACR,cAAc,EACd,OAAO,EACP,qBAAqB,EACrB,gBAAgB,EAChB,KAAK,EACL,qBAAqB,EACrB,UAAU,GACX,EAAE,wBAAwB,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG;IAClC,OAAO,EAAE,KAAK,CAAC,SAAS,CAAC,cAAc,GAAG,IAAI,CAAC,CAAC;IAChD,WAAW,EAAE,KAAK,CAAC,SAAS,CAAC,cAAc,GAAG,IAAI,CAAC,CAAC;IACpD,IAAI,EAAE,OAAO,CAAC;IACd,YAAY,EAAE,MAAM,IAAI,CAAC;IACzB,aAAa,EAAE,MAAM,IAAI,CAAC;IAC1B,cAAc,EAAE,MAAM,IAAI,CAAC;IAC3B,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,iBAAiB,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC,CAAC;IACvE,aAAa,EAAE,CAAC,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC,eAAe,CAAC,KAAK,IAAI,CAAC;IACjE,KAAK,EAAE,MAAM,IAAI,CAAC;IAClB,gBAAgB,EAAE,MAAM,IAAI,CAAC;IAC7B,oBAAoB,EAAE,MAAM,IAAI,CAAC;IACjC,kBAAkB,EAAE,MAAM,OAAO,CAAC;CACnC,CAuNA"}
|
|
@@ -10,7 +10,13 @@ export function useDateInput({ maxElement, refs, autoFocus, disabled, elementsCo
|
|
|
10
10
|
const calendarRef = React.useRef(null);
|
|
11
11
|
const [internalValue, setInternalValue] = React.useState([]);
|
|
12
12
|
const [focusedElement, setFocusedElement] = React.useState(null);
|
|
13
|
+
const isClickedOutsideRef = React.useRef(false);
|
|
13
14
|
const { window } = useDOM();
|
|
15
|
+
const handleRestoreFocus = React.useCallback(()=>{
|
|
16
|
+
// если календарь был закрыт кликом вне календаря
|
|
17
|
+
// то FocusTrap возвращать фокус не должен
|
|
18
|
+
return !isClickedOutsideRef.current;
|
|
19
|
+
}, []);
|
|
14
20
|
const _onCalendarClose = useCallback(()=>{
|
|
15
21
|
if (open) {
|
|
16
22
|
closeCalendar();
|
|
@@ -28,6 +34,7 @@ export function useDateInput({ maxElement, refs, autoFocus, disabled, elementsCo
|
|
|
28
34
|
if (accessible) {
|
|
29
35
|
setFocusedElement(null);
|
|
30
36
|
}
|
|
37
|
+
isClickedOutsideRef.current = false;
|
|
31
38
|
}
|
|
32
39
|
}, [
|
|
33
40
|
onCalendarOpenChanged,
|
|
@@ -47,20 +54,24 @@ export function useDateInput({ maxElement, refs, autoFocus, disabled, elementsCo
|
|
|
47
54
|
_onCalendarClose
|
|
48
55
|
]);
|
|
49
56
|
const removeFocusFromField = React.useCallback(()=>{
|
|
50
|
-
|
|
51
|
-
|
|
57
|
+
if (focusedElement !== null) {
|
|
58
|
+
var _window_getSelection;
|
|
59
|
+
setFocusedElement(null);
|
|
60
|
+
(_window_getSelection = window.getSelection()) === null || _window_getSelection === void 0 ? void 0 : _window_getSelection.removeAllRanges();
|
|
61
|
+
setInternalValue(getInternalValue(value));
|
|
62
|
+
}
|
|
52
63
|
_onCalendarClose();
|
|
53
|
-
(_window_getSelection = window.getSelection()) === null || _window_getSelection === void 0 ? void 0 : _window_getSelection.removeAllRanges();
|
|
54
|
-
setInternalValue(getInternalValue(value));
|
|
55
64
|
}, [
|
|
56
65
|
_onCalendarClose,
|
|
57
66
|
window,
|
|
58
67
|
getInternalValue,
|
|
59
|
-
value
|
|
68
|
+
value,
|
|
69
|
+
focusedElement
|
|
60
70
|
]);
|
|
61
71
|
const handleClickOutside = React.useCallback((e)=>{
|
|
62
72
|
var _rootRef_current, _calendarRef_current;
|
|
63
73
|
if (!((_rootRef_current = rootRef.current) === null || _rootRef_current === void 0 ? void 0 : _rootRef_current.contains(e.target)) && !((_calendarRef_current = calendarRef.current) === null || _calendarRef_current === void 0 ? void 0 : _calendarRef_current.contains(e.target))) {
|
|
74
|
+
isClickedOutsideRef.current = true;
|
|
64
75
|
removeFocusFromField();
|
|
65
76
|
}
|
|
66
77
|
}, [
|
|
@@ -180,6 +191,7 @@ export function useDateInput({ maxElement, refs, autoFocus, disabled, elementsCo
|
|
|
180
191
|
} else if (e.key === 'Delete' || e.key === 'Del') {
|
|
181
192
|
_value[focusedElement] = '';
|
|
182
193
|
} else if (e.key === ' ') {
|
|
194
|
+
e.preventDefault();
|
|
183
195
|
_onCalendarOpen();
|
|
184
196
|
return;
|
|
185
197
|
} else {
|
|
@@ -210,7 +222,8 @@ export function useDateInput({ maxElement, refs, autoFocus, disabled, elementsCo
|
|
|
210
222
|
handleKeyDown,
|
|
211
223
|
clear,
|
|
212
224
|
handleFieldEnter,
|
|
213
|
-
removeFocusFromField
|
|
225
|
+
removeFocusFromField,
|
|
226
|
+
handleRestoreFocus
|
|
214
227
|
};
|
|
215
228
|
}
|
|
216
229
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/hooks/useDateInput.ts"],"sourcesContent":["import { useCallback } from 'react';\nimport * as React from 'react';\nimport { useDOM } from '../lib/dom';\nimport { useBooleanState } from './useBooleanState';\nimport { useGlobalEventListener } from './useGlobalEventListener';\n\nexport interface UseDateInputDependencies<T, D> {\n maxElement: number;\n refs: Array<React.RefObject<T | null>>;\n autoFocus?: boolean;\n disabled?: boolean;\n value?: D | null;\n elementsConfig: (index: number) => {\n length: number;\n min: number;\n max: number;\n };\n onInternalValueChange: (value: string[]) => void;\n getInternalValue: (value?: D | null | undefined) => string[];\n onClear: () => void;\n onCalendarOpenChanged?: (opened: boolean) => void;\n accessible?: boolean;\n}\n\nexport function useDateInput<T extends HTMLElement, D>({\n maxElement,\n refs,\n autoFocus,\n disabled,\n elementsConfig,\n onClear,\n onInternalValueChange,\n getInternalValue,\n value,\n onCalendarOpenChanged,\n accessible,\n}: UseDateInputDependencies<T, D>): {\n rootRef: React.RefObject<HTMLDivElement | null>;\n calendarRef: React.RefObject<HTMLDivElement | null>;\n open: boolean;\n openCalendar: () => void;\n closeCalendar: () => void;\n toggleCalendar: () => void;\n internalValue: string[];\n focusedElement: number | null;\n setFocusedElement: React.Dispatch<React.SetStateAction<number | null>>;\n handleKeyDown: (e: React.KeyboardEvent<HTMLSpanElement>) => void;\n clear: () => void;\n handleFieldEnter: () => void;\n removeFocusFromField: () => void;\n} {\n const { document } = useDOM();\n const { value: open, setTrue: openCalendar, setFalse: closeCalendar } = useBooleanState(false);\n const rootRef = React.useRef<HTMLDivElement | null>(null);\n const calendarRef = React.useRef<HTMLDivElement | null>(null);\n const [internalValue, setInternalValue] = React.useState<string[]>([]);\n const [focusedElement, setFocusedElement] = React.useState<number | null>(null);\n const { window } = useDOM();\n\n const _onCalendarClose = useCallback(() => {\n if (open) {\n closeCalendar();\n onCalendarOpenChanged?.(false);\n }\n }, [closeCalendar, onCalendarOpenChanged, open]);\n\n const _onCalendarOpen = useCallback(() => {\n if (!open) {\n openCalendar();\n onCalendarOpenChanged?.(true);\n if (accessible) {\n setFocusedElement(null);\n }\n }\n }, [onCalendarOpenChanged, open, openCalendar, accessible]);\n\n const toggleCalendar = useCallback(() => {\n if (open) {\n _onCalendarClose();\n } else {\n _onCalendarOpen();\n }\n }, [open, _onCalendarOpen, _onCalendarClose]);\n\n const removeFocusFromField = React.useCallback(() => {\n setFocusedElement(null);\n _onCalendarClose();\n window!.getSelection()?.removeAllRanges();\n setInternalValue(getInternalValue(value));\n }, [_onCalendarClose, window, getInternalValue, value]);\n\n const handleClickOutside = React.useCallback(\n (e: MouseEvent) => {\n if (\n !rootRef.current?.contains(e.target as Node | null) &&\n !calendarRef.current?.contains(e.target as Node | null)\n ) {\n removeFocusFromField();\n }\n },\n [removeFocusFromField],\n );\n\n const selectFirst = React.useCallback(() => {\n if (focusedElement !== null) {\n return;\n }\n\n setFocusedElement(0);\n }, [focusedElement]);\n\n useGlobalEventListener(document, 'click', handleClickOutside, {\n capture: true,\n });\n\n React.useEffect(() => {\n setInternalValue(getInternalValue(value));\n }, [getInternalValue, value]);\n\n React.useEffect(() => {\n if (autoFocus) {\n selectFirst();\n }\n }, [autoFocus, selectFirst]);\n\n React.useEffect(() => {\n if (disabled || focusedElement === null) {\n return;\n }\n\n const range = window!.document.createRange();\n\n let element = refs[focusedElement].current;\n\n let timerId: ReturnType<typeof setTimeout>;\n if (element) {\n element.focus();\n if (!accessible) {\n _onCalendarOpen();\n }\n range.selectNodeContents(element as Node);\n\n // Fix для Firefox: setTimeout нужен чтобы отложить range selection на\n // какое-то время, иначе, при фокусе на InputLike\n // извне, контент визуально не будет выбран\n timerId = setTimeout(() => {\n const selection = window!.getSelection();\n selection?.removeAllRanges();\n selection?.addRange(range);\n }, 0);\n }\n\n return () => {\n clearTimeout(timerId);\n };\n }, [disabled, focusedElement, refs, window, _onCalendarOpen, accessible]);\n\n const clear = React.useCallback(() => {\n onClear?.();\n selectFirst();\n }, [onClear, selectFirst]);\n\n const handleFieldEnter = React.useCallback(() => {\n selectFirst();\n }, [selectFirst]);\n\n const handleKeyDown = React.useCallback(\n (e: React.KeyboardEvent<HTMLSpanElement>) => {\n if (focusedElement === null) {\n return;\n }\n\n const _value = [...internalValue];\n const config = elementsConfig(focusedElement);\n\n if (/^\\d+$/.test(e.key)) {\n if (_value[focusedElement].length >= config.length) {\n _value[focusedElement] = e.key;\n } else {\n _value[focusedElement] += e.key;\n if (_value[focusedElement].length >= config.length && focusedElement < maxElement) {\n setFocusedElement(focusedElement + 1);\n }\n }\n } else if (e.key === 'Backspace') {\n if (!_value[focusedElement]) {\n setFocusedElement(focusedElement <= 0 ? maxElement : focusedElement - 1);\n } else {\n _value[focusedElement] = _value[focusedElement].slice(0, -1);\n }\n } else if (e.key === 'ArrowDown' || e.key === 'Down') {\n let currentValue = Number(_value[focusedElement]);\n _value[focusedElement] = String(\n currentValue <= config.min ? config.max : currentValue - 1,\n ).padStart(config.length, '0');\n } else if (e.key === 'ArrowUp' || e.key === 'Up') {\n let currentValue = Number(_value[focusedElement]);\n _value[focusedElement] = String(\n currentValue >= config.max ? config.min : currentValue + 1,\n ).padStart(config.length, '0');\n } else if (e.key === 'ArrowLeft' || e.key === 'Left' || (e.key === 'Tab' && e.shiftKey)) {\n if (focusedElement <= 0) {\n removeFocusFromField();\n return;\n }\n setFocusedElement(focusedElement - 1);\n } else if (e.key === 'ArrowRight' || e.key === 'Right' || e.key === 'Tab') {\n if (focusedElement >= maxElement) {\n removeFocusFromField();\n return;\n }\n\n setFocusedElement(focusedElement + 1);\n } else if (e.key === 'Delete' || e.key === 'Del') {\n _value[focusedElement] = '';\n } else if (e.key === ' ') {\n _onCalendarOpen();\n return;\n } else {\n return;\n }\n\n e.preventDefault();\n setInternalValue(_value);\n onInternalValueChange(_value);\n },\n [\n _onCalendarOpen,\n removeFocusFromField,\n elementsConfig,\n focusedElement,\n internalValue,\n maxElement,\n onInternalValueChange,\n ],\n );\n\n return {\n rootRef,\n calendarRef,\n open,\n openCalendar: _onCalendarOpen,\n closeCalendar: _onCalendarClose,\n toggleCalendar,\n internalValue,\n focusedElement,\n setFocusedElement,\n handleKeyDown,\n clear,\n handleFieldEnter,\n removeFocusFromField,\n };\n}\n"],"names":["useCallback","React","useDOM","useBooleanState","useGlobalEventListener","useDateInput","maxElement","refs","autoFocus","disabled","elementsConfig","onClear","onInternalValueChange","getInternalValue","value","onCalendarOpenChanged","accessible","document","open","setTrue","openCalendar","setFalse","closeCalendar","rootRef","useRef","calendarRef","internalValue","setInternalValue","useState","focusedElement","setFocusedElement","window","_onCalendarClose","_onCalendarOpen","toggleCalendar","removeFocusFromField","getSelection","removeAllRanges","handleClickOutside","e","current","contains","target","selectFirst","capture","useEffect","range","createRange","element","timerId","focus","selectNodeContents","setTimeout","selection","addRange","clearTimeout","clear","handleFieldEnter","handleKeyDown","_value","config","test","key","length","slice","currentValue","Number","String","min","max","padStart","shiftKey","preventDefault"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../src/hooks/useDateInput.ts"],"sourcesContent":["import { useCallback } from 'react';\nimport * as React from 'react';\nimport { useDOM } from '../lib/dom';\nimport { useBooleanState } from './useBooleanState';\nimport { useGlobalEventListener } from './useGlobalEventListener';\n\nexport interface UseDateInputDependencies<T, D> {\n maxElement: number;\n refs: Array<React.RefObject<T | null>>;\n autoFocus?: boolean;\n disabled?: boolean;\n value?: D | null;\n elementsConfig: (index: number) => {\n length: number;\n min: number;\n max: number;\n };\n onInternalValueChange: (value: string[]) => void;\n getInternalValue: (value?: D | null | undefined) => string[];\n onClear: () => void;\n onCalendarOpenChanged?: (opened: boolean) => void;\n accessible?: boolean;\n}\n\nexport function useDateInput<T extends HTMLElement, D>({\n maxElement,\n refs,\n autoFocus,\n disabled,\n elementsConfig,\n onClear,\n onInternalValueChange,\n getInternalValue,\n value,\n onCalendarOpenChanged,\n accessible,\n}: UseDateInputDependencies<T, D>): {\n rootRef: React.RefObject<HTMLDivElement | null>;\n calendarRef: React.RefObject<HTMLDivElement | null>;\n open: boolean;\n openCalendar: () => void;\n closeCalendar: () => void;\n toggleCalendar: () => void;\n internalValue: string[];\n focusedElement: number | null;\n setFocusedElement: React.Dispatch<React.SetStateAction<number | null>>;\n handleKeyDown: (e: React.KeyboardEvent<HTMLSpanElement>) => void;\n clear: () => void;\n handleFieldEnter: () => void;\n removeFocusFromField: () => void;\n handleRestoreFocus: () => boolean;\n} {\n const { document } = useDOM();\n const { value: open, setTrue: openCalendar, setFalse: closeCalendar } = useBooleanState(false);\n const rootRef = React.useRef<HTMLDivElement | null>(null);\n const calendarRef = React.useRef<HTMLDivElement | null>(null);\n const [internalValue, setInternalValue] = React.useState<string[]>([]);\n const [focusedElement, setFocusedElement] = React.useState<number | null>(null);\n const isClickedOutsideRef = React.useRef(false);\n const { window } = useDOM();\n\n const handleRestoreFocus = React.useCallback(() => {\n // если календарь был закрыт кликом вне календаря\n // то FocusTrap возвращать фокус не должен\n return !isClickedOutsideRef.current;\n }, []);\n\n const _onCalendarClose = useCallback(() => {\n if (open) {\n closeCalendar();\n onCalendarOpenChanged?.(false);\n }\n }, [closeCalendar, onCalendarOpenChanged, open]);\n\n const _onCalendarOpen = useCallback(() => {\n if (!open) {\n openCalendar();\n onCalendarOpenChanged?.(true);\n if (accessible) {\n setFocusedElement(null);\n }\n isClickedOutsideRef.current = false;\n }\n }, [onCalendarOpenChanged, open, openCalendar, accessible]);\n\n const toggleCalendar = useCallback(() => {\n if (open) {\n _onCalendarClose();\n } else {\n _onCalendarOpen();\n }\n }, [open, _onCalendarOpen, _onCalendarClose]);\n\n const removeFocusFromField = React.useCallback(() => {\n if (focusedElement !== null) {\n setFocusedElement(null);\n window!.getSelection()?.removeAllRanges();\n setInternalValue(getInternalValue(value));\n }\n _onCalendarClose();\n }, [_onCalendarClose, window, getInternalValue, value, focusedElement]);\n\n const handleClickOutside = React.useCallback(\n (e: MouseEvent) => {\n if (\n !rootRef.current?.contains(e.target as Node | null) &&\n !calendarRef.current?.contains(e.target as Node | null)\n ) {\n isClickedOutsideRef.current = true;\n removeFocusFromField();\n }\n },\n [removeFocusFromField],\n );\n\n const selectFirst = React.useCallback(() => {\n if (focusedElement !== null) {\n return;\n }\n\n setFocusedElement(0);\n }, [focusedElement]);\n\n useGlobalEventListener(document, 'click', handleClickOutside, {\n capture: true,\n });\n\n React.useEffect(() => {\n setInternalValue(getInternalValue(value));\n }, [getInternalValue, value]);\n\n React.useEffect(() => {\n if (autoFocus) {\n selectFirst();\n }\n }, [autoFocus, selectFirst]);\n\n React.useEffect(() => {\n if (disabled || focusedElement === null) {\n return;\n }\n\n const range = window!.document.createRange();\n\n let element = refs[focusedElement].current;\n\n let timerId: ReturnType<typeof setTimeout>;\n if (element) {\n element.focus();\n if (!accessible) {\n _onCalendarOpen();\n }\n range.selectNodeContents(element as Node);\n\n // Fix для Firefox: setTimeout нужен чтобы отложить range selection на\n // какое-то время, иначе, при фокусе на InputLike\n // извне, контент визуально не будет выбран\n timerId = setTimeout(() => {\n const selection = window!.getSelection();\n selection?.removeAllRanges();\n selection?.addRange(range);\n }, 0);\n }\n\n return () => {\n clearTimeout(timerId);\n };\n }, [disabled, focusedElement, refs, window, _onCalendarOpen, accessible]);\n\n const clear = React.useCallback(() => {\n onClear?.();\n selectFirst();\n }, [onClear, selectFirst]);\n\n const handleFieldEnter = React.useCallback(() => {\n selectFirst();\n }, [selectFirst]);\n\n const handleKeyDown = React.useCallback(\n (e: React.KeyboardEvent<HTMLSpanElement>) => {\n if (focusedElement === null) {\n return;\n }\n\n const _value = [...internalValue];\n const config = elementsConfig(focusedElement);\n\n if (/^\\d+$/.test(e.key)) {\n if (_value[focusedElement].length >= config.length) {\n _value[focusedElement] = e.key;\n } else {\n _value[focusedElement] += e.key;\n if (_value[focusedElement].length >= config.length && focusedElement < maxElement) {\n setFocusedElement(focusedElement + 1);\n }\n }\n } else if (e.key === 'Backspace') {\n if (!_value[focusedElement]) {\n setFocusedElement(focusedElement <= 0 ? maxElement : focusedElement - 1);\n } else {\n _value[focusedElement] = _value[focusedElement].slice(0, -1);\n }\n } else if (e.key === 'ArrowDown' || e.key === 'Down') {\n let currentValue = Number(_value[focusedElement]);\n _value[focusedElement] = String(\n currentValue <= config.min ? config.max : currentValue - 1,\n ).padStart(config.length, '0');\n } else if (e.key === 'ArrowUp' || e.key === 'Up') {\n let currentValue = Number(_value[focusedElement]);\n _value[focusedElement] = String(\n currentValue >= config.max ? config.min : currentValue + 1,\n ).padStart(config.length, '0');\n } else if (e.key === 'ArrowLeft' || e.key === 'Left' || (e.key === 'Tab' && e.shiftKey)) {\n if (focusedElement <= 0) {\n removeFocusFromField();\n return;\n }\n setFocusedElement(focusedElement - 1);\n } else if (e.key === 'ArrowRight' || e.key === 'Right' || e.key === 'Tab') {\n if (focusedElement >= maxElement) {\n removeFocusFromField();\n return;\n }\n\n setFocusedElement(focusedElement + 1);\n } else if (e.key === 'Delete' || e.key === 'Del') {\n _value[focusedElement] = '';\n } else if (e.key === ' ') {\n e.preventDefault();\n _onCalendarOpen();\n return;\n } else {\n return;\n }\n\n e.preventDefault();\n setInternalValue(_value);\n onInternalValueChange(_value);\n },\n [\n _onCalendarOpen,\n removeFocusFromField,\n elementsConfig,\n focusedElement,\n internalValue,\n maxElement,\n onInternalValueChange,\n ],\n );\n\n return {\n rootRef,\n calendarRef,\n open,\n openCalendar: _onCalendarOpen,\n closeCalendar: _onCalendarClose,\n toggleCalendar,\n internalValue,\n focusedElement,\n setFocusedElement,\n handleKeyDown,\n clear,\n handleFieldEnter,\n removeFocusFromField,\n handleRestoreFocus,\n };\n}\n"],"names":["useCallback","React","useDOM","useBooleanState","useGlobalEventListener","useDateInput","maxElement","refs","autoFocus","disabled","elementsConfig","onClear","onInternalValueChange","getInternalValue","value","onCalendarOpenChanged","accessible","document","open","setTrue","openCalendar","setFalse","closeCalendar","rootRef","useRef","calendarRef","internalValue","setInternalValue","useState","focusedElement","setFocusedElement","isClickedOutsideRef","window","handleRestoreFocus","current","_onCalendarClose","_onCalendarOpen","toggleCalendar","removeFocusFromField","getSelection","removeAllRanges","handleClickOutside","e","contains","target","selectFirst","capture","useEffect","range","createRange","element","timerId","focus","selectNodeContents","setTimeout","selection","addRange","clearTimeout","clear","handleFieldEnter","handleKeyDown","_value","config","test","key","length","slice","currentValue","Number","String","min","max","padStart","shiftKey","preventDefault"],"mappings":"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"}
|
package/dist/lib/calendar.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type KeysValues } from './accessibility';
|
|
1
2
|
export declare const DEFAULT_MAX_YEAR = 9999;
|
|
2
3
|
export declare const DEFAULT_MIN_YEAR = 100;
|
|
3
4
|
export declare const getYears: (currentYear: number, range: number) => Array<{
|
|
@@ -12,7 +13,8 @@ export declare const getDaysNames: (now: Date, weekStartsOn: 0 | 1 | 2 | 3 | 4 |
|
|
|
12
13
|
short: string;
|
|
13
14
|
long: string;
|
|
14
15
|
}>;
|
|
15
|
-
export declare const
|
|
16
|
+
export declare const NAVIGATION_KEYS: KeysValues[];
|
|
17
|
+
export declare const navigateDate: (date?: Date | null, key?: (typeof NAVIGATION_KEYS)[number]) => Date;
|
|
16
18
|
export declare const getWeeks: (viewDate: Date, weekStartsOn: 0 | 1 | 2 | 3 | 4 | 5 | 6) => Date[][];
|
|
17
19
|
export declare const setTimeEqual: (to: Date, from?: Date | null) => Date;
|
|
18
20
|
export declare const isFirstDay: (day: Date, dayOfWeek: number) => boolean;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"calendar.d.ts","sourceRoot":"","sources":["../../src/lib/calendar.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"calendar.d.ts","sourceRoot":"","sources":["../../src/lib/calendar.ts"],"names":[],"mappings":"AAmBA,OAAO,EAAQ,KAAK,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAExD,eAAO,MAAM,gBAAgB,OAAO,CAAC;AAErC,eAAO,MAAM,gBAAgB,MAAM,CAAC;AAEpC,eAAO,MAAM,QAAQ,GACnB,aAAa,MAAM,EACnB,OAAO,MAAM,KACZ,KAAK,CAAC;IACP,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;CACf,CAcA,CAAC;AAEF,eAAO,MAAM,SAAS,GACpB,SAAS,MAAM,KACd,KAAK,CAAC;IACP,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;CACf,CAiBA,CAAC;AAEF,eAAO,MAAM,YAAY,GACvB,KAAK,IAAI,EACT,cAAc,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,EACvC,SAAS,MAAM,KACd,KAAK,CAAC;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAWvC,CAAC;AAEF,eAAO,MAAM,eAAe,EAAE,UAAU,EASvC,CAAC;AAEF,eAAO,MAAM,YAAY,GAAI,OAAO,IAAI,GAAG,IAAI,EAAE,MAAM,CAAC,OAAO,eAAe,EAAE,MAAM,CAAC,KAAG,IA+BzF,CAAC;AAEF,eAAO,MAAM,QAAQ,GAAI,UAAU,IAAI,EAAE,cAAc,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,KAAG,IAAI,EAAE,EAoBxF,CAAC;AAEF,eAAO,MAAM,YAAY,GAAI,IAAI,IAAI,EAAE,OAAO,IAAI,GAAG,IAAI,KAAG,IAS3D,CAAC;AAEF,eAAO,MAAM,UAAU,GAAI,KAAK,IAAI,EAAE,WAAW,MAAM,KAAG,OACf,CAAC;AAE5C,eAAO,MAAM,SAAS,GAAI,KAAK,IAAI,EAAE,WAAW,MAAM,KAAG,OACf,CAAC;AAE3C;;GAEG;AACH,wBAAgB,KAAK,CAAC,GAAG,EAAE,IAAI,EAAE,OAAO,GAAE;IAAE,GAAG,CAAC,EAAE,IAAI,CAAC;IAAC,GAAG,CAAC,EAAE,IAAI,CAAA;CAAO,GAAG,IAAI,CAS/E;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CACnC,GAAG,EAAE,IAAI,EACT,OAAO,GAAE;IAAE,GAAG,CAAC,EAAE,IAAI,CAAC;IAAC,GAAG,CAAC,EAAE,IAAI,CAAC;IAAC,QAAQ,CAAC,EAAE,OAAO,CAAA;CAAO,GAC3D,OAAO,CAMT"}
|
package/dist/lib/calendar.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { addDays, addMonths, addWeeks, eachDayOfInterval, endOfMonth, endOfWeek, isAfter, isBefore, isFirstDayOfMonth, isLastDayOfMonth, isSameDay, startOfMonth, startOfWeek, subDays, subMonths, subWeeks } from "date-fns";
|
|
2
2
|
import { clamp as clampNumber } from "../helpers/math.js";
|
|
3
|
+
import { Keys } from "./accessibility.js";
|
|
3
4
|
export const DEFAULT_MAX_YEAR = 9999;
|
|
4
5
|
// 100 - из-за ограничений dayjs https://github.com/iamkun/dayjs/issues/2591
|
|
5
6
|
export const DEFAULT_MIN_YEAR = 100;
|
|
@@ -47,35 +48,45 @@ export const getDaysNames = (now, weekStartsOn, locale)=>{
|
|
|
47
48
|
long: longFormatter.format(day)
|
|
48
49
|
}));
|
|
49
50
|
};
|
|
51
|
+
export const NAVIGATION_KEYS = [
|
|
52
|
+
Keys.ARROW_UP,
|
|
53
|
+
Keys.ARROW_DOWN,
|
|
54
|
+
Keys.ARROW_LEFT,
|
|
55
|
+
Keys.ARROW_RIGHT,
|
|
56
|
+
Keys.HOME,
|
|
57
|
+
Keys.END,
|
|
58
|
+
Keys.PAGE_UP,
|
|
59
|
+
Keys.PAGE_DOWN
|
|
60
|
+
];
|
|
50
61
|
export const navigateDate = (date, key)=>{
|
|
51
62
|
let newDate = date !== null && date !== void 0 ? date : new Date();
|
|
52
63
|
switch(key){
|
|
53
|
-
case
|
|
64
|
+
case Keys.ARROW_RIGHT:
|
|
54
65
|
newDate = addDays(newDate, 1);
|
|
55
66
|
break;
|
|
56
|
-
case
|
|
67
|
+
case Keys.ARROW_LEFT:
|
|
57
68
|
newDate = subDays(newDate, 1);
|
|
58
69
|
break;
|
|
59
|
-
case
|
|
70
|
+
case Keys.ARROW_UP:
|
|
60
71
|
newDate = subWeeks(newDate, 1);
|
|
61
72
|
break;
|
|
62
|
-
case
|
|
73
|
+
case Keys.ARROW_DOWN:
|
|
63
74
|
newDate = addWeeks(newDate, 1);
|
|
64
75
|
break;
|
|
65
|
-
case
|
|
76
|
+
case Keys.HOME:
|
|
66
77
|
newDate = startOfWeek(newDate, {
|
|
67
78
|
weekStartsOn: 1
|
|
68
79
|
});
|
|
69
80
|
break;
|
|
70
|
-
case
|
|
81
|
+
case Keys.END:
|
|
71
82
|
newDate = endOfWeek(newDate, {
|
|
72
83
|
weekStartsOn: 1
|
|
73
84
|
});
|
|
74
85
|
break;
|
|
75
|
-
case
|
|
86
|
+
case Keys.PAGE_UP:
|
|
76
87
|
newDate = subMonths(newDate, 1);
|
|
77
88
|
break;
|
|
78
|
-
case
|
|
89
|
+
case Keys.PAGE_DOWN:
|
|
79
90
|
newDate = addMonths(newDate, 1);
|
|
80
91
|
break;
|
|
81
92
|
}
|
package/dist/lib/calendar.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/lib/calendar.ts"],"sourcesContent":["import {\n addDays,\n addMonths,\n addWeeks,\n eachDayOfInterval,\n endOfMonth,\n endOfWeek,\n isAfter,\n isBefore,\n isFirstDayOfMonth,\n isLastDayOfMonth,\n isSameDay,\n startOfMonth,\n startOfWeek,\n subDays,\n subMonths,\n subWeeks,\n} from 'date-fns';\nimport { clamp as clampNumber } from '../helpers/math';\n\nexport const DEFAULT_MAX_YEAR = 9999;\n// 100 - из-за ограничений dayjs https://github.com/iamkun/dayjs/issues/2591\nexport const DEFAULT_MIN_YEAR = 100;\n\nexport const getYears = (\n currentYear: number,\n range: number,\n): Array<{\n value: number;\n label: string;\n}> => {\n const years: Array<{\n value: number;\n label: string;\n }> = [];\n\n const minYear = clampNumber(currentYear - range, DEFAULT_MIN_YEAR, DEFAULT_MAX_YEAR);\n const maxYear = clampNumber(currentYear + range, DEFAULT_MIN_YEAR, DEFAULT_MAX_YEAR);\n\n for (let i = minYear; i <= maxYear; i++) {\n years.push({ label: String(i).padStart(4, '0'), value: i });\n }\n\n return years;\n};\n\nexport const getMonths = (\n locale?: string,\n): Array<{\n value: number;\n label: string;\n}> => {\n const months: Array<{\n value: number;\n label: string;\n }> = [];\n const formatter = new Intl.DateTimeFormat(locale, {\n month: 'long',\n });\n\n for (let i = 0; i < 12; i++) {\n months.push({\n label: formatter.format(new Date('1970-01-01').setMonth(i)),\n value: i,\n });\n }\n\n return months;\n};\n\nexport const getDaysNames = (\n now: Date,\n weekStartsOn: 0 | 1 | 2 | 3 | 4 | 5 | 6,\n locale?: string,\n): Array<{ short: string; long: string }> => {\n const shortFormatter = new Intl.DateTimeFormat(locale, {\n weekday: 'short',\n });\n const longFormatter = new Intl.DateTimeFormat(locale, {\n weekday: 'long',\n });\n return eachDayOfInterval({\n start: startOfWeek(now, { weekStartsOn }),\n end: endOfWeek(now, { weekStartsOn }),\n }).map((day) => ({ short: shortFormatter.format(day), long: longFormatter.format(day) }));\n};\n\nexport const navigateDate = (date?: Date | null, key?:
|
|
1
|
+
{"version":3,"sources":["../../src/lib/calendar.ts"],"sourcesContent":["import {\n addDays,\n addMonths,\n addWeeks,\n eachDayOfInterval,\n endOfMonth,\n endOfWeek,\n isAfter,\n isBefore,\n isFirstDayOfMonth,\n isLastDayOfMonth,\n isSameDay,\n startOfMonth,\n startOfWeek,\n subDays,\n subMonths,\n subWeeks,\n} from 'date-fns';\nimport { clamp as clampNumber } from '../helpers/math';\nimport { Keys, type KeysValues } from './accessibility';\n\nexport const DEFAULT_MAX_YEAR = 9999;\n// 100 - из-за ограничений dayjs https://github.com/iamkun/dayjs/issues/2591\nexport const DEFAULT_MIN_YEAR = 100;\n\nexport const getYears = (\n currentYear: number,\n range: number,\n): Array<{\n value: number;\n label: string;\n}> => {\n const years: Array<{\n value: number;\n label: string;\n }> = [];\n\n const minYear = clampNumber(currentYear - range, DEFAULT_MIN_YEAR, DEFAULT_MAX_YEAR);\n const maxYear = clampNumber(currentYear + range, DEFAULT_MIN_YEAR, DEFAULT_MAX_YEAR);\n\n for (let i = minYear; i <= maxYear; i++) {\n years.push({ label: String(i).padStart(4, '0'), value: i });\n }\n\n return years;\n};\n\nexport const getMonths = (\n locale?: string,\n): Array<{\n value: number;\n label: string;\n}> => {\n const months: Array<{\n value: number;\n label: string;\n }> = [];\n const formatter = new Intl.DateTimeFormat(locale, {\n month: 'long',\n });\n\n for (let i = 0; i < 12; i++) {\n months.push({\n label: formatter.format(new Date('1970-01-01').setMonth(i)),\n value: i,\n });\n }\n\n return months;\n};\n\nexport const getDaysNames = (\n now: Date,\n weekStartsOn: 0 | 1 | 2 | 3 | 4 | 5 | 6,\n locale?: string,\n): Array<{ short: string; long: string }> => {\n const shortFormatter = new Intl.DateTimeFormat(locale, {\n weekday: 'short',\n });\n const longFormatter = new Intl.DateTimeFormat(locale, {\n weekday: 'long',\n });\n return eachDayOfInterval({\n start: startOfWeek(now, { weekStartsOn }),\n end: endOfWeek(now, { weekStartsOn }),\n }).map((day) => ({ short: shortFormatter.format(day), long: longFormatter.format(day) }));\n};\n\nexport const NAVIGATION_KEYS: KeysValues[] = [\n Keys.ARROW_UP,\n Keys.ARROW_DOWN,\n Keys.ARROW_LEFT,\n Keys.ARROW_RIGHT,\n Keys.HOME,\n Keys.END,\n Keys.PAGE_UP,\n Keys.PAGE_DOWN,\n];\n\nexport const navigateDate = (date?: Date | null, key?: (typeof NAVIGATION_KEYS)[number]): Date => {\n let newDate = date ?? new Date();\n\n switch (key) {\n case Keys.ARROW_RIGHT:\n newDate = addDays(newDate, 1);\n break;\n case Keys.ARROW_LEFT:\n newDate = subDays(newDate, 1);\n break;\n case Keys.ARROW_UP:\n newDate = subWeeks(newDate, 1);\n break;\n case Keys.ARROW_DOWN:\n newDate = addWeeks(newDate, 1);\n break;\n case Keys.HOME:\n newDate = startOfWeek(newDate, { weekStartsOn: 1 });\n break;\n case Keys.END:\n newDate = endOfWeek(newDate, { weekStartsOn: 1 });\n break;\n case Keys.PAGE_UP:\n newDate = subMonths(newDate, 1);\n break;\n case Keys.PAGE_DOWN:\n newDate = addMonths(newDate, 1);\n break;\n }\n\n return newDate;\n};\n\nexport const getWeeks = (viewDate: Date, weekStartsOn: 0 | 1 | 2 | 3 | 4 | 5 | 6): Date[][] => {\n const start = startOfWeek(startOfMonth(viewDate), { weekStartsOn });\n const end = endOfWeek(endOfMonth(viewDate), { weekStartsOn });\n\n let count = 0;\n let current = start;\n const nestedWeeks: Date[][] = [];\n let lastDay = null;\n while (isBefore(current, end)) {\n const weekNumber = Math.floor(count / 7);\n nestedWeeks[weekNumber] = nestedWeeks[weekNumber] || [];\n const day = current.getDay();\n if (lastDay !== day) {\n lastDay = day;\n nestedWeeks[weekNumber].push(current);\n count += 1;\n }\n current = addDays(current, 1);\n }\n return nestedWeeks;\n};\n\nexport const setTimeEqual = (to: Date, from?: Date | null): Date => {\n if (from) {\n to.setHours(from.getHours());\n to.setMinutes(from.getMinutes());\n to.setSeconds(from.getSeconds());\n to.setMilliseconds(from.getMilliseconds());\n }\n\n return to;\n};\n\nexport const isFirstDay = (day: Date, dayOfWeek: number): boolean =>\n dayOfWeek === 0 || isFirstDayOfMonth(day);\n\nexport const isLastDay = (day: Date, dayOfWeek: number): boolean =>\n dayOfWeek === 6 || isLastDayOfMonth(day);\n\n/**\n * Возвращает дату, ограниченную `min` и/или `max` значениями\n */\nexport function clamp(day: Date, options: { min?: Date; max?: Date } = {}): Date {\n const { min, max } = options;\n if (min && isBefore(day, min)) {\n return min;\n }\n if (max && isAfter(day, max)) {\n return max;\n }\n return day;\n}\n\n/**\n * Позволяет определить удовлетворяет ли исходная дата заданным ограничения `min` и/или `max`\n */\nexport function isDayMinMaxRestricted(\n day: Date,\n options: { min?: Date; max?: Date; withTime?: boolean } = {},\n): boolean {\n const { min, max, withTime = false } = options;\n if (!withTime && ((min && isSameDay(day, min)) || (max && isSameDay(day, max)))) {\n return false;\n }\n return Boolean((min && isBefore(day, min)) || (max && isAfter(day, max)));\n}\n"],"names":["addDays","addMonths","addWeeks","eachDayOfInterval","endOfMonth","endOfWeek","isAfter","isBefore","isFirstDayOfMonth","isLastDayOfMonth","isSameDay","startOfMonth","startOfWeek","subDays","subMonths","subWeeks","clamp","clampNumber","Keys","DEFAULT_MAX_YEAR","DEFAULT_MIN_YEAR","getYears","currentYear","range","years","minYear","maxYear","i","push","label","String","padStart","value","getMonths","locale","months","formatter","Intl","DateTimeFormat","month","format","Date","setMonth","getDaysNames","now","weekStartsOn","shortFormatter","weekday","longFormatter","start","end","map","day","short","long","NAVIGATION_KEYS","ARROW_UP","ARROW_DOWN","ARROW_LEFT","ARROW_RIGHT","HOME","END","PAGE_UP","PAGE_DOWN","navigateDate","date","key","newDate","getWeeks","viewDate","count","current","nestedWeeks","lastDay","weekNumber","Math","floor","getDay","setTimeEqual","to","from","setHours","getHours","setMinutes","getMinutes","setSeconds","getSeconds","setMilliseconds","getMilliseconds","isFirstDay","dayOfWeek","isLastDay","options","min","max","isDayMinMaxRestricted","withTime","Boolean"],"mappings":"AAAA,SACEA,OAAO,EACPC,SAAS,EACTC,QAAQ,EACRC,iBAAiB,EACjBC,UAAU,EACVC,SAAS,EACTC,OAAO,EACPC,QAAQ,EACRC,iBAAiB,EACjBC,gBAAgB,EAChBC,SAAS,EACTC,YAAY,EACZC,WAAW,EACXC,OAAO,EACPC,SAAS,EACTC,QAAQ,QACH,WAAW;AAClB,SAASC,SAASC,WAAW,QAAQ,qBAAkB;AACvD,SAASC,IAAI,QAAyB,qBAAkB;AAExD,OAAO,MAAMC,mBAAmB,KAAK;AACrC,4EAA4E;AAC5E,OAAO,MAAMC,mBAAmB,IAAI;AAEpC,OAAO,MAAMC,WAAW,CACtBC,aACAC;IAKA,MAAMC,QAGD,EAAE;IAEP,MAAMC,UAAUR,YAAYK,cAAcC,OAAOH,kBAAkBD;IACnE,MAAMO,UAAUT,YAAYK,cAAcC,OAAOH,kBAAkBD;IAEnE,IAAK,IAAIQ,IAAIF,SAASE,KAAKD,SAASC,IAAK;QACvCH,MAAMI,IAAI,CAAC;YAAEC,OAAOC,OAAOH,GAAGI,QAAQ,CAAC,GAAG;YAAMC,OAAOL;QAAE;IAC3D;IAEA,OAAOH;AACT,EAAE;AAEF,OAAO,MAAMS,YAAY,CACvBC;IAKA,MAAMC,SAGD,EAAE;IACP,MAAMC,YAAY,IAAIC,KAAKC,cAAc,CAACJ,QAAQ;QAChDK,OAAO;IACT;IAEA,IAAK,IAAIZ,IAAI,GAAGA,IAAI,IAAIA,IAAK;QAC3BQ,OAAOP,IAAI,CAAC;YACVC,OAAOO,UAAUI,MAAM,CAAC,IAAIC,KAAK,cAAcC,QAAQ,CAACf;YACxDK,OAAOL;QACT;IACF;IAEA,OAAOQ;AACT,EAAE;AAEF,OAAO,MAAMQ,eAAe,CAC1BC,KACAC,cACAX;IAEA,MAAMY,iBAAiB,IAAIT,KAAKC,cAAc,CAACJ,QAAQ;QACrDa,SAAS;IACX;IACA,MAAMC,gBAAgB,IAAIX,KAAKC,cAAc,CAACJ,QAAQ;QACpDa,SAAS;IACX;IACA,OAAO5C,kBAAkB;QACvB8C,OAAOrC,YAAYgC,KAAK;YAAEC;QAAa;QACvCK,KAAK7C,UAAUuC,KAAK;YAAEC;QAAa;IACrC,GAAGM,GAAG,CAAC,CAACC,MAAS,CAAA;YAAEC,OAAOP,eAAeN,MAAM,CAACY;YAAME,MAAMN,cAAcR,MAAM,CAACY;QAAK,CAAA;AACxF,EAAE;AAEF,OAAO,MAAMG,kBAAgC;IAC3CrC,KAAKsC,QAAQ;IACbtC,KAAKuC,UAAU;IACfvC,KAAKwC,UAAU;IACfxC,KAAKyC,WAAW;IAChBzC,KAAK0C,IAAI;IACT1C,KAAK2C,GAAG;IACR3C,KAAK4C,OAAO;IACZ5C,KAAK6C,SAAS;CACf,CAAC;AAEF,OAAO,MAAMC,eAAe,CAACC,MAAoBC;IAC/C,IAAIC,UAAUF,iBAAAA,kBAAAA,OAAQ,IAAIxB;IAE1B,OAAQyB;QACN,KAAKhD,KAAKyC,WAAW;YACnBQ,UAAUnE,QAAQmE,SAAS;YAC3B;QACF,KAAKjD,KAAKwC,UAAU;YAClBS,UAAUtD,QAAQsD,SAAS;YAC3B;QACF,KAAKjD,KAAKsC,QAAQ;YAChBW,UAAUpD,SAASoD,SAAS;YAC5B;QACF,KAAKjD,KAAKuC,UAAU;YAClBU,UAAUjE,SAASiE,SAAS;YAC5B;QACF,KAAKjD,KAAK0C,IAAI;YACZO,UAAUvD,YAAYuD,SAAS;gBAAEtB,cAAc;YAAE;YACjD;QACF,KAAK3B,KAAK2C,GAAG;YACXM,UAAU9D,UAAU8D,SAAS;gBAAEtB,cAAc;YAAE;YAC/C;QACF,KAAK3B,KAAK4C,OAAO;YACfK,UAAUrD,UAAUqD,SAAS;YAC7B;QACF,KAAKjD,KAAK6C,SAAS;YACjBI,UAAUlE,UAAUkE,SAAS;YAC7B;IACJ;IAEA,OAAOA;AACT,EAAE;AAEF,OAAO,MAAMC,WAAW,CAACC,UAAgBxB;IACvC,MAAMI,QAAQrC,YAAYD,aAAa0D,WAAW;QAAExB;IAAa;IACjE,MAAMK,MAAM7C,UAAUD,WAAWiE,WAAW;QAAExB;IAAa;IAE3D,IAAIyB,QAAQ;IACZ,IAAIC,UAAUtB;IACd,MAAMuB,cAAwB,EAAE;IAChC,IAAIC,UAAU;IACd,MAAOlE,SAASgE,SAASrB,KAAM;QAC7B,MAAMwB,aAAaC,KAAKC,KAAK,CAACN,QAAQ;QACtCE,WAAW,CAACE,WAAW,GAAGF,WAAW,CAACE,WAAW,IAAI,EAAE;QACvD,MAAMtB,MAAMmB,QAAQM,MAAM;QAC1B,IAAIJ,YAAYrB,KAAK;YACnBqB,UAAUrB;YACVoB,WAAW,CAACE,WAAW,CAAC9C,IAAI,CAAC2C;YAC7BD,SAAS;QACX;QACAC,UAAUvE,QAAQuE,SAAS;IAC7B;IACA,OAAOC;AACT,EAAE;AAEF,OAAO,MAAMM,eAAe,CAACC,IAAUC;IACrC,IAAIA,MAAM;QACRD,GAAGE,QAAQ,CAACD,KAAKE,QAAQ;QACzBH,GAAGI,UAAU,CAACH,KAAKI,UAAU;QAC7BL,GAAGM,UAAU,CAACL,KAAKM,UAAU;QAC7BP,GAAGQ,eAAe,CAACP,KAAKQ,eAAe;IACzC;IAEA,OAAOT;AACT,EAAE;AAEF,OAAO,MAAMU,aAAa,CAACrC,KAAWsC,YACpCA,cAAc,KAAKlF,kBAAkB4C,KAAK;AAE5C,OAAO,MAAMuC,YAAY,CAACvC,KAAWsC,YACnCA,cAAc,KAAKjF,iBAAiB2C,KAAK;AAE3C;;CAEC,GACD,OAAO,SAASpC,MAAMoC,GAAS,EAAEwC,UAAsC,CAAC,CAAC;IACvE,MAAM,EAAEC,GAAG,EAAEC,GAAG,EAAE,GAAGF;IACrB,IAAIC,OAAOtF,SAAS6C,KAAKyC,MAAM;QAC7B,OAAOA;IACT;IACA,IAAIC,OAAOxF,QAAQ8C,KAAK0C,MAAM;QAC5B,OAAOA;IACT;IACA,OAAO1C;AACT;AAEA;;CAEC,GACD,OAAO,SAAS2C,sBACd3C,GAAS,EACTwC,UAA0D,CAAC,CAAC;IAE5D,MAAM,EAAEC,GAAG,EAAEC,GAAG,EAAEE,WAAW,KAAK,EAAE,GAAGJ;IACvC,IAAI,CAACI,YAAa,CAAA,AAACH,OAAOnF,UAAU0C,KAAKyC,QAAUC,OAAOpF,UAAU0C,KAAK0C,IAAI,GAAI;QAC/E,OAAO;IACT;IACA,OAAOG,QAAQ,AAACJ,OAAOtF,SAAS6C,KAAKyC,QAAUC,OAAOxF,QAAQ8C,KAAK0C;AACrE"}
|
package/package.json
CHANGED
|
@@ -5,7 +5,15 @@ import { classNames } from '@vkontakte/vkjs';
|
|
|
5
5
|
import { isSameDay, isSameMonth, startOfMonth } from 'date-fns';
|
|
6
6
|
import { useCalendar } from '../../hooks/useCalendar';
|
|
7
7
|
import { useCustomEnsuredControl } from '../../hooks/useEnsuredControl';
|
|
8
|
-
import {
|
|
8
|
+
import { Keys, pressedKey } from '../../lib/accessibility';
|
|
9
|
+
import {
|
|
10
|
+
clamp,
|
|
11
|
+
isFirstDay,
|
|
12
|
+
isLastDay,
|
|
13
|
+
navigateDate,
|
|
14
|
+
NAVIGATION_KEYS,
|
|
15
|
+
setTimeEqual,
|
|
16
|
+
} from '../../lib/calendar';
|
|
9
17
|
import { convertDateFromTimeZone, convertDateToTimeZone } from '../../lib/date';
|
|
10
18
|
import { isHTMLElement } from '../../lib/dom';
|
|
11
19
|
import { useIsomorphicLayoutEffect } from '../../lib/useIsomorphicLayoutEffect';
|
|
@@ -246,21 +254,11 @@ export const Calendar = ({
|
|
|
246
254
|
|
|
247
255
|
const handleKeyDown = React.useCallback(
|
|
248
256
|
(event: React.KeyboardEvent) => {
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
'ArrowUp',
|
|
252
|
-
'ArrowDown',
|
|
253
|
-
'ArrowLeft',
|
|
254
|
-
'ArrowRight',
|
|
255
|
-
'Home',
|
|
256
|
-
'End',
|
|
257
|
-
'PageUp',
|
|
258
|
-
'PageDown',
|
|
259
|
-
].includes(event.key)
|
|
260
|
-
) {
|
|
257
|
+
const key = pressedKey(event);
|
|
258
|
+
if (key && NAVIGATION_KEYS.includes(key)) {
|
|
261
259
|
event.preventDefault();
|
|
262
260
|
|
|
263
|
-
const newFocusedDay = navigateDate(focusedDay ?? timeZonedValue,
|
|
261
|
+
const newFocusedDay = navigateDate(focusedDay ?? timeZonedValue, key);
|
|
264
262
|
|
|
265
263
|
if (newFocusedDay && !isSameMonth(newFocusedDay, viewDate)) {
|
|
266
264
|
setViewDate(newFocusedDay);
|
|
@@ -271,14 +269,14 @@ export const Calendar = ({
|
|
|
271
269
|
return;
|
|
272
270
|
}
|
|
273
271
|
|
|
274
|
-
if (
|
|
272
|
+
if (key === Keys.TAB) {
|
|
275
273
|
setFocusedDay(undefined);
|
|
276
274
|
setFocusableDay(focusedDay);
|
|
277
275
|
|
|
278
276
|
return;
|
|
279
277
|
}
|
|
280
278
|
|
|
281
|
-
if ((
|
|
279
|
+
if ((key === Keys.ENTER || key === Keys.SPACE) && isHTMLElement(event.target)) {
|
|
282
280
|
event.preventDefault();
|
|
283
281
|
event.target.click?.();
|
|
284
282
|
}
|
|
@@ -14,7 +14,8 @@ import {
|
|
|
14
14
|
} from 'date-fns';
|
|
15
15
|
import { useCalendar } from '../../hooks/useCalendar';
|
|
16
16
|
import { useCustomEnsuredControl } from '../../hooks/useEnsuredControl';
|
|
17
|
-
import {
|
|
17
|
+
import { Keys, pressedKey } from '../../lib/accessibility';
|
|
18
|
+
import { isFirstDay, isLastDay, navigateDate, NAVIGATION_KEYS } from '../../lib/calendar';
|
|
18
19
|
import { isHTMLElement } from '../../lib/dom';
|
|
19
20
|
import type { HTMLAttributesWithRootRef } from '../../types';
|
|
20
21
|
import {
|
|
@@ -165,21 +166,12 @@ export const CalendarRange = ({
|
|
|
165
166
|
|
|
166
167
|
const handleKeyDown = React.useCallback(
|
|
167
168
|
(event: React.KeyboardEvent) => {
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
'ArrowDown',
|
|
172
|
-
'ArrowLeft',
|
|
173
|
-
'ArrowRight',
|
|
174
|
-
'Home',
|
|
175
|
-
'End',
|
|
176
|
-
'PageUp',
|
|
177
|
-
'PageDown',
|
|
178
|
-
].includes(event.key)
|
|
179
|
-
) {
|
|
169
|
+
const key = pressedKey(event);
|
|
170
|
+
|
|
171
|
+
if (key && NAVIGATION_KEYS.includes(key)) {
|
|
180
172
|
event.preventDefault();
|
|
181
173
|
|
|
182
|
-
const newFocusedDay = navigateDate(focusedDay ?? value?.[1],
|
|
174
|
+
const newFocusedDay = navigateDate(focusedDay ?? value?.[1], key);
|
|
183
175
|
|
|
184
176
|
if (
|
|
185
177
|
newFocusedDay &&
|
|
@@ -192,7 +184,7 @@ export const CalendarRange = ({
|
|
|
192
184
|
return;
|
|
193
185
|
}
|
|
194
186
|
|
|
195
|
-
if ((
|
|
187
|
+
if ((key === Keys.ENTER || key === Keys.SPACE) && isHTMLElement(event.target)) {
|
|
196
188
|
event.preventDefault();
|
|
197
189
|
event.target.click?.();
|
|
198
190
|
}
|
|
@@ -159,11 +159,9 @@ export interface DateInputProps
|
|
|
159
159
|
* - иконка календаря видна всегда, чтобы пользователи
|
|
160
160
|
* ассистивных технологий могли открыть календарь по клику на иконку;
|
|
161
161
|
* - календарь при открытии получает фокус, клавиатурный
|
|
162
|
-
* фокус зациклен и не выходит за пределы календаря пока календарь не
|
|
163
|
-
*
|
|
164
|
-
* TODO [>=8]: включить по умолчанию.
|
|
162
|
+
* фокус зациклен и не выходит за пределы календаря пока календарь не закрыт.
|
|
165
163
|
*/
|
|
166
|
-
accessible?: boolean
|
|
164
|
+
accessible?: boolean /* TODO [>=v8] включить по умолчанию */;
|
|
167
165
|
/**
|
|
168
166
|
* Позволяет отключить захват фокуса при появлении календаря.
|
|
169
167
|
*/
|
|
@@ -334,6 +332,7 @@ export const DateInput = ({
|
|
|
334
332
|
closeCalendar,
|
|
335
333
|
toggleCalendar,
|
|
336
334
|
openCalendar,
|
|
335
|
+
handleRestoreFocus,
|
|
337
336
|
} = useDateInput({
|
|
338
337
|
maxElement,
|
|
339
338
|
refs,
|
|
@@ -577,7 +576,7 @@ export const DateInput = ({
|
|
|
577
576
|
<FocusTrap
|
|
578
577
|
onClose={closeCalendar}
|
|
579
578
|
disabled={disableFocusTrap ?? !accessible}
|
|
580
|
-
restoreFocus={restoreFocus ?? Boolean(accessible)}
|
|
579
|
+
restoreFocus={restoreFocus ?? (Boolean(accessible) && handleRestoreFocus)}
|
|
581
580
|
captureEscapeKeyboardEvent={false}
|
|
582
581
|
>
|
|
583
582
|
<Calendar
|