funuicss 2.7.7 → 2.7.8
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/css/fun.css +92 -2
- package/index.d.ts +2 -0
- package/index.js +6 -1
- package/index.tsx +2 -0
- package/package.json +2 -1
- package/tsconfig.tsbuildinfo +1 -1
- package/ui/ScrollInView/ScrollInView.js +6 -6
- package/ui/ScrollInView/ScrollInView.tsx +6 -6
- package/ui/avatar/Avatar.d.ts +3 -2
- package/ui/avatar/Avatar.js +25 -4
- package/ui/avatar/Avatar.tsx +16 -8
- package/ui/datepicker/DatePicker.d.ts +10 -0
- package/ui/datepicker/DatePicker.js +129 -0
- package/ui/datepicker/DatePicker.tsx +143 -0
|
@@ -38,12 +38,12 @@ var react_1 = __importStar(require("react"));
|
|
|
38
38
|
var framer_motion_1 = require("framer-motion");
|
|
39
39
|
var react_intersection_observer_1 = require("react-intersection-observer");
|
|
40
40
|
var animationVariants = {
|
|
41
|
-
'fade-up': { hidden: { opacity: 0, y:
|
|
42
|
-
'fade-down': { hidden: { opacity: 0, y: -
|
|
41
|
+
'fade-up': { hidden: { opacity: 0, y: 20 }, visible: { opacity: 1, y: 0 } },
|
|
42
|
+
'fade-down': { hidden: { opacity: 0, y: -20 }, visible: { opacity: 1, y: 0 } },
|
|
43
43
|
'fade-in': { hidden: { opacity: 0 }, visible: { opacity: 1 } },
|
|
44
|
-
'zoom-in': { hidden: { scale: 0.
|
|
45
|
-
'slide-left': { hidden: { x:
|
|
46
|
-
'slide-right': { hidden: { x: -
|
|
44
|
+
'zoom-in': { hidden: { scale: 0.95, opacity: 0 }, visible: { scale: 1, opacity: 1 } },
|
|
45
|
+
'slide-left': { hidden: { x: 20, opacity: 0 }, visible: { x: 0, opacity: 1 } },
|
|
46
|
+
'slide-right': { hidden: { x: -20, opacity: 0 }, visible: { x: 0, opacity: 1 } },
|
|
47
47
|
};
|
|
48
48
|
var ScrollInView = function (_a) {
|
|
49
49
|
var children = _a.children, _b = _a.animationType, animationType = _b === void 0 ? 'fade-up' : _b, _c = _a.delay, delay = _c === void 0 ? 0 : _c, _d = _a.duration, duration = _d === void 0 ? 0.6 : _d, _e = _a.threshold, threshold = _e === void 0 ? 0.2 : _e, _f = _a.once, once = _f === void 0 ? false : _f, _g = _a.className, className = _g === void 0 ? '' : _g;
|
|
@@ -64,7 +64,7 @@ var ScrollInView = function (_a) {
|
|
|
64
64
|
return (react_1.default.createElement(framer_motion_1.motion.div, { ref: ref, variants: variants, initial: "hidden", animate: controls, transition: {
|
|
65
65
|
delay: delay,
|
|
66
66
|
duration: duration,
|
|
67
|
-
ease:
|
|
67
|
+
ease: 'linear', // SMOOTH and STRAIGHT
|
|
68
68
|
}, className: className }, children));
|
|
69
69
|
};
|
|
70
70
|
exports.default = ScrollInView;
|
|
@@ -5,12 +5,12 @@ import { motion, useAnimation } from 'framer-motion';
|
|
|
5
5
|
import { useInView } from 'react-intersection-observer';
|
|
6
6
|
|
|
7
7
|
const animationVariants = {
|
|
8
|
-
'fade-up': { hidden: { opacity: 0, y:
|
|
9
|
-
'fade-down': { hidden: { opacity: 0, y: -
|
|
8
|
+
'fade-up': { hidden: { opacity: 0, y: 20 }, visible: { opacity: 1, y: 0 } },
|
|
9
|
+
'fade-down': { hidden: { opacity: 0, y: -20 }, visible: { opacity: 1, y: 0 } },
|
|
10
10
|
'fade-in': { hidden: { opacity: 0 }, visible: { opacity: 1 } },
|
|
11
|
-
'zoom-in': { hidden: { scale: 0.
|
|
12
|
-
'slide-left': { hidden: { x:
|
|
13
|
-
'slide-right': { hidden: { x: -
|
|
11
|
+
'zoom-in': { hidden: { scale: 0.95, opacity: 0 }, visible: { scale: 1, opacity: 1 } },
|
|
12
|
+
'slide-left': { hidden: { x: 20, opacity: 0 }, visible: { x: 0, opacity: 1 } },
|
|
13
|
+
'slide-right': { hidden: { x: -20, opacity: 0 }, visible: { x: 0, opacity: 1 } },
|
|
14
14
|
};
|
|
15
15
|
|
|
16
16
|
interface ScrollInViewProps {
|
|
@@ -57,7 +57,7 @@ const ScrollInView: React.FC<ScrollInViewProps> = ({
|
|
|
57
57
|
transition={{
|
|
58
58
|
delay,
|
|
59
59
|
duration,
|
|
60
|
-
ease:
|
|
60
|
+
ease: 'linear', // SMOOTH and STRAIGHT
|
|
61
61
|
}}
|
|
62
62
|
className={className}
|
|
63
63
|
>
|
package/ui/avatar/Avatar.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ReactNode } from 'react';
|
|
1
|
+
import { ReactNode, MouseEventHandler } from 'react';
|
|
2
2
|
import * as React from 'react';
|
|
3
3
|
interface AvatarProps {
|
|
4
4
|
funcss?: string;
|
|
@@ -8,6 +8,7 @@ interface AvatarProps {
|
|
|
8
8
|
bordered?: boolean;
|
|
9
9
|
color?: string;
|
|
10
10
|
content?: ReactNode;
|
|
11
|
+
onClick?: MouseEventHandler<HTMLDivElement>;
|
|
11
12
|
}
|
|
12
|
-
export default function Avatar({ funcss, children, size, bordered, bg, content, color }: AvatarProps): React.JSX.Element;
|
|
13
|
+
export default function Avatar({ funcss, children, size, bordered, bg, content, color, onClick, ...rest }: AvatarProps): React.JSX.Element;
|
|
13
14
|
export {};
|
package/ui/avatar/Avatar.js
CHANGED
|
@@ -1,5 +1,16 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
'use client';
|
|
3
|
+
var __assign = (this && this.__assign) || function () {
|
|
4
|
+
__assign = Object.assign || function(t) {
|
|
5
|
+
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
6
|
+
s = arguments[i];
|
|
7
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
|
8
|
+
t[p] = s[p];
|
|
9
|
+
}
|
|
10
|
+
return t;
|
|
11
|
+
};
|
|
12
|
+
return __assign.apply(this, arguments);
|
|
13
|
+
};
|
|
3
14
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
4
15
|
if (k2 === undefined) k2 = k;
|
|
5
16
|
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
@@ -33,14 +44,24 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
33
44
|
return result;
|
|
34
45
|
};
|
|
35
46
|
})();
|
|
47
|
+
var __rest = (this && this.__rest) || function (s, e) {
|
|
48
|
+
var t = {};
|
|
49
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
50
|
+
t[p] = s[p];
|
|
51
|
+
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
52
|
+
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
53
|
+
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
54
|
+
t[p[i]] = s[p[i]];
|
|
55
|
+
}
|
|
56
|
+
return t;
|
|
57
|
+
};
|
|
36
58
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
37
59
|
exports.default = Avatar;
|
|
38
60
|
var React = __importStar(require("react"));
|
|
39
61
|
function Avatar(_a) {
|
|
40
|
-
var funcss = _a.funcss, children = _a.children, _b = _a.size, size = _b === void 0 ? 2 : _b, _c = _a.bordered, bordered = _c === void 0 ? true : _c, bg = _a.bg, content = _a.content, color = _a.color;
|
|
41
|
-
return (React.createElement("div", { className: "\n animated \n fade-in \n avatar \n ".concat(funcss || '', " \n ").concat(bg || 'lighter', " \n ").concat(bordered ? 'border' : '', "\n
|
|
62
|
+
var funcss = _a.funcss, children = _a.children, _b = _a.size, size = _b === void 0 ? 2 : _b, _c = _a.bordered, bordered = _c === void 0 ? true : _c, bg = _a.bg, content = _a.content, color = _a.color, onClick = _a.onClick, rest = __rest(_a, ["funcss", "children", "size", "bordered", "bg", "content", "color", "onClick"]);
|
|
63
|
+
return (React.createElement("div", __assign({ className: "\n animated \n pointer\n fade-in \n avatar \n ".concat(funcss || '', " \n ").concat(bg || 'lighter', " \n ").concat(bordered ? 'border' : '', "\n ").concat(color ? "text-".concat(color) : '', "\n "), style: {
|
|
42
64
|
width: "".concat(size, "rem"),
|
|
43
65
|
height: "".concat(size, "rem"),
|
|
44
|
-
} },
|
|
45
|
-
React.createElement(React.Fragment, null, content || children)));
|
|
66
|
+
}, onClick: onClick }, rest), content || children));
|
|
46
67
|
}
|
package/ui/avatar/Avatar.tsx
CHANGED
|
@@ -1,14 +1,17 @@
|
|
|
1
|
-
'use client';
|
|
2
|
-
|
|
3
|
-
import
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { ReactNode, MouseEventHandler } from 'react';
|
|
4
|
+
import * as React from 'react';
|
|
5
|
+
|
|
4
6
|
interface AvatarProps {
|
|
5
7
|
funcss?: string;
|
|
6
8
|
children?: ReactNode;
|
|
7
9
|
size?: number;
|
|
8
10
|
bg?: string;
|
|
9
|
-
bordered?:boolean
|
|
10
|
-
color?: string
|
|
11
|
+
bordered?: boolean;
|
|
12
|
+
color?: string;
|
|
11
13
|
content?: ReactNode;
|
|
14
|
+
onClick?: MouseEventHandler<HTMLDivElement>;
|
|
12
15
|
}
|
|
13
16
|
|
|
14
17
|
export default function Avatar({
|
|
@@ -18,25 +21,30 @@ export default function Avatar({
|
|
|
18
21
|
bordered = true,
|
|
19
22
|
bg,
|
|
20
23
|
content,
|
|
21
|
-
color
|
|
24
|
+
color,
|
|
25
|
+
onClick,
|
|
26
|
+
...rest
|
|
22
27
|
}: AvatarProps) {
|
|
23
28
|
return (
|
|
24
29
|
<div
|
|
25
30
|
className={`
|
|
26
31
|
animated
|
|
32
|
+
pointer
|
|
27
33
|
fade-in
|
|
28
34
|
avatar
|
|
29
35
|
${funcss || ''}
|
|
30
36
|
${bg || 'lighter'}
|
|
31
37
|
${bordered ? 'border' : ''}
|
|
32
|
-
|
|
38
|
+
${color ? `text-${color}` : ''}
|
|
33
39
|
`}
|
|
34
40
|
style={{
|
|
35
41
|
width: `${size}rem`,
|
|
36
42
|
height: `${size}rem`,
|
|
37
43
|
}}
|
|
44
|
+
onClick={onClick}
|
|
45
|
+
{...rest}
|
|
38
46
|
>
|
|
39
|
-
|
|
47
|
+
{content || children}
|
|
40
48
|
</div>
|
|
41
49
|
);
|
|
42
50
|
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
interface DatePickerProps {
|
|
3
|
+
mode?: 'single' | 'interval';
|
|
4
|
+
funcss?: string;
|
|
5
|
+
onSelect?: (value: Date | [Date, Date]) => void;
|
|
6
|
+
value?: Date | [Date, Date];
|
|
7
|
+
className?: string;
|
|
8
|
+
}
|
|
9
|
+
declare const DatePicker: React.FC<DatePickerProps>;
|
|
10
|
+
export default DatePicker;
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
'use client';
|
|
3
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
4
|
+
if (k2 === undefined) k2 = k;
|
|
5
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
6
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
7
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
8
|
+
}
|
|
9
|
+
Object.defineProperty(o, k2, desc);
|
|
10
|
+
}) : (function(o, m, k, k2) {
|
|
11
|
+
if (k2 === undefined) k2 = k;
|
|
12
|
+
o[k2] = m[k];
|
|
13
|
+
}));
|
|
14
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
15
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
16
|
+
}) : function(o, v) {
|
|
17
|
+
o["default"] = v;
|
|
18
|
+
});
|
|
19
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
20
|
+
var ownKeys = function(o) {
|
|
21
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
22
|
+
var ar = [];
|
|
23
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
24
|
+
return ar;
|
|
25
|
+
};
|
|
26
|
+
return ownKeys(o);
|
|
27
|
+
};
|
|
28
|
+
return function (mod) {
|
|
29
|
+
if (mod && mod.__esModule) return mod;
|
|
30
|
+
var result = {};
|
|
31
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
32
|
+
__setModuleDefault(result, mod);
|
|
33
|
+
return result;
|
|
34
|
+
};
|
|
35
|
+
})();
|
|
36
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
37
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
38
|
+
};
|
|
39
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
40
|
+
var react_1 = __importStar(require("react"));
|
|
41
|
+
var dayjs_1 = __importDefault(require("dayjs"));
|
|
42
|
+
var Avatar_1 = __importDefault(require("../avatar/Avatar"));
|
|
43
|
+
var pi_1 = require("react-icons/pi");
|
|
44
|
+
var DatePicker = function (_a) {
|
|
45
|
+
var _b = _a.mode, mode = _b === void 0 ? 'single' : _b, onSelect = _a.onSelect, value = _a.value, funcss = _a.funcss, _c = _a.className, className = _c === void 0 ? '' : _c;
|
|
46
|
+
var _d = (0, react_1.useState)((0, dayjs_1.default)()), currentMonth = _d[0], setCurrentMonth = _d[1];
|
|
47
|
+
var _e = (0, react_1.useState)(value || null), selected = _e[0], setSelected = _e[1];
|
|
48
|
+
var daysInMonth = currentMonth.daysInMonth();
|
|
49
|
+
var firstDay = currentMonth.startOf('month').day(); // 0 = Sunday
|
|
50
|
+
var days = [];
|
|
51
|
+
for (var i = 0; i < firstDay; i++) {
|
|
52
|
+
days.push(null); // padding
|
|
53
|
+
}
|
|
54
|
+
for (var i = 1; i <= daysInMonth; i++) {
|
|
55
|
+
days.push(currentMonth.date(i).toDate());
|
|
56
|
+
}
|
|
57
|
+
var handleSelect = function (date) {
|
|
58
|
+
if (mode === 'single') {
|
|
59
|
+
setSelected(date);
|
|
60
|
+
onSelect === null || onSelect === void 0 ? void 0 : onSelect(date);
|
|
61
|
+
}
|
|
62
|
+
else if (mode === 'interval') {
|
|
63
|
+
if (!selected || !Array.isArray(selected)) {
|
|
64
|
+
setSelected([date, null]);
|
|
65
|
+
}
|
|
66
|
+
else {
|
|
67
|
+
var start = selected[0], end = selected[1];
|
|
68
|
+
if (!end) {
|
|
69
|
+
var range = (0, dayjs_1.default)(date).isBefore((0, dayjs_1.default)(start)) ? [date, start] : [start, date];
|
|
70
|
+
setSelected(range);
|
|
71
|
+
onSelect === null || onSelect === void 0 ? void 0 : onSelect(range);
|
|
72
|
+
}
|
|
73
|
+
else {
|
|
74
|
+
setSelected([date, null]); // restart
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
};
|
|
79
|
+
var isSelected = function (date) {
|
|
80
|
+
if (!selected)
|
|
81
|
+
return false;
|
|
82
|
+
if (mode === 'single' && selected instanceof Date) {
|
|
83
|
+
return (0, dayjs_1.default)(selected).isSame(date, 'day');
|
|
84
|
+
}
|
|
85
|
+
if (Array.isArray(selected)) {
|
|
86
|
+
var start = selected[0], end = selected[1];
|
|
87
|
+
if (start && end) {
|
|
88
|
+
return ((0, dayjs_1.default)(date).isSame(start, 'day') ||
|
|
89
|
+
(0, dayjs_1.default)(date).isSame(end, 'day') ||
|
|
90
|
+
((0, dayjs_1.default)(date).isAfter(start) && (0, dayjs_1.default)(date).isBefore(end)));
|
|
91
|
+
}
|
|
92
|
+
return (0, dayjs_1.default)(date).isSame(start, 'day');
|
|
93
|
+
}
|
|
94
|
+
return false;
|
|
95
|
+
};
|
|
96
|
+
var nextMonth = function () { return setCurrentMonth(currentMonth.add(1, 'month')); };
|
|
97
|
+
var prevMonth = function () { return setCurrentMonth(currentMonth.subtract(1, 'month')); };
|
|
98
|
+
var handleClear = function () {
|
|
99
|
+
setSelected(null);
|
|
100
|
+
onSelect === null || onSelect === void 0 ? void 0 : onSelect(mode === 'single' ? null : null);
|
|
101
|
+
};
|
|
102
|
+
var formatDate = function (date) {
|
|
103
|
+
return date ? (0, dayjs_1.default)(date).format('MMM D, YYYY') : '...';
|
|
104
|
+
};
|
|
105
|
+
return (react_1.default.createElement("div", { className: "datepicker ".concat(funcss, " ").concat(className) },
|
|
106
|
+
react_1.default.createElement("div", { className: "datepicker-header" },
|
|
107
|
+
react_1.default.createElement(Avatar_1.default, { onClick: prevMonth },
|
|
108
|
+
react_1.default.createElement(pi_1.PiCaretLeft, null)),
|
|
109
|
+
react_1.default.createElement("span", null, currentMonth.format('MMMM YYYY')),
|
|
110
|
+
react_1.default.createElement(Avatar_1.default, { onClick: nextMonth },
|
|
111
|
+
react_1.default.createElement(pi_1.PiCaretRight, null))),
|
|
112
|
+
selected && (react_1.default.createElement("div", { className: "datepicker-selected" },
|
|
113
|
+
react_1.default.createElement("span", { className: "interval-display" },
|
|
114
|
+
mode === 'single' && selected instanceof Date && (react_1.default.createElement(react_1.default.Fragment, null,
|
|
115
|
+
"Selected: ",
|
|
116
|
+
formatDate(selected))),
|
|
117
|
+
mode === 'interval' && Array.isArray(selected) && (react_1.default.createElement("div", { className: 'text-sm' }, selected[1]
|
|
118
|
+
? "From ".concat(formatDate(selected[0]), " to ").concat(formatDate(selected[1]))
|
|
119
|
+
: "Start: ".concat(formatDate(selected[0]), " - Select end date")))),
|
|
120
|
+
react_1.default.createElement("div", { style: { lineHeight: "0" } },
|
|
121
|
+
react_1.default.createElement(pi_1.PiX, { className: "clear-icon", onClick: handleClear, style: { cursor: 'pointer' } })))),
|
|
122
|
+
react_1.default.createElement("div", { className: "datepicker-weekdays" }, ['Su', 'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa'].map(function (d) { return (react_1.default.createElement("div", { key: d }, d)); })),
|
|
123
|
+
react_1.default.createElement("div", { className: "datepicker-grid" }, days.map(function (date, idx) {
|
|
124
|
+
var isSelectedClass = date && isSelected(date) ? 'selected' : '';
|
|
125
|
+
var isInRangeClass = date && isSelected(date) && Array.isArray(selected) ? 'in-range' : '';
|
|
126
|
+
return (react_1.default.createElement("div", { key: idx, onClick: function () { return date && handleSelect(date); }, className: "datepicker-day ".concat(!date ? 'empty' : '', " ").concat(isSelectedClass, " ").concat(isInRangeClass) }, date ? (0, dayjs_1.default)(date).date() : ''));
|
|
127
|
+
}))));
|
|
128
|
+
};
|
|
129
|
+
exports.default = DatePicker;
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import React, { useState } from 'react';
|
|
3
|
+
import dayjs from 'dayjs';
|
|
4
|
+
import Avatar from '../avatar/Avatar';
|
|
5
|
+
import { PiCaretLeft, PiCaretRight, PiX, PiXCircle } from 'react-icons/pi';
|
|
6
|
+
|
|
7
|
+
interface DatePickerProps {
|
|
8
|
+
mode?: 'single' | 'interval';
|
|
9
|
+
funcss?: string;
|
|
10
|
+
onSelect?: (value: Date | [Date, Date]) => void;
|
|
11
|
+
value?: Date | [Date, Date];
|
|
12
|
+
className?: string;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
type Selection = Date | [Date, Date | null] | null;
|
|
16
|
+
|
|
17
|
+
const DatePicker: React.FC<DatePickerProps> = ({
|
|
18
|
+
mode = 'single',
|
|
19
|
+
onSelect,
|
|
20
|
+
value,
|
|
21
|
+
funcss,
|
|
22
|
+
className = '',
|
|
23
|
+
}) => {
|
|
24
|
+
const [currentMonth, setCurrentMonth] = useState(dayjs());
|
|
25
|
+
const [selected, setSelected] = useState<Selection>(value || null);
|
|
26
|
+
|
|
27
|
+
const daysInMonth = currentMonth.daysInMonth();
|
|
28
|
+
const firstDay = currentMonth.startOf('month').day(); // 0 = Sunday
|
|
29
|
+
|
|
30
|
+
const days: (Date | null)[] = [];
|
|
31
|
+
for (let i = 0; i < firstDay; i++) {
|
|
32
|
+
days.push(null); // padding
|
|
33
|
+
}
|
|
34
|
+
for (let i = 1; i <= daysInMonth; i++) {
|
|
35
|
+
days.push(currentMonth.date(i).toDate());
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const handleSelect = (date: Date) => {
|
|
39
|
+
if (mode === 'single') {
|
|
40
|
+
setSelected(date);
|
|
41
|
+
onSelect?.(date);
|
|
42
|
+
} else if (mode === 'interval') {
|
|
43
|
+
if (!selected || !Array.isArray(selected)) {
|
|
44
|
+
setSelected([date, null]);
|
|
45
|
+
} else {
|
|
46
|
+
const [start, end] = selected;
|
|
47
|
+
if (!end) {
|
|
48
|
+
const range: [Date, Date] =
|
|
49
|
+
dayjs(date).isBefore(dayjs(start)) ? [date, start] : [start, date];
|
|
50
|
+
setSelected(range);
|
|
51
|
+
onSelect?.(range);
|
|
52
|
+
} else {
|
|
53
|
+
setSelected([date, null]); // restart
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
const isSelected = (date: Date) => {
|
|
60
|
+
if (!selected) return false;
|
|
61
|
+
if (mode === 'single' && selected instanceof Date) {
|
|
62
|
+
return dayjs(selected).isSame(date, 'day');
|
|
63
|
+
}
|
|
64
|
+
if (Array.isArray(selected)) {
|
|
65
|
+
const [start, end] = selected;
|
|
66
|
+
if (start && end) {
|
|
67
|
+
return (
|
|
68
|
+
dayjs(date).isSame(start, 'day') ||
|
|
69
|
+
dayjs(date).isSame(end, 'day') ||
|
|
70
|
+
(dayjs(date).isAfter(start) && dayjs(date).isBefore(end))
|
|
71
|
+
);
|
|
72
|
+
}
|
|
73
|
+
return dayjs(date).isSame(start, 'day');
|
|
74
|
+
}
|
|
75
|
+
return false;
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
const nextMonth = () => setCurrentMonth(currentMonth.add(1, 'month'));
|
|
79
|
+
const prevMonth = () => setCurrentMonth(currentMonth.subtract(1, 'month'));
|
|
80
|
+
|
|
81
|
+
const handleClear = () => {
|
|
82
|
+
setSelected(null);
|
|
83
|
+
onSelect?.(mode === 'single' ? null as unknown as Date : null as unknown as [Date, Date]);
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
const formatDate = (date: Date | null | undefined) =>
|
|
87
|
+
date ? dayjs(date).format('MMM D, YYYY') : '...';
|
|
88
|
+
|
|
89
|
+
return (
|
|
90
|
+
<div className={`datepicker ${funcss} ${className}`}>
|
|
91
|
+
<div className="datepicker-header">
|
|
92
|
+
<Avatar onClick={prevMonth}><PiCaretLeft /></Avatar>
|
|
93
|
+
<span>{currentMonth.format('MMMM YYYY')}</span>
|
|
94
|
+
<Avatar onClick={nextMonth}><PiCaretRight /></Avatar>
|
|
95
|
+
</div>
|
|
96
|
+
|
|
97
|
+
{selected && (
|
|
98
|
+
<div className="datepicker-selected">
|
|
99
|
+
<span className="interval-display">
|
|
100
|
+
{mode === 'single' && selected instanceof Date && (
|
|
101
|
+
<>Selected: {formatDate(selected)}</>
|
|
102
|
+
)}
|
|
103
|
+
{mode === 'interval' && Array.isArray(selected) && (
|
|
104
|
+
<div className='text-sm'>
|
|
105
|
+
{selected[1]
|
|
106
|
+
? `From ${formatDate(selected[0])} to ${formatDate(selected[1])}`
|
|
107
|
+
: `Start: ${formatDate(selected[0])} - Select end date`}
|
|
108
|
+
</div>
|
|
109
|
+
)}
|
|
110
|
+
</span>
|
|
111
|
+
<div style={{lineHeight:"0"}}>
|
|
112
|
+
<PiX className="clear-icon" onClick={handleClear} style={{ cursor: 'pointer' }} />
|
|
113
|
+
</div>
|
|
114
|
+
</div>
|
|
115
|
+
)}
|
|
116
|
+
|
|
117
|
+
<div className="datepicker-weekdays">
|
|
118
|
+
{['Su', 'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa'].map((d) => (
|
|
119
|
+
<div key={d}>{d}</div>
|
|
120
|
+
))}
|
|
121
|
+
</div>
|
|
122
|
+
|
|
123
|
+
<div className="datepicker-grid">
|
|
124
|
+
{days.map((date, idx) => {
|
|
125
|
+
const isSelectedClass = date && isSelected(date) ? 'selected' : '';
|
|
126
|
+
const isInRangeClass =
|
|
127
|
+
date && isSelected(date) && Array.isArray(selected) ? 'in-range' : '';
|
|
128
|
+
return (
|
|
129
|
+
<div
|
|
130
|
+
key={idx}
|
|
131
|
+
onClick={() => date && handleSelect(date)}
|
|
132
|
+
className={`datepicker-day ${!date ? 'empty' : ''} ${isSelectedClass} ${isInRangeClass}`}
|
|
133
|
+
>
|
|
134
|
+
{date ? dayjs(date).date() : ''}
|
|
135
|
+
</div>
|
|
136
|
+
);
|
|
137
|
+
})}
|
|
138
|
+
</div>
|
|
139
|
+
</div>
|
|
140
|
+
);
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
export default DatePicker;
|