@soul-refiner/design-system 0.2.87 → 0.2.89
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/index.d.ts +1 -0
- package/dist/components/index.js +1 -0
- package/dist/components/input/calendar/calendar.d.ts +6 -0
- package/dist/components/input/calendar/calendar.js +250 -0
- package/dist/components/input/calendar/index.d.ts +2 -0
- package/dist/components/input/calendar/index.js +1 -0
- package/dist/components/input/index.d.ts +2 -0
- package/dist/components/input/index.js +1 -0
- package/package.json +1 -1
package/dist/components/index.js
CHANGED
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import styled from 'styled-components';
|
|
4
|
+
import { MONTHS, WEEKDAYS } from '../../../common';
|
|
5
|
+
import { Button, P } from '../..';
|
|
6
|
+
import { ChevronLeft, ChevronRight } from '../../../icons';
|
|
7
|
+
import { buildCalendar, zeroPad } from '../../../utils';
|
|
8
|
+
import { Icons } from 'index';
|
|
9
|
+
export const CalendarInput = ({ selectedDate, onSelect: parentOnSelect, }) => {
|
|
10
|
+
const today = new Date();
|
|
11
|
+
today.setHours(0);
|
|
12
|
+
today.setMinutes(0);
|
|
13
|
+
today.setSeconds(0);
|
|
14
|
+
today.setMilliseconds(0);
|
|
15
|
+
const firstOfMonth = new Date(today);
|
|
16
|
+
firstOfMonth.setDate(1);
|
|
17
|
+
const pickerRef = React.useRef(null);
|
|
18
|
+
const [show, setShow] = React.useState(false);
|
|
19
|
+
const [displayDate, setDisplayDate] = React.useState(() => selectedDate.toDateString());
|
|
20
|
+
const [componentSelectedDate, setComponentSelectedDate] = React.useState(() => selectedDate.toDateString());
|
|
21
|
+
React.useEffect(() => {
|
|
22
|
+
setComponentSelectedDate(selectedDate.toDateString());
|
|
23
|
+
}, [selectedDate]);
|
|
24
|
+
const handleShow = () => setShow((prev) => !prev);
|
|
25
|
+
const handleBlur = (event) => {
|
|
26
|
+
if (pickerRef?.current &&
|
|
27
|
+
!pickerRef?.current?.contains(event.relatedTarget)) {
|
|
28
|
+
setShow(false);
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
const handlePreviousMonth = () => {
|
|
32
|
+
setDisplayDate((prev) => {
|
|
33
|
+
const newDate = new Date(prev);
|
|
34
|
+
newDate.setMonth(newDate.getMonth() - 1);
|
|
35
|
+
return newDate.toDateString();
|
|
36
|
+
});
|
|
37
|
+
};
|
|
38
|
+
const handleNextMonth = () => {
|
|
39
|
+
setDisplayDate((prev) => {
|
|
40
|
+
const newDate = new Date(prev);
|
|
41
|
+
newDate.setMonth(newDate.getMonth() + 1);
|
|
42
|
+
return newDate.toDateString();
|
|
43
|
+
});
|
|
44
|
+
};
|
|
45
|
+
const onSelect = (newDate) => {
|
|
46
|
+
setComponentSelectedDate(newDate.toDateString());
|
|
47
|
+
};
|
|
48
|
+
const handleApply = () => {
|
|
49
|
+
parentOnSelect(new Date(componentSelectedDate));
|
|
50
|
+
setShow(false);
|
|
51
|
+
};
|
|
52
|
+
const handleClick = (event) => {
|
|
53
|
+
const target = event.target;
|
|
54
|
+
const day = target.getAttribute('data-day');
|
|
55
|
+
const month = target.getAttribute('data-month');
|
|
56
|
+
const year = target.getAttribute('data-year');
|
|
57
|
+
onSelect(new Date(`${month}-${day}-${year}`));
|
|
58
|
+
};
|
|
59
|
+
const handleCancel = () => {
|
|
60
|
+
setComponentSelectedDate(selectedDate.toDateString());
|
|
61
|
+
setShow(false);
|
|
62
|
+
};
|
|
63
|
+
const calendar = buildCalendar(new Date(displayDate).getMonth() + 1, new Date(displayDate).getFullYear());
|
|
64
|
+
const [month, day, year] = selectedDate
|
|
65
|
+
.toLocaleString('default', {
|
|
66
|
+
year: '2-digit',
|
|
67
|
+
month: '2-digit',
|
|
68
|
+
day: '2-digit',
|
|
69
|
+
})
|
|
70
|
+
.split('/');
|
|
71
|
+
return (React.createElement(Wrapper, { onBlurCapture: handleBlur, ref: pickerRef, tabIndex: 0 },
|
|
72
|
+
React.createElement(InputWrapper, null,
|
|
73
|
+
React.createElement(Input, { value: `${month} / ${day} / ${year}`, onFocus: handleShow, style: { letterSpacing: '1px', fontSize: '16px' }, readOnly: true }),
|
|
74
|
+
React.createElement(Icons.Calendar, null)),
|
|
75
|
+
show && (React.createElement(DateSelector, null,
|
|
76
|
+
React.createElement(InnerWrapper, null,
|
|
77
|
+
React.createElement("div", null,
|
|
78
|
+
React.createElement(MonthBar, null,
|
|
79
|
+
React.createElement(Arrow, { onClick: handlePreviousMonth },
|
|
80
|
+
React.createElement(ChevronLeft, { size: 24 })),
|
|
81
|
+
React.createElement(P, null, `${Object.values(MONTHS)[Math.max(0, Math.min(new Date(displayDate).getMonth(), 11))]} ${new Date(displayDate).getFullYear()}`),
|
|
82
|
+
React.createElement(Arrow, { onClick: handleNextMonth },
|
|
83
|
+
React.createElement(ChevronRight, { size: 24 }))),
|
|
84
|
+
React.createElement(WeekdayWrapper, null, Object.values(WEEKDAYS).map((day) => (React.createElement(P, { key: day }, day)))),
|
|
85
|
+
React.createElement(Calendar, null, calendar.map((week, index) => {
|
|
86
|
+
return (React.createElement(Week, { key: 'week-' + index.toString(36) }, week.map((day, dayIndex) => {
|
|
87
|
+
const isCurrMonth = day[1] !==
|
|
88
|
+
zeroPad(new Date(displayDate).getMonth() + 1, 2);
|
|
89
|
+
const dateObj = new Date(`${day[1]}-${day[2]}-${day[0]}`);
|
|
90
|
+
const isToday = Math.abs(dateObj.getTime() - today.getTime()) < 0.5;
|
|
91
|
+
const isSelected = new Date(componentSelectedDate).getTime() ===
|
|
92
|
+
dateObj.getTime();
|
|
93
|
+
return (React.createElement(Day, { className: `${isToday ? 'today' : ''}${isCurrMonth ? ' not-current' : ''}${isSelected ? ' selected' : ''}`.trim(), "data-day": day[2], "data-month": day[1], "data-year": day[0], key: 'day-' + dayIndex.toString(36), onClick: handleClick }, `${day[2]}`.startsWith('0')
|
|
94
|
+
? `${day[2]}`[1]
|
|
95
|
+
: day[2]));
|
|
96
|
+
})));
|
|
97
|
+
})),
|
|
98
|
+
React.createElement(BottomWrapper, null,
|
|
99
|
+
React.createElement(Button, { onClick: handleCancel, size: "small", sx: "width: 80px;", type: "outlined" }, "Cancel"),
|
|
100
|
+
React.createElement(Button, { onClick: handleApply, size: "small", sx: "width: 80px;" }, "Apply"))))))));
|
|
101
|
+
};
|
|
102
|
+
const Wrapper = styled.div `
|
|
103
|
+
position: relative;
|
|
104
|
+
width: fit-content;
|
|
105
|
+
font-family: var(--font-inter);
|
|
106
|
+
`;
|
|
107
|
+
const DateSelector = styled.div `
|
|
108
|
+
transform: translateY(26px);
|
|
109
|
+
position: absolute;
|
|
110
|
+
z-index: 5;
|
|
111
|
+
background-color: #ffffff;
|
|
112
|
+
border-radius: 25px;
|
|
113
|
+
box-shadow: 0px 4px 20px rgba(0, 0, 0, 0.25);
|
|
114
|
+
`;
|
|
115
|
+
const InnerWrapper = styled.div `
|
|
116
|
+
display: flex;
|
|
117
|
+
gap: 31px;
|
|
118
|
+
padding: 30px;
|
|
119
|
+
position: relative;
|
|
120
|
+
border-radius: 25px;
|
|
121
|
+
|
|
122
|
+
&::before {
|
|
123
|
+
position: absolute;
|
|
124
|
+
content: '';
|
|
125
|
+
width: 24px;
|
|
126
|
+
height: 24px;
|
|
127
|
+
top: -12px;
|
|
128
|
+
left: 48px;
|
|
129
|
+
background-color: #ffffff;
|
|
130
|
+
transform: rotate(45deg);
|
|
131
|
+
box-shadow: -3px -3px 5px rgba(0, 0, 0, 0.1);
|
|
132
|
+
}
|
|
133
|
+
`;
|
|
134
|
+
const MonthBar = styled.div `
|
|
135
|
+
display: flex;
|
|
136
|
+
justify-content: space-between;
|
|
137
|
+
align-items: center;
|
|
138
|
+
margin-bottom: 32px;
|
|
139
|
+
user-select: none;
|
|
140
|
+
`;
|
|
141
|
+
const Arrow = styled.button `
|
|
142
|
+
appearance: none;
|
|
143
|
+
border: none;
|
|
144
|
+
outline: none;
|
|
145
|
+
padding: 12px;
|
|
146
|
+
display: flex;
|
|
147
|
+
justify-content: center;
|
|
148
|
+
align-items: center;
|
|
149
|
+
border-radius: 50%;
|
|
150
|
+
cursor: pointer;
|
|
151
|
+
background-color: transparent;
|
|
152
|
+
|
|
153
|
+
&:hover {
|
|
154
|
+
background-color: var(--color-primary-blue-2);
|
|
155
|
+
border-color: #ffffff;
|
|
156
|
+
svg {
|
|
157
|
+
fill: #ffffff;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
`;
|
|
161
|
+
const WeekdayWrapper = styled.div `
|
|
162
|
+
display: flex;
|
|
163
|
+
gap: 32px;
|
|
164
|
+
user-select: none;
|
|
165
|
+
`;
|
|
166
|
+
const Calendar = styled.div `
|
|
167
|
+
display: flex;
|
|
168
|
+
flex-direction: column;
|
|
169
|
+
gap: 32px;
|
|
170
|
+
margin: 32px 0px;
|
|
171
|
+
user-select: none;
|
|
172
|
+
`;
|
|
173
|
+
const Week = styled.div `
|
|
174
|
+
display: flex;
|
|
175
|
+
gap: 32px;
|
|
176
|
+
border-radius: 24px;
|
|
177
|
+
`;
|
|
178
|
+
const Day = styled.button `
|
|
179
|
+
outline: none;
|
|
180
|
+
border: none;
|
|
181
|
+
background: transparent;
|
|
182
|
+
display: flex;
|
|
183
|
+
align-items: center;
|
|
184
|
+
justify-content: center;
|
|
185
|
+
width: 32px;
|
|
186
|
+
height: 32px;
|
|
187
|
+
border-radius: 50%;
|
|
188
|
+
cursor: pointer;
|
|
189
|
+
font-family: var(--font-inter);
|
|
190
|
+
font-size: 16px;
|
|
191
|
+
line-height: 24px;
|
|
192
|
+
|
|
193
|
+
&.today {
|
|
194
|
+
color: var(--color-primary-blue-2);
|
|
195
|
+
font-weight: 600;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
&.not-current {
|
|
199
|
+
color: var(--color-grey-9);
|
|
200
|
+
cursor: default;
|
|
201
|
+
pointer-events: none;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
&.selected {
|
|
205
|
+
background-color: var(--color-primary-blue-2);
|
|
206
|
+
color: #ffffff;
|
|
207
|
+
|
|
208
|
+
&.not-current {
|
|
209
|
+
background-color: var(--color-blue-9);
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
`;
|
|
213
|
+
const BottomWrapper = styled.div `
|
|
214
|
+
display: flex;
|
|
215
|
+
justify-content: flex-end;
|
|
216
|
+
gap: 18px;
|
|
217
|
+
`;
|
|
218
|
+
const Input = styled.input `
|
|
219
|
+
padding: 0px;
|
|
220
|
+
flex: 1;
|
|
221
|
+
font-family: var(--font-inter);
|
|
222
|
+
font-size: 14px;
|
|
223
|
+
color: var(--color-grey-3);
|
|
224
|
+
border: none;
|
|
225
|
+
outline: none;
|
|
226
|
+
border-radius: 8px;
|
|
227
|
+
background-color: transparent;
|
|
228
|
+
|
|
229
|
+
&::placeholder {
|
|
230
|
+
color: var(--color-grey-6);
|
|
231
|
+
}
|
|
232
|
+
`;
|
|
233
|
+
const InputWrapper = styled.div `
|
|
234
|
+
display: flex;
|
|
235
|
+
gap: 8px;
|
|
236
|
+
align-items: center;
|
|
237
|
+
box-sizing: border-box;
|
|
238
|
+
padding: 12px;
|
|
239
|
+
background-color: var(--color-blue-10);
|
|
240
|
+
border-radius: 8px;
|
|
241
|
+
border: 1px solid transparent;
|
|
242
|
+
|
|
243
|
+
&:hover {
|
|
244
|
+
border-color: var(--color-grey-8);
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
&:focus-within {
|
|
248
|
+
border-color: var(--color-primary-blue-2);
|
|
249
|
+
}
|
|
250
|
+
`;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { CalendarInput } from './calendar';
|
|
@@ -14,3 +14,5 @@ export { TextArea } from './text_area';
|
|
|
14
14
|
export type { TextAreaProps } from './text_area';
|
|
15
15
|
export { TextInput } from './text_input';
|
|
16
16
|
export type { TextInputProps } from './text_input';
|
|
17
|
+
export { CalendarInput } from './calendar';
|
|
18
|
+
export type { CalendarInputProps } from './calendar';
|