wini-web-components 2.8.5 → 2.8.6

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 (129) hide show
  1. package/dist/index.js.js +9 -9
  2. package/dist/index.js.mjs +745 -895
  3. package/global.d.ts +6 -0
  4. package/package.json +3 -4
  5. package/dist/component/button/button.d.ts +0 -22
  6. package/dist/component/button/button.d.ts.map +0 -1
  7. package/dist/component/calendar/calendar.d.ts +0 -31
  8. package/dist/component/calendar/calendar.d.ts.map +0 -1
  9. package/dist/component/carousel/carousel.d.ts +0 -32
  10. package/dist/component/carousel/carousel.d.ts.map +0 -1
  11. package/dist/component/checkbox/checkbox.d.ts +0 -25
  12. package/dist/component/checkbox/checkbox.d.ts.map +0 -1
  13. package/dist/component/ck-editor/ckeditor.d.ts +0 -36
  14. package/dist/component/ck-editor/ckeditor.d.ts.map +0 -1
  15. package/dist/component/component-status.d.ts +0 -8
  16. package/dist/component/component-status.d.ts.map +0 -1
  17. package/dist/component/date-time-picker/date-time-picker.d.ts +0 -36
  18. package/dist/component/date-time-picker/date-time-picker.d.ts.map +0 -1
  19. package/dist/component/dialog/dialog.d.ts +0 -18
  20. package/dist/component/dialog/dialog.d.ts.map +0 -1
  21. package/dist/component/import-file/import-file.d.ts +0 -34
  22. package/dist/component/import-file/import-file.d.ts.map +0 -1
  23. package/dist/component/infinite-scroll/infinite-scroll.d.ts +0 -18
  24. package/dist/component/infinite-scroll/infinite-scroll.d.ts.map +0 -1
  25. package/dist/component/input-multi-select/input-multi-select.d.ts +0 -22
  26. package/dist/component/input-multi-select/input-multi-select.d.ts.map +0 -1
  27. package/dist/component/input-otp/input-otp.d.ts +0 -23
  28. package/dist/component/input-otp/input-otp.d.ts.map +0 -1
  29. package/dist/component/number-picker/number-picker.d.ts +0 -24
  30. package/dist/component/number-picker/number-picker.d.ts.map +0 -1
  31. package/dist/component/pagination/pagination.d.ts +0 -14
  32. package/dist/component/pagination/pagination.d.ts.map +0 -1
  33. package/dist/component/popup/popup.d.ts +0 -40
  34. package/dist/component/popup/popup.d.ts.map +0 -1
  35. package/dist/component/progress-bar/progress-bar.d.ts +0 -16
  36. package/dist/component/progress-bar/progress-bar.d.ts.map +0 -1
  37. package/dist/component/progress-circle/progress-circle.d.ts +0 -13
  38. package/dist/component/progress-circle/progress-circle.d.ts.map +0 -1
  39. package/dist/component/radio-button/radio-button.d.ts +0 -21
  40. package/dist/component/radio-button/radio-button.d.ts.map +0 -1
  41. package/dist/component/rating/rating.d.ts +0 -24
  42. package/dist/component/rating/rating.d.ts.map +0 -1
  43. package/dist/component/select1/select1.d.ts +0 -32
  44. package/dist/component/select1/select1.d.ts.map +0 -1
  45. package/dist/component/switch/switch.d.ts +0 -24
  46. package/dist/component/switch/switch.d.ts.map +0 -1
  47. package/dist/component/table/table.d.ts +0 -51
  48. package/dist/component/table/table.d.ts.map +0 -1
  49. package/dist/component/tag/tag.d.ts +0 -23
  50. package/dist/component/tag/tag.d.ts.map +0 -1
  51. package/dist/component/text/text.d.ts +0 -16
  52. package/dist/component/text/text.d.ts.map +0 -1
  53. package/dist/component/text-area/text-area.d.ts +0 -28
  54. package/dist/component/text-area/text-area.d.ts.map +0 -1
  55. package/dist/component/text-field/text-field.d.ts +0 -37
  56. package/dist/component/text-field/text-field.d.ts.map +0 -1
  57. package/dist/component/toast-noti/toast-noti.d.ts +0 -5
  58. package/dist/component/toast-noti/toast-noti.d.ts.map +0 -1
  59. package/dist/component/wini-icon/winicon.d.ts +0 -27
  60. package/dist/component/wini-icon/winicon.d.ts.map +0 -1
  61. package/dist/form/login/view.d.ts +0 -41
  62. package/dist/form/login/view.d.ts.map +0 -1
  63. package/dist/index.d.ts +0 -34
  64. package/dist/index.d.ts.map +0 -1
  65. package/dist/language/i18n.d.ts +0 -3
  66. package/dist/language/i18n.d.ts.map +0 -1
  67. package/src/component/button/button.module.css +0 -210
  68. package/src/component/button/button.tsx +0 -57
  69. package/src/component/calendar/calendar.module.css +0 -153
  70. package/src/component/calendar/calendar.tsx +0 -389
  71. package/src/component/carousel/carousel.css +0 -622
  72. package/src/component/carousel/carousel.tsx +0 -91
  73. package/src/component/checkbox/checkbox.module.css +0 -48
  74. package/src/component/checkbox/checkbox.tsx +0 -80
  75. package/src/component/ck-editor/ck-editor.css +0 -206
  76. package/src/component/ck-editor/ckeditor.tsx +0 -522
  77. package/src/component/component-status.tsx +0 -53
  78. package/src/component/date-time-picker/date-time-picker.module.css +0 -94
  79. package/src/component/date-time-picker/date-time-picker.tsx +0 -663
  80. package/src/component/dialog/dialog.module.css +0 -111
  81. package/src/component/dialog/dialog.tsx +0 -109
  82. package/src/component/import-file/import-file.module.css +0 -83
  83. package/src/component/import-file/import-file.tsx +0 -174
  84. package/src/component/infinite-scroll/infinite-scroll.module.css +0 -34
  85. package/src/component/infinite-scroll/infinite-scroll.tsx +0 -35
  86. package/src/component/input-multi-select/input-multi-select.module.css +0 -121
  87. package/src/component/input-multi-select/input-multi-select.tsx +0 -263
  88. package/src/component/input-otp/input-otp.module.css +0 -41
  89. package/src/component/input-otp/input-otp.tsx +0 -110
  90. package/src/component/number-picker/number-picker.module.css +0 -137
  91. package/src/component/number-picker/number-picker.tsx +0 -107
  92. package/src/component/pagination/pagination.module.css +0 -48
  93. package/src/component/pagination/pagination.tsx +0 -88
  94. package/src/component/popup/popup.css +0 -136
  95. package/src/component/popup/popup.tsx +0 -125
  96. package/src/component/progress-bar/progress-bar.module.css +0 -42
  97. package/src/component/progress-bar/progress-bar.tsx +0 -33
  98. package/src/component/progress-circle/progress-circle.css +0 -0
  99. package/src/component/progress-circle/progress-circle.tsx +0 -25
  100. package/src/component/radio-button/radio-button.module.css +0 -51
  101. package/src/component/radio-button/radio-button.tsx +0 -60
  102. package/src/component/rating/rating.module.css +0 -11
  103. package/src/component/rating/rating.tsx +0 -65
  104. package/src/component/select1/select1.module.css +0 -108
  105. package/src/component/select1/select1.tsx +0 -271
  106. package/src/component/switch/switch.module.css +0 -53
  107. package/src/component/switch/switch.tsx +0 -68
  108. package/src/component/table/table.css +0 -74
  109. package/src/component/table/table.tsx +0 -108
  110. package/src/component/tag/tag.module.css +0 -108
  111. package/src/component/tag/tag.tsx +0 -31
  112. package/src/component/text/text.css +0 -27
  113. package/src/component/text/text.tsx +0 -24
  114. package/src/component/text-area/text-area.module.css +0 -57
  115. package/src/component/text-area/text-area.tsx +0 -65
  116. package/src/component/text-field/text-field.module.css +0 -71
  117. package/src/component/text-field/text-field.tsx +0 -102
  118. package/src/component/toast-noti/toast-noti.css +0 -866
  119. package/src/component/toast-noti/toast-noti.tsx +0 -22
  120. package/src/component/wini-icon/winicon.module.css +0 -110
  121. package/src/component/wini-icon/winicon.tsx +0 -9424
  122. package/src/form/login/view.module.css +0 -80
  123. package/src/form/login/view.tsx +0 -138
  124. package/src/index.tsx +0 -66
  125. package/src/language/i18n.tsx +0 -143
  126. package/src/skin/layout.css +0 -649
  127. package/src/skin/root.css +0 -294
  128. package/src/skin/typography.css +0 -314
  129. package/src/vite-env.d.ts +0 -1
@@ -1,663 +0,0 @@
1
- import styles from "./date-time-picker.module.css"
2
- import { CSSProperties, forwardRef, ReactNode, useEffect, useMemo, useRef, useState } from "react"
3
- import { useForm } from "react-hook-form"
4
- import { useTranslation } from "react-i18next"
5
- import { differenceInCalendarDays } from "date-fns"
6
- import { closePopup, Popup, showPopup } from "../popup/popup"
7
- import { Text } from "../text/text"
8
- import { Winicon } from "../wini-icon/winicon"
9
- import { TextField } from "../text-field/text-field"
10
- import { Calendar } from "../calendar/calendar"
11
- import { Button } from "../button/button"
12
- import { Checkbox } from "../checkbox/checkbox"
13
-
14
- const today = new Date()
15
- const startDate = new Date(
16
- today.getFullYear() - 100,
17
- today.getMonth(),
18
- today.getDate()
19
- )
20
- const endDate = new Date(
21
- today.getFullYear() + 100,
22
- today.getMonth(),
23
- today.getDate()
24
- )
25
-
26
- const dateToString = (x: Date, y: string = "dd/mm/yyyy") => {
27
- let splitDateTime: Array<string> = y.split(" ");
28
- let dateFormat = splitDateTime[0]
29
- let timeFormat = splitDateTime[1]
30
- if (dateFormat.includes('hh')) {
31
- dateFormat = splitDateTime[1]
32
- timeFormat = splitDateTime[0]
33
- }
34
- let dateConvert: string = dateFormat.split(y.includes("/") ? "/" : "-").map(type => {
35
- switch (type.toLowerCase()) {
36
- case "dd":
37
- return x.getDate() < 10 ? `0${x.getDate()}` : `${x.getDate()}`;
38
- case "mm":
39
- return (x.getMonth() + 1) < 10 ? `0${(x.getMonth() + 1)}` : `${(x.getMonth() + 1)}`;
40
- case "yyyy":
41
- return `${x.getFullYear()}`;
42
- default:
43
- return ''
44
- }
45
- }).join(y.includes("/") ? "/" : "-");
46
- if (timeFormat) {
47
- let timeConvert = timeFormat.split(":").map(type => {
48
- switch (type) {
49
- case "hh":
50
- return x.getHours() < 10 ? `0${x.getHours()}` : `${x.getHours()}`;
51
- case "mm":
52
- return x.getMinutes() < 10 ? `0${x.getMinutes()}` : `${x.getMinutes()}`;
53
- case "ss":
54
- return x.getSeconds() < 10 ? `0${x.getSeconds()}` : `${x.getSeconds()}`;
55
- default:
56
- return ''
57
- }
58
- }).join(":")
59
- return dateConvert + " " + timeConvert;
60
- }
61
- return dateConvert;
62
- }
63
-
64
- const stringToDate = (_date: string, _format: string = "dd/mm/yyyy", _delimiter: string = "/") => {
65
- let dayformat: string = _format;
66
- let hourformat: string = '';
67
- let day: string = _date;
68
- let hours: string = '';
69
- let isHour: boolean = false;
70
- if (_format.trim().indexOf(" ") > -1) {
71
- dayformat = _format.trim().split(" ")[0];
72
- hourformat = _format.trim().split(" ")[1];
73
- day = _date.trim().split(" ")[0];
74
- hours = _date.trim().split(" ")[1] ?? '00:00:00';
75
- isHour = true;
76
- }
77
- let formatLowerCase: string = dayformat.toLowerCase();
78
- let formatItems: Array<string> = formatLowerCase.split(_delimiter);
79
- let dateItems: Array<string> = day.split(_delimiter);
80
- let monthIndex: number = formatItems.indexOf("mm");
81
- let dayIndex: number = formatItems.indexOf("dd");
82
- let yearIndex: number = formatItems.indexOf("yyyy");
83
- let hour: number = 0;
84
- let min: number = 0;
85
- let sec: number = 0;
86
- if (isHour) {
87
- let tmpHour: Array<string> = hourformat.split(":");
88
- let hourindex: number = tmpHour.indexOf("HH");
89
- if (hourindex < 0) {
90
- hourindex = tmpHour.indexOf("hh");
91
- }
92
- let mmindex: number = tmpHour.indexOf("mm");
93
- let ssindex: number = tmpHour.indexOf("ss");
94
- let time: Array<string> = hours.split(":");
95
- hour = parseInt(time[hourindex] ?? '0'); min = parseInt(time[mmindex] ?? '0'); sec = parseInt(time[ssindex] ?? '0');
96
- }
97
- let month: number = parseInt(dateItems[monthIndex]);
98
- month -= 1;
99
- var formatedDate = new Date(parseInt(dateItems[yearIndex]), month, parseInt(dateItems[dayIndex] ?? '0'), hour, min, sec);
100
- return formatedDate;
101
- }
102
- const inRangeTime = (date: Date, startDate: Date, endDate: Date) => (differenceInCalendarDays(date, startDate) > -1 && differenceInCalendarDays(endDate, date) > -1)
103
-
104
- interface ValueProps {
105
- start?: Date,
106
- end?: Date,
107
- /** type: 1: daily, 2: weekly, 3: monthly */
108
- repeatData?: { type: 1 | 2 | 3, value: Array<string | number> }
109
- }
110
-
111
- interface DateTimePickerProps {
112
- id?: string,
113
- value?: Date,
114
- endValue?: Date,
115
- min?: Date,
116
- max?: Date,
117
- pickOnly?: boolean,
118
- helperText?: string,
119
- helperTextColor?: string,
120
- placeholder?: string,
121
- className?: string,
122
- style?: CSSProperties,
123
- disabled?: boolean,
124
- pickerType?: "auto" | "date" | "datetime" | "daterange" | "datetimerange",
125
- enableRepeat?: boolean,
126
- /** type: 1: daily, 2: weekly, 3: monthly */
127
- repeatValue?: { type: 1 | 2 | 3, value: Array<"everyday" | "last" | number> },
128
- prefix?: ReactNode,
129
- onChange?: (ev?: Date | ValueProps) => void,
130
- }
131
-
132
- export function DateTimePicker(props: DateTimePickerProps) {
133
- const popupRef = useRef<any>(null)
134
- const inputRef = useRef<HTMLInputElement>(null)
135
- const [value, setValue] = useState<Date | ValueProps>()
136
- const txtValue = useMemo(() => {
137
- if (!value) return <Text className={styles["value"]} style={{ color: "var(--neutral-text-subtitle-color)" }}>{props.placeholder ?? ""}</Text>
138
- if (value instanceof Date) return <Text className={styles["value"]}>{dateToString(value, `dd/mm/yyyy${props.pickerType?.includes("time") ? " hh:mm" : ""}`)}</Text>
139
- else return <>
140
- <Text className={styles["value"]} style={{ flex: "none", width: "fit-content" }}>{dateToString(value.start ?? new Date(), `dd/mm/yyyy${(props.pickerType?.includes("time") || props.pickerType === "auto") ? " hh:mm" : ""}`)} - {dateToString(value.end ?? new Date(), `dd/mm/yyyy${(props.pickerType?.includes("time") || props.pickerType === "auto") ? " hh:mm" : ""}`)}</Text>
141
- {value.repeatData && <Winicon src="outline/arrows/loop-2" size={"1.2rem"} />}
142
- </>
143
- }, [value])
144
-
145
- useEffect(() => {
146
- if (inputRef.current) {
147
- if (value && value instanceof Date) inputRef.current.value = dateToString(value, `dd/mm/yyyy`)
148
- else inputRef.current.value = ""
149
- }
150
- }, [value, inputRef.current])
151
-
152
- useEffect(() => {
153
- switch (props.pickerType) {
154
- case "date":
155
- case "datetime":
156
- setValue(props.value)
157
- break;
158
- default:
159
- setValue((!props.value || !props.endValue) ? undefined : { start: props.value, end: props.endValue, repeatData: props.pickerType === "auto" ? props.repeatValue : undefined })
160
- break;
161
- }
162
- }, [props.value, props.endValue, props.repeatValue, props.pickerType])
163
-
164
- const showCalendar = (rect: any) => {
165
- showPopup({
166
- ref: popupRef,
167
- clickOverlayClosePopup: true,
168
- content: <PopupDateTimePicker
169
- ref={popupRef}
170
- max={props.max}
171
- min={props.min}
172
- value={value instanceof Date ? value : value?.start}
173
- endValue={value instanceof Date ? undefined : value?.end}
174
- pickerType={props.pickerType}
175
- enableRepeat={props.enableRepeat}
176
- style={{ top: rect.bottom + 2, left: rect.left + 16 }}
177
- onApply={(ev) => {
178
- setValue(ev)
179
- closePopup(popupRef)
180
- if (props.onChange) props.onChange(ev)
181
- if (inputRef.current) inputRef.current.focus()
182
- }}
183
- />
184
- })
185
- }
186
-
187
- const returnUI = () => {
188
- switch (props.pickerType) {
189
- case "date":
190
- return <div
191
- id={props.id}
192
- className={`row ${styles["date-time-picker"]} ${props.className ?? "body-3"} ${props.helperText?.length ? styles['helper-text'] : ""}`}
193
- helper-text={props.helperText}
194
- style={props.style ? { ...({ '--helper-text-color': props.helperTextColor ?? '#e14337' } as CSSProperties), ...props.style } : ({ '--helper-text-color': props.helperTextColor ?? '#e14337' } as CSSProperties)}
195
- onClick={(ev: any) => {
196
- const rect = ev.target.closest("div").getBoundingClientRect()
197
- showCalendar(rect)
198
- }}>
199
- {props.prefix ?? <Winicon className={styles["prefix-icon"]} src="outline/user interface/calendar-date" size={"1.2rem"} />}
200
- <input
201
- className={styles["value"]}
202
- ref={inputRef}
203
- autoComplete='off'
204
- disabled={props.disabled}
205
- placeholder={props.placeholder}
206
- readOnly={props.pickOnly}
207
- onKeyDown={(ev: any) => {
208
- switch (ev.key.toLowerCase()) {
209
- case "enter":
210
- ev.target.blur()
211
- break;
212
- default:
213
- break;
214
- }
215
- }}
216
- onBlur={props.pickOnly ? undefined : (ev) => {
217
- const inputValue = ev.target.value.trim()
218
- let dateValue: Date | undefined = undefined
219
- if (inputValue.match(/[0-9]{1,2}(\/|-)[0-9]{1,2}(\/|-)[0-9]{4}/g)) {
220
- dateValue = stringToDate(inputValue, 'dd/MM/yyyy', '/')
221
- if (inRangeTime(dateValue, props.min ?? startDate, props.min ?? endDate)) {
222
- } else if (differenceInCalendarDays(props.min ?? startDate, dateValue) > -1) {
223
- dateValue = props.min ?? startDate
224
- } else if (differenceInCalendarDays(dateValue, props.min ?? endDate) > -1) {
225
- dateValue = props.max ?? endDate
226
- } else {
227
- dateValue = undefined
228
- }
229
- }
230
- setValue(dateValue)
231
- if (props.onChange) props.onChange(dateValue)
232
- }}
233
- />
234
- </div>
235
- default:
236
- return <button id={props.id} type="button" disabled={props.disabled} className={`row ${styles["date-time-picker"]} ${props.className ?? "body-3"}`} style={props.style} onClick={(ev: any) => {
237
- const rect = ev.target.closest("button").getBoundingClientRect()
238
- showCalendar(rect)
239
- }}>
240
- {props.prefix ?? <Winicon className={styles["prefix-icon"]} src="outline/user interface/calendar-date" size={"1.2rem"} />}
241
- {txtValue}
242
- </button>
243
- }
244
- }
245
-
246
- return <>
247
- <Popup ref={popupRef} />
248
- {returnUI()}
249
- </>
250
-
251
- }
252
-
253
- interface PopupPickerProps {
254
- value?: Date,
255
- endValue?: Date,
256
- min?: Date,
257
- style?: CSSProperties,
258
- max?: Date,
259
- pickerType?: "auto" | "date" | "datetime" | "daterange" | "datetimerange",
260
- repeatValue?: { type: 1 | 2 | 3, value: Array<"everyday" | "last" | number> },
261
- onApply?: (ev: Date | ValueProps) => void,
262
- enableRepeat?: boolean,
263
- }
264
-
265
- const PopupDateTimePicker = forwardRef(function PopupDateTimePicker({ value, style, endValue, repeatValue, onApply, pickerType = "auto", enableRepeat = false, min, max }: PopupPickerProps, ref: any) {
266
- const methods = useForm({ shouldFocusError: false })
267
- const [selectTime, setSelectTime] = useState(false)
268
- const [isRepeat, setIsRepeat] = useState(false)
269
- const today = new Date()
270
- const [repeatData, setRepeatData] = useState<{ type: 1 | 2 | 3, value: Array<string | number> }>({ type: 1, value: ["everyday"] }) // 1: daily, 2: weekly, 3: monthly
271
- const popupRef = useRef<any>(null)
272
- const inputStartRef = useRef<TextField>(null)
273
- const inputEndRef = useRef<TextField>(null)
274
- const { t } = useTranslation()
275
- const regexDate = /[0-9]{1,2}(\/|-)[0-9]{1,2}(\/|-)[0-9]{4}/g
276
- const regexTime = /^(?:[01]\d|2[0-3]):[0-5]\d(?:[:][0-5]\d)?$/g
277
-
278
- useEffect(() => {
279
- if (repeatValue && enableRepeat) {
280
- setIsRepeat(true)
281
- setRepeatData(repeatValue)
282
- } else setIsRepeat(false)
283
- }, [repeatValue])
284
-
285
- useEffect(() => {
286
- if (selectTime && pickerType !== "auto" && !pickerType.includes("time")) {
287
- setSelectTime(false)
288
- methods.setValue('time-start', null)
289
- methods.setValue('time-end', null)
290
- } else if (!selectTime && pickerType.includes("time")) {
291
- setSelectTime(true)
292
- }
293
- }, [pickerType])
294
-
295
- const initStartValue = () => {
296
- if (value) {
297
- const initStart = new Date(value)
298
- methods.setValue('date-start', initStart)
299
- inputStartRef.current!.getInput()!.value = dateToString(initStart)
300
- if (pickerType.includes("time") || initStart.getSeconds() === 1) {
301
- setSelectTime(true)
302
- methods.setValue('time-start', `${initStart.getHours() < 9 ? `0${initStart.getHours()}` : initStart.getHours()}:${initStart.getMinutes() < 9 ? `0${initStart.getMinutes()}` : initStart.getMinutes()}`)
303
- }
304
- } else inputStartRef.current!.getInput()!.value = ""
305
- }
306
-
307
- const initEndValue = () => {
308
- if ((pickerType?.includes("range") || pickerType === "auto") && inputEndRef.current) {
309
- if (endValue) {
310
- const initEnd = new Date(endValue)
311
- methods.setValue('date-end', initEnd)
312
- inputEndRef.current.getInput()!.value = dateToString(initEnd)
313
- if (pickerType.includes("time") || initEnd.getSeconds() === 59) methods.setValue('time-end', `${initEnd.getHours() < 9 ? `0${initEnd.getHours()}` : initEnd.getHours()}:${initEnd.getMinutes() < 9 ? `0${initEnd.getMinutes()}` : initEnd.getMinutes()}`)
314
- } else inputEndRef.current.getInput()!.value = ""
315
- }
316
- }
317
-
318
- useEffect(() => {
319
- if (value && inputStartRef.current) initStartValue()
320
- }, [value, inputStartRef])
321
-
322
- useEffect(() => {
323
- initEndValue()
324
- }, [endValue, inputEndRef, pickerType])
325
-
326
- return <div className="col" style={{ width: "31.2rem", ...style }}>
327
- <Popup ref={popupRef} />
328
- <Calendar
329
- min={min}
330
- max={max}
331
- range={pickerType.includes("range") || pickerType === "auto"}
332
- value={pickerType === "date" || pickerType === "datetime" ? methods.watch('date-start') : (methods.watch('date-start') && methods.watch('date-end') ? { sTime: methods.watch('date-start'), eTime: methods.watch('date-end') } : undefined)}
333
- header={pickerType !== "date" && <div className='row' style={{ flexWrap: "wrap", gap: "0.8rem 1.2rem", padding: "1.6rem", borderBottom: "var(--neutral-main-border)" }}>
334
- <TextField
335
- ref={inputStartRef}
336
- autoComplete="off"
337
- className='col12 body-3'
338
- style={{ "--gutter": "1.2rem", padding: "0.4rem 1.2rem" } as any}
339
- placeholder={pickerType.includes("range") || pickerType === "auto" ? t("start-date") : "dd/mm/yyyy"}
340
- onComplete={(ev: any) => ev.target.blur()}
341
- onBlur={(ev) => {
342
- const inputValue = ev.target.value
343
- if (regexDate.test(inputValue)) {
344
- const dateValue = stringToDate(inputValue, 'dd/mm/yyyy', '/')
345
- if ((pickerType.includes("range") || pickerType === "auto") && differenceInCalendarDays(methods.getValues('date-end'), dateValue) < 0) {
346
- methods.setValue('date-end', dateValue)
347
- inputEndRef.current!.getInput()!.value = dateToString(dateValue)
348
- }
349
- methods.setValue('date-start', dateValue)
350
- } else ev.target.value = methods.getValues('date-start') ? dateToString(methods.getValues('date-start')) : ""
351
- }}
352
- />
353
- {(pickerType.includes("range") || pickerType === "auto") &&
354
- <TextField
355
- ref={inputEndRef}
356
- autoComplete="off"
357
- className='col12 body-3'
358
- style={{ "--gutter": "1.2rem", padding: "0.4rem 1.2rem" } as any}
359
- placeholder={t("end-date")}
360
- onComplete={(ev: any) => ev.target.blur()}
361
- onBlur={(ev) => {
362
- const inputValue = ev.target.value
363
- if (regexDate.test(inputValue)) {
364
- const dateValue = stringToDate(inputValue, 'dd/mm/yyyy', '/')
365
- if (differenceInCalendarDays(dateValue, methods.getValues('date-start')) < 0) {
366
- methods.setValue('date-start', dateValue)
367
- inputStartRef.current!.getInput()!.value = dateToString(dateValue)
368
- }
369
- methods.setValue('date-end', dateValue)
370
- } else ev.target.value = methods.getValues('date-end') ? dateToString(methods.getValues('date-end')) : ""
371
- }}
372
- />}
373
- {selectTime && <>
374
- <TextField
375
- autoComplete="off"
376
- name='time-start'
377
- style={{ "--gutter": "1.2rem", padding: "0.4rem 1.2rem" } as any}
378
- onComplete={(ev: any) => { ev.target.blur() }}
379
- register={methods.register("time-start", {
380
- onChange: (ev) => ev.target.value = ev.target.value.trim(),
381
- onBlur: (ev) => {
382
- if (regexTime.test(ev.target.value)) {
383
- methods.setValue('time-start', ev.target.value)
384
- } else ev.target.value = ""
385
- }
386
- }) as any}
387
- className='col12 body-3'
388
- placeholder={"hh:mm"}
389
- onFocus={(ev) => {
390
- const rect = ev.target.closest("div")!.getBoundingClientRect()
391
- showPopup({
392
- ref: popupRef,
393
- clickOverlayClosePopup: true,
394
- content: <div className={`col ${styles['popup-actions']}`} style={{ maxHeight: "24rem", top: rect.bottom + 2, right: document.body.offsetWidth - rect.right, width: rect.width, overflow: "hidden auto", border: "var(--neutral-main-border)" }}>
395
- {Array.from({ length: 48 }).map((_, i) => {
396
- if (i % 2 === 0) var timeValue = `${(i / 2) < 9 ? `0${i / 2}` : (i / 2)}:00`
397
- else timeValue = `${((i - 1) / 2) < 9 ? `0${(i - 1) / 2}` : ((i - 1) / 2)}:30`
398
- return <button key={"time-" + i} type="button" className="row" onClick={() => {
399
- methods.setValue("time-start", timeValue)
400
- closePopup(popupRef)
401
- }}>
402
- <Text className="body-3">{timeValue}</Text>
403
- </button>
404
- })}
405
- </div>
406
- })
407
- }}
408
- />
409
- {(pickerType.includes("range") || pickerType === "auto") &&
410
- <TextField
411
- autoComplete="off"
412
- name='time-end'
413
- style={{ "--gutter": "1.2rem", padding: "0.4rem 1.2rem" } as any}
414
- onComplete={(ev: any) => { ev.target.blur() }}
415
- register={methods.register("time-end", {
416
- onChange: (ev) => ev.target.value = ev.target.value.trim(),
417
- onBlur: (ev) => {
418
- if (regexTime.test(ev.target.value)) {
419
- methods.setValue('time-end', ev.target.value)
420
- } else ev.target.value = ""
421
- }
422
- }) as any}
423
- className='col12 body-3'
424
- placeholder={"hh:mm"}
425
- onFocus={(ev) => {
426
- const rect = ev.target.closest("div")!.getBoundingClientRect()
427
- showPopup({
428
- ref: popupRef,
429
- clickOverlayClosePopup: true,
430
- content: <div className={`col ${styles['popup-actions']}`} style={{ maxHeight: "24rem", top: rect.bottom + 2, right: document.body.offsetWidth - rect.right, width: rect.width, overflow: "hidden auto", border: "var(--neutral-main-border)" }}>
431
- {Array.from({ length: 48 }).map((_, i) => {
432
- if (i % 2 === 0) var timeValue = `${(i / 2) < 9 ? `0${i / 2}` : (i / 2)}:00`
433
- else timeValue = `${((i - 1) / 2) < 9 ? `0${(i - 1) / 2}` : ((i - 1) / 2)}:30`
434
- return <button key={"time-" + i} type="button" className="row" onClick={() => {
435
- methods.setValue("time-end", timeValue)
436
- closePopup(popupRef)
437
- }}>
438
- <Text className="body-3">{timeValue}</Text>
439
- </button>
440
- })}
441
- </div>
442
- })
443
- }}
444
- />}
445
- </>}
446
- </div>}
447
- footer={pickerType !== "date" && <>
448
- {isRepeat && <div className='col' style={{ borderTop: "var(--neutral-main-border)" }}>
449
- <div className='row' style={{ gap: 4, padding: "1.2rem 1.6rem" }}>
450
- <Text className='heading-8' style={{ flex: 1 }}>Lặp lại</Text>
451
- <Button
452
- style={{ padding: 0 }}
453
- label={(() => {
454
- switch (repeatData.type) {
455
- case 1:
456
- return t("daily")
457
- case 2:
458
- return t("weekly")
459
- case 3:
460
- return t("monthly")
461
- default:
462
- return ""
463
- }
464
- })()}
465
- suffix={<Winicon src='outline/arrows/down-arrow' size={"1.4rem"} style={{ padding: "0.2rem" }} />}
466
- onClick={(ev: any) => {
467
- const rect = ev.target.closest("button").getBoundingClientRect()
468
- showPopup({
469
- ref: popupRef,
470
- clickOverlayClosePopup: true,
471
- style: { position: "absolute", top: rect.bottom + 2, left: rect.x + 8 },
472
- body: <div className="col popup-actions">
473
- {Array.from({ length: 3 }).map((_, num) => {
474
- let label = ""
475
- switch (num) {
476
- case 0:
477
- label = t("daily")
478
- break;
479
- case 1:
480
- label = t("weekly")
481
- break;
482
- case 2:
483
- label = t("monthly")
484
- break;
485
- default:
486
- break;
487
- }
488
- return <button key={"tStatus-" + num} type="button" className="row" onClick={() => {
489
- let newValue: any = ["everyday"]
490
- switch (num) {
491
- case 0:
492
- newValue = ["everyday"]
493
- break;
494
- case 1:
495
- newValue = today.getDay()
496
- break;
497
- case 2:
498
- newValue = today.getDate()
499
- break;
500
- default:
501
- break;
502
- }
503
- setRepeatData({ type: (num + 1) as any, value: [newValue] })
504
- closePopup(popupRef)
505
- }}>
506
- <Text className="button-text-3">{label}</Text>
507
- </button>
508
- })}
509
- </div>
510
- })
511
- }}
512
- />
513
- </div>
514
- {(() => {
515
- switch (repeatData.type) {
516
- case 2:
517
- return <>
518
- <Text className='heading-8' style={{ padding: "0 1.6rem" }}>{t("on") + " " + t("date").toLowerCase()}</Text>
519
- <div className='row' style={{ justifyContent: "space-between", padding: "0.4rem 1.6rem" }}>
520
- {Array.from({ length: 7 }).map((_, i) => {
521
- switch (i) {
522
- case 0:
523
- var weekdayTitle = t("su")
524
- break
525
- case 1:
526
- weekdayTitle = t("mo")
527
- break
528
- case 2:
529
- weekdayTitle = t("tu")
530
- break
531
- case 3:
532
- weekdayTitle = t("we")
533
- break
534
- case 4:
535
- weekdayTitle = t("th")
536
- break
537
- case 5:
538
- weekdayTitle = t("fr")
539
- break
540
- case 6:
541
- weekdayTitle = t("sa")
542
- break
543
- default:
544
- weekdayTitle = ''
545
- break
546
- }
547
- return <div key={"weekday-" + i} className='col' style={{ gap: 4, alignItems: "center" }}>
548
- <Checkbox size={"1.8rem"} value={repeatData.value.includes(i)} disabled={repeatData.value.includes(i) && repeatData.value.length === 1} onChange={(v) => {
549
- if (v) setRepeatData({ type: 2, value: [...repeatData.value, i] })
550
- else setRepeatData({ type: 2, value: repeatData.value.filter(id => id !== i) })
551
- }} />
552
- <Text className='placeholder-2'>{weekdayTitle}</Text>
553
- </div>
554
- })}
555
- </div>
556
- </>
557
- case 3:
558
- return <div className='row' style={{ justifyContent: "space-between", padding: "0.4rem 1.6rem", gap: "1.2rem" }}>
559
- <Text className='heading-8' style={{ flex: 1 }}>{t("on") + " " + t("date").toLowerCase()}</Text>
560
- <Button
561
- style={{ padding: 0 }}
562
- label={repeatData.value[0] === "last" ? t("Last") : `${repeatData.value[0]}`}
563
- suffix={<Winicon src='outline/arrows/down-arrow' size={"1.4rem"} style={{ padding: "0.2rem" }} />}
564
- onClick={(ev: any) => {
565
- const rect = ev.target.closest("button").getBoundingClientRect()
566
- showPopup({
567
- ref: popupRef,
568
- clickOverlayClosePopup: true,
569
- style: { top: rect.bottom + 2, right: document.body.offsetWidth - rect.right, maxHeight: "30.4rem" },
570
- body: <div className="col popup-actions" style={{ flex: 1, overflow: "hidden auto" }}>
571
- {Array.from({ length: 29 }).map((_, num) => {
572
- switch (num) {
573
- case 28:
574
- var label = t("Last")
575
- break;
576
- default:
577
- label = `${num + 1}`
578
- break;
579
- }
580
- return <button key={"date-" + num} type="button" className="row" onClick={() => {
581
- setRepeatData({ type: 3, value: [num === 28 ? "last" : (num + 1)] })
582
- closePopup(popupRef)
583
- }}>
584
- <Text className="button-text-3">{label}</Text>
585
- </button>
586
- })}
587
- </div>
588
- })
589
- }}
590
- />
591
- </div>
592
- default:
593
- return null
594
- }
595
- })()}
596
- </div>}
597
- {onApply && <div className='row' style={{ gap: "0.8rem", padding: "1.2rem 1.6rem", borderTop: "var(--neutral-main-border)" }}>
598
- {pickerType === "auto" && <div className='row' style={{ gap: 4 }}>
599
- <Winicon
600
- src='outline/user interface/time-alarm'
601
- size={"1.6rem"}
602
- style={{ padding: "0.7rem", borderRadius: "50%", backgroundColor: selectTime ? "var(--neutral-disable-background-color)" : undefined }}
603
- onClick={() => { setSelectTime(!selectTime) }}
604
- />
605
- {(enableRepeat || pickerType === "auto") && <Winicon
606
- src='outline/arrows/loop-2'
607
- size={"1.6rem"}
608
- style={{ padding: "0.7rem", borderRadius: "50%", backgroundColor: isRepeat ? "var(--neutral-disable-background-color)" : undefined }}
609
- onClick={() => { setIsRepeat(!isRepeat) }}
610
- />}
611
- </div>}
612
- <div style={{ flex: 1 }} />
613
- <Button
614
- label={t("reset")}
615
- onClick={() => {
616
- methods.setValue("date-start", null)
617
- methods.setValue("date-end", null)
618
- methods.setValue("time-start", null)
619
- methods.setValue("time-end", null)
620
- initStartValue()
621
- initEndValue()
622
- }}
623
- />
624
- <Button
625
- label={t("apply")}
626
- disabled={!methods.watch("date-start") || (!methods.watch("date-end") && (pickerType.includes("range") || pickerType === "auto"))}
627
- className={`button-text-3 button-primary`}
628
- onClick={() => {
629
- let dateStartValue = methods.getValues("date-start")
630
- let timeStartValue = selectTime ? (methods.getValues("time-start")?.length ? methods.getValues("time-start") : "00:00") : "00:00"
631
- dateStartValue.setHours(parseInt(timeStartValue.split(':')[0]), parseInt(timeStartValue.split(':')[1]), selectTime ? 1 : 0, 0)
632
- if (pickerType.includes("range") || pickerType === "auto") {
633
- var dateEndValue = methods.getValues("date-end")
634
- let timeEndValue = selectTime ? (methods.getValues("time-end")?.length ? methods.getValues("time-end") : "23:59") : "23:59"
635
- dateEndValue.setHours(parseInt(timeEndValue.split(':')[0]), parseInt(timeEndValue.split(':')[1]), selectTime ? 59 : 0, 0)
636
- }
637
- onApply(!pickerType.includes("range") && pickerType !== "auto" ? dateStartValue : { start: dateStartValue, end: dateEndValue, repeatData: isRepeat ? repeatData : undefined })
638
- closePopup(ref)
639
- }}
640
- />
641
- </div>}
642
- </>}
643
- onSelect={(ev: any) => {
644
- if (pickerType !== "date") {
645
- if (ev instanceof Date) {
646
- methods.setValue('date-start', ev)
647
- if (inputStartRef.current) inputStartRef.current.getInput()!.value = dateToString(ev)
648
- } else {
649
- methods.setValue('date-start', ev.sTime)
650
- if (inputStartRef.current) inputStartRef.current.getInput()!.value = dateToString(ev.sTime)
651
- if (pickerType.includes("range") || pickerType === "auto") {
652
- methods.setValue('date-end', ev.eTime)
653
- if (inputEndRef.current) inputEndRef.current.getInput()!.value = dateToString(ev.eTime)
654
- }
655
- }
656
- } else if (onApply) {
657
- onApply(ev)
658
- closePopup(ref)
659
- }
660
- }}
661
- />
662
- </div>
663
- })