intelicoreact 0.0.53 → 0.0.64
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/Atomic/FormElements/DateTime/DateTime.stories.js +1 -1
- package/dist/Atomic/FormElements/Input/Input.js +5 -5
- package/dist/Atomic/FormElements/InputCalendar/InputCalendar.js +4 -4
- package/dist/Atomic/FormElements/InputDateRange/InputDateRange.js +265 -0
- package/dist/Atomic/FormElements/InputDateRange/InputDateRange.scss +569 -0
- package/dist/Atomic/FormElements/InputDateRange/InputDateRange.stories.js +243 -0
- package/dist/Atomic/FormElements/InputDateRange/components/Datepicker.js +486 -0
- package/dist/Atomic/FormElements/InputDateRange/components/OpenedPart.js +154 -0
- package/dist/Atomic/FormElements/InputDateRange/components/SelectItem.js +46 -0
- package/dist/Atomic/FormElements/InputDateRange/dependencies.js +249 -0
- package/dist/Atomic/FormElements/Modal/Modal.stories.js +64 -18
- package/dist/Atomic/FormElements/RangeCalendar/RangeCalendar.js +162 -0
- package/dist/Atomic/FormElements/RangeCalendar/RangeCalendar.scss +101 -0
- package/dist/Atomic/FormElements/RangeCalendar/RangeCalendar.stories.js +81 -0
- package/dist/Atomic/UI/Arrow/Arrow.js +80 -0
- package/dist/Atomic/UI/Arrow/Arrow.scss +19 -0
- package/dist/Atomic/UI/Arrow/Arrow.stories.js +46 -0
- package/dist/Atomic/UI/Button/Button.js +4 -2
- package/dist/Atomic/UI/Button/Button.scss +26 -0
- package/dist/Atomic/UI/Button/Button.stories.js +2 -2
- package/dist/Atomic/{FormElements → UI}/Calendar/Calendar.js +0 -0
- package/dist/Atomic/UI/Calendar/Calendar.scss +544 -0
- package/dist/Atomic/{FormElements → UI}/Calendar/Calendar.stories.js +5 -1
- package/dist/Functions/utils.js +10 -2
- package/package.json +7 -5
- package/src/Atomic/FormElements/DateTime/DateTime.stories.js +1 -1
- package/src/Atomic/FormElements/Input/Input.js +5 -5
- package/src/Atomic/FormElements/InputCalendar/InputCalendar.js +6 -6
- package/src/Atomic/FormElements/InputDateRange/InputDateRange.js +247 -0
- package/src/Atomic/FormElements/InputDateRange/InputDateRange.scss +569 -0
- package/src/Atomic/FormElements/InputDateRange/InputDateRange.stories.js +148 -0
- package/src/Atomic/FormElements/InputDateRange/components/Datepicker.js +406 -0
- package/src/Atomic/FormElements/InputDateRange/components/OpenedPart.js +112 -0
- package/src/Atomic/FormElements/InputDateRange/components/SelectItem.js +24 -0
- package/src/Atomic/FormElements/InputDateRange/dependencies.js +161 -0
- package/src/Atomic/FormElements/Modal/Modal.stories.js +60 -15
- package/src/Atomic/FormElements/RangeCalendar/RangeCalendar.js +143 -0
- package/src/Atomic/FormElements/RangeCalendar/RangeCalendar.scss +101 -0
- package/src/Atomic/FormElements/RangeCalendar/RangeCalendar.stories.js +54 -0
- package/src/Atomic/UI/Arrow/Arrow.js +41 -0
- package/src/Atomic/UI/Arrow/Arrow.scss +19 -0
- package/src/Atomic/UI/Arrow/Arrow.stories.js +32 -0
- package/src/Atomic/UI/Button/Button.js +3 -3
- package/src/Atomic/UI/Button/Button.scss +26 -0
- package/src/Atomic/UI/Button/Button.stories.js +4 -3
- package/src/Atomic/{FormElements → UI}/Calendar/Calendar.js +0 -0
- package/src/Atomic/UI/Calendar/Calendar.scss +544 -0
- package/src/Atomic/{FormElements → UI}/Calendar/Calendar.stories.js +5 -1
- package/src/Functions/utils.js +6 -0
- package/dist/Atomic/FormElements/Calendar/Calendar.scss +0 -543
- package/src/Atomic/FormElements/Calendar/Calendar.scss +0 -543
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
import React, { useState, useEffect, useRef, useCallback } from 'react';
|
|
2
|
+
import moment from 'moment-timezone';
|
|
3
|
+
|
|
4
|
+
import InputDateRange from './InputDateRange';
|
|
5
|
+
|
|
6
|
+
export const useClickOutside = (hideComponent, additionalComponent) => {
|
|
7
|
+
const ref = useRef(null);
|
|
8
|
+
|
|
9
|
+
const checkCondition = target =>
|
|
10
|
+
(additionalComponent
|
|
11
|
+
? !ref.current?.contains(target) && !additionalComponent?.contains(target)
|
|
12
|
+
: !ref.current?.contains(target));
|
|
13
|
+
|
|
14
|
+
const handleClickOutside = useCallback(
|
|
15
|
+
({ target }) => {
|
|
16
|
+
if (checkCondition(target)) hideComponent();
|
|
17
|
+
},
|
|
18
|
+
[hideComponent],
|
|
19
|
+
);
|
|
20
|
+
|
|
21
|
+
useEffect(() => {
|
|
22
|
+
document.addEventListener('mousedown', handleClickOutside, true);
|
|
23
|
+
return () => {
|
|
24
|
+
document.removeEventListener('mousedown', handleClickOutside, true);
|
|
25
|
+
};
|
|
26
|
+
}, []);
|
|
27
|
+
|
|
28
|
+
return ref;
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
export const useToggle = initialState => {
|
|
32
|
+
const [isToggled, setToggle] = useState(!!initialState);
|
|
33
|
+
const toggle = useCallback(() => setToggle(isOn => !isOn), []);
|
|
34
|
+
const toggleOn = useCallback(() => setToggle(true), []);
|
|
35
|
+
const toggleOff = useCallback(() => setToggle(false), []);
|
|
36
|
+
|
|
37
|
+
return {
|
|
38
|
+
isToggled,
|
|
39
|
+
toggle,
|
|
40
|
+
toggleOn,
|
|
41
|
+
toggleOff,
|
|
42
|
+
};
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
export const INTERVALS = {
|
|
46
|
+
today: {
|
|
47
|
+
label: 'today',
|
|
48
|
+
start: () => moment().startOf('day'),
|
|
49
|
+
end: () => moment().add(1, 'day').startOf('day'),
|
|
50
|
+
},
|
|
51
|
+
yesterday: {
|
|
52
|
+
label: 'yesterday',
|
|
53
|
+
start: () => moment().subtract(1, 'day').startOf('day'),
|
|
54
|
+
end: () => moment().startOf('day'),
|
|
55
|
+
},
|
|
56
|
+
thisWeek: {
|
|
57
|
+
label: 'This Week',
|
|
58
|
+
start: () => moment().startOf('week'),
|
|
59
|
+
end: () => moment().add(1, 'day').startOf('day'),
|
|
60
|
+
},
|
|
61
|
+
lastWeek: {
|
|
62
|
+
label: 'Last Week',
|
|
63
|
+
start: () => moment().subtract(1, 'week').startOf('week'),
|
|
64
|
+
end: () => moment().startOf('week'),
|
|
65
|
+
},
|
|
66
|
+
last3Days: {
|
|
67
|
+
label: 'Last 3 Days',
|
|
68
|
+
start: () => moment().subtract(2, 'day').startOf('day'),
|
|
69
|
+
end: () => moment().add(1, 'day').startOf('day'),
|
|
70
|
+
},
|
|
71
|
+
last7Days: {
|
|
72
|
+
label: 'Last 7 Days',
|
|
73
|
+
start: () => moment().subtract(6, 'day').startOf('day'),
|
|
74
|
+
end: () => moment().add(1, 'day').startOf('day'),
|
|
75
|
+
},
|
|
76
|
+
last14Days: {
|
|
77
|
+
label: 'Last 14 Days',
|
|
78
|
+
start: () => moment().subtract(13, 'day').startOf('day'),
|
|
79
|
+
end: () => moment().add(1, 'day').startOf('day'),
|
|
80
|
+
},
|
|
81
|
+
thisMonth: {
|
|
82
|
+
label: 'This Month',
|
|
83
|
+
start: () => moment().startOf('month'),
|
|
84
|
+
end: () => moment().add(1, 'day').startOf('day'),
|
|
85
|
+
},
|
|
86
|
+
lastMonth: {
|
|
87
|
+
label: 'Last Month',
|
|
88
|
+
start: () => moment().subtract(1, 'month').startOf('month'),
|
|
89
|
+
end: () => moment().startOf('month'),
|
|
90
|
+
},
|
|
91
|
+
last6Months: {
|
|
92
|
+
label: 'Last 6 Months',
|
|
93
|
+
start: () => moment().subtract(6, 'month').startOf('month'),
|
|
94
|
+
end: () => moment().startOf('month'),
|
|
95
|
+
},
|
|
96
|
+
thisYear: {
|
|
97
|
+
label: 'This Year',
|
|
98
|
+
start: () => moment().startOf('year'),
|
|
99
|
+
end: () => moment().add(1, 'day').startOf('day'),
|
|
100
|
+
},
|
|
101
|
+
lastYear: {
|
|
102
|
+
label: 'Last Year',
|
|
103
|
+
start: () => moment().subtract(1, 'year').startOf('year'),
|
|
104
|
+
end: () => moment().startOf('year'),
|
|
105
|
+
},
|
|
106
|
+
allTime: {
|
|
107
|
+
label: 'All Time',
|
|
108
|
+
start: () => null,
|
|
109
|
+
end: () => null,
|
|
110
|
+
}
|
|
111
|
+
};
|
|
112
|
+
export const ALL_TIME_KEY = 'allTime';
|
|
113
|
+
export const CUSTOM_INTERVAL_KEY = 'customDate';
|
|
114
|
+
export const CUSTOM_INTERVAL_KEY_TEXT = 'Custom Date';
|
|
115
|
+
|
|
116
|
+
export const getActualDateRange = inputDateRange => {
|
|
117
|
+
const actualIntervalKey = (() => {
|
|
118
|
+
if (inputDateRange.intervalKey && inputDateRange.intervalKey !== CUSTOM_INTERVAL_KEY) {
|
|
119
|
+
return inputDateRange.intervalKey;
|
|
120
|
+
}
|
|
121
|
+
if (inputDateRange.start && inputDateRange.end) {
|
|
122
|
+
for (const [key, interval] of Object.entries(INTERVALS)) {
|
|
123
|
+
if (
|
|
124
|
+
moment(inputDateRange.start).isSame(interval.start()) &&
|
|
125
|
+
moment(inputDateRange.end).isSame(interval.end())
|
|
126
|
+
) {
|
|
127
|
+
return key;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
return null;
|
|
132
|
+
})();
|
|
133
|
+
if (actualIntervalKey === ALL_TIME_KEY) return {
|
|
134
|
+
intervalKey: ALL_TIME_KEY,
|
|
135
|
+
start: null,
|
|
136
|
+
end: null,
|
|
137
|
+
compare: inputDateRange.compare,
|
|
138
|
+
startPrevDate: null,
|
|
139
|
+
endPrevDate:null
|
|
140
|
+
};
|
|
141
|
+
const actualValues = {
|
|
142
|
+
// intervalKey: inputDateRange.intervalKey || customIntervalKey,
|
|
143
|
+
intervalKey: actualIntervalKey || CUSTOM_INTERVAL_KEY,
|
|
144
|
+
start:
|
|
145
|
+
inputDateRange.intervalKey === CUSTOM_INTERVAL_KEY
|
|
146
|
+
? inputDateRange?.start
|
|
147
|
+
: INTERVALS[inputDateRange.intervalKey]?.start()?.toDate(),
|
|
148
|
+
end:
|
|
149
|
+
inputDateRange.intervalKey === CUSTOM_INTERVAL_KEY
|
|
150
|
+
? inputDateRange?.end
|
|
151
|
+
: INTERVALS[inputDateRange.intervalKey]?.end()?.toDate(),
|
|
152
|
+
compare: inputDateRange.compare,
|
|
153
|
+
};
|
|
154
|
+
|
|
155
|
+
if (actualValues.compare) {
|
|
156
|
+
const intervalHoursCount = moment(actualValues.end).diff(actualValues.start, 'hours');
|
|
157
|
+
actualValues.startPrevDate = moment(actualValues.start).subtract(intervalHoursCount, 'hours').toDate();
|
|
158
|
+
actualValues.endPrevDate = actualValues.start;
|
|
159
|
+
}
|
|
160
|
+
return actualValues;
|
|
161
|
+
};
|
|
@@ -6,6 +6,25 @@ import Alert from '../../UI/Alert/Alert';
|
|
|
6
6
|
|
|
7
7
|
global.lng = 'en';
|
|
8
8
|
|
|
9
|
+
const examples = [
|
|
10
|
+
JSON.stringify({ withConfirmation: { cancel: true } }),
|
|
11
|
+
JSON.stringify({ withConfirmation: { confirm: true } }),
|
|
12
|
+
JSON.stringify({ withConfirmation: { confirm: true, cancel: true } }),
|
|
13
|
+
JSON.stringify({
|
|
14
|
+
withConfirmation: {
|
|
15
|
+
title: 'some value',
|
|
16
|
+
children: 'some value',
|
|
17
|
+
confirmBtnLabel: 'some value'
|
|
18
|
+
}
|
|
19
|
+
})
|
|
20
|
+
];
|
|
21
|
+
const confirmationDescrip =
|
|
22
|
+
'If you pass the "withConfirmation" property, you will be able to request confirmation of the user\'s action.\n\n' +
|
|
23
|
+
`For example, if you want to request confirmation to close a modal window, pass the property like this: ${examples[0]}\n\n` +
|
|
24
|
+
`To confirm submit, pass the property like this: with Confirmation: ${examples[1]}\n\n` +
|
|
25
|
+
`If you want confirmation for each action, pass the property like this: with Confirmation: ${examples[2]}\n\n` +
|
|
26
|
+
`If you want to control the contents of the confirmation window, pass an object with values instead of boolean values, like this:\n\n${examples[3]}\n\n`;
|
|
27
|
+
|
|
9
28
|
export default {
|
|
10
29
|
title: 'Modal',
|
|
11
30
|
component: Modal,
|
|
@@ -27,18 +46,15 @@ export default {
|
|
|
27
46
|
type: 'select',
|
|
28
47
|
options: ['default', '290', '420', '870', '770', '950']
|
|
29
48
|
}
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
control: {
|
|
40
|
-
type: 'select',
|
|
41
|
-
options: ['default', '290', '420', '770', '870', '950']
|
|
49
|
+
},
|
|
50
|
+
type: {
|
|
51
|
+
control: {
|
|
52
|
+
type: 'select',
|
|
53
|
+
options: ['default', 'primary']
|
|
54
|
+
}
|
|
55
|
+
},
|
|
56
|
+
withConfirmation: {
|
|
57
|
+
description: confirmationDescrip
|
|
42
58
|
}
|
|
43
59
|
}
|
|
44
60
|
};
|
|
@@ -49,8 +65,16 @@ const Template = args => {
|
|
|
49
65
|
|
|
50
66
|
return (
|
|
51
67
|
<>
|
|
52
|
-
<Button onClick={() => setIsOpen(true)}
|
|
53
|
-
<Modal
|
|
68
|
+
<Button onClick={() => setIsOpen(true)} text="Show modal" />
|
|
69
|
+
<Modal
|
|
70
|
+
{...args}
|
|
71
|
+
closeModal={closeModal}
|
|
72
|
+
submitHandler={() => {
|
|
73
|
+
args.submitHandler();
|
|
74
|
+
closeModal();
|
|
75
|
+
}}
|
|
76
|
+
isOpen={isOpen}
|
|
77
|
+
>
|
|
54
78
|
<Alert message="Alert message" variant="error" className="mb5" />
|
|
55
79
|
<Alert message="Alert message" variant="warning" className="mb5" />
|
|
56
80
|
<Alert message="Alert message" variant="success" className="mb5" />
|
|
@@ -61,11 +85,32 @@ const Template = args => {
|
|
|
61
85
|
};
|
|
62
86
|
|
|
63
87
|
export const ModalTemplate = Template.bind({});
|
|
88
|
+
export const ModalWithConfirmation = Template.bind({});
|
|
64
89
|
|
|
65
|
-
|
|
90
|
+
const mainProps = {
|
|
66
91
|
title: 'Modal',
|
|
67
92
|
variant: 'primary',
|
|
68
93
|
mode: 'edit',
|
|
69
94
|
size: '',
|
|
95
|
+
confirmBtnLabel: '',
|
|
96
|
+
submitHandler: () => {
|
|
97
|
+
console.log('Hi');
|
|
98
|
+
}
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
const confirmationProps = {
|
|
102
|
+
title: '',
|
|
103
|
+
children: '',
|
|
70
104
|
confirmBtnLabel: ''
|
|
71
105
|
};
|
|
106
|
+
|
|
107
|
+
const confirmationVariants = {
|
|
108
|
+
// confirm: { ...confirmationProps },
|
|
109
|
+
cancel: { ...confirmationProps }
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
ModalTemplate.args = { ...mainProps };
|
|
113
|
+
ModalWithConfirmation.args = {
|
|
114
|
+
...mainProps,
|
|
115
|
+
withConfirmation: { ...confirmationVariants }
|
|
116
|
+
};
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import React, { useEffect, useMemo, useState } from 'react';
|
|
2
|
+
import cn from 'classnames';
|
|
3
|
+
import moment from 'moment-timezone';
|
|
4
|
+
|
|
5
|
+
import Arrow from '../../UI/Arrow/Arrow'
|
|
6
|
+
|
|
7
|
+
import './RangeCalendar.scss'
|
|
8
|
+
|
|
9
|
+
const RangeCalendar = props => {
|
|
10
|
+
const {
|
|
11
|
+
className,
|
|
12
|
+
date,
|
|
13
|
+
setDate,
|
|
14
|
+
startDate,
|
|
15
|
+
endDate,
|
|
16
|
+
allowPrev = true,
|
|
17
|
+
allowNext = true,
|
|
18
|
+
onClick = () => {},
|
|
19
|
+
onHover = () => {},
|
|
20
|
+
startPrevDate,
|
|
21
|
+
endPrevDate,
|
|
22
|
+
limitRange
|
|
23
|
+
} = props;
|
|
24
|
+
|
|
25
|
+
const [days, setDays] = useState({});
|
|
26
|
+
|
|
27
|
+
const title = useMemo(() => `${moment(date).format('MMM')} ${moment(date).format('YYYY')}`, [date]);
|
|
28
|
+
|
|
29
|
+
useEffect(() => {
|
|
30
|
+
const result = {};
|
|
31
|
+
const day = moment(date).startOf('month');
|
|
32
|
+
const daysInMonth = day.daysInMonth();
|
|
33
|
+
for (let d = 0; d < daysInMonth; d += 1) {
|
|
34
|
+
let week = day.week();
|
|
35
|
+
if (day.month() === 11 && week === 1) week = 53;
|
|
36
|
+
if (day.month() === 0 && week === 53) week = 0;
|
|
37
|
+
if (!Object.prototype.hasOwnProperty.call(result, week)) {
|
|
38
|
+
result[week] = {};
|
|
39
|
+
}
|
|
40
|
+
result[week][day.weekday()] = { date: day.toDate() };
|
|
41
|
+
day.add(1, 'd');
|
|
42
|
+
}
|
|
43
|
+
setDays(result);
|
|
44
|
+
}, [date]);
|
|
45
|
+
|
|
46
|
+
const renderDay = (week, dayOfWeek) => {
|
|
47
|
+
const day = days[week][dayOfWeek];
|
|
48
|
+
const isFutureDay = day && moment(day.date).isAfter(moment(), 'day');
|
|
49
|
+
const isPastDay = limitRange
|
|
50
|
+
? day && moment(day.date).isBefore(moment().subtract(limitRange, 'days'), 'day')
|
|
51
|
+
: null;
|
|
52
|
+
const isRangeStart = day && moment(day.date).isSame(startDate, 'day');
|
|
53
|
+
const isRangeEnd = day && moment(day.date).isSame(moment(endDate).subtract(1, 'hour'), 'day');
|
|
54
|
+
const isRangeInside =
|
|
55
|
+
day &&
|
|
56
|
+
startDate &&
|
|
57
|
+
endDate &&
|
|
58
|
+
moment(day.date).isAfter(startDate, 'day') &&
|
|
59
|
+
moment(day.date).isBefore(moment(endDate).subtract(1, 'hour'), 'day');
|
|
60
|
+
const isPrevRangeEnd =
|
|
61
|
+
day &&
|
|
62
|
+
(moment(day.date).isSame(startPrevDate, 'day') ||
|
|
63
|
+
moment(day.date).isSame(moment(endPrevDate).subtract(1, 'day'), 'day'));
|
|
64
|
+
const isPrevRangeInside =
|
|
65
|
+
day &&
|
|
66
|
+
startPrevDate &&
|
|
67
|
+
endPrevDate &&
|
|
68
|
+
moment(day.date).isAfter(startPrevDate, 'day') &&
|
|
69
|
+
moment(day.date).isBefore(moment(endPrevDate).subtract(1, 'day'), 'day');
|
|
70
|
+
const classNames = cn(
|
|
71
|
+
'range-calendar__day',
|
|
72
|
+
{ 'range-calendar__day--clickable': day },
|
|
73
|
+
{ 'range-calendar__day--disabled': isFutureDay },
|
|
74
|
+
{ 'range-calendar__day--disabled': isPastDay },
|
|
75
|
+
{ 'range-calendar__day--range-start': isRangeStart },
|
|
76
|
+
{ 'range-calendar__day--range-end': isRangeEnd },
|
|
77
|
+
{ 'range-calendar__day--range-inside': isRangeInside },
|
|
78
|
+
{ 'range-calendar__day--prev-range-end': isPrevRangeEnd },
|
|
79
|
+
{ 'range-calendar__day--prev-range-inside': isPrevRangeInside }
|
|
80
|
+
);
|
|
81
|
+
|
|
82
|
+
return (
|
|
83
|
+
<div
|
|
84
|
+
key={`${week}_${dayOfWeek}`}
|
|
85
|
+
className={classNames}
|
|
86
|
+
onClick={day && !isFutureDay ? e => onClick(day.date, e) : null}
|
|
87
|
+
onMouseOver={day && !isFutureDay ? () => onHover(day.date) : null}
|
|
88
|
+
onMouseLeave={() => onHover(null)}
|
|
89
|
+
>
|
|
90
|
+
{day && day.date.getDate()}
|
|
91
|
+
</div>
|
|
92
|
+
);
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
const handlePrev = () => {
|
|
96
|
+
setDate(moment(date).subtract(1, 'month').toDate());
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
const handleNext = () => {
|
|
100
|
+
setDate(moment(date).add(1, 'month').toDate());
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
return (
|
|
104
|
+
<div className={cn('range-calendar', className)}>
|
|
105
|
+
<div className="range-calendar-header">
|
|
106
|
+
<Arrow type="left" disabled={!allowPrev} onClick={handlePrev} className="range-calendar-header__prev" />
|
|
107
|
+
{/* <div className="range-calendar-header__prev">
|
|
108
|
+
{allowPrev && (
|
|
109
|
+
<div onClick={handlePrev}>
|
|
110
|
+
<Arrow type="left" disabled={!allowPrev} />
|
|
111
|
+
</div>
|
|
112
|
+
)}
|
|
113
|
+
</div> */}
|
|
114
|
+
<div className="range-calendar-header__title">{title}</div>
|
|
115
|
+
<Arrow type="right" disabled={!allowNext} onClick={handleNext} className="range-calendar-header__next" />
|
|
116
|
+
|
|
117
|
+
{/* <div className="range-calendar-header__next">
|
|
118
|
+
{allowNext && (
|
|
119
|
+
<div onClick={handleNext}>
|
|
120
|
+
<Arrow type="right" disabled={!allowNext} />
|
|
121
|
+
</div>
|
|
122
|
+
)}
|
|
123
|
+
</div> */}
|
|
124
|
+
</div>
|
|
125
|
+
<div className="range-calendar__week range-calendar__week-title">
|
|
126
|
+
{[...Array(7).keys()].map(dayOfWeek => {
|
|
127
|
+
return (
|
|
128
|
+
<div key={`day-of-week_${dayOfWeek}`} className="range-calendar__day range-calendar__day--title">
|
|
129
|
+
{moment().weekday(dayOfWeek).format('dd').charAt(0)}
|
|
130
|
+
</div>
|
|
131
|
+
);
|
|
132
|
+
})}
|
|
133
|
+
</div>
|
|
134
|
+
{Object.keys(days).map((week, index) => (
|
|
135
|
+
<div key={`week_${index}`} className="range-calendar__week">
|
|
136
|
+
{[...Array(7).keys()].map(dayOfWeek => renderDay(week, dayOfWeek))}
|
|
137
|
+
</div>
|
|
138
|
+
))}
|
|
139
|
+
</div>
|
|
140
|
+
);
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
export default RangeCalendar;
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
.range-calendar {
|
|
2
|
+
width: 195px;
|
|
3
|
+
min-height: 195px;
|
|
4
|
+
display: flex;
|
|
5
|
+
flex-direction: column;
|
|
6
|
+
user-select: none;
|
|
7
|
+
|
|
8
|
+
&-header {
|
|
9
|
+
height: 24px;
|
|
10
|
+
margin-bottom: 12px;
|
|
11
|
+
|
|
12
|
+
display: flex;
|
|
13
|
+
justify-content: space-between;
|
|
14
|
+
align-items: center;
|
|
15
|
+
|
|
16
|
+
&__title {
|
|
17
|
+
line-height: 20px;
|
|
18
|
+
font-weight: 500;
|
|
19
|
+
text-align: center;
|
|
20
|
+
flex-grow: 1;
|
|
21
|
+
color: #000000;
|
|
22
|
+
display: flex;
|
|
23
|
+
align-items: center;
|
|
24
|
+
justify-content: center;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
&__next, &__prev {
|
|
28
|
+
width: 16px;
|
|
29
|
+
height: 16px;
|
|
30
|
+
background-color: #E2E6F8;
|
|
31
|
+
border-radius: 5px;
|
|
32
|
+
color: #171D33;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
&__week {
|
|
37
|
+
display: flex;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
&__day {
|
|
41
|
+
font-size: 13px;
|
|
42
|
+
line-height: 20px;
|
|
43
|
+
margin: 1px 0;
|
|
44
|
+
flex-grow: 1;
|
|
45
|
+
flex-basis: 0;
|
|
46
|
+
text-align: center;
|
|
47
|
+
padding: 1px 6px;
|
|
48
|
+
user-select: none;
|
|
49
|
+
|
|
50
|
+
&--clickable {
|
|
51
|
+
cursor: pointer;
|
|
52
|
+
|
|
53
|
+
&:hover {
|
|
54
|
+
background: #E2E6F8;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
&--disabled {
|
|
59
|
+
cursor: default;
|
|
60
|
+
color: #9aa0b9;
|
|
61
|
+
pointer-events: none;
|
|
62
|
+
|
|
63
|
+
&:hover {
|
|
64
|
+
background: inherit;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
&--range-start, &--range-end {
|
|
69
|
+
background: #6B81DD;
|
|
70
|
+
color: white;
|
|
71
|
+
border-radius: 4px;
|
|
72
|
+
|
|
73
|
+
&:hover {
|
|
74
|
+
background: #6B81DD;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
&--range-inside {
|
|
79
|
+
background: #E2E6F8;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
&--prev-range-end {
|
|
83
|
+
background: #E2E5EC;
|
|
84
|
+
border-radius: 4px;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
&--prev-range-inside {
|
|
88
|
+
background: #F7F8FA;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
&--title {
|
|
92
|
+
font-size: 10px;
|
|
93
|
+
color: #9AA0B9;
|
|
94
|
+
font-weight: normal;
|
|
95
|
+
|
|
96
|
+
&:hover {
|
|
97
|
+
background: inherit;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import React, {useState, useMemo, useRef, useEffect} from 'react';
|
|
2
|
+
import moment from 'moment-timezone';
|
|
3
|
+
|
|
4
|
+
import RangeCalendar from './RangeCalendar';
|
|
5
|
+
|
|
6
|
+
global.lng = 'en';
|
|
7
|
+
|
|
8
|
+
export default {
|
|
9
|
+
title: 'RangeCalendar',
|
|
10
|
+
component: RangeCalendar,
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
const Template = args => {
|
|
14
|
+
const [dateOfRenderedMonth, setDateOfRenderedMonth] = useState(moment().subtract(1, 'month').toDate());
|
|
15
|
+
|
|
16
|
+
const [startDate, setStartDate] = useState(dateOfRenderedMonth);
|
|
17
|
+
const [endDate, setEndDate] = useState(dateOfRenderedMonth);
|
|
18
|
+
const isFirstClickRef = useRef(false);
|
|
19
|
+
|
|
20
|
+
const handleClick = date => {
|
|
21
|
+
if (
|
|
22
|
+
!startDate ||
|
|
23
|
+
(startDate && endDate && !(moment(startDate).add(1, 'd').isSame(endDate, 'day')))
|
|
24
|
+
) {
|
|
25
|
+
setStartDate(moment(date).startOf('day').toDate());
|
|
26
|
+
setEndDate(moment(date).add(1, 'd').startOf('day').toDate());
|
|
27
|
+
} else if (moment(date).isBefore(moment(startDate), 'day')) {
|
|
28
|
+
setEndDate(moment(startDate).add(1, 'd').startOf('day').toDate());
|
|
29
|
+
setStartDate(moment(date).set('hour', parseInt(0, 10)).toDate());
|
|
30
|
+
} else if (moment(date).isAfter(moment(startDate), 'day')) {
|
|
31
|
+
setEndDate(moment(date).add(1, 'd').startOf('day').toDate());
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
return <RangeCalendar
|
|
36
|
+
{...args}
|
|
37
|
+
date={dateOfRenderedMonth}
|
|
38
|
+
setDate={setDateOfRenderedMonth}
|
|
39
|
+
// allowNext={true}
|
|
40
|
+
// allowPrev={true}
|
|
41
|
+
startDate={startDate}
|
|
42
|
+
endDate={endDate}
|
|
43
|
+
// startPrevDate={startPrevDate}
|
|
44
|
+
// endPrevDate={endPrevDate}
|
|
45
|
+
onClick={handleClick}
|
|
46
|
+
// onHover={handleHover}
|
|
47
|
+
/>
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
export const RangeCalendarTemplate = Template.bind({});
|
|
51
|
+
|
|
52
|
+
RangeCalendarTemplate.args = {
|
|
53
|
+
limitRange: 60
|
|
54
|
+
};
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import React, { useEffect, useRef, useState } from 'react';
|
|
2
|
+
import cn from 'classnames';
|
|
3
|
+
|
|
4
|
+
import { getStyles } from '../../../Functions/utils';
|
|
5
|
+
|
|
6
|
+
import './Arrow.scss';
|
|
7
|
+
|
|
8
|
+
const Arrow = ({type, className, onClick, disabled}) => {
|
|
9
|
+
if (!type || (type !== 'left' && type !== 'right')) return null;
|
|
10
|
+
const ref = useRef();
|
|
11
|
+
const [color, setColor] = useState('black');
|
|
12
|
+
|
|
13
|
+
useEffect(() => {
|
|
14
|
+
if (ref.current) {
|
|
15
|
+
setColor(getStyles(ref.current, 'color'));
|
|
16
|
+
};
|
|
17
|
+
}, [ref.current]);
|
|
18
|
+
|
|
19
|
+
return (
|
|
20
|
+
<div
|
|
21
|
+
ref={ref}
|
|
22
|
+
className={cn('arrow', `arrow_${type}`, className, {
|
|
23
|
+
'arrow_disabled': disabled
|
|
24
|
+
})}
|
|
25
|
+
onClick={onClick} >
|
|
26
|
+
{type !== 'right'
|
|
27
|
+
? (
|
|
28
|
+
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
29
|
+
<path d="M15 18L9 12L15 6" stroke={color} stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
|
30
|
+
</svg>
|
|
31
|
+
) : (
|
|
32
|
+
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
33
|
+
<path d="M9 18L15 12L9 6" stroke={color} stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
|
34
|
+
</svg>
|
|
35
|
+
)
|
|
36
|
+
}
|
|
37
|
+
</div>
|
|
38
|
+
);
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
export default Arrow;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import {Check} from 'react-feather';
|
|
3
|
+
import Arrow from './Arrow';
|
|
4
|
+
|
|
5
|
+
global.lng = 'en';
|
|
6
|
+
|
|
7
|
+
export default {
|
|
8
|
+
title: 'UI/Arrow',
|
|
9
|
+
component: Arrow,
|
|
10
|
+
argTypes: {
|
|
11
|
+
type: {
|
|
12
|
+
description: 'string: ["left", "right"]',
|
|
13
|
+
control: {
|
|
14
|
+
type: 'select',
|
|
15
|
+
options: ['left', 'right']
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
const Template = args => {
|
|
22
|
+
const { className, onClick } = args;
|
|
23
|
+
return <Arrow {...args} />;
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
export const ArrowTemplate = Template.bind({});
|
|
27
|
+
|
|
28
|
+
ArrowTemplate.args = {
|
|
29
|
+
type: 'left',
|
|
30
|
+
className: 'externall-class-name',
|
|
31
|
+
onClick: ev => console.log(ev.target.className)
|
|
32
|
+
};
|
|
@@ -3,11 +3,11 @@ import cn from 'classnames';
|
|
|
3
3
|
|
|
4
4
|
import './Button.scss';
|
|
5
5
|
|
|
6
|
-
const Button = ({ label, variant = 'primary', onClick, disabled, icon, className, children, style }) => {
|
|
7
|
-
|
|
6
|
+
const Button = ({ label, variant = 'primary', onClick, disabled, icon, className, children, style, noIcon }) => {
|
|
7
|
+
const noRenderIcon = noIcon || variant === "ellipse-apply" || variant === "ellipse-cancel";
|
|
8
8
|
return (
|
|
9
9
|
<button style={style} className={cn(className, 'button', { [`button_${variant}`]: variant })} onClick={onClick} disabled={disabled}>
|
|
10
|
-
{icon}
|
|
10
|
+
{!noRenderIcon && icon}
|
|
11
11
|
{label && <div className="button__text">{label}</div>}
|
|
12
12
|
{!label && children ? children : null}
|
|
13
13
|
</button>
|