x-ui-design 1.0.31-gamma.1 → 1.0.33

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.
Files changed (218) hide show
  1. package/.github/workflows/x-ui-design.yml +14 -0
  2. package/README.md +22 -1
  3. package/compile.sh +15 -0
  4. package/dist/{components → esm/types/components}/DatePicker/DatePicker.d.ts +2 -1
  5. package/dist/{components → esm/types/components}/DatePicker/RangePicker/RangePicker.d.ts +2 -1
  6. package/dist/{components → esm/types/components}/Dropdown/Dropdown.d.ts +2 -1
  7. package/dist/{components → esm/types/components}/Empty/Empty.d.ts +2 -1
  8. package/dist/{components → esm/types/components}/Form/Item/Item.d.ts +2 -1
  9. package/dist/esm/types/components/Icons/Icons.d.ts +19 -0
  10. package/dist/{components → esm/types/components}/Input/Input.d.ts +2 -1
  11. package/dist/{components → esm/types/components}/Input/Textarea/Textarea.d.ts +2 -1
  12. package/dist/{components → esm/types/components}/Popover/Popover.d.ts +2 -1
  13. package/dist/{components → esm/types/components}/Radio/Button/Button.d.ts +2 -1
  14. package/dist/{components → esm/types/components}/Radio/Group/Group.d.ts +2 -1
  15. package/dist/{components → esm/types/components}/Radio/Radio.d.ts +2 -1
  16. package/dist/{components → esm/types/components}/Result/Result.d.ts +2 -1
  17. package/dist/{components → esm/types/components}/Switch/Switch.d.ts +2 -1
  18. package/dist/{components → esm/types/components}/Upload/Upload.d.ts +2 -1
  19. package/dist/esm/types/index.d.ts +50 -0
  20. package/dist/{types → esm/types/types}/input.d.ts +2 -2
  21. package/dist/index.d.ts +144 -1
  22. package/dist/index.esm.js +4233 -3792
  23. package/dist/index.esm.js.map +1 -1
  24. package/dist/index.js +4338 -3897
  25. package/dist/index.js.map +1 -1
  26. package/eslint.config.mjs +16 -0
  27. package/lib/components/Button/Button.tsx +136 -0
  28. package/lib/components/Button/index.ts +1 -0
  29. package/lib/components/Button/style.css +197 -0
  30. package/lib/components/Checkbox/Checkbox.tsx +131 -0
  31. package/lib/components/Checkbox/index.ts +1 -0
  32. package/lib/components/Checkbox/style.css +95 -0
  33. package/lib/components/ConditionalWrapper/index.tsx +12 -0
  34. package/lib/components/DatePicker/DatePicker.tsx +526 -0
  35. package/lib/components/DatePicker/RangePicker/RangePicker.tsx +500 -0
  36. package/lib/components/DatePicker/RangePicker/index.ts +1 -0
  37. package/lib/components/DatePicker/RangePicker/style.css +434 -0
  38. package/lib/components/DatePicker/TimePicker/TimePicker.tsx +497 -0
  39. package/lib/components/DatePicker/TimePicker/index.ts +1 -0
  40. package/lib/components/DatePicker/TimePicker/style.css +197 -0
  41. package/lib/components/DatePicker/index.ts +1 -0
  42. package/lib/components/DatePicker/style.css +318 -0
  43. package/lib/components/Dropdown/Dropdown.tsx +234 -0
  44. package/lib/components/Dropdown/index.ts +1 -0
  45. package/lib/components/Dropdown/style.css +124 -0
  46. package/lib/components/Empty/Empty.tsx +45 -0
  47. package/lib/components/Empty/index.ts +1 -0
  48. package/lib/components/Empty/style.css +13 -0
  49. package/lib/components/Form/Form.tsx +130 -0
  50. package/lib/components/Form/Item/Item.tsx +294 -0
  51. package/lib/components/Form/Item/index.ts +1 -0
  52. package/lib/components/Form/Item/style.css +61 -0
  53. package/lib/components/Form/index.ts +1 -0
  54. package/lib/components/Icons/Icons.tsx +433 -0
  55. package/lib/components/Icons/index.ts +15 -0
  56. package/lib/components/Input/Input.tsx +218 -0
  57. package/lib/components/Input/Textarea/Textarea.tsx +110 -0
  58. package/lib/components/Input/Textarea/index.ts +1 -0
  59. package/lib/components/Input/Textarea/style.css +104 -0
  60. package/lib/components/Input/index.ts +1 -0
  61. package/lib/components/Input/style.css +137 -0
  62. package/lib/components/Menu/Item/Item.tsx +65 -0
  63. package/lib/components/Menu/Menu.tsx +261 -0
  64. package/lib/components/Menu/SubMenu/SubMenu.tsx +68 -0
  65. package/lib/components/Menu/index.css +145 -0
  66. package/lib/components/Menu/index.ts +1 -0
  67. package/lib/components/Popover/Popover.tsx +135 -0
  68. package/lib/components/Popover/index.ts +1 -0
  69. package/lib/components/Popover/style.css +82 -0
  70. package/lib/components/Radio/Button/Button.tsx +42 -0
  71. package/lib/components/Radio/Button/index.ts +1 -0
  72. package/lib/components/Radio/Button/style.css +43 -0
  73. package/lib/components/Radio/Group/Group.tsx +105 -0
  74. package/lib/components/Radio/Group/index.ts +1 -0
  75. package/lib/components/Radio/Group/style.css +53 -0
  76. package/lib/components/Radio/Radio.tsx +83 -0
  77. package/lib/components/Radio/index.ts +1 -0
  78. package/lib/components/Radio/style.css +73 -0
  79. package/lib/components/Result/Result.tsx +39 -0
  80. package/lib/components/Result/index.ts +1 -0
  81. package/lib/components/Result/style.css +173 -0
  82. package/lib/components/Select/Option/Option.tsx +49 -0
  83. package/lib/components/Select/Option/index.ts +1 -0
  84. package/lib/components/Select/Option/style.css +50 -0
  85. package/lib/components/Select/Select.tsx +935 -0
  86. package/lib/components/Select/Tag/Tag.tsx +43 -0
  87. package/lib/components/Select/Tag/index.ts +1 -0
  88. package/lib/components/Select/Tag/style.css +87 -0
  89. package/lib/components/Select/index.ts +1 -0
  90. package/lib/components/Select/style.css +186 -0
  91. package/lib/components/Skeleton/Avatar/Avatar.tsx +61 -0
  92. package/lib/components/Skeleton/Avatar/index.ts +1 -0
  93. package/lib/components/Skeleton/Avatar/style.css +27 -0
  94. package/lib/components/Skeleton/Button/Button.tsx +44 -0
  95. package/lib/components/Skeleton/Button/index.ts +1 -0
  96. package/lib/components/Skeleton/Button/style.css +50 -0
  97. package/lib/components/Skeleton/Image/Image.tsx +45 -0
  98. package/lib/components/Skeleton/Image/index.ts +1 -0
  99. package/lib/components/Skeleton/Image/style.css +23 -0
  100. package/lib/components/Skeleton/Input/Input.tsx +42 -0
  101. package/lib/components/Skeleton/Input/index.ts +1 -0
  102. package/lib/components/Skeleton/Input/style.css +56 -0
  103. package/lib/components/Skeleton/Skeleton.tsx +97 -0
  104. package/lib/components/Skeleton/index.ts +1 -0
  105. package/lib/components/Skeleton/style.css +84 -0
  106. package/lib/components/Switch/Switch.tsx +68 -0
  107. package/lib/components/Switch/index.css +50 -0
  108. package/lib/components/Switch/index.ts +1 -0
  109. package/lib/components/Upload/Upload.tsx +291 -0
  110. package/lib/components/Upload/index.ts +1 -0
  111. package/lib/components/Upload/style.css +151 -0
  112. package/lib/global.d.ts +1 -0
  113. package/lib/helpers/flatten.ts +26 -0
  114. package/lib/helpers/index.ts +52 -0
  115. package/lib/helpers/mask.ts +52 -0
  116. package/lib/hooks/useForm.ts +548 -0
  117. package/lib/hooks/usePosition.ts +206 -0
  118. package/lib/hooks/useWatch.ts +41 -0
  119. package/lib/hooks/useWatchError.ts +20 -0
  120. package/lib/index.ts +184 -0
  121. package/lib/styles/global.css +57 -0
  122. package/lib/types/button.ts +83 -0
  123. package/lib/types/checkbox.ts +32 -0
  124. package/lib/types/datepicker.ts +165 -0
  125. package/lib/types/dropdown.ts +41 -0
  126. package/lib/types/empty.ts +8 -0
  127. package/lib/types/form.ts +179 -0
  128. package/lib/types/index.ts +38 -0
  129. package/lib/types/input.ts +72 -0
  130. package/lib/types/menu.ts +55 -0
  131. package/lib/types/popover.ts +16 -0
  132. package/lib/types/radio.ts +69 -0
  133. package/lib/types/result.ts +22 -0
  134. package/lib/types/select.ts +126 -0
  135. package/lib/types/skeleton.ts +62 -0
  136. package/lib/types/switch.ts +22 -0
  137. package/lib/types/upload.ts +67 -0
  138. package/lib/utils/index.ts +37 -0
  139. package/lib/utils/lazy.ts +17 -0
  140. package/next.config.ts +7 -0
  141. package/package.json +18 -20
  142. package/rollup.config.js +71 -0
  143. package/src/app/favicon.ico +0 -0
  144. package/src/app/globals.css +48 -0
  145. package/src/app/layout.d.ts +5 -0
  146. package/src/app/layout.tsx +16 -0
  147. package/src/app/page.d.ts +1 -0
  148. package/src/app/page.tsx +22 -0
  149. package/tsconfig.json +46 -0
  150. package/dist/components/Icons/Icons.d.ts +0 -18
  151. /package/dist/{components → esm/types/components}/Button/Button.d.ts +0 -0
  152. /package/dist/{components → esm/types/components}/Button/index.d.ts +0 -0
  153. /package/dist/{components → esm/types/components}/Checkbox/Checkbox.d.ts +0 -0
  154. /package/dist/{components → esm/types/components}/Checkbox/index.d.ts +0 -0
  155. /package/dist/{components → esm/types/components}/ConditionalWrapper/index.d.ts +0 -0
  156. /package/dist/{components → esm/types/components}/DatePicker/RangePicker/index.d.ts +0 -0
  157. /package/dist/{components → esm/types/components}/DatePicker/TimePicker/TimePicker.d.ts +0 -0
  158. /package/dist/{components → esm/types/components}/DatePicker/TimePicker/index.d.ts +0 -0
  159. /package/dist/{components → esm/types/components}/DatePicker/index.d.ts +0 -0
  160. /package/dist/{components → esm/types/components}/Dropdown/index.d.ts +0 -0
  161. /package/dist/{components → esm/types/components}/Empty/index.d.ts +0 -0
  162. /package/dist/{components → esm/types/components}/Form/Form.d.ts +0 -0
  163. /package/dist/{components → esm/types/components}/Form/Item/index.d.ts +0 -0
  164. /package/dist/{components → esm/types/components}/Form/index.d.ts +0 -0
  165. /package/dist/{components → esm/types/components}/Icons/index.d.ts +0 -0
  166. /package/dist/{components → esm/types/components}/Input/Textarea/index.d.ts +0 -0
  167. /package/dist/{components → esm/types/components}/Input/index.d.ts +0 -0
  168. /package/dist/{components → esm/types/components}/Menu/Item/Item.d.ts +0 -0
  169. /package/dist/{components → esm/types/components}/Menu/Menu.d.ts +0 -0
  170. /package/dist/{components → esm/types/components}/Menu/SubMenu/SubMenu.d.ts +0 -0
  171. /package/dist/{components → esm/types/components}/Menu/index.d.ts +0 -0
  172. /package/dist/{components → esm/types/components}/Popover/index.d.ts +0 -0
  173. /package/dist/{components → esm/types/components}/Radio/Button/index.d.ts +0 -0
  174. /package/dist/{components → esm/types/components}/Radio/Group/index.d.ts +0 -0
  175. /package/dist/{components → esm/types/components}/Radio/index.d.ts +0 -0
  176. /package/dist/{components → esm/types/components}/Result/index.d.ts +0 -0
  177. /package/dist/{components → esm/types/components}/Select/Option/Option.d.ts +0 -0
  178. /package/dist/{components → esm/types/components}/Select/Option/index.d.ts +0 -0
  179. /package/dist/{components → esm/types/components}/Select/Select.d.ts +0 -0
  180. /package/dist/{components → esm/types/components}/Select/Tag/Tag.d.ts +0 -0
  181. /package/dist/{components → esm/types/components}/Select/Tag/index.d.ts +0 -0
  182. /package/dist/{components → esm/types/components}/Select/index.d.ts +0 -0
  183. /package/dist/{components → esm/types/components}/Skeleton/Avatar/Avatar.d.ts +0 -0
  184. /package/dist/{components → esm/types/components}/Skeleton/Avatar/index.d.ts +0 -0
  185. /package/dist/{components → esm/types/components}/Skeleton/Button/Button.d.ts +0 -0
  186. /package/dist/{components → esm/types/components}/Skeleton/Button/index.d.ts +0 -0
  187. /package/dist/{components → esm/types/components}/Skeleton/Image/Image.d.ts +0 -0
  188. /package/dist/{components → esm/types/components}/Skeleton/Image/index.d.ts +0 -0
  189. /package/dist/{components → esm/types/components}/Skeleton/Input/Input.d.ts +0 -0
  190. /package/dist/{components → esm/types/components}/Skeleton/Input/index.d.ts +0 -0
  191. /package/dist/{components → esm/types/components}/Skeleton/Skeleton.d.ts +0 -0
  192. /package/dist/{components → esm/types/components}/Skeleton/index.d.ts +0 -0
  193. /package/dist/{components → esm/types/components}/Switch/index.d.ts +0 -0
  194. /package/dist/{components → esm/types/components}/Upload/index.d.ts +0 -0
  195. /package/dist/{helpers → esm/types/helpers}/flatten.d.ts +0 -0
  196. /package/dist/{helpers → esm/types/helpers}/index.d.ts +0 -0
  197. /package/dist/{helpers → esm/types/helpers}/mask.d.ts +0 -0
  198. /package/dist/{hooks → esm/types/hooks}/useForm.d.ts +0 -0
  199. /package/dist/{hooks → esm/types/hooks}/usePosition.d.ts +0 -0
  200. /package/dist/{hooks → esm/types/hooks}/useWatch.d.ts +0 -0
  201. /package/dist/{hooks → esm/types/hooks}/useWatchError.d.ts +0 -0
  202. /package/dist/{types → esm/types/types}/button.d.ts +0 -0
  203. /package/dist/{types → esm/types/types}/checkbox.d.ts +0 -0
  204. /package/dist/{types → esm/types/types}/datepicker.d.ts +0 -0
  205. /package/dist/{types → esm/types/types}/dropdown.d.ts +0 -0
  206. /package/dist/{types → esm/types/types}/empty.d.ts +0 -0
  207. /package/dist/{types → esm/types/types}/form.d.ts +0 -0
  208. /package/dist/{types → esm/types/types}/index.d.ts +0 -0
  209. /package/dist/{types → esm/types/types}/menu.d.ts +0 -0
  210. /package/dist/{types → esm/types/types}/popover.d.ts +0 -0
  211. /package/dist/{types → esm/types/types}/radio.d.ts +0 -0
  212. /package/dist/{types → esm/types/types}/result.d.ts +0 -0
  213. /package/dist/{types → esm/types/types}/select.d.ts +0 -0
  214. /package/dist/{types → esm/types/types}/skeleton.d.ts +0 -0
  215. /package/dist/{types → esm/types/types}/switch.d.ts +0 -0
  216. /package/dist/{types → esm/types/types}/upload.d.ts +0 -0
  217. /package/dist/{utils → esm/types/utils}/index.d.ts +0 -0
  218. /package/dist/{utils → esm/types/utils}/lazy.d.ts +0 -0
@@ -0,0 +1,500 @@
1
+ 'use client';
2
+
3
+ import React, { useEffect, useRef, useState } from 'react';
4
+ import { clsx } from '../../../helpers';
5
+ import { TRangePickerProps } from '../../../types/datepicker';
6
+ import { prefixClsRangePicker } from '../../../utils';
7
+ import { MONTH_LENGTH, NEXT_DAYS_COUNT_AS_CURRENT_MUNTH, NUMBER_SIX } from '../DatePicker';
8
+ import { CalendarIcon, ClearIcon, DateDistanceIcon } from '../../Icons/Icons';
9
+ import { createPortal } from 'react-dom';
10
+ import { ConditionalWrapper } from '../../../components/ConditionalWrapper';
11
+ import { usePosition } from '../../../hooks/usePosition';
12
+ import './style.css';
13
+
14
+ const RangePicker = ({
15
+ prefixCls = prefixClsRangePicker,
16
+ value,
17
+ onChange,
18
+ placeholder = ['Start date', 'End date'],
19
+ disabled,
20
+ error,
21
+ format = 'YYYY-MM-DD',
22
+ prefix,
23
+ allowClear = true,
24
+ inputReadOnly = false,
25
+ size = 'large',
26
+ picker = 'date',
27
+ locale,
28
+ disabledDate,
29
+ onVisibleChange,
30
+ onCalendarChange,
31
+ style = {},
32
+ className = '',
33
+ separator,
34
+ defaultValue,
35
+ bordered = true,
36
+ getPopupContainer,
37
+ placement
38
+ }: TRangePickerProps) => {
39
+ const triggerRef = useRef<HTMLDivElement>(null);
40
+ const [isOpen, setIsOpen] = useState(false);
41
+ const [selectedDates, setSelectedDates] = useState<
42
+ [Date | null, Date | null]
43
+ >([
44
+ value?.[0] || defaultValue?.[0] || null,
45
+ value?.[1] || defaultValue?.[1] || null
46
+ ]);
47
+
48
+ useEffect(() => {
49
+ setSelectedDates([
50
+ value?.[0] || defaultValue?.[0] || null,
51
+ value?.[1] || defaultValue?.[1] || null
52
+ ])
53
+ }, [value])
54
+
55
+ const popupRef = useRef<HTMLDivElement>(null);
56
+
57
+ const [hoveredDate, setHoveredDate] = useState<Date | null>(null);
58
+ const [currentMonth, setCurrentMonth] = useState(new Date().getMonth());
59
+ const [currentYear, setCurrentYear] = useState(new Date().getFullYear());
60
+ const [viewMode, setViewMode] = useState<'day' | 'month' | 'year'>(
61
+ picker === 'month' ? 'month' : picker === 'year' ? 'year' : 'day'
62
+ );
63
+
64
+ const { dropdownPosition } = usePosition({
65
+ isOpen,
66
+ popupRef,
67
+ placement,
68
+ triggerRef,
69
+ getPopupContainer: getPopupContainer?.(triggerRef.current as HTMLElement)
70
+ })
71
+
72
+ const localeMonths =
73
+ locale?.shortMonths ||
74
+ Array.from({ length: 12 }, (_, i) =>
75
+ new Date(0, i).toLocaleString(locale?.locale || 'default', {
76
+ month: 'short'
77
+ })
78
+ );
79
+
80
+ const localeWeekdays = locale?.shortWeekDays || [
81
+ 'Su',
82
+ 'Mo',
83
+ 'Tu',
84
+ 'We',
85
+ 'Th',
86
+ 'Fr',
87
+ 'Sa'
88
+ ];
89
+
90
+ useEffect(() => {
91
+ const handleClickOutside = (event: MouseEvent) => {
92
+ if (
93
+ popupRef.current &&
94
+ !popupRef.current.contains(event.target as Node) &&
95
+ triggerRef.current &&
96
+ !triggerRef.current.contains(event.target as Node)
97
+ ) {
98
+ setIsOpen(false);
99
+ onVisibleChange?.(false);
100
+ }
101
+ };
102
+
103
+ document.addEventListener('mousedown', handleClickOutside);
104
+
105
+ return () => document.removeEventListener('mousedown', handleClickOutside);
106
+ }, []);
107
+
108
+ const isInHoverRange = (date: Date) => {
109
+ const [start, end] = selectedDates;
110
+ if (!start || end || !hoveredDate) return false;
111
+
112
+ const rangeStart = hoveredDate < start ? hoveredDate : start;
113
+ const rangeEnd = hoveredDate < start ? start : hoveredDate;
114
+
115
+ return date > rangeStart && date < rangeEnd;
116
+ };
117
+
118
+ const handleSelect = (date: Date) => {
119
+ if (!selectedDates[0] || (selectedDates[0] && selectedDates[1])) {
120
+ setSelectedDates([date, null]);
121
+ onCalendarChange?.([date.toUTCString(), undefined], [formatDate(date)], {});
122
+ } else {
123
+ const start = selectedDates[0];
124
+ const end = date < start ? start : date;
125
+ const begin = date < start ? date : start;
126
+ setSelectedDates([begin, end]);
127
+ onChange?.(
128
+ [begin.toUTCString(), end.toUTCString()],
129
+ [formatDate(begin), formatDate(end)]
130
+ );
131
+ onCalendarChange?.(
132
+ [begin.toUTCString(), end.toUTCString()],
133
+ [formatDate(begin), formatDate(end)], {}
134
+ );
135
+ setIsOpen(false);
136
+ onVisibleChange?.(false);
137
+ }
138
+ };
139
+
140
+ const isMonthDisabled = (month: number) => {
141
+ const date = new Date(currentYear, month + 1, 1);
142
+
143
+ return disabledDate?.(date, { from: undefined, to: undefined });
144
+ };
145
+
146
+ const isYearDisabled = (year: number) => {
147
+ const date = new Date(year + 1, currentMonth, 1);
148
+
149
+ return disabledDate?.(date, { from: undefined, to: undefined });
150
+ };
151
+
152
+ const formatDate = (date: Date) => {
153
+ if (typeof format === 'function') {
154
+ return format(date);
155
+ }
156
+
157
+ return `${format}`
158
+ .replace(/YYYY/, date.getFullYear().toString())
159
+ .replace(/MM/, (date.getMonth() + 1).toString().padStart(2, '0'))
160
+ .replace(/DD/, date.getDate().toString().padStart(2, '0'));
161
+ };
162
+
163
+ const isInRange = (date: Date) => {
164
+ const [start, end] = selectedDates;
165
+
166
+ return start && end && date > start && date < end;
167
+ };
168
+
169
+ const renderMonthYearSelector = (monthOffset = 0, all?: boolean) => {
170
+ const baseYear = currentYear;
171
+ const baseMonth = currentMonth + monthOffset;
172
+
173
+ return (
174
+ <div className={`${prefixCls}-header ${className}`}>
175
+ {all || !monthOffset ? (
176
+ <div className={`${prefixCls}-nav-buttons`}>
177
+ <button onClick={(e) => {
178
+ e.preventDefault();
179
+ e.stopPropagation();
180
+
181
+ setCurrentYear((y: number) => y - 1)
182
+ }}
183
+ >
184
+ &laquo;
185
+ </button>
186
+ <button
187
+ onClick={(e) => {
188
+ e.preventDefault();
189
+ e.stopPropagation();
190
+
191
+ setCurrentMonth((m: number) =>
192
+ m === 0
193
+ ? (setCurrentYear((y: number) => y - 1), MONTH_LENGTH)
194
+ : m - 1
195
+ )
196
+ }
197
+ }
198
+ >
199
+ &lsaquo;
200
+ </button>
201
+ </div>
202
+ ) : (
203
+ <span />
204
+ )}
205
+ <div className={`${prefixCls}-dropdown-selects`}>
206
+ <button
207
+ type="button"
208
+ className={`${prefixCls}-select`}
209
+ onClick={(e) => {
210
+ e.preventDefault();
211
+ e.stopPropagation();
212
+
213
+ setViewMode('year')
214
+ }}
215
+ >
216
+ {baseYear}
217
+ </button>
218
+ <button
219
+ type="button"
220
+ className={`${prefixCls}-select`}
221
+ onClick={(e) => {
222
+ e.preventDefault();
223
+ e.stopPropagation();
224
+
225
+ setViewMode('month')
226
+ }}
227
+ >
228
+ {localeMonths[baseMonth]}
229
+ </button>
230
+ </div>
231
+ {all || monthOffset ? (
232
+ <div className={`${prefixCls}-nav-buttons`}>
233
+ <button
234
+ onClick={(e) => {
235
+ e.preventDefault();
236
+ e.stopPropagation();
237
+
238
+ setCurrentMonth((m: number) =>
239
+ m === MONTH_LENGTH
240
+ ? (setCurrentYear((y: number) => y + 1), 0)
241
+ : m + 1
242
+ )
243
+ }
244
+ }
245
+ >
246
+ &rsaquo;
247
+ </button>
248
+ <button onClick={(e) => {
249
+ e.preventDefault();
250
+ e.stopPropagation();
251
+
252
+ setCurrentYear((y: number) => y + 1)
253
+ }}>
254
+ &raquo;
255
+ </button>
256
+ </div>
257
+ ) : (
258
+ <span />
259
+ )}
260
+ </div>
261
+ );
262
+ };
263
+
264
+ const renderCalendar = (monthOffset = 0, all?: boolean) => {
265
+ const baseDate = new Date(currentYear, currentMonth + monthOffset, 1);
266
+ const year = baseDate.getFullYear();
267
+ const month = baseDate.getMonth();
268
+ const firstDay = new Date(year, month, 1).getDay();
269
+ const daysInMonth = new Date(year, month + 1, 0).getDate();
270
+
271
+ const prevMonthDays = (() => {
272
+ const prevMonth = new Date(year, month, 0);
273
+ const totalDays = prevMonth.getDate();
274
+
275
+ return Array.from(
276
+ { length: firstDay },
277
+ (_, i) => new Date(year, month - 1, totalDays - firstDay + i + 1)
278
+ );
279
+ })();
280
+
281
+ const currentMonthDays = Array.from(
282
+ { length: daysInMonth },
283
+ (_, i) => new Date(year, month, i + 1)
284
+ );
285
+
286
+ const totalDisplayed = prevMonthDays.length + currentMonthDays.length;
287
+ const remaining = NEXT_DAYS_COUNT_AS_CURRENT_MUNTH - totalDisplayed;
288
+ const nextMonthDays = Array.from(
289
+ { length: remaining },
290
+ (_, i) => new Date(year, month + 1, i + 1)
291
+ );
292
+
293
+ const days = [...prevMonthDays, ...currentMonthDays, ...nextMonthDays];
294
+
295
+ return (
296
+ <div className={`${prefixCls}-calendar ${viewMode}`}>
297
+ <div className={`${prefixCls}-calendar-header`}>
298
+ {renderMonthYearSelector(monthOffset, all)}
299
+ </div>
300
+ {viewMode === 'day' && (
301
+ <div className={`${prefixCls}-days-grid day`}>
302
+ {localeWeekdays.map((day, i) => (
303
+ <div key={i} className={`${prefixCls}-weekday`}>
304
+ {day}
305
+ </div>
306
+ ))}
307
+ {days.map((day, i) => {
308
+ const isSelected =
309
+ day &&
310
+ selectedDates.some(
311
+ d => d?.toDateString() === day?.toDateString()
312
+ );
313
+
314
+ const inRange = day && isInRange(day);
315
+ const isSameMonth = day?.getMonth() === month;
316
+
317
+ return (
318
+ <button
319
+ key={i}
320
+ disabled={disabledDate?.(day, {
321
+ from: undefined,
322
+ to: undefined
323
+ })}
324
+ onClick={(e) => {
325
+ e.preventDefault();
326
+ e.stopPropagation();
327
+
328
+ day && handleSelect(day)
329
+ }}
330
+ onMouseEnter={(e) => {
331
+ e.preventDefault();
332
+ e.stopPropagation();;
333
+
334
+ day && setHoveredDate(day);
335
+ }}
336
+ className={clsx([
337
+ `${prefixCls}-day`,
338
+ {
339
+ [`${prefixCls}-selected`]: isSelected,
340
+ [`${prefixCls}-in-range`]: inRange,
341
+ [`${prefixCls}-hover-end`]:
342
+ hoveredDate &&
343
+ selectedDates[0] &&
344
+ !selectedDates[1] &&
345
+ hoveredDate > selectedDates[0] &&
346
+ hoveredDate?.toDateString() === day?.toDateString(),
347
+ [`${prefixCls}-other-month`]: !isSameMonth,
348
+ [`${prefixCls}-in-hover-range`]: isInHoverRange(day),
349
+ }
350
+ ])}
351
+ >
352
+ {day?.getDate()}
353
+ </button>
354
+ );
355
+ })}
356
+ </div>
357
+ )}
358
+
359
+ {viewMode === 'month' && (
360
+ <div className={`${prefixCls}-grid`}>
361
+ {localeMonths.map((m, i) => (
362
+ <button
363
+ key={i}
364
+ className={`${prefixCls}-month`}
365
+ onClick={(e) => {
366
+ e.preventDefault();
367
+ e.stopPropagation();
368
+
369
+ setCurrentMonth(i);
370
+ setViewMode('day');
371
+ }}
372
+ disabled={isMonthDisabled(i)}
373
+ >
374
+ {m}
375
+ </button>
376
+ ))}
377
+ </div>
378
+ )}
379
+
380
+ {viewMode === 'year' && (
381
+ <div className={`${prefixCls}-grid`}>
382
+ {Array.from({ length: 12 }, (_, i) => {
383
+ const year = currentYear - NUMBER_SIX + i;
384
+
385
+ return (
386
+ <button
387
+ key={year}
388
+ className={`${prefixCls}-year`}
389
+ disabled={isYearDisabled(year)}
390
+ onClick={(e) => {
391
+ e.preventDefault();
392
+ e.stopPropagation();
393
+
394
+ setCurrentYear(year);
395
+ setViewMode('month');
396
+ }}
397
+ >
398
+ {year}
399
+ </button>
400
+ );
401
+ })}
402
+ </div>
403
+ )}
404
+ </div>
405
+ );
406
+ };
407
+
408
+ const handleClear = () => {
409
+ setSelectedDates([null, null]);
410
+ onChange?.(null, ['', '']);
411
+ };
412
+
413
+ return (
414
+ <div
415
+ style={style}
416
+ className={clsx([
417
+ `${prefixCls}-range-container`,
418
+ {
419
+ [`${prefixCls}-${size}`]: size,
420
+ [className]: className
421
+ }
422
+ ])}
423
+ >
424
+ <div className={`${prefixCls}-range-input-wrapper`} ref={triggerRef}>
425
+ <button
426
+ type="button"
427
+ className={clsx([
428
+ `${prefixCls}-input`,
429
+ {
430
+ noBordered: !bordered,
431
+ [`${prefixCls}-error`]: error,
432
+ [`${prefixCls}-disabled`]: disabled
433
+ }
434
+ ])}
435
+ disabled={disabled}
436
+ onClick={(e) => {
437
+ e.preventDefault();
438
+ e.stopPropagation();
439
+
440
+ if (!isOpen) {
441
+ setIsOpen(!isOpen);
442
+ onVisibleChange?.(!isOpen);
443
+ }
444
+ }}
445
+ >
446
+ {prefix}
447
+ <input
448
+ readOnly={inputReadOnly}
449
+ className={`${prefixCls}-selected-date`}
450
+ placeholder={placeholder[0]}
451
+ key={`0_${selectedDates[0]?.toUTCString()}`}
452
+ {...({
453
+ [inputReadOnly ? 'value' : 'defaultValue']: selectedDates[0] ? formatDate(selectedDates[0]) : ''
454
+ })}
455
+ />
456
+ <span className={`${prefixCls}-range-separator`}>
457
+ {separator || <DateDistanceIcon />}
458
+ </span>
459
+ <input
460
+ readOnly={inputReadOnly}
461
+ className={`${prefixCls}-selected-date`}
462
+ placeholder={placeholder[1]}
463
+ key={`1_${selectedDates[1]?.toUTCString()}`}
464
+ {...({
465
+ [inputReadOnly ? 'value' : 'defaultValue']: selectedDates[1] ? formatDate(selectedDates[1]) : ''
466
+ })}
467
+ />
468
+ <span className={`${prefixCls}-icon`}>
469
+ {allowClear && (selectedDates[0] || selectedDates[1]) ? (
470
+ <span className={`${prefixCls}-clear`} onClick={handleClear}>
471
+ <ClearIcon />
472
+ </span>
473
+ ) : (
474
+ <CalendarIcon />
475
+ )}
476
+ </span>
477
+ </button>
478
+ </div>
479
+
480
+ {isOpen && (
481
+ <ConditionalWrapper
482
+ condition={getPopupContainer !== undefined}
483
+ wrapper={(element) => getPopupContainer ? createPortal(element, getPopupContainer(popupRef.current as HTMLElement)) : <>{element}</>}>
484
+ <div
485
+ ref={popupRef}
486
+ className={`${prefixCls}-dropdown-wrapper show`}
487
+ style={dropdownPosition}
488
+ >
489
+ <div className={`${prefixCls}-dropdown-range`}>
490
+ {renderCalendar(0, viewMode !== 'day')}
491
+ {viewMode === 'day' && renderCalendar(1, viewMode !== 'day')}
492
+ </div>
493
+ </div>
494
+ </ConditionalWrapper>
495
+ )}
496
+ </div>
497
+ );
498
+ };
499
+
500
+ export default RangePicker;
@@ -0,0 +1 @@
1
+ export { default as RangePicker } from '../RangePicker/RangePicker'