clayui-date-picker 3.165.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE.md +30 -0
- package/README.md +19 -0
- package/lib/cjs/DateNavigation.js +124 -0
- package/lib/cjs/DayNumber.js +116 -0
- package/lib/cjs/DaysTable.js +49 -0
- package/lib/cjs/Helpers.js +98 -0
- package/lib/cjs/Hooks.js +298 -0
- package/lib/cjs/InputDate.js +58 -0
- package/lib/cjs/Select.js +56 -0
- package/lib/cjs/TimePicker.js +82 -0
- package/lib/cjs/Weekday.js +38 -0
- package/lib/cjs/WeekdayHeader.js +57 -0
- package/lib/cjs/index.js +705 -0
- package/lib/cjs/types.js +33 -0
- package/lib/esm/DateNavigation.js +94 -0
- package/lib/esm/DayNumber.js +86 -0
- package/lib/esm/DaysTable.js +19 -0
- package/lib/esm/Helpers.js +68 -0
- package/lib/esm/Hooks.js +278 -0
- package/lib/esm/InputDate.js +28 -0
- package/lib/esm/Select.js +26 -0
- package/lib/esm/TimePicker.js +52 -0
- package/lib/esm/Weekday.js +8 -0
- package/lib/esm/WeekdayHeader.js +27 -0
- package/lib/esm/index.js +697 -0
- package/lib/esm/types.js +13 -0
- package/package.json +51 -0
package/lib/cjs/types.js
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
var types_exports = {};
|
|
20
|
+
__export(types_exports, {
|
|
21
|
+
FirstDayOfWeek: () => FirstDayOfWeek
|
|
22
|
+
});
|
|
23
|
+
module.exports = __toCommonJS(types_exports);
|
|
24
|
+
var FirstDayOfWeek = /* @__PURE__ */ ((FirstDayOfWeek2) => {
|
|
25
|
+
FirstDayOfWeek2[FirstDayOfWeek2["Sunday"] = 0] = "Sunday";
|
|
26
|
+
FirstDayOfWeek2[FirstDayOfWeek2["Monday"] = 1] = "Monday";
|
|
27
|
+
FirstDayOfWeek2[FirstDayOfWeek2["Tuesday"] = 2] = "Tuesday";
|
|
28
|
+
FirstDayOfWeek2[FirstDayOfWeek2["Wednesday"] = 3] = "Wednesday";
|
|
29
|
+
FirstDayOfWeek2[FirstDayOfWeek2["Thursday"] = 4] = "Thursday";
|
|
30
|
+
FirstDayOfWeek2[FirstDayOfWeek2["Friday"] = 5] = "Friday";
|
|
31
|
+
FirstDayOfWeek2[FirstDayOfWeek2["Saturday"] = 6] = "Saturday";
|
|
32
|
+
return FirstDayOfWeek2;
|
|
33
|
+
})(FirstDayOfWeek || {});
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import Button from "@clayui/button";
|
|
2
|
+
import Icon from "@clayui/icon";
|
|
3
|
+
import React from "react";
|
|
4
|
+
import { setMonth } from "./Helpers";
|
|
5
|
+
import Select from "./Select";
|
|
6
|
+
function ClayDatePickerDateNavigation({
|
|
7
|
+
ariaLabels,
|
|
8
|
+
currentMonth,
|
|
9
|
+
disabled,
|
|
10
|
+
months,
|
|
11
|
+
onDotClicked,
|
|
12
|
+
onMonthChange,
|
|
13
|
+
spritemap,
|
|
14
|
+
years
|
|
15
|
+
}) {
|
|
16
|
+
function handleChangeMonth(month) {
|
|
17
|
+
const date = setMonth(years, month, currentMonth);
|
|
18
|
+
if (date) {
|
|
19
|
+
onMonthChange(date);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
const handlePreviousMonthClicked = () => handleChangeMonth(-1);
|
|
23
|
+
const handleNextMonthClicked = () => handleChangeMonth(1);
|
|
24
|
+
return /* @__PURE__ */ React.createElement("div", { className: "date-picker-calendar-header" }, /* @__PURE__ */ React.createElement("div", { className: "date-picker-nav" }, /* @__PURE__ */ React.createElement("div", { className: "date-picker-nav-item input-date-picker-month" }, /* @__PURE__ */ React.createElement(
|
|
25
|
+
Select,
|
|
26
|
+
{
|
|
27
|
+
"aria-label": ariaLabels.selectMonth,
|
|
28
|
+
disabled,
|
|
29
|
+
name: "month",
|
|
30
|
+
onChange: (event) => onMonthChange(
|
|
31
|
+
new Date(
|
|
32
|
+
currentMonth.getFullYear(),
|
|
33
|
+
Number(event.target.value)
|
|
34
|
+
)
|
|
35
|
+
),
|
|
36
|
+
options: months,
|
|
37
|
+
testId: "month-select",
|
|
38
|
+
value: currentMonth.getMonth()
|
|
39
|
+
}
|
|
40
|
+
)), /* @__PURE__ */ React.createElement("div", { className: "date-picker-nav-item input-date-picker-year" }, /* @__PURE__ */ React.createElement(
|
|
41
|
+
Select,
|
|
42
|
+
{
|
|
43
|
+
"aria-label": ariaLabels.selectYear,
|
|
44
|
+
disabled,
|
|
45
|
+
name: "year",
|
|
46
|
+
onChange: (event) => onMonthChange(
|
|
47
|
+
new Date(
|
|
48
|
+
Number(event.target.value),
|
|
49
|
+
currentMonth.getMonth()
|
|
50
|
+
)
|
|
51
|
+
),
|
|
52
|
+
options: years,
|
|
53
|
+
testId: "year-select",
|
|
54
|
+
value: currentMonth.getFullYear()
|
|
55
|
+
}
|
|
56
|
+
)), /* @__PURE__ */ React.createElement("div", { className: "date-picker-nav-controls date-picker-nav-item date-picker-nav-item-expand" }, /* @__PURE__ */ React.createElement(
|
|
57
|
+
Button,
|
|
58
|
+
{
|
|
59
|
+
"aria-label": ariaLabels.buttonPreviousMonth,
|
|
60
|
+
className: "nav-btn nav-btn-monospaced",
|
|
61
|
+
disabled,
|
|
62
|
+
displayType: null,
|
|
63
|
+
onClick: handlePreviousMonthClicked,
|
|
64
|
+
title: ariaLabels.buttonPreviousMonth
|
|
65
|
+
},
|
|
66
|
+
/* @__PURE__ */ React.createElement(Icon, { spritemap, symbol: "angle-left" })
|
|
67
|
+
), /* @__PURE__ */ React.createElement(
|
|
68
|
+
Button,
|
|
69
|
+
{
|
|
70
|
+
"aria-label": ariaLabels.buttonDot,
|
|
71
|
+
className: "nav-btn nav-btn-monospaced",
|
|
72
|
+
disabled,
|
|
73
|
+
displayType: null,
|
|
74
|
+
onClick: onDotClicked,
|
|
75
|
+
title: ariaLabels.buttonDot
|
|
76
|
+
},
|
|
77
|
+
/* @__PURE__ */ React.createElement(Icon, { spritemap, symbol: "simple-circle" })
|
|
78
|
+
), /* @__PURE__ */ React.createElement(
|
|
79
|
+
Button,
|
|
80
|
+
{
|
|
81
|
+
"aria-label": ariaLabels.buttonNextMonth,
|
|
82
|
+
className: "nav-btn nav-btn-monospaced",
|
|
83
|
+
disabled,
|
|
84
|
+
displayType: null,
|
|
85
|
+
onClick: handleNextMonthClicked,
|
|
86
|
+
title: ariaLabels.buttonNextMonth
|
|
87
|
+
},
|
|
88
|
+
/* @__PURE__ */ React.createElement(Icon, { spritemap, symbol: "angle-right" })
|
|
89
|
+
))));
|
|
90
|
+
}
|
|
91
|
+
var DateNavigation_default = ClayDatePickerDateNavigation;
|
|
92
|
+
export {
|
|
93
|
+
DateNavigation_default as default
|
|
94
|
+
};
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { Keys } from "@clayui/shared";
|
|
2
|
+
import classnames from "classnames";
|
|
3
|
+
import React from "react";
|
|
4
|
+
import { setDate } from "./Helpers";
|
|
5
|
+
function ClayDatePickerDayNumber({
|
|
6
|
+
day,
|
|
7
|
+
daysSelected,
|
|
8
|
+
disabled,
|
|
9
|
+
index,
|
|
10
|
+
isFocused,
|
|
11
|
+
onClick,
|
|
12
|
+
outOfRange,
|
|
13
|
+
range
|
|
14
|
+
}) {
|
|
15
|
+
const { date, nextMonth, previousMonth } = day;
|
|
16
|
+
const [startDate, endDate] = daysSelected;
|
|
17
|
+
const isStartAndEndDateRange = startDate.toDateString() !== endDate.toDateString() && isWithinInterval(date, daysSelected);
|
|
18
|
+
const hasEndDateSelected = date.toDateString() === endDate.toDateString();
|
|
19
|
+
const hasStartDateSelected = date.toDateString() === startDate.toDateString();
|
|
20
|
+
return /* @__PURE__ */ React.createElement(
|
|
21
|
+
"div",
|
|
22
|
+
{
|
|
23
|
+
"aria-selected": isStartAndEndDateRange || hasStartDateSelected ? true : void 0,
|
|
24
|
+
className: classnames(
|
|
25
|
+
"date-picker-col",
|
|
26
|
+
range && {
|
|
27
|
+
"c-selected": isStartAndEndDateRange,
|
|
28
|
+
"c-selected-end": hasEndDateSelected && !hasStartDateSelected,
|
|
29
|
+
"c-selected-start": hasStartDateSelected && !hasEndDateSelected
|
|
30
|
+
}
|
|
31
|
+
),
|
|
32
|
+
role: "gridcell"
|
|
33
|
+
},
|
|
34
|
+
/* @__PURE__ */ React.createElement(
|
|
35
|
+
"button",
|
|
36
|
+
{
|
|
37
|
+
"aria-disabled": outOfRange ? true : void 0,
|
|
38
|
+
"aria-label": setDate(date, {
|
|
39
|
+
hours: 12,
|
|
40
|
+
milliseconds: 0,
|
|
41
|
+
minutes: 0,
|
|
42
|
+
seconds: 0
|
|
43
|
+
}).toDateString(),
|
|
44
|
+
className: classnames(
|
|
45
|
+
"date-picker-date date-picker-calendar-item",
|
|
46
|
+
{
|
|
47
|
+
"active": hasStartDateSelected || range && hasEndDateSelected,
|
|
48
|
+
"disabled": disabled || outOfRange,
|
|
49
|
+
"next-month-date": nextMonth,
|
|
50
|
+
"previous-month-date": previousMonth
|
|
51
|
+
}
|
|
52
|
+
),
|
|
53
|
+
"data-index": index,
|
|
54
|
+
disabled,
|
|
55
|
+
onClick: () => onClick(date),
|
|
56
|
+
onKeyDown: (event) => {
|
|
57
|
+
if (event.key === Keys.Spacebar) {
|
|
58
|
+
event.preventDefault();
|
|
59
|
+
}
|
|
60
|
+
},
|
|
61
|
+
onKeyUp: (event) => {
|
|
62
|
+
if (event.key === Keys.Spacebar) {
|
|
63
|
+
onClick(date);
|
|
64
|
+
}
|
|
65
|
+
},
|
|
66
|
+
tabIndex: isFocused ? void 0 : -1,
|
|
67
|
+
type: "button"
|
|
68
|
+
},
|
|
69
|
+
date.getDate()
|
|
70
|
+
)
|
|
71
|
+
);
|
|
72
|
+
}
|
|
73
|
+
function isWithinInterval(date, interval) {
|
|
74
|
+
const [start, end] = interval;
|
|
75
|
+
const time = date.getTime();
|
|
76
|
+
const startTime = start.getTime();
|
|
77
|
+
const endTime = end.getTime();
|
|
78
|
+
if (startTime > endTime) {
|
|
79
|
+
return false;
|
|
80
|
+
}
|
|
81
|
+
return time >= startTime && time <= endTime;
|
|
82
|
+
}
|
|
83
|
+
var DayNumber_default = ClayDatePickerDayNumber;
|
|
84
|
+
export {
|
|
85
|
+
DayNumber_default as default
|
|
86
|
+
};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
function ClayDatePickerDaysTable({ children, weeks }) {
|
|
3
|
+
return /* @__PURE__ */ React.createElement(React.Fragment, null, weeks.map((days, index) => /* @__PURE__ */ React.createElement(
|
|
4
|
+
"div",
|
|
5
|
+
{
|
|
6
|
+
className: "date-picker-date-row date-picker-row",
|
|
7
|
+
"data-index": index,
|
|
8
|
+
key: index,
|
|
9
|
+
role: "row"
|
|
10
|
+
},
|
|
11
|
+
days.map((day, index2) => {
|
|
12
|
+
return React.Children.only(children({ day, key: index2 }));
|
|
13
|
+
})
|
|
14
|
+
)));
|
|
15
|
+
}
|
|
16
|
+
var DaysTable_default = ClayDatePickerDaysTable;
|
|
17
|
+
export {
|
|
18
|
+
DaysTable_default as default
|
|
19
|
+
};
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { default as formatDate } from "date-fns/format";
|
|
2
|
+
import { default as parseDate } from "date-fns/parse";
|
|
3
|
+
function addMonths(date, months) {
|
|
4
|
+
date = clone(date);
|
|
5
|
+
date.setMonth(date.getMonth() + months);
|
|
6
|
+
return date;
|
|
7
|
+
}
|
|
8
|
+
function clamp(date, min, max) {
|
|
9
|
+
if (min && isBefore(date, min)) {
|
|
10
|
+
return clone(min);
|
|
11
|
+
}
|
|
12
|
+
if (max && isAfter(date, max)) {
|
|
13
|
+
return clone(max);
|
|
14
|
+
}
|
|
15
|
+
return clone(date);
|
|
16
|
+
}
|
|
17
|
+
function clone(date) {
|
|
18
|
+
return new Date(date instanceof Date ? date.getTime() : date);
|
|
19
|
+
}
|
|
20
|
+
function isAfter(a, b) {
|
|
21
|
+
return a.getTime() > b.getTime();
|
|
22
|
+
}
|
|
23
|
+
function isBefore(a, b) {
|
|
24
|
+
return a.getTime() < b.getTime();
|
|
25
|
+
}
|
|
26
|
+
function isSameDay(a, b) {
|
|
27
|
+
return a.getFullYear() === b.getFullYear() && a.getMonth() === b.getMonth() && a.getDate() === b.getDate();
|
|
28
|
+
}
|
|
29
|
+
function isValid(date) {
|
|
30
|
+
return date instanceof Date && !isNaN(date.getTime());
|
|
31
|
+
}
|
|
32
|
+
function range({ end, start }) {
|
|
33
|
+
return Array.from(
|
|
34
|
+
{
|
|
35
|
+
length: end - start + 1
|
|
36
|
+
},
|
|
37
|
+
(_v, k) => k + start
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
function setDate(date, options) {
|
|
41
|
+
date = clone(date);
|
|
42
|
+
return Object.keys(options).reduce((acc, key) => {
|
|
43
|
+
const method = `set${key.charAt(0).toUpperCase() + key.slice(1)}`;
|
|
44
|
+
acc[method](options[key]);
|
|
45
|
+
return acc;
|
|
46
|
+
}, date);
|
|
47
|
+
}
|
|
48
|
+
function setMonth(range2, month, currentMonth) {
|
|
49
|
+
const date = addMonths(currentMonth, month);
|
|
50
|
+
const year = date.getFullYear();
|
|
51
|
+
if (range2.find((elem) => elem.value === year)) {
|
|
52
|
+
return date;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
export {
|
|
56
|
+
addMonths,
|
|
57
|
+
clamp,
|
|
58
|
+
clone,
|
|
59
|
+
formatDate,
|
|
60
|
+
isAfter,
|
|
61
|
+
isBefore,
|
|
62
|
+
isSameDay,
|
|
63
|
+
isValid,
|
|
64
|
+
parseDate,
|
|
65
|
+
range,
|
|
66
|
+
setDate,
|
|
67
|
+
setMonth
|
|
68
|
+
};
|
package/lib/esm/Hooks.js
ADDED
|
@@ -0,0 +1,278 @@
|
|
|
1
|
+
import { Keys } from "@clayui/shared";
|
|
2
|
+
import { useCallback, useEffect, useRef, useState } from "react";
|
|
3
|
+
import { clone, formatDate, setDate } from "./Helpers";
|
|
4
|
+
function normalizeTime(date) {
|
|
5
|
+
return setDate(date, { hours: 12, milliseconds: 0, minutes: 0, seconds: 0 });
|
|
6
|
+
}
|
|
7
|
+
function useDaysSelected(defaultDays) {
|
|
8
|
+
const [daysSelected, set] = useState(defaultDays);
|
|
9
|
+
const setDaysSelected = useCallback(([start, end]) => {
|
|
10
|
+
if (start === end) {
|
|
11
|
+
const date = normalizeTime(start);
|
|
12
|
+
set([date, date]);
|
|
13
|
+
} else {
|
|
14
|
+
set([normalizeTime(start), normalizeTime(end)]);
|
|
15
|
+
}
|
|
16
|
+
}, []);
|
|
17
|
+
return [daysSelected, setDaysSelected];
|
|
18
|
+
}
|
|
19
|
+
function useWeeks(currentMonth, firstDayOfWeek) {
|
|
20
|
+
const [weeks, set] = useState(
|
|
21
|
+
() => getWeekArray(currentMonth, firstDayOfWeek)
|
|
22
|
+
);
|
|
23
|
+
const setWeeks = useCallback(
|
|
24
|
+
(value) => set(getWeekArray(value, firstDayOfWeek)),
|
|
25
|
+
[firstDayOfWeek]
|
|
26
|
+
);
|
|
27
|
+
return [weeks, setWeeks];
|
|
28
|
+
}
|
|
29
|
+
function useCurrentTime(defaultTime, use12Hours) {
|
|
30
|
+
const [currentTime, set] = useState(defaultTime);
|
|
31
|
+
const setCurrentTime = useCallback(
|
|
32
|
+
(hours, minutes, ampm) => {
|
|
33
|
+
const date = setDate(/* @__PURE__ */ new Date(), { hours, minutes });
|
|
34
|
+
if (typeof hours !== "string") {
|
|
35
|
+
if (use12Hours) {
|
|
36
|
+
hours = formatDate(date, "hh");
|
|
37
|
+
} else {
|
|
38
|
+
hours = formatDate(date, "HH");
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
if (typeof minutes !== "string") {
|
|
42
|
+
minutes = formatDate(date, "mm");
|
|
43
|
+
}
|
|
44
|
+
const value = ampm ? `${hours}:${minutes} ${ampm}` : `${hours}:${minutes}`;
|
|
45
|
+
set(value);
|
|
46
|
+
return value;
|
|
47
|
+
},
|
|
48
|
+
[use12Hours]
|
|
49
|
+
);
|
|
50
|
+
return [currentTime, setCurrentTime];
|
|
51
|
+
}
|
|
52
|
+
function useCalendarNavigation({
|
|
53
|
+
daysSelected,
|
|
54
|
+
isOpen,
|
|
55
|
+
onChangeMonth,
|
|
56
|
+
weeks
|
|
57
|
+
}) {
|
|
58
|
+
const [lastItemFocused, setLastItemFocused] = useState(null);
|
|
59
|
+
const gridRef = useRef(null);
|
|
60
|
+
const lastKeyPressedRef = useRef("");
|
|
61
|
+
const hasNextFocusRef = useRef(false);
|
|
62
|
+
const focusNext = useCallback((day) => {
|
|
63
|
+
if (!gridRef.current) {
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
const nextFocusElement = gridRef.current.querySelector(
|
|
67
|
+
`button[aria-label="${setDate(day.date, {
|
|
68
|
+
hours: 12,
|
|
69
|
+
milliseconds: 0,
|
|
70
|
+
minutes: 0,
|
|
71
|
+
seconds: 0
|
|
72
|
+
}).toDateString()}"]`
|
|
73
|
+
);
|
|
74
|
+
if (nextFocusElement) {
|
|
75
|
+
nextFocusElement.focus();
|
|
76
|
+
setLastItemFocused(String(day.date.getDate()));
|
|
77
|
+
}
|
|
78
|
+
}, []);
|
|
79
|
+
const onKeyDown = useCallback(
|
|
80
|
+
(event) => {
|
|
81
|
+
switch (event.key) {
|
|
82
|
+
case Keys.Down:
|
|
83
|
+
case Keys.Up:
|
|
84
|
+
case Keys.Right:
|
|
85
|
+
case Keys.Left: {
|
|
86
|
+
event.preventDefault();
|
|
87
|
+
const currentRowPosition = Number(
|
|
88
|
+
document.activeElement.closest("[role=row]").getAttribute("data-index")
|
|
89
|
+
);
|
|
90
|
+
const position = Number(
|
|
91
|
+
document.activeElement.getAttribute("data-index")
|
|
92
|
+
);
|
|
93
|
+
const currentRow = weeks[currentRowPosition];
|
|
94
|
+
let nextFocus = null;
|
|
95
|
+
switch (event.key) {
|
|
96
|
+
case Keys.Right:
|
|
97
|
+
case Keys.Left: {
|
|
98
|
+
nextFocus = currentRow[event.key === Keys.Left ? position - 1 : position + 1];
|
|
99
|
+
if (!nextFocus) {
|
|
100
|
+
nextFocus = weeks[event.key === Keys.Left ? currentRowPosition - 1 : currentRowPosition + 1]?.[event.key === Keys.Left ? currentRow.length - 1 : 0];
|
|
101
|
+
}
|
|
102
|
+
break;
|
|
103
|
+
}
|
|
104
|
+
case Keys.Up:
|
|
105
|
+
case Keys.Down: {
|
|
106
|
+
nextFocus = weeks[event.key === Keys.Up ? currentRowPosition - 1 : currentRowPosition + 1]?.[position];
|
|
107
|
+
break;
|
|
108
|
+
}
|
|
109
|
+
default:
|
|
110
|
+
break;
|
|
111
|
+
}
|
|
112
|
+
if (nextFocus && !nextFocus.nextMonth && !nextFocus.previousMonth) {
|
|
113
|
+
focusNext(nextFocus);
|
|
114
|
+
} else {
|
|
115
|
+
onChangeMonth(
|
|
116
|
+
event.key === Keys.Left || event.key === Keys.Up ? -1 : 1
|
|
117
|
+
);
|
|
118
|
+
lastKeyPressedRef.current = event.key;
|
|
119
|
+
hasNextFocusRef.current = true;
|
|
120
|
+
}
|
|
121
|
+
break;
|
|
122
|
+
}
|
|
123
|
+
case Keys.End:
|
|
124
|
+
case Keys.Home: {
|
|
125
|
+
event.preventDefault();
|
|
126
|
+
const grid = event.currentTarget.querySelectorAll(
|
|
127
|
+
"button:not(.previous-month-date):not(.next-month-date)"
|
|
128
|
+
);
|
|
129
|
+
const day = grid[event.key === Keys.Home ? 0 : grid.length - 1];
|
|
130
|
+
if (day) {
|
|
131
|
+
day.focus();
|
|
132
|
+
setLastItemFocused(day.innerText);
|
|
133
|
+
}
|
|
134
|
+
break;
|
|
135
|
+
}
|
|
136
|
+
case "PageDown":
|
|
137
|
+
case "PageUp": {
|
|
138
|
+
event.preventDefault();
|
|
139
|
+
const value = event.key === "PageUp" ? -1 : 1;
|
|
140
|
+
if (event.shiftKey) {
|
|
141
|
+
onChangeMonth(0, value);
|
|
142
|
+
} else {
|
|
143
|
+
onChangeMonth(value);
|
|
144
|
+
}
|
|
145
|
+
lastKeyPressedRef.current = event.key;
|
|
146
|
+
hasNextFocusRef.current = true;
|
|
147
|
+
break;
|
|
148
|
+
}
|
|
149
|
+
default:
|
|
150
|
+
break;
|
|
151
|
+
}
|
|
152
|
+
},
|
|
153
|
+
[weeks]
|
|
154
|
+
);
|
|
155
|
+
const onFocus = useCallback((event) => {
|
|
156
|
+
setLastItemFocused(event.target.innerText);
|
|
157
|
+
}, []);
|
|
158
|
+
const isFocused = useCallback(
|
|
159
|
+
(day) => {
|
|
160
|
+
return !day.nextMonth && !day.previousMonth && (lastItemFocused === String(day.date.getDate()) || lastItemFocused === null && day.date.toDateString() === daysSelected[0].toDateString());
|
|
161
|
+
},
|
|
162
|
+
[lastItemFocused, daysSelected]
|
|
163
|
+
);
|
|
164
|
+
useEffect(() => {
|
|
165
|
+
if (gridRef.current && isOpen) {
|
|
166
|
+
focusNext({ date: daysSelected[0] });
|
|
167
|
+
}
|
|
168
|
+
}, [daysSelected]);
|
|
169
|
+
useEffect(() => {
|
|
170
|
+
if (gridRef.current) {
|
|
171
|
+
if (isOpen) {
|
|
172
|
+
const focusNext2 = gridRef.current.querySelector(
|
|
173
|
+
'button:not([tabindex="-1"])'
|
|
174
|
+
);
|
|
175
|
+
if (focusNext2) {
|
|
176
|
+
focusNext2.focus();
|
|
177
|
+
}
|
|
178
|
+
} else {
|
|
179
|
+
setLastItemFocused(null);
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
}, [isOpen]);
|
|
183
|
+
useEffect(() => {
|
|
184
|
+
if (hasNextFocusRef.current && gridRef.current) {
|
|
185
|
+
hasNextFocusRef.current = false;
|
|
186
|
+
const position = Number(
|
|
187
|
+
document.activeElement.getAttribute("data-index")
|
|
188
|
+
);
|
|
189
|
+
const row = weeks[lastKeyPressedRef.current === Keys.Left || lastKeyPressedRef.current === Keys.Up ? weeks.length - 1 : 0];
|
|
190
|
+
switch (lastKeyPressedRef.current) {
|
|
191
|
+
case Keys.Right:
|
|
192
|
+
case Keys.Left: {
|
|
193
|
+
const newRow = row.filter(
|
|
194
|
+
(value) => !value.nextMonth && !value.previousMonth
|
|
195
|
+
);
|
|
196
|
+
focusNext(
|
|
197
|
+
newRow[lastKeyPressedRef.current === Keys.Left ? newRow.length - 1 : 0]
|
|
198
|
+
);
|
|
199
|
+
break;
|
|
200
|
+
}
|
|
201
|
+
case Keys.Down:
|
|
202
|
+
case Keys.Up: {
|
|
203
|
+
let nextFocus = row.map(
|
|
204
|
+
(value) => !value.nextMonth && !value.previousMonth ? value : null
|
|
205
|
+
)[position];
|
|
206
|
+
if (!nextFocus) {
|
|
207
|
+
nextFocus = weeks[lastKeyPressedRef.current === Keys.Up ? weeks.length - 2 : 1][position];
|
|
208
|
+
}
|
|
209
|
+
focusNext(nextFocus);
|
|
210
|
+
break;
|
|
211
|
+
}
|
|
212
|
+
case "PageDown":
|
|
213
|
+
case "PageUp": {
|
|
214
|
+
const focusNext2 = gridRef.current.querySelector(
|
|
215
|
+
'button:not([tabindex="-1"])'
|
|
216
|
+
);
|
|
217
|
+
if (focusNext2) {
|
|
218
|
+
focusNext2.focus();
|
|
219
|
+
}
|
|
220
|
+
break;
|
|
221
|
+
}
|
|
222
|
+
default:
|
|
223
|
+
break;
|
|
224
|
+
}
|
|
225
|
+
lastKeyPressedRef.current = "";
|
|
226
|
+
}
|
|
227
|
+
}, [weeks]);
|
|
228
|
+
const gridProps = { onFocus, onKeyDown, ref: gridRef };
|
|
229
|
+
return {
|
|
230
|
+
gridProps,
|
|
231
|
+
isFocused
|
|
232
|
+
};
|
|
233
|
+
}
|
|
234
|
+
function getDaysInMonth(d) {
|
|
235
|
+
const firstDayOfMonth = new Date(d.getFullYear(), d.getMonth(), 1, 12);
|
|
236
|
+
firstDayOfMonth.setMonth(firstDayOfMonth.getMonth() + 1);
|
|
237
|
+
firstDayOfMonth.setDate(firstDayOfMonth.getDate() - 1);
|
|
238
|
+
return firstDayOfMonth.getDate();
|
|
239
|
+
}
|
|
240
|
+
function getWeekArray(d, firstDayOfWeek = 0) {
|
|
241
|
+
const daysInMonth = getDaysInMonth(d);
|
|
242
|
+
const dayArray = [];
|
|
243
|
+
let week = [];
|
|
244
|
+
const weekArray = [];
|
|
245
|
+
for (let i = 1; i <= daysInMonth; i += 1) {
|
|
246
|
+
const genDay = new Date(d.getFullYear(), d.getMonth(), i, 12);
|
|
247
|
+
dayArray.push({ date: genDay });
|
|
248
|
+
}
|
|
249
|
+
dayArray.forEach((day) => {
|
|
250
|
+
if (!!week.length && day.date.getDay() === firstDayOfWeek) {
|
|
251
|
+
weekArray.push(week);
|
|
252
|
+
week = [];
|
|
253
|
+
}
|
|
254
|
+
week.push(day);
|
|
255
|
+
if (dayArray.indexOf(day) === dayArray.length - 1) {
|
|
256
|
+
weekArray.push(week);
|
|
257
|
+
}
|
|
258
|
+
});
|
|
259
|
+
const firstWeek = weekArray[0];
|
|
260
|
+
for (let i = 7 - firstWeek.length; i > 0; i -= 1) {
|
|
261
|
+
const outsideDate = clone(firstWeek[0].date);
|
|
262
|
+
outsideDate.setDate(firstWeek[0].date.getDate() - 1);
|
|
263
|
+
firstWeek.unshift({ date: outsideDate, previousMonth: true });
|
|
264
|
+
}
|
|
265
|
+
const lastWeek = weekArray[weekArray.length - 1];
|
|
266
|
+
for (let i = lastWeek.length; i < 7; i += 1) {
|
|
267
|
+
const outsideDate = clone(lastWeek[lastWeek.length - 1].date);
|
|
268
|
+
outsideDate.setDate(lastWeek[lastWeek.length - 1].date.getDate() + 1);
|
|
269
|
+
lastWeek.push({ date: outsideDate, nextMonth: true });
|
|
270
|
+
}
|
|
271
|
+
return weekArray;
|
|
272
|
+
}
|
|
273
|
+
export {
|
|
274
|
+
useCalendarNavigation,
|
|
275
|
+
useCurrentTime,
|
|
276
|
+
useDaysSelected,
|
|
277
|
+
useWeeks
|
|
278
|
+
};
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { ClayInput } from "@clayui/form";
|
|
2
|
+
import React from "react";
|
|
3
|
+
const ClayDatePickerInputDate = React.forwardRef(
|
|
4
|
+
({
|
|
5
|
+
ariaLabel,
|
|
6
|
+
inputName = "datePicker",
|
|
7
|
+
useNative = false,
|
|
8
|
+
value = "",
|
|
9
|
+
...otherProps
|
|
10
|
+
}, ref) => {
|
|
11
|
+
return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement("input", { name: inputName, type: "hidden", value }), /* @__PURE__ */ React.createElement(
|
|
12
|
+
ClayInput,
|
|
13
|
+
{
|
|
14
|
+
...otherProps,
|
|
15
|
+
"aria-label": ariaLabel,
|
|
16
|
+
insetAfter: !useNative,
|
|
17
|
+
ref,
|
|
18
|
+
type: useNative ? "date" : "text",
|
|
19
|
+
value
|
|
20
|
+
}
|
|
21
|
+
));
|
|
22
|
+
}
|
|
23
|
+
);
|
|
24
|
+
ClayDatePickerInputDate.displayName = "ClayDatePickerInputDate";
|
|
25
|
+
var InputDate_default = ClayDatePickerInputDate;
|
|
26
|
+
export {
|
|
27
|
+
InputDate_default as default
|
|
28
|
+
};
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
const ClayDatePickerSelect = React.forwardRef(
|
|
3
|
+
({ options, testId, ...otherProps }, ref) => /* @__PURE__ */ React.createElement(
|
|
4
|
+
"select",
|
|
5
|
+
{
|
|
6
|
+
...otherProps,
|
|
7
|
+
className: "form-control form-control-sm",
|
|
8
|
+
"data-testid": testId,
|
|
9
|
+
ref
|
|
10
|
+
},
|
|
11
|
+
options.map((option, index) => /* @__PURE__ */ React.createElement(
|
|
12
|
+
"option",
|
|
13
|
+
{
|
|
14
|
+
key: index,
|
|
15
|
+
selected: option.selected ? true : void 0,
|
|
16
|
+
value: option.value
|
|
17
|
+
},
|
|
18
|
+
option.label
|
|
19
|
+
))
|
|
20
|
+
)
|
|
21
|
+
);
|
|
22
|
+
ClayDatePickerSelect.displayName = "ClayDatePickerSelect";
|
|
23
|
+
var Select_default = ClayDatePickerSelect;
|
|
24
|
+
export {
|
|
25
|
+
Select_default as default
|
|
26
|
+
};
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import ClayTimePicker from "@clayui/time-picker";
|
|
2
|
+
import React from "react";
|
|
3
|
+
const DEFAULT_VALUE = "--";
|
|
4
|
+
function ClayDatePickerTimePicker({
|
|
5
|
+
config,
|
|
6
|
+
currentTime,
|
|
7
|
+
disabled,
|
|
8
|
+
onTimeChange,
|
|
9
|
+
spritemap,
|
|
10
|
+
timezone,
|
|
11
|
+
use12Hours
|
|
12
|
+
}) {
|
|
13
|
+
const [values, setValues] = React.useState({
|
|
14
|
+
ampm: DEFAULT_VALUE,
|
|
15
|
+
hours: DEFAULT_VALUE,
|
|
16
|
+
minutes: DEFAULT_VALUE
|
|
17
|
+
});
|
|
18
|
+
const handleOnChange = (values2) => {
|
|
19
|
+
const hours = values2.hours === DEFAULT_VALUE ? DEFAULT_VALUE : Number(values2.hours);
|
|
20
|
+
const minutes = values2.minutes === DEFAULT_VALUE ? DEFAULT_VALUE : Number(values2.minutes);
|
|
21
|
+
const ampm = values2.ampm ? values2.ampm : DEFAULT_VALUE;
|
|
22
|
+
setValues(values2);
|
|
23
|
+
onTimeChange(hours, minutes, ampm);
|
|
24
|
+
};
|
|
25
|
+
React.useEffect(() => {
|
|
26
|
+
const [hours, minutesAndAmpm] = currentTime.split(":");
|
|
27
|
+
const [minutes, ampm] = minutesAndAmpm.split(" ");
|
|
28
|
+
setValues((prevValues) => ({
|
|
29
|
+
...prevValues,
|
|
30
|
+
ampm,
|
|
31
|
+
hours: String(hours),
|
|
32
|
+
minutes: String(minutes)
|
|
33
|
+
}));
|
|
34
|
+
}, [currentTime, use12Hours]);
|
|
35
|
+
return /* @__PURE__ */ React.createElement("div", { className: "time-picker" }, /* @__PURE__ */ React.createElement(
|
|
36
|
+
ClayTimePicker,
|
|
37
|
+
{
|
|
38
|
+
config,
|
|
39
|
+
disabled,
|
|
40
|
+
icon: true,
|
|
41
|
+
onInputChange: handleOnChange,
|
|
42
|
+
spritemap,
|
|
43
|
+
timezone,
|
|
44
|
+
use12Hours,
|
|
45
|
+
values
|
|
46
|
+
}
|
|
47
|
+
));
|
|
48
|
+
}
|
|
49
|
+
var TimePicker_default = ClayDatePickerTimePicker;
|
|
50
|
+
export {
|
|
51
|
+
TimePicker_default as default
|
|
52
|
+
};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
function ClayDatePickerWeekday({ weekday }) {
|
|
3
|
+
return /* @__PURE__ */ React.createElement("div", { className: "date-picker-col" }, /* @__PURE__ */ React.createElement("div", { className: "date-picker-calendar-item date-picker-day" }, /* @__PURE__ */ React.createElement("abbr", null, weekday)));
|
|
4
|
+
}
|
|
5
|
+
var Weekday_default = ClayDatePickerWeekday;
|
|
6
|
+
export {
|
|
7
|
+
Weekday_default as default
|
|
8
|
+
};
|