evui 3.4.207 → 3.4.209

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 (162) hide show
  1. package/README.md +18 -33
  2. package/dist/404.html +44 -0
  3. package/dist/favicon.ico +0 -0
  4. package/dist/index.js +22738 -0
  5. package/dist/index.umd.cjs +28 -0
  6. package/dist/style.css +1 -0
  7. package/package.json +46 -43
  8. package/dist/evui.common.js +0 -63681
  9. package/dist/evui.common.js.map +0 -1
  10. package/dist/evui.umd.js +0 -63691
  11. package/dist/evui.umd.js.map +0 -1
  12. package/dist/evui.umd.min.js +0 -2
  13. package/dist/evui.umd.min.js.map +0 -1
  14. package/dist/img/EVUI.b82ee81a.svg +0 -293
  15. package/src/assets/logo.png +0 -0
  16. package/src/common/emitter.js +0 -20
  17. package/src/common/utils.bignumber.js +0 -67
  18. package/src/common/utils.debounce.js +0 -223
  19. package/src/common/utils.js +0 -151
  20. package/src/common/utils.table.js +0 -78
  21. package/src/common/utils.throttle.js +0 -83
  22. package/src/common/utils.tree.js +0 -18
  23. package/src/components/button/Button.vue +0 -195
  24. package/src/components/button/index.js +0 -7
  25. package/src/components/buttonGroup/ButtonGroup.vue +0 -11
  26. package/src/components/buttonGroup/index.js +0 -7
  27. package/src/components/calendar/Calendar.vue +0 -725
  28. package/src/components/calendar/index.js +0 -7
  29. package/src/components/calendar/uses.js +0 -1410
  30. package/src/components/chart/Chart.vue +0 -363
  31. package/src/components/chart/ChartToolbar.vue +0 -52
  32. package/src/components/chart/chart.core.js +0 -1170
  33. package/src/components/chart/chartZoom.core.js +0 -540
  34. package/src/components/chart/element/element.bar.js +0 -672
  35. package/src/components/chart/element/element.bar.time.js +0 -166
  36. package/src/components/chart/element/element.heatmap.js +0 -743
  37. package/src/components/chart/element/element.line.js +0 -611
  38. package/src/components/chart/element/element.pie.js +0 -197
  39. package/src/components/chart/element/element.scatter.js +0 -320
  40. package/src/components/chart/element/element.tip.js +0 -717
  41. package/src/components/chart/helpers/helpers.canvas.js +0 -265
  42. package/src/components/chart/helpers/helpers.constant.js +0 -235
  43. package/src/components/chart/helpers/helpers.util.js +0 -400
  44. package/src/components/chart/index.js +0 -9
  45. package/src/components/chart/model/index.js +0 -50
  46. package/src/components/chart/model/model.series.js +0 -125
  47. package/src/components/chart/model/model.store.js +0 -1427
  48. package/src/components/chart/plugins/plugins.interaction.js +0 -1659
  49. package/src/components/chart/plugins/plugins.legend.gradient.js +0 -606
  50. package/src/components/chart/plugins/plugins.legend.js +0 -1543
  51. package/src/components/chart/plugins/plugins.pie.js +0 -254
  52. package/src/components/chart/plugins/plugins.scrollbar.js +0 -732
  53. package/src/components/chart/plugins/plugins.title.js +0 -61
  54. package/src/components/chart/plugins/plugins.tooltip.js +0 -1041
  55. package/src/components/chart/scale/scale.js +0 -951
  56. package/src/components/chart/scale/scale.linear.js +0 -268
  57. package/src/components/chart/scale/scale.logarithmic.js +0 -135
  58. package/src/components/chart/scale/scale.step.js +0 -430
  59. package/src/components/chart/scale/scale.time.category.js +0 -338
  60. package/src/components/chart/scale/scale.time.js +0 -49
  61. package/src/components/chart/style/chart.scss +0 -405
  62. package/src/components/chart/uses.js +0 -721
  63. package/src/components/chartBrush/ChartBrush.vue +0 -323
  64. package/src/components/chartBrush/chartBrush.core.js +0 -691
  65. package/src/components/chartBrush/index.js +0 -9
  66. package/src/components/chartBrush/uses.js +0 -23
  67. package/src/components/chartGroup/ChartGroup.vue +0 -144
  68. package/src/components/chartGroup/index.js +0 -9
  69. package/src/components/chartGroup/style/chartGroup.scss +0 -5
  70. package/src/components/chartGroup/uses.js +0 -53
  71. package/src/components/checkbox/Checkbox.vue +0 -229
  72. package/src/components/checkbox/index.js +0 -7
  73. package/src/components/checkboxGroup/CheckboxGroup.vue +0 -44
  74. package/src/components/checkboxGroup/index.js +0 -7
  75. package/src/components/contextMenu/ContextMenu.vue +0 -95
  76. package/src/components/contextMenu/MenuList.vue +0 -182
  77. package/src/components/contextMenu/index.js +0 -7
  78. package/src/components/contextMenu/uses.js +0 -223
  79. package/src/components/datePicker/DatePicker.vue +0 -504
  80. package/src/components/datePicker/index.js +0 -7
  81. package/src/components/datePicker/uses.js +0 -460
  82. package/src/components/grid/Grid.vue +0 -1535
  83. package/src/components/grid/GridColumnSetting.vue +0 -358
  84. package/src/components/grid/GridFilterSetting.vue +0 -323
  85. package/src/components/grid/GridPagination.vue +0 -75
  86. package/src/components/grid/GridSummary.vue +0 -314
  87. package/src/components/grid/GridToolbar.vue +0 -35
  88. package/src/components/grid/icon/icon-option-button.vue +0 -17
  89. package/src/components/grid/icon/icon-sort-button.vue +0 -67
  90. package/src/components/grid/index.js +0 -11
  91. package/src/components/grid/style/grid.scss +0 -417
  92. package/src/components/grid/uses.js +0 -1629
  93. package/src/components/icon/Icon.vue +0 -53
  94. package/src/components/icon/index.js +0 -8
  95. package/src/components/inputNumber/InputNumber.vue +0 -212
  96. package/src/components/inputNumber/index.js +0 -7
  97. package/src/components/inputNumber/uses.js +0 -217
  98. package/src/components/loading/Loading.vue +0 -125
  99. package/src/components/loading/index.js +0 -7
  100. package/src/components/menu/Menu.vue +0 -79
  101. package/src/components/menu/MenuItem.vue +0 -201
  102. package/src/components/menu/index.js +0 -7
  103. package/src/components/message/Message.vue +0 -229
  104. package/src/components/message/index.js +0 -34
  105. package/src/components/messageBox/MessageBox.vue +0 -358
  106. package/src/components/messageBox/index.js +0 -22
  107. package/src/components/notification/Notification.vue +0 -316
  108. package/src/components/notification/index.js +0 -49
  109. package/src/components/pagination/Pagination.vue +0 -317
  110. package/src/components/pagination/index.js +0 -7
  111. package/src/components/pagination/pageButton.vue +0 -31
  112. package/src/components/progress/Progress.vue +0 -139
  113. package/src/components/progress/index.js +0 -7
  114. package/src/components/radio/Radio.vue +0 -159
  115. package/src/components/radio/index.js +0 -7
  116. package/src/components/radioGroup/RadioGroup.vue +0 -41
  117. package/src/components/radioGroup/index.js +0 -7
  118. package/src/components/scheduler/Scheduler.vue +0 -149
  119. package/src/components/scheduler/index.js +0 -7
  120. package/src/components/scheduler/uses.js +0 -183
  121. package/src/components/select/Select.vue +0 -556
  122. package/src/components/select/index.js +0 -7
  123. package/src/components/select/uses.js +0 -379
  124. package/src/components/slider/Slider.vue +0 -505
  125. package/src/components/slider/index.js +0 -7
  126. package/src/components/slider/uses.js +0 -391
  127. package/src/components/tabPanel/TabPanel.vue +0 -74
  128. package/src/components/tabPanel/index.js +0 -7
  129. package/src/components/tabs/Tabs.vue +0 -517
  130. package/src/components/tabs/index.js +0 -7
  131. package/src/components/textField/TextField.vue +0 -399
  132. package/src/components/textField/index.js +0 -7
  133. package/src/components/timePicker/TimePicker.vue +0 -364
  134. package/src/components/timePicker/index.js +0 -7
  135. package/src/components/toggle/Toggle.vue +0 -115
  136. package/src/components/toggle/index.js +0 -7
  137. package/src/components/tree/Tree.vue +0 -338
  138. package/src/components/tree/TreeNode.vue +0 -293
  139. package/src/components/tree/index.js +0 -7
  140. package/src/components/treeGrid/TreeGrid.vue +0 -1074
  141. package/src/components/treeGrid/TreeGridNode.vue +0 -349
  142. package/src/components/treeGrid/TreeGridToolbar.vue +0 -35
  143. package/src/components/treeGrid/icon/icon-tree.png +0 -0
  144. package/src/components/treeGrid/index.js +0 -9
  145. package/src/components/treeGrid/style/treeGrid.scss +0 -277
  146. package/src/components/treeGrid/uses.js +0 -1178
  147. package/src/components/window/Window.vue +0 -329
  148. package/src/components/window/index.js +0 -7
  149. package/src/components/window/uses.js +0 -908
  150. package/src/directives/clickoutside.js +0 -90
  151. package/src/main.js +0 -120
  152. package/src/style/components/input.scss +0 -108
  153. package/src/style/functions.scss +0 -3
  154. package/src/style/index.scss +0 -6
  155. package/src/style/lib/fonts/EVUI.eot +0 -0
  156. package/src/style/lib/fonts/EVUI.svg +0 -293
  157. package/src/style/lib/fonts/EVUI.ttf +0 -0
  158. package/src/style/lib/fonts/EVUI.woff +0 -0
  159. package/src/style/lib/icon.css +0 -888
  160. package/src/style/mixins.scss +0 -94
  161. package/src/style/themes.scss +0 -69
  162. package/src/style/variables.scss +0 -22
@@ -1,1410 +0,0 @@
1
- import {
2
- ref, reactive, computed, getCurrentInstance, unref, onBeforeMount, watch,
3
- } from 'vue';
4
- import { throttle } from 'lodash-es';
5
-
6
- const CALENDAR_ROWS = 6;
7
- const CALENDAR_COLS = 7;
8
- const CALENDAR_MONTH_ROWS = 4;
9
- const CALENDAR_MONTH_COLS = 3;
10
- const CALENDAR_YEAR_ROWS = 5;
11
- const CALENDAR_YEAR_COLS = 4;
12
- const MONTH_CNT = 12;
13
- const HOUR_CNT = 24;
14
- const MIN_CNT = 60;
15
- const SEC_CNT = 60;
16
- const CELL_CNT_IN_ONE_PAGE = 12;
17
- const CELL_CNT_IN_ONE_ROW = 4;
18
- const YEAR_CNT_IN_ONE_PAGE = 20;
19
- const MONTH_NAME_LIST = {
20
- fullName: ['January', 'February', 'March', 'April', 'May', 'June',
21
- 'July', 'August', 'September', 'October', 'November', 'December'],
22
- numberName: ['1', '2', '3', '4', '5', '6',
23
- '7', '8', '9', '10', '11', '12'],
24
- abbrName: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
25
- 'Jul', 'Aug', 'Sept', 'Oct', 'Nov', 'Dec'],
26
- korName: ['1월', '2월', '3월', '4월', '5월', '6월',
27
- '7월', '8월', '9월', '10월', '11월', '12월'],
28
- };
29
- const DAY_OF_THE_WEEK_NAME_LIST = {
30
- abbrUpperName: ['SUN', 'MON', 'TUE', 'WED', 'THU', 'FRI', 'SAT'],
31
- abbrLowerName: ['sun', 'mon', 'tue', 'wed', 'thu', 'fri', 'sat'],
32
- abbrPascalName: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
33
- abbrKorName: ['일', '월', '화', '수', '목', '금', '토'],
34
- };
35
-
36
- const LIST_TYPE = {
37
- DATE: 'date',
38
- MONTH: 'month',
39
- YEAR: 'year',
40
- };
41
-
42
- const ONE_DAY_MS = 86400000;
43
- const MIN_DATE_MS = +new Date('1970-01-01 00:00:00'); // javascript 객체 최소 시간
44
- const dateReg = new RegExp(/[0-9]{4}-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])/);
45
- const dateTimeReg = new RegExp(/[0-9]{4}-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1]) (2[0-3]|[01][0-9]):[0-5][0-9]:[0-5][0-9]/);
46
-
47
- /**
48
- * 배열 내 여러 날짜(eg. 'YYYY-MM-DD' || 'YYYY-MM-DD HH:MI:SS') 중 가장 끝의 날짜 텍스트 구하기
49
- * @param arr
50
- * @param sideDirection - 끝의 방향 (first: 가장 멀리 오래된 날짜, last: 가장 최근의 날짜)
51
- * @returns {String} - 날짜 텍스트
52
- */
53
- const getSideDateStr = (arr, sideDirection) => {
54
- if (!arr.length) return '';
55
- if (sideDirection === 'last') {
56
- return arr
57
- .reduce((prev, cur) => (new Date(prev).getTime() > new Date(cur).getTime() ? prev : cur));
58
- }
59
- return arr
60
- .reduce((prev, cur) => (new Date(prev).getTime() < new Date(cur).getTime() ? prev : cur));
61
- };
62
-
63
- /**
64
- * 월, 일을 두자리 숫자로 보정
65
- * @param num
66
- * @returns {string|*}
67
- */
68
- export const lpadToTwoDigits = (num) => {
69
- if (num === null) {
70
- return '00';
71
- } else if (+num < 10) {
72
- return `0${num}`;
73
- }
74
- return num;
75
- };
76
-
77
- /**
78
- * 이차원 배열 만들기
79
- * @param row
80
- * @param col
81
- * @returns {Array} - [row][col]
82
- */
83
- const getMatrixArr = (row, col) => Array.from(Array(row), () => Array(col).fill(false));
84
-
85
- /**
86
- * y년 m월 1일의 요일 구하기
87
- * @param y - 년
88
- * @param m - 월
89
- * @returns {number} - 해당 y년 m월 1일의 요일 (e.g. 0: SUN, ..., 6: SAT)
90
- * - 1주차에서 일요일부터 1일까지의 공백 개수
91
- */
92
- const getDayOfWeekOnThe1stOfMonth = (y, m) => new Date(`${y}-${m}-1`).getDay();
93
-
94
- /**
95
- * y년 m월 마지막 일자 구하기
96
- * @param y
97
- * @param m
98
- * @returns {number} - 해당 년, 월의 마지막 일자
99
- */
100
- export const getLastDateOfMonth = (y, m) => {
101
- let day;
102
- switch (m) {
103
- case 4:
104
- case 6:
105
- case 9:
106
- case 11:
107
- day = 30;
108
- break;
109
- case 2:
110
- if (((y % 4 === 0) && (y % 100 !== 0)) || (y % 400 === 0)) {
111
- day = 29;
112
- } else {
113
- day = 28;
114
- }
115
- break;
116
- default:
117
- day = 31;
118
- break;
119
- }
120
- return day;
121
- };
122
-
123
- /**
124
- * date또는 time 형태로 format string으로 조합
125
- * @param year
126
- * @param month
127
- * @param date
128
- * @param hour
129
- * @param min
130
- * @param sec
131
- * @returns {string}
132
- */
133
- const formatDateTime = ({ year, month, date, hour, min, sec }) => {
134
- if (hour !== undefined && min !== undefined && sec !== undefined) {
135
- return `${year}-${lpadToTwoDigits(month)}-${lpadToTwoDigits(date)} ${lpadToTwoDigits(hour)}:${lpadToTwoDigits(min)}:${lpadToTwoDigits(sec)}`;
136
- }
137
- return `${year}-${lpadToTwoDigits(month)}-${lpadToTwoDigits(date)}`;
138
- };
139
-
140
- /**
141
- * 첫번째 인자로 받은 날짜 형식 String ('YYYY-MM-DD' || 'YYYY-MM-DD HH:MI:SS')이나
142
- * 해당 날짜형식이 들어있는 Array를 받아서 최신날짜의 정보를 추출하는 함수
143
- * typeToImport가 존재하는 경우 해당 timeType의 값을
144
- * typeToImport가 존재하지 않는 경우 최신날짜 텍스트를 timeType별로 분할한 Object를 리턴
145
- * @param param {String | Array} - 변경하려는 날짜
146
- * @param typeToImport
147
- * @returns {object|number}
148
- */
149
- const getDateTimeInfoByType = (param, typeToImport) => {
150
- let str = unref(param);
151
- if (Array.isArray(str)) {
152
- str = getSideDateStr(param, 'last');
153
- }
154
- const result = {
155
- year: +(str?.split(' ')[0]?.split('-')[0]) || null,
156
- month: +(str?.split(' ')[0]?.split('-')[1]) || null,
157
- date: +(str?.split(' ')[0]?.split('-')[2]) || null,
158
- hour: +(str?.split(' ')[1]?.split(':')[0]) || 0,
159
- min: +(str?.split(' ')[1]?.split(':')[1]) || 0,
160
- sec: +(str?.split(' ')[1]?.split(':')[2]) || 0,
161
- };
162
- if (typeToImport === 'year') return result.year;
163
- if (typeToImport === 'month') return result.month;
164
- if (typeToImport === 'date') return result.date;
165
- if (typeToImport === 'hour') return result.hour;
166
- if (typeToImport === 'min') return result.min;
167
- if (typeToImport === 'sec') return result.sec;
168
- return result;
169
- };
170
- /**
171
- * 이전달, 다음달의 달력 상 연도, 월 정보 구하기
172
- * @param prevNext - 이전, 다음 여부 ('prev'|'next')
173
- * @param year
174
- * @param month
175
- * @returns {{month: number, year: *}}
176
- */
177
- const getSideMonthCalendarInfo = (prevNext, year, month) => {
178
- if (prevNext === 'next') {
179
- return {
180
- year: month === 12 ? year + 1 : year,
181
- month: ((month + 1) % 12) || 12,
182
- };
183
- }
184
- return {
185
- year: month === 1 ? year - 1 : year,
186
- month: ((month - 1) % 12) || 12,
187
- };
188
- };
189
-
190
- /**
191
- * timeFormat을 체크하여 timeFormat이 있으면 format에 맞는 형식으로 반환
192
- * @param timeFormat -- props.option?.timeFormat
193
- * @param dateTimeValue
194
- * @param typeToImport
195
- * @returns {Object|number}
196
- */
197
- const getTimeInfoByTimeFormat = (timeFormat, dateTimeValue, typeToImport) => {
198
- const value = getDateTimeInfoByType(dateTimeValue, typeToImport);
199
- if (timeFormat) {
200
- const hour = timeFormat?.split(':')[0];
201
- const min = timeFormat?.split(':')[1];
202
- const sec = timeFormat?.split(':')[2];
203
- if (typeToImport === 'hour') {
204
- return hour === 'HH' ? value : +hour;
205
- } else if (typeToImport === 'min') {
206
- return min === 'mm' ? value : +min;
207
- } else if (typeToImport === 'sec') {
208
- return sec === 'ss' ? value : +sec;
209
- }
210
- }
211
- return value;
212
- };
213
-
214
- /**
215
- * 초기 timeFormat에 따른 modelValue update 함수
216
- * @param timeFormat - props.options.timeFormat
217
- * @param modelValue
218
- * @returns string
219
- */
220
- export const getChangedValueByTimeFormat = (timeFormat, modelValue) => {
221
- if (!modelValue) {
222
- return '';
223
- }
224
-
225
- const hourByTimeFormat = lpadToTwoDigits(getTimeInfoByTimeFormat(timeFormat, modelValue, 'hour'));
226
- const minByTimeFormat = lpadToTwoDigits(getTimeInfoByTimeFormat(timeFormat, modelValue, 'min'));
227
- const secByTimeFormat = lpadToTwoDigits(getTimeInfoByTimeFormat(timeFormat, modelValue, 'sec'));
228
-
229
- return `${modelValue.split(' ')[0]} ${hourByTimeFormat}:${minByTimeFormat}:${secByTimeFormat}`;
230
- };
231
-
232
- /**
233
- * 현재 달력의 날짜와 다음 달력의 날짜 비교 (disabledDate 옵션이 없는 경우만 적용)
234
- * @param mode - calendar mode
235
- * @param calendarType - 달력 종류 {main | expanded}
236
- * @param targetDate - 기준 날짜
237
- * @param modelValue - model value
238
- * @returns {*|boolean}
239
- */
240
- const compareFromAndToDateTime = (mode, calendarType, targetDate, modelValue) => {
241
- if (!modelValue.length) {
242
- return false;
243
- }
244
- let fromDate = calendarType === 'main' ? targetDate : modelValue[0];
245
- let toDate = calendarType === 'expanded' ? targetDate : modelValue[1];
246
-
247
- let fromDateTime = fromDate;
248
- let toDateTime = toDate;
249
- if (!targetDate.split(' ')[1]) {
250
- if (mode === 'dateTimeRange') {
251
- fromDate = fromDate.split(' ')[0];
252
- toDate = toDate.split(' ')[0];
253
- const fromTime = modelValue[0].split(' ')[1];
254
- const toTime = modelValue[1].split(' ')[1];
255
- fromDateTime = `${fromDate} ${fromTime}`;
256
- toDateTime = `${toDate} ${toTime}`;
257
- } else {
258
- fromDateTime = `${fromDate} 00:00:00`;
259
- toDateTime = `${toDate} 23:59:59`;
260
- }
261
- }
262
-
263
- return (fromDateTime && toDateTime)
264
- && new Date(fromDateTime).getTime() > +new Date(toDateTime).getTime();
265
- };
266
-
267
- /**
268
- * date string 값의 MS 값 구하기
269
- * @param dateStr
270
- * @returns {number}
271
- */
272
- const getDateMs = dateStr => new Date(`${dateStr}`).getTime();
273
-
274
- /**
275
- * Calendar 년도 범위 구하기
276
- * @param currentYear - 현재 Calendar 페이지 정보의 년도
277
- * @returns {{start: number, end: number}} - start: 시작년도, end: 마지막 년도
278
- */
279
- const getYearRange = (currentYear) => {
280
- const multipleOf10 = 10 ** (currentYear.toString().length - 1);
281
- const quotient = Math.floor(currentYear / multipleOf10);
282
- const remainder = Math.floor(currentYear % (multipleOf10 * quotient));
283
- const startYear = (quotient * multipleOf10)
284
- + (Math.floor(remainder / YEAR_CNT_IN_ONE_PAGE) * YEAR_CNT_IN_ONE_PAGE);
285
- const endYear = startYear + YEAR_CNT_IN_ONE_PAGE - 1;
286
- return {
287
- start: startYear,
288
- end: endYear,
289
- };
290
- };
291
-
292
- export const useModel = () => {
293
- const { props } = getCurrentInstance();
294
- const timeFormat = props.options?.timeFormat;
295
-
296
- // 달력 list - 'dateRange | dateTimeRange' 모드인 경우 확장 달력 추가
297
- const calendarList = computed(() =>
298
- (['dateRange', 'dateTimeRange'].includes(props.mode) ? ['main', 'expanded'] : ['main']),
299
- );
300
-
301
- /**
302
- * 현재 선택된 값, 배열인 경우 반응형을 끊기위해 rest 사용
303
- * selectValue ref로 변환하기 전 modelValue timeFormat에 따라 fetch
304
- * 1) props.mode: 'date' or 'dateTime' > String
305
- * 2) props.mode: 'dateMulti' or 'dateRange' > [...Array]
306
- */
307
- let selectedValue;
308
- if (props.mode !== 'dateMulti' && props.mode !== 'dateRange' && props.mode !== 'dateTimeRange') {
309
- if (props.modelValue
310
- && ((props.modelValue.length === 10 && dateReg.exec(props.modelValue?.toString()))
311
- || (props.modelValue.length === 19 && dateTimeReg.exec(props.modelValue?.toString())))
312
- ) {
313
- if (props.mode === 'dateTime' && timeFormat) {
314
- const modelValue = getChangedValueByTimeFormat(timeFormat, props.modelValue);
315
- selectedValue = ref(modelValue);
316
- } else {
317
- selectedValue = ref(props.modelValue);
318
- }
319
- } else {
320
- selectedValue = ref('');
321
- }
322
- } else if (Array.isArray(props.modelValue)
323
- && props.modelValue.every(v => (
324
- !v
325
- || (v.length === 10 && dateReg.exec(v))
326
- || (v.length === 19 && dateTimeReg.exec(v))
327
- ))
328
- ) {
329
- if (props.mode === 'dateTimeRange' && props.modelValue.length === 2 && timeFormat) {
330
- const modelValue = [];
331
- modelValue.push(getChangedValueByTimeFormat(timeFormat[0], props.modelValue[0]));
332
- modelValue.push(getChangedValueByTimeFormat(timeFormat[1], props.modelValue[1]));
333
- selectedValue = ref([...modelValue]);
334
- } else {
335
- selectedValue = ref([...props.modelValue]);
336
- }
337
- } else {
338
- selectedValue = ref([]);
339
- }
340
-
341
- /**
342
- * validate v-model's value
343
- */
344
- const validateModelValue = () => {
345
- if (props.mode === 'date' && props.modelValue && typeof props.modelValue !== 'string') {
346
- console.warn('[EVUI][Calendar] When mode is \'date\', v-model must be \'String\' type.');
347
- } else if (props.mode === 'dateTime' && props.modelValue && typeof props.modelValue !== 'string') {
348
- console.warn('[EVUI][Calendar] When mode is \'dateTime\', v-model must be \'String\' type.');
349
- } else if (props.mode === 'dateMulti' && props.modelValue && !Array.isArray(props.modelValue)) {
350
- console.warn('[EVUI][Calendar] When mode is \'dateMulti\', v-model must be \'Array\' type.');
351
- } else if (props.mode === 'dateRange' && props.modelValue) {
352
- if (!Array.isArray(props.modelValue)) {
353
- console.warn('[EVUI][Calendar] When mode is \'dateRange\', v-model must be \'Array\' type.');
354
- } else if (getDateMs(`${props.modelValue[0]} 00:00:00`) > getDateMs(`${props.modelValue[1]} 00:00:00`)) {
355
- console.warn('[EVUI][Calendar] When mode is \'dateRange\', fromDate must be less than toDate.');
356
- }
357
- } else if (props.mode === 'dateTimeRange' && props.modelValue) {
358
- if (!Array.isArray(props.modelValue)) {
359
- console.warn('[EVUI][Calendar] When mode is \'dateTimeRange\', v-model must be \'Array\' type.');
360
- } else if (getDateMs(props.modelValue[0]) > getDateMs(props.modelValue[1])) {
361
- console.warn('[EVUI][Calendar] When mode is \'dateRange\', fromDate must be less than toDate.');
362
- }
363
- }
364
- };
365
-
366
- // 메인(좌측) 달력(연, 월, 시, 분, 초) 페이징 정보
367
- let mainCalendarPageInfo;
368
- const mainValue = !['dateRange', 'dateTimeRange'].includes(props.mode) ? selectedValue.value : selectedValue.value[0];
369
- if (mainValue?.length) {
370
- mainCalendarPageInfo = {
371
- year: getDateTimeInfoByType(mainValue, 'year'),
372
- month: getDateTimeInfoByType(mainValue, 'month'),
373
- hour: Math.floor(getDateTimeInfoByType(mainValue, 'hour') / CELL_CNT_IN_ONE_PAGE) + 1 || 1,
374
- min: Math.floor(getDateTimeInfoByType(mainValue, 'min') / CELL_CNT_IN_ONE_PAGE) + 1 || 1,
375
- sec: Math.floor(getDateTimeInfoByType(mainValue, 'sec') / CELL_CNT_IN_ONE_PAGE) + 1 || 1,
376
- };
377
- } else {
378
- mainCalendarPageInfo = {
379
- year: new Date().getFullYear(),
380
- month: new Date().getMonth() + 1,
381
- hour: 1,
382
- min: 1,
383
- sec: 1,
384
- };
385
- }
386
-
387
- // 'mode: dateRange || dateTimeRange', 인 경우 확장된 달력(연, 월) 페이징 정보
388
- let expandedCalendarPageInfo;
389
- if ((['dateRange', 'dateTimeRange'].includes(props.mode))
390
- && Array.isArray(selectedValue.value)
391
- && selectedValue.value[1]
392
- ) {
393
- const expandedValue = selectedValue.value[1];
394
- expandedCalendarPageInfo = {
395
- year: getDateTimeInfoByType(expandedValue, 'year'),
396
- month: getDateTimeInfoByType(expandedValue, 'month'),
397
- };
398
-
399
- if (props.mode === 'dateTimeRange') {
400
- expandedCalendarPageInfo.hour = Math.floor(getDateTimeInfoByType(expandedValue, 'hour') / CELL_CNT_IN_ONE_PAGE) + 1 || 1;
401
- expandedCalendarPageInfo.min = Math.floor(getDateTimeInfoByType(expandedValue, 'min') / CELL_CNT_IN_ONE_PAGE) + 1 || 1;
402
- expandedCalendarPageInfo.sec = Math.floor(getDateTimeInfoByType(expandedValue, 'sec') / CELL_CNT_IN_ONE_PAGE) + 1 || 1;
403
- }
404
- } else {
405
- expandedCalendarPageInfo = {
406
- year: new Date().getFullYear(),
407
- month: new Date().getMonth() + 1,
408
- hour: 1,
409
- min: 1,
410
- sec: 1,
411
- };
412
- }
413
-
414
- // 현재, 다음 달력(연, 월, 시, 분, 초) 페이징 정보
415
- const calendarPageInfo = reactive({
416
- main: mainCalendarPageInfo,
417
- expanded: expandedCalendarPageInfo,
418
- });
419
-
420
- // 현재, 다음 달력 년도 목록 정보
421
- const calendarYearRangeInfo = reactive({
422
- main: computed(() => getYearRange(calendarPageInfo.main.year)),
423
- expanded: computed(() => getYearRange(calendarPageInfo.expanded.year)),
424
- });
425
-
426
- // 현재 달력이 표현되는 월
427
- const mainCalendarMonth = computed(() =>
428
- MONTH_NAME_LIST[props.monthNotation][calendarPageInfo.main.month - 1]);
429
- // 다음페이지 달력이 표현되는 월
430
- const expandedCalendarMonth = computed(() =>
431
- MONTH_NAME_LIST[props.monthNotation][calendarPageInfo.expanded.month - 1]);
432
-
433
- // 현재, 다음 달력에 표현되는 월 정보
434
- const calendarMonth = reactive({
435
- main: mainCalendarMonth,
436
- expanded: expandedCalendarMonth,
437
- });
438
-
439
- // 현재 달력에 표현되는 타입별 요일
440
- const dayOfTheWeekList = computed(() =>
441
- DAY_OF_THE_WEEK_NAME_LIST[props.dayOfTheWeekNotation]);
442
- // mode: dateRange에 두 달력이 연속적인 경우
443
- // const isContinuousMonths = computed(
444
- // () => ['dateRange', 'dateTimeRange'].includes(props.mode)
445
- // && (mainCalendarPageInfo.year === expandedCalendarPageInfo.year
446
- // && mainCalendarPageInfo.month === expandedCalendarPageInfo.month),
447
- // );
448
-
449
- // Calendar 선택 type ('date' | 'month' | 'year')
450
- const selectedListType = reactive({
451
- main: LIST_TYPE.DATE,
452
- expanded: LIST_TYPE.DATE,
453
- });
454
-
455
- onBeforeMount(() => {
456
- validateModelValue();
457
- });
458
-
459
- return {
460
- calendarList,
461
- selectedValue,
462
- calendarPageInfo,
463
- calendarYearRangeInfo,
464
- calendarMonth,
465
- dayOfTheWeekList,
466
- selectedListType,
467
- // isContinuousMonths,
468
- };
469
- };
470
-
471
- export const useCalendarDate = (param) => {
472
- const { props } = getCurrentInstance();
473
- const { selectedValue, calendarPageInfo, calendarYearRangeInfo } = param;
474
-
475
- // 달력 테이블의 년도 정보 (5X4, 2차원 배열)
476
- const calendarYearTableInfo = reactive({
477
- main: getMatrixArr(CALENDAR_YEAR_ROWS, CALENDAR_YEAR_COLS),
478
- expanded: getMatrixArr(CALENDAR_YEAR_ROWS, CALENDAR_YEAR_COLS),
479
- });
480
-
481
- // 달력 테이블의 월 정보 (4X3, 2차원 배열)
482
- const calendarMonthTableInfo = reactive({
483
- main: getMatrixArr(CALENDAR_MONTH_ROWS, CALENDAR_MONTH_COLS),
484
- expanded: getMatrixArr(CALENDAR_MONTH_ROWS, CALENDAR_MONTH_COLS),
485
- });
486
-
487
- // 달력 테이블의 날짜 정보 (6X7, 2차원배열)
488
- const calendarTableInfo = reactive({
489
- main: getMatrixArr(CALENDAR_ROWS, CALENDAR_COLS),
490
- expanded: getMatrixArr(CALENDAR_ROWS, CALENDAR_COLS),
491
- });
492
- // 시간박스 정보
493
- const calendarTimeTableInfo = reactive({
494
- main: {
495
- hour: [],
496
- min: [],
497
- sec: [],
498
- },
499
- expanded: {
500
- hour: [],
501
- min: [],
502
- sec: [],
503
- },
504
- });
505
-
506
- /**
507
- * Calendar 년도 정보 세팅하기
508
- * @param calendarType - 달력 종류 ('main'|'expanded')
509
- */
510
- const setCalendarYear = (calendarType) => {
511
- let yearValue = calendarYearRangeInfo[calendarType].start;
512
- const thisYear = new Date().getFullYear();
513
- const minYear = new Date(MIN_DATE_MS).getFullYear();
514
- for (let i = 0; i < CALENDAR_YEAR_ROWS; i++) {
515
- for (let j = 0; j < CALENDAR_YEAR_COLS; j++) {
516
- calendarYearTableInfo[calendarType][i][j] = {
517
- label: yearValue,
518
- value: yearValue,
519
- today: yearValue === thisYear,
520
- isSelected: yearValue === calendarPageInfo[calendarType].year,
521
- disabled: (yearValue < minYear),
522
- };
523
- yearValue++;
524
- }
525
- }
526
- };
527
-
528
- /**
529
- * Calendar 월 정보 세팅하기
530
- * @param calendarType - 달력 종류 ('main'|'expanded')
531
- */
532
- const setCalendarMonth = (calendarType) => {
533
- let monthValue = 0;
534
- const todayYear = new Date().getFullYear();
535
- const todayMonth = new Date().getMonth() + 1;
536
- const { year: currentYear, month: currentMonth } = calendarPageInfo[calendarType];
537
- for (let i = 0; i < CALENDAR_MONTH_ROWS; i++) {
538
- for (let j = 0; j < CALENDAR_MONTH_COLS; j++) {
539
- calendarMonthTableInfo[calendarType][i][j] = {
540
- label: MONTH_NAME_LIST.abbrName[monthValue++],
541
- value: monthValue,
542
- today: currentYear === todayYear
543
- && monthValue === todayMonth,
544
- isSelected: monthValue === currentMonth,
545
- };
546
- }
547
- }
548
- };
549
-
550
- /**
551
- * Dropdown Calendar 날짜 정보 세팅하기
552
- * @param calendarType - 달력 종류 ('main'|'expanded')
553
- */
554
- const setCalendarDate = (calendarType) => {
555
- const pageInfo = calendarPageInfo[calendarType];
556
- let disabledDate = props.options.disabledDate;
557
- if (disabledDate && Array.isArray(disabledDate)) {
558
- disabledDate = calendarType === 'main' ? disabledDate[0] : disabledDate[1];
559
- }
560
- const isRangeMode = ['dateRange', 'dateTimeRange'].includes(props.mode);
561
-
562
- const TODAY_YMD = formatDateTime({
563
- year: new Date().getFullYear(),
564
- month: new Date().getMonth() + 1,
565
- date: new Date().getDate(),
566
- });
567
- const PREV_MONTH = ((MONTH_CNT + pageInfo.month - 1) % MONTH_CNT) || MONTH_CNT;
568
- const NEXT_MONTH = ((pageInfo.month + 1) % MONTH_CNT) || MONTH_CNT;
569
- const YEAR_OF_PREV_MONTH = (pageInfo.month === 1
570
- ? pageInfo.year - 1 : pageInfo.year);
571
- const YEAR_OF_NEXT_MONTH = pageInfo.month === 12
572
- ? pageInfo.year + 1 : pageInfo.year;
573
- // 이번달 1일의 요일
574
- const dayOfWeekOnThe1stOfThisMonth = getDayOfWeekOnThe1stOfMonth(
575
- pageInfo.year,
576
- pageInfo.month,
577
- );
578
- // 저번달 마지막 날짜
579
- const lastDateOfPrevMonth = getLastDateOfMonth(
580
- pageInfo.month === 1
581
- ? pageInfo.year - 1 : pageInfo.year,
582
- (MONTH_CNT + pageInfo.month - 1) % MONTH_CNT || MONTH_CNT,
583
- );
584
- // 이번달 마지막 날짜
585
- const lastDateOfThisMonth = getLastDateOfMonth(
586
- pageInfo.year,
587
- pageInfo.month,
588
- );
589
-
590
- let modelValue = '';
591
- if (props.mode.includes('Time')) {
592
- if (props.mode === 'dateTime') {
593
- modelValue = selectedValue.value;
594
- } else {
595
- modelValue = calendarType === 'main' ? selectedValue.value[0] : selectedValue.value[1];
596
- }
597
- }
598
-
599
- let monthDate = 0;
600
- let year = 0;
601
- let month = 0;
602
- let date = 0;
603
- let currDate = '';
604
- // date 숫자 및 속성 세팅
605
- const setDateInfo = (monthType, i, j) => {
606
- currDate = formatDateTime({ year, month, date });
607
-
608
- // time 모드인 경우 현재 값의 시간을 가지고 테스트
609
- const timeValue = modelValue?.split(' ')[1] ?? '';
610
-
611
- // range 모드인 경우 from 날짜가 to 날짜를 넘는지 확인 || 최소 날짜보다 이전 날짜인지 확인
612
- const isInvalidDate = (isRangeMode && !disabledDate
613
- && compareFromAndToDateTime(props.mode, calendarType, currDate, selectedValue.value))
614
- || (+new Date(`${currDate} ${timeValue}`) < MIN_DATE_MS);
615
-
616
- const isDisabled = (disabledDate && disabledDate(new Date(`${currDate} ${timeValue}`)))
617
- || isInvalidDate;
618
-
619
- const index = +(calendarType !== 'main');
620
- const isRangeSelected = isRangeMode && selectedValue.value.length > index
621
- && selectedValue.value?.[index]?.includes(currDate);
622
- const isSelected = !isDisabled
623
- && (isRangeMode ? isRangeSelected : selectedValue.value?.includes(currDate));
624
-
625
- // mode가 dateRange일 때는 이전, 다음달에 selected 를 하지 않는다.
626
- calendarTableInfo[calendarType][i][j] = {
627
- monthType: `${monthType}${isDisabled ? ' disabled' : ''}`,
628
- isToday: TODAY_YMD === currDate,
629
- isSelected,
630
- year,
631
- month,
632
- date,
633
- };
634
- };
635
-
636
- for (let i = 0; i < CALENDAR_ROWS; i++) {
637
- for (let j = 0; j < CALENDAR_COLS; j++) {
638
- if (i === 0) {
639
- // 첫번째 주
640
- if (dayOfWeekOnThe1stOfThisMonth !== 0) {
641
- if (j < dayOfWeekOnThe1stOfThisMonth) {
642
- year = YEAR_OF_PREV_MONTH;
643
- month = PREV_MONTH;
644
- date = lastDateOfPrevMonth - dayOfWeekOnThe1stOfThisMonth + 1 + j;
645
- setDateInfo('prev', i, j);
646
- } else {
647
- monthDate++;
648
- year = pageInfo.year;
649
- month = pageInfo.month;
650
- date = monthDate;
651
- setDateInfo('', i, j);
652
- }
653
- } else {
654
- year = YEAR_OF_PREV_MONTH;
655
- month = PREV_MONTH;
656
- date = lastDateOfPrevMonth - 6 + j;
657
- setDateInfo('prev', i, j);
658
- }
659
- } else if (lastDateOfThisMonth <= monthDate) {
660
- // 마지막 -1, 마지막 주의 다음달 날짜
661
- monthDate++;
662
- year = YEAR_OF_NEXT_MONTH;
663
- month = NEXT_MONTH;
664
- date = monthDate - lastDateOfThisMonth;
665
- setDateInfo('next', i, j);
666
- } else {
667
- // 첫번째 주를 제외한 이번달 날짜
668
- monthDate++;
669
- year = pageInfo.year;
670
- month = pageInfo.month;
671
- date = monthDate;
672
- setDateInfo('', i, j);
673
- }
674
- }
675
- }
676
- };
677
-
678
- /**
679
- * Calendar 시간 정보 세팅하기
680
- */
681
- const setHmsTime = () => {
682
- const timeFormat = props.options?.timeFormat;
683
- const disabledDate = props.options?.disabledDate;
684
- const mainTimeFormat = Array.isArray(timeFormat) ? timeFormat[0] : timeFormat;
685
- const expandedTimeFormat = Array.isArray(timeFormat) ? timeFormat[1] : '';
686
- const mainDateTimeValue = props.mode === 'dateTimeRange' ? selectedValue.value[0] : selectedValue.value;
687
- const expandedDateTimeValue = props.mode === 'dateTimeRange' ? selectedValue.value[1] : '';
688
- const mainDisabledDate = Array.isArray(disabledDate) ? disabledDate[0] : disabledDate;
689
- const expandedDisabledDate = Array.isArray(disabledDate) ? disabledDate[1] : disabledDate;
690
-
691
- const compareDateTimeValue = (calendarType, timeType, value) => {
692
- const dateTimeValue = calendarType === 'main' ? mainDateTimeValue : expandedDateTimeValue;
693
- const disabledDateFunc = calendarType === 'main' ? mainDisabledDate : expandedDisabledDate;
694
- if (!dateTimeValue) {
695
- return false;
696
- }
697
-
698
- const date = dateTimeValue.split(' ')[0];
699
- let hour = getDateTimeInfoByType(dateTimeValue, 'hour');
700
- let min = getDateTimeInfoByType(dateTimeValue, 'min');
701
- let sec = getDateTimeInfoByType(dateTimeValue, 'sec');
702
-
703
- if (timeType === 'hour') {
704
- hour = value;
705
- } else if (timeType === 'min') {
706
- min = value;
707
- } else if (timeType === 'sec') {
708
- sec = value;
709
- }
710
-
711
- const targetDateTimeValue = `${date} ${lpadToTwoDigits(hour)}:${lpadToTwoDigits(min)}:${lpadToTwoDigits(sec)}`;
712
- if (disabledDateFunc && disabledDateFunc(new Date(targetDateTimeValue))) {
713
- return true;
714
- }
715
-
716
- return !disabledDateFunc && compareFromAndToDateTime(
717
- props.mode,
718
- calendarType,
719
- targetDateTimeValue,
720
- selectedValue.value,
721
- );
722
- };
723
-
724
- ['hour', 'min', 'sec'].forEach((v) => {
725
- let cnt = SEC_CNT;
726
- if (v === 'hour') {
727
- cnt = HOUR_CNT;
728
- } else if (v === 'min') {
729
- cnt = MIN_CNT;
730
- }
731
- const mainTimeValue = mainDateTimeValue && mainDateTimeValue.length > 0
732
- ? getTimeInfoByTimeFormat(mainTimeFormat, mainDateTimeValue, v) : -1;
733
- const expandedTimeValue = expandedDateTimeValue && expandedDateTimeValue.length > 0
734
- ? getTimeInfoByTimeFormat(expandedTimeFormat, expandedDateTimeValue, v) : -1;
735
- for (let i = 0; i < cnt; i++) {
736
- let isDisabled = props.mode === 'dateTimeRange' && compareDateTimeValue('main', v, i);
737
- calendarTimeTableInfo.main[v][i] = {
738
- timeType: v,
739
- num: i,
740
- isSelected: !isDisabled && mainTimeValue === i,
741
- isDisabled,
742
- };
743
- if (props.mode === 'dateTimeRange') {
744
- isDisabled = compareDateTimeValue('expanded', v, i);
745
- calendarTimeTableInfo.expanded[v][i] = {
746
- timeType: v,
747
- num: i,
748
- isSelected: !isDisabled && expandedTimeValue === i,
749
- isDisabled,
750
- };
751
- }
752
- }
753
- });
754
- };
755
-
756
- /**
757
- * HMS 영역 내 tr, td, 페이지에 맞는 시간 정보 가져오기
758
- * @param timeType - {'hour'|'min'|'sec'}
759
- * @param i - rows
760
- * @param j - cols
761
- * @param calendarType - {'main'|'expanded'}
762
- * @returns {object} - cellInfo
763
- */
764
- const getTimeInfo = (timeType, i, j, calendarType) => {
765
- const pageInfo = calendarPageInfo[calendarType];
766
- const timeInfo = calendarTimeTableInfo[calendarType];
767
- const currPage = pageInfo[timeType] - 1;
768
- const currRowIdx = i - 1;
769
- const currColIdx = j - 1;
770
- const currIdx = (currPage * CELL_CNT_IN_ONE_PAGE)
771
- + (currRowIdx * CELL_CNT_IN_ONE_ROW) + currColIdx;
772
- return timeInfo[timeType][currIdx];
773
- };
774
-
775
-
776
- return {
777
- calendarTableInfo,
778
- calendarMonthTableInfo,
779
- calendarYearTableInfo,
780
- calendarTimeTableInfo,
781
- setCalendarDate,
782
- setCalendarMonth,
783
- setCalendarYear,
784
- setHmsTime,
785
- getTimeInfo,
786
- };
787
- };
788
-
789
- export const useEvent = (param) => {
790
- const { props, emit } = getCurrentInstance();
791
- const timeFormat = props.options?.timeFormat;
792
- const {
793
- selectedValue,
794
- calendarPageInfo,
795
- calendarTimeTableInfo,
796
- setCalendarDate,
797
- setCalendarMonth,
798
- setCalendarYear,
799
- setHmsTime,
800
- selectedListType,
801
- } = param;
802
-
803
- // dateRange mode에서 클릭하여 첫번째 선택된 날짜
804
- const dateRangeClickedDate = ref('');
805
- // dateRange mode에서 클릭한번 후 커서에 따라 날짜를 마우스오버하는 경우 dynamic argument로 이벤트명 설정
806
- const calendarEventName = ref(null);
807
- // dateTime 또는 dateTimeRange에서 timeFormat이 있는 경우 event 막음
808
- const mainTimeFormat = Array.isArray(timeFormat) ? timeFormat[0] : timeFormat;
809
- const expandedTimeFormat = Array.isArray(timeFormat) ? timeFormat[1] : '';
810
- const preventTimeEventType = {
811
- main: {
812
- hour: mainTimeFormat && mainTimeFormat.split(':')[0] !== 'HH',
813
- min: mainTimeFormat && mainTimeFormat.split(':')[1] !== 'mm',
814
- sec: mainTimeFormat && mainTimeFormat.split(':')[2] !== 'ss',
815
- },
816
- expanded: {
817
- hour: expandedTimeFormat && expandedTimeFormat.split(':')[0] !== 'HH',
818
- min: expandedTimeFormat && expandedTimeFormat.split(':')[1] !== 'mm',
819
- sec: expandedTimeFormat && expandedTimeFormat.split(':')[2] !== 'ss',
820
- },
821
- };
822
-
823
- /**
824
- * 입력받은 dateTime object에 calendar date, time 영역 페이지 세팅
825
- * @param calendarType - 달력 종류 ('main'|'expanded')
826
- * @param dateTime - 입력된 페이지 정보 ({ year, month, hour, min, sec })
827
- */
828
- const setCalendarPageInfo = (calendarType, dateTime) => {
829
- const pageInfo = calendarPageInfo[calendarType];
830
- const { year, month, hour, min, sec } = dateTime;
831
- if (year) {
832
- pageInfo.year = year;
833
- }
834
- if (month) {
835
- pageInfo.month = month;
836
- }
837
- if (hour) {
838
- pageInfo.hour = hour;
839
- }
840
- if (min) {
841
- pageInfo.min = min;
842
- }
843
- if (sec) {
844
- pageInfo.sec = sec;
845
- }
846
- };
847
-
848
- /**
849
- * value를 Array로 담아 페이지 세팅
850
- * @param valueList
851
- */
852
- const updateCalendarPage = (valueList) => {
853
- valueList?.forEach((currValue, index) => {
854
- const changeCalendarType = index === 0 ? 'main' : 'expanded';
855
- setCalendarPageInfo(changeCalendarType, {
856
- year: getDateTimeInfoByType(currValue, 'year'),
857
- month: getDateTimeInfoByType(currValue, 'month'),
858
- hour: Math.floor(getDateTimeInfoByType(currValue, 'hour') / CELL_CNT_IN_ONE_PAGE) + 1,
859
- min: Math.floor(getDateTimeInfoByType(currValue, 'min') / CELL_CNT_IN_ONE_PAGE) + 1,
860
- sec: Math.floor(getDateTimeInfoByType(currValue, 'sec') / CELL_CNT_IN_ONE_PAGE) + 1,
861
- });
862
- setCalendarDate(changeCalendarType);
863
- });
864
- };
865
-
866
- /**
867
- * Calendar 의 year 이동시키기 (이전, 이후)
868
- * @param calendarType
869
- * @param type
870
- */
871
- const moveYear = (calendarType, type) => {
872
- const increaseValue = selectedListType[calendarType] === LIST_TYPE.MONTH ? 1 : 20;
873
- const offset = type === 'prev' ? -increaseValue : increaseValue;
874
- const minYear = new Date(MIN_DATE_MS).getFullYear();
875
- const movedYear = calendarPageInfo[calendarType].year + offset;
876
- calendarPageInfo[calendarType].year = (movedYear < minYear) ? minYear : movedYear;
877
- };
878
-
879
- /**
880
- * Calendar 의 Month 이동시키기 (이전, 이후)
881
- * @param calendarType - 달력 종류 ('main'|'expanded')
882
- * @param type - {'prev'|'next'}
883
- */
884
- const moveMonth = (calendarType, type) => {
885
- const pageInfo = calendarPageInfo[calendarType];
886
-
887
- if (type === 'prev') {
888
- const minYear = new Date(MIN_DATE_MS).getFullYear();
889
- if (pageInfo.year === minYear && pageInfo.month === 1) {
890
- return;
891
- }
892
- if (pageInfo.month === 1) {
893
- pageInfo.year -= 1;
894
- pageInfo.month = 12;
895
- } else {
896
- pageInfo.month -= 1;
897
- }
898
- } else if (pageInfo.month === 12) {
899
- pageInfo.year += 1;
900
- pageInfo.month = 1;
901
- } else {
902
- pageInfo.month += 1;
903
- }
904
- };
905
-
906
- /**
907
- * Calendar Header의 prev, next 아이콘 클릭 이벤트
908
- * @param calendarType - 달력 종류 ('main'|'expanded')
909
- * @param type - 이전달, 다음달 ('prev'|'next')
910
- */
911
- const clickPrevNextBtn = (calendarType, type) => {
912
- const listType = selectedListType[calendarType];
913
- switch (listType) {
914
- case LIST_TYPE.DATE: {
915
- moveMonth(calendarType, type);
916
- setCalendarDate(calendarType);
917
- break;
918
- }
919
- case LIST_TYPE.MONTH:
920
- moveYear(calendarType, type);
921
- setCalendarMonth(calendarType);
922
- break;
923
- case LIST_TYPE.YEAR:
924
- moveYear(calendarType, type);
925
- setCalendarYear(calendarType);
926
- break;
927
- default:
928
- break;
929
- }
930
- };
931
-
932
- /**
933
- * Calendar Header 의 year, month 버튼 클릭 이벤트
934
- * @param calendarType - 달력 종류 ('main'|'expanded')
935
- * @param type - 클릭 정보 ('year' | 'month')
936
- */
937
- const clickYearMonthBtn = (calendarType, type) => {
938
- if (type === LIST_TYPE.DATE) {
939
- setCalendarDate(calendarType);
940
- } else if (type === LIST_TYPE.MONTH) {
941
- setCalendarMonth(calendarType);
942
- } else if (type === LIST_TYPE.YEAR) {
943
- setCalendarYear(calendarType);
944
- }
945
- selectedListType[calendarType] = type;
946
- };
947
-
948
- /**
949
- * Calendar year, month 클릭 이벤트
950
- * @param calendarType - 달력 종류 ('main'|'expanded')
951
- * @param clickedInfo - 클릭 정보
952
- */
953
- const clickYearMonth = (calendarType, clickedInfo) => {
954
- const { value } = clickedInfo;
955
-
956
- if (clickedInfo.disabled) {
957
- return;
958
- }
959
-
960
- if (selectedListType[calendarType] === LIST_TYPE.YEAR) {
961
- calendarPageInfo[calendarType].year = value;
962
- selectedListType[calendarType] = LIST_TYPE.MONTH;
963
- setCalendarMonth(calendarType);
964
- } else {
965
- calendarPageInfo[calendarType].month = value;
966
- selectedListType[calendarType] = LIST_TYPE.DATE;
967
- setCalendarDate(calendarType);
968
- }
969
- };
970
-
971
- /**
972
- * Calendar Date 일자 클릭 이벤트
973
- * @param calendarType - {main|expanded}
974
- * @param dateInfo
975
- */
976
- const clickDate = (calendarType, dateInfo) => {
977
- const { year, month, date, monthType } = dateInfo;
978
- const CURR_DATE_STR = formatDateTime({ year, month, date });
979
- const isExistCurrDate = props.modelValue ? (Array.isArray(props.modelValue)
980
- ? props.modelValue?.map(v => v.split(' ')[0])
981
- : props.modelValue.split(' ')[0])
982
- .includes(CURR_DATE_STR) : false;
983
-
984
- let disabledDate = props.options.disabledDate;
985
- if (disabledDate && Array.isArray(disabledDate)) {
986
- disabledDate = calendarType === 'main' ? disabledDate[0] : disabledDate[1];
987
- }
988
- // 제한된 날짜는 선택할 수 없다.
989
- if (disabledDate && disabledDate(new Date(CURR_DATE_STR)) && !isExistCurrDate) {
990
- return;
991
- } else if (!disabledDate && ['dateRange', 'dateTimeRange'].includes(props.mode)
992
- && compareFromAndToDateTime(props.mode, calendarType, CURR_DATE_STR, selectedValue.value)) {
993
- return;
994
- }
995
-
996
- const pageInfo = calendarPageInfo[calendarType];
997
- const PREV_MONTH = ((MONTH_CNT + pageInfo.month - 1) % MONTH_CNT) || MONTH_CNT;
998
- const YEAR_OF_PREV_MONTH = pageInfo.month === 1
999
- ? pageInfo.year - 1 : pageInfo.year;
1000
- const NEXT_MONTH = ((pageInfo.month + 1) % MONTH_CNT) || MONTH_CNT;
1001
- const YEAR_OF_NEXT_MONTH = pageInfo.month === 12
1002
- ? pageInfo.year + 1 : pageInfo.year;
1003
-
1004
- const moveDispCalendarMonth = () => {
1005
- if (monthType.includes('prev')) {
1006
- pageInfo.year = YEAR_OF_PREV_MONTH;
1007
- pageInfo.month = PREV_MONTH;
1008
- } else if (monthType.includes('next')) {
1009
- pageInfo.year = YEAR_OF_NEXT_MONTH;
1010
- pageInfo.month = NEXT_MONTH;
1011
- }
1012
- };
1013
-
1014
- switch (props.mode) {
1015
- case 'date':
1016
- // moveDispCalendarMonth();
1017
- emit('update:modelValue', CURR_DATE_STR);
1018
- break;
1019
- case 'dateTime': {
1020
- const isExistTime = !!(selectedValue.value?.split(' ')[1]);
1021
- const CURR_TIME_HMS = isExistTime
1022
- ? selectedValue.value?.split(' ')[1] : '00:00:00';
1023
- const changedValueByTimeFormat = getChangedValueByTimeFormat(
1024
- timeFormat,
1025
- `${CURR_DATE_STR} ${CURR_TIME_HMS}`,
1026
- );
1027
- // moveDispCalendarMonth();
1028
- emit('update:modelValue', changedValueByTimeFormat);
1029
- break;
1030
- }
1031
- case 'dateMulti': {
1032
- const multiType = props.options.multiType;
1033
- const multiDayLimit = props.options.multiDayLimit;
1034
- if (multiType === 'date') {
1035
- const selectedIdx = selectedValue.value.indexOf(CURR_DATE_STR);
1036
- if (selectedIdx > -1) {
1037
- selectedValue.value.splice(selectedIdx, 1);
1038
- emit('update:modelValue', [...selectedValue.value]);
1039
- } else if (selectedValue.value.length < multiDayLimit) {
1040
- selectedValue.value.push(CURR_DATE_STR);
1041
- moveDispCalendarMonth();
1042
- emit('update:modelValue', [...selectedValue.value]);
1043
- }
1044
- } else if (multiType === 'week' || multiType === 'weekday') {
1045
- const NUMBER_OF_DAYS_IN_RANGE = multiType === 'week' ? 7 : 5; // 범위 내 선택된 날짜 개수
1046
- const DIFF_UNTIL_THE_LAST_DATE = multiType === 'week' ? 6 : 5; // 한 주의 마지막 날짜까지의 차이
1047
- const exactSelectedDate = new Date(`${CURR_DATE_STR} 00:00:00`);
1048
- const dayOfTheWeekOfTheSelectedDate = exactSelectedDate.getDay();
1049
- const diffFromTheLastDay = DIFF_UNTIL_THE_LAST_DATE - dayOfTheWeekOfTheSelectedDate;
1050
- const theLastDayTime = exactSelectedDate.getTime() + (ONE_DAY_MS * diffFromTheLastDay);
1051
-
1052
- for (let i = 0; i < NUMBER_OF_DAYS_IN_RANGE; i++) {
1053
- const loopYear = new Date(theLastDayTime - (i * ONE_DAY_MS)).getFullYear();
1054
- const loopMonth = new Date(theLastDayTime - (i * ONE_DAY_MS)).getMonth() + 1;
1055
- const loopDate = new Date(theLastDayTime - (i * ONE_DAY_MS)).getDate();
1056
- const dateStr = `${loopYear}-${lpadToTwoDigits(loopMonth)}-${lpadToTwoDigits(loopDate)}`;
1057
- if (i === 0) {
1058
- if (selectedValue.value.includes(dateStr)) {
1059
- selectedValue.value.splice(0);
1060
- break;
1061
- } else {
1062
- selectedValue.value.splice(0);
1063
- moveDispCalendarMonth();
1064
- }
1065
- }
1066
- if (!disabledDate || !disabledDate(new Date(dateStr))) {
1067
- selectedValue.value.unshift(dateStr);
1068
- }
1069
- }
1070
- emit('update:modelValue', [...selectedValue.value]);
1071
- }
1072
- setCalendarDate('main');
1073
- break;
1074
- }
1075
- case 'dateRange': {
1076
- let changedValue = [...selectedValue.value];
1077
- if (!selectedValue.value.length) {
1078
- changedValue = [CURR_DATE_STR, CURR_DATE_STR];
1079
- } else {
1080
- const currIndex = +(calendarType === 'expanded');
1081
- changedValue[currIndex] = CURR_DATE_STR;
1082
- }
1083
- emit('update:modelValue', changedValue);
1084
- break;
1085
- }
1086
- case 'dateTimeRange': {
1087
- let changedValue = [...selectedValue.value];
1088
- if (!changedValue.length) {
1089
- let fromDate = `${CURR_DATE_STR} 00:00:00`;
1090
- let toDate = `${CURR_DATE_STR} 00:00:00`;
1091
- if (timeFormat && timeFormat.length) {
1092
- fromDate = getChangedValueByTimeFormat(
1093
- timeFormat[0],
1094
- fromDate,
1095
- );
1096
- toDate = getChangedValueByTimeFormat(
1097
- timeFormat[1],
1098
- toDate,
1099
- );
1100
- }
1101
- changedValue = [fromDate, toDate];
1102
- } else {
1103
- const currIndex = +(calendarType === 'expanded');
1104
- const CURR_TIME_HMS = changedValue[currIndex]?.split(' ')[1] || '00:00:00';
1105
- let currDate = `${CURR_DATE_STR} ${CURR_TIME_HMS}`;
1106
- if (timeFormat && timeFormat.length) {
1107
- currDate = getChangedValueByTimeFormat(
1108
- timeFormat[currIndex],
1109
- currDate,
1110
- );
1111
- }
1112
- changedValue[currIndex] = currDate;
1113
- }
1114
- emit('update:modelValue', changedValue);
1115
- break;
1116
- }
1117
- default:
1118
- break;
1119
- }
1120
- };
1121
-
1122
- /**
1123
- * Calendar mode: dateTime인 경우 HMS 이동 화살표 클릭 이벤트
1124
- * @param calendarType - {main|expanded}
1125
- * @param timeType - {hour|min|sec}
1126
- * @param arrow - {up|down}
1127
- */
1128
- const clickHmsBtn = (calendarType, timeType, arrow) => {
1129
- if (preventTimeEventType[calendarType][timeType]) {
1130
- return;
1131
- }
1132
-
1133
- const pageInfo = calendarPageInfo[calendarType];
1134
- const FIRST_PAGE = 1;
1135
- const HOUR_MAX_PAGE = 2;
1136
- const MINUTE_MAX_PAGE = 5;
1137
- const SECOND_MAX_PAGE = 5;
1138
- if (timeType === 'hour') {
1139
- if (arrow === 'down' && pageInfo.hour < HOUR_MAX_PAGE) {
1140
- pageInfo.hour++;
1141
- } else if (arrow === 'up' && pageInfo.hour > FIRST_PAGE) {
1142
- pageInfo.hour--;
1143
- }
1144
- } else if (timeType === 'min') {
1145
- if (arrow === 'down' && pageInfo.min < MINUTE_MAX_PAGE) {
1146
- pageInfo.min++;
1147
- } else if (arrow === 'up' && pageInfo.min > FIRST_PAGE) {
1148
- pageInfo.min--;
1149
- }
1150
- } else if (timeType === 'sec') {
1151
- if (arrow === 'down' && pageInfo.sec < SECOND_MAX_PAGE) {
1152
- pageInfo.sec++;
1153
- } else if (arrow === 'up' && pageInfo.sec > FIRST_PAGE) {
1154
- pageInfo.sec--;
1155
- }
1156
- }
1157
- };
1158
-
1159
- /**
1160
- * Click cell In HMS area
1161
- * @param calendarType - {main|expanded}
1162
- * @param timeType - {hour|min|sec}
1163
- * @param i - row
1164
- * @param j - col
1165
- */
1166
- const clickTime = (calendarType, timeType, i, j) => {
1167
- if (preventTimeEventType[calendarType][timeType]) {
1168
- return;
1169
- }
1170
-
1171
- const pageInfo = calendarPageInfo[calendarType];
1172
- const timeInfo = calendarTimeTableInfo[calendarType];
1173
- const currPage = pageInfo[timeType] - 1;
1174
- const currRowIdx = i - 1;
1175
- const currColIdx = j - 1;
1176
- const clickedNum = (currPage * CELL_CNT_IN_ONE_PAGE)
1177
- + (currRowIdx * CELL_CNT_IN_ONE_ROW) + currColIdx;
1178
-
1179
- if (timeInfo[timeType][clickedNum]?.isDisabled) {
1180
- return;
1181
- }
1182
-
1183
- const TODAY = new Date();
1184
- const TODAY_INFO = {
1185
- year: TODAY.getFullYear(),
1186
- month: TODAY.getMonth() + 1,
1187
- date: TODAY.getDate(),
1188
- };
1189
- let EXIST_MODEL = true;
1190
- let valueListByUpdatePage = [];
1191
-
1192
- const getTimeValueByType = () => {
1193
- let targetTimeValue;
1194
- if (timeType === 'hour') {
1195
- targetTimeValue = `${lpadToTwoDigits(clickedNum)}:00:00'`;
1196
- } else if (timeType === 'min') {
1197
- targetTimeValue = `00:${lpadToTwoDigits(clickedNum)}:00`;
1198
- } else if (timeType === 'sec') {
1199
- targetTimeValue = `00:00:${lpadToTwoDigits(clickedNum)}`;
1200
- }
1201
- return `${formatDateTime(TODAY_INFO)} ${targetTimeValue}`;
1202
- };
1203
-
1204
- const getChangedValue = (targetValue) => {
1205
- const HOUR_START_IDX = 11;
1206
- const MIN_START_IDX = 14;
1207
- const SEC_START_IDX = 17;
1208
- const REPLACE_TEXT_SIZE = 2;
1209
- let START_IDX = HOUR_START_IDX;
1210
- if (timeType === 'min') {
1211
- START_IDX = MIN_START_IDX;
1212
- } else if (timeType === 'sec') {
1213
- START_IDX = SEC_START_IDX;
1214
- }
1215
- return `${targetValue?.substr(0, START_IDX)}`
1216
- + `${lpadToTwoDigits(clickedNum)}${targetValue?.substr(START_IDX + REPLACE_TEXT_SIZE)}`;
1217
- };
1218
-
1219
- if (props.mode === 'dateTime') {
1220
- let changedValue;
1221
- if (!props.modelValue) {
1222
- EXIST_MODEL = false;
1223
- changedValue = getChangedValueByTimeFormat(
1224
- timeFormat,
1225
- getTimeValueByType(),
1226
- );
1227
- } else {
1228
- changedValue = getChangedValueByTimeFormat(
1229
- timeFormat,
1230
- getChangedValue(props.modelValue),
1231
- );
1232
- }
1233
- emit('update:modelValue', changedValue);
1234
- valueListByUpdatePage.push(changedValue);
1235
- } else {
1236
- const index = calendarType !== 'main' | 0;
1237
- let changedValue = [...selectedValue.value];
1238
- if (!props.modelValue.length) {
1239
- const timeValue = getTimeValueByType();
1240
- changedValue = [timeValue, timeValue];
1241
-
1242
- if (timeFormat && timeFormat.length) {
1243
- changedValue = [...changedValue
1244
- .map((v, idx) => getChangedValueByTimeFormat(timeFormat[idx], v))];
1245
- }
1246
-
1247
- EXIST_MODEL = false;
1248
- valueListByUpdatePage = changedValue;
1249
- } else {
1250
- let currDateTime = getChangedValue(props.modelValue[index]);
1251
- if (timeFormat && timeFormat.length) {
1252
- currDateTime = getChangedValueByTimeFormat(
1253
- timeFormat[index],
1254
- currDateTime,
1255
- );
1256
- }
1257
-
1258
- changedValue[index] = currDateTime;
1259
- }
1260
- emit('update:modelValue', changedValue);
1261
- }
1262
- setHmsTime();
1263
- // dateTime의 v-model값이 없는 경우 time area를 클릭하였을 때 date의 값은 today로 세팅
1264
- if (!EXIST_MODEL) {
1265
- updateCalendarPage(valueListByUpdatePage);
1266
- }
1267
- };
1268
-
1269
- /**
1270
- * Wheel up or wheel down In Calendar Month(tbody) area
1271
- * @param calendarType - {main|expanded}
1272
- * @param e
1273
- */
1274
- const wheelMonth = (calendarType, e) => {
1275
- clickPrevNextBtn(calendarType, e.deltaY > 0 ? 'next' : 'prev');
1276
- };
1277
-
1278
- /**
1279
- * Wheel up or wheel down In Calendar Time(HMS) area
1280
- * @param calendarType - {main|expanded}
1281
- * @param timeType - {hour|min|sec}
1282
- * @param e
1283
- */
1284
- const wheelTime = (calendarType, timeType, e) => {
1285
- if (preventTimeEventType[calendarType][timeType]) {
1286
- return;
1287
- }
1288
-
1289
- clickHmsBtn(calendarType, timeType, e.deltaY > 0 ? 'down' : 'up');
1290
- };
1291
-
1292
- /**
1293
- * dateRange 모드에서 한번 클릭 후 날짜에 마우스무브하는 경우
1294
- * 커서 위에 있는 날짜까지의 selectedValue의 영역 선택한 selection 로직
1295
- * 일반적인 마우스무브 로직에 성능향상을 위한 throttle 10ms를 설정
1296
- * @param calendarType - 캘린더 종류 ('main'|'expanded')
1297
- * @param e - 마우스이벤트
1298
- * @type {function(): (*)}
1299
- */
1300
- const onMousemoveDate = throttle((calendarType, e) => {
1301
- const target = e.target.tagName === 'TD' ? e.target : e.target.parentElement;
1302
- const isDisabled = target.classList.contains('disabled');
1303
- const isPrev = target.classList.contains('prev');
1304
- const isNext = target.classList.contains('next');
1305
- if (target.classList.length > 0 && !isDisabled) {
1306
- const pageInfo = calendarPageInfo[calendarType];
1307
- let yearMonth = {
1308
- year: +pageInfo.year,
1309
- month: +pageInfo.month,
1310
- date: e.target.innerText,
1311
- };
1312
- // 달력 내 이전달, 다음달 일자의 경우 연, 월 보정
1313
- if (isPrev) {
1314
- yearMonth = { ...yearMonth, ...getSideMonthCalendarInfo('prev', yearMonth.year, yearMonth.month) };
1315
- } else if (isNext) {
1316
- yearMonth = { ...yearMonth, ...getSideMonthCalendarInfo('next', yearMonth.year, yearMonth.month) };
1317
- }
1318
- const STANDARD_DATE_STR = dateRangeClickedDate.value;
1319
- const MOUSEMOVE_DATE_STR = formatDateTime({
1320
- year: yearMonth.year,
1321
- month: yearMonth.month,
1322
- date: yearMonth.date,
1323
- });
1324
-
1325
- // fromDate ~ toDate selection 순서 세팅
1326
- if (getDateMs(MOUSEMOVE_DATE_STR) < getDateMs(STANDARD_DATE_STR)) {
1327
- selectedValue.value[0] = MOUSEMOVE_DATE_STR;
1328
- selectedValue.value[1] = STANDARD_DATE_STR;
1329
- } else {
1330
- selectedValue.value[0] = STANDARD_DATE_STR;
1331
- selectedValue.value[1] = MOUSEMOVE_DATE_STR;
1332
- }
1333
- setCalendarDate('main');
1334
- setCalendarDate('expanded');
1335
- }
1336
- }, 10);
1337
-
1338
- /**
1339
- * calendar setting 하기 전 선택된 날짜가 disabledDate에 포함되는지 체크
1340
- * @param currValue
1341
- */
1342
- const checkDisabledDate = (currValue) => {
1343
- const isRangeMode = ['dateRange', 'dateMulti', 'dateTimeRange'].includes(props.mode);
1344
- const disabledDate = props.options.disabledDate;
1345
- if (isRangeMode) {
1346
- const [fromDate, toDate] = selectedValue.value;
1347
- let [disabledFromDate, disabledToDate] = [disabledDate, disabledDate];
1348
- if (disabledDate && Array.isArray(disabledDate)) {
1349
- [disabledFromDate, disabledToDate] = disabledDate;
1350
- }
1351
-
1352
- if (currValue[0] && currValue[0] !== fromDate
1353
- && disabledFromDate && disabledFromDate(new Date(currValue[0]))) {
1354
- return true;
1355
- } else if (currValue[1] && currValue[1] !== toDate
1356
- && disabledToDate && disabledToDate(new Date(currValue[1]))) {
1357
- return true;
1358
- } else if (!disabledDate
1359
- && compareFromAndToDateTime(props.mode, 'main', currValue[0], currValue)) {
1360
- return true;
1361
- }
1362
- } else if (props.mode === 'dateMulti') {
1363
- return currValue.some(value => disabledDate && disabledDate(new Date(value)));
1364
- } else if (disabledDate && disabledDate(new Date(currValue))) {
1365
- return true;
1366
- }
1367
- return false;
1368
- };
1369
-
1370
- watch(
1371
- () => props.modelValue,
1372
- (curr) => {
1373
- if (checkDisabledDate(curr)) {
1374
- emit('update:modelValue', selectedValue.value);
1375
- return;
1376
- }
1377
-
1378
- const isRangeMode = ['dateRange', 'dateMulti', 'dateTimeRange'].includes(props.mode);
1379
- selectedValue.value = isRangeMode ? [...curr] : curr;
1380
-
1381
- if (props.mode === 'dateRange') {
1382
- updateCalendarPage(curr);
1383
- } else if (props.mode.includes('Time')) {
1384
- let updateValue = [];
1385
- if (props.mode === 'dateTime') {
1386
- updateValue = [curr];
1387
- } else if (props.mode === 'dateTimeRange') {
1388
- updateValue = curr;
1389
- }
1390
- updateCalendarPage(updateValue);
1391
- setHmsTime();
1392
- } else if (props.mode === 'date') {
1393
- updateCalendarPage([curr]);
1394
- }
1395
- });
1396
-
1397
- return {
1398
- clickYearMonthBtn,
1399
- clickPrevNextBtn,
1400
- clickDate,
1401
- clickYearMonth,
1402
- clickHmsBtn,
1403
- clickTime,
1404
- wheelMonth,
1405
- wheelTime,
1406
- calendarEventName,
1407
- onMousemoveDate,
1408
- preventTimeEventType,
1409
- };
1410
- };