evui 3.4.206 → 3.4.208

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 +22645 -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 -63678
  9. package/dist/evui.common.js.map +0 -1
  10. package/dist/evui.umd.js +0 -63688
  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 -1655
  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,908 +0,0 @@
1
- import {
2
- getCurrentInstance,
3
- ref,
4
- computed,
5
- reactive,
6
- watch,
7
- nextTick,
8
- onMounted,
9
- onBeforeUnmount,
10
- } from 'vue';
11
-
12
- // 세로 스크롤 너비
13
- const getVScrollWidth = () => window.innerWidth - document.documentElement.clientWidth;
14
- // 가로 스크롤 너비
15
- // const getHScrollWidth = () => window.innerHeight - document.documentElement.clientHeight;
16
-
17
- const useModel = () => {
18
- const { props, emit } = getCurrentInstance();
19
-
20
- const windowRef = ref();
21
- const headerRef = ref();
22
- const isFullExpandWindow = ref(false);
23
- const maximizableIcon = computed(() => (isFullExpandWindow.value ? 'ev-icon-compress' : 'ev-icon-expand'));
24
-
25
- // body에 #ev-window-modal div append
26
- let root = document.getElementById('ev-window-modal');
27
- const initWrapperDiv = () => {
28
- if (!root) {
29
- const rootDiv = document.createElement('div');
30
- rootDiv.id = 'ev-window-modal';
31
- document.body.appendChild(rootDiv);
32
- root = document.getElementById('ev-window-modal');
33
- }
34
- };
35
- initWrapperDiv();
36
-
37
- const numberToUnit = (input) => {
38
- let output;
39
- let result;
40
-
41
- if (typeof input === 'string' || typeof input === 'number') {
42
- const match = (/^(normal|(-*\d+(?:\.\d+)?)(px|%|vw|vh)?)$/).exec(input);
43
- output = match ? { value: +match[2], unit: match[3] || undefined } : undefined;
44
- } else {
45
- output = undefined;
46
- }
47
-
48
- if (output === null || output === undefined) {
49
- result = undefined;
50
- } else if (output.unit) {
51
- result = `${output.value}${output.unit}`;
52
- } else {
53
- result = `${output.value}px`;
54
- }
55
-
56
- return result;
57
- };
58
-
59
- const removeUnit = (input, direction = 'horizontal') => {
60
- if (typeof input === 'number') {
61
- return input;
62
- } else if (!input) {
63
- return 0;
64
- }
65
-
66
- let result = 0;
67
- const match = (/^(normal|(\d+(?:\.\d+)?)(px|%|vw|vh)?)$/).exec(input);
68
-
69
- if (direction && ['%', 'vw', 'vh'].includes(match[3]) && match[2]) {
70
- const standard = direction === 'horizontal' ? window.innerWidth : window.innerHeight;
71
- result = Math.floor((standard * +match[2]) / 100);
72
- } else if (match[2]) {
73
- result = +match[2];
74
- }
75
-
76
- return result;
77
- };
78
-
79
- // set base style
80
- const basePosition = reactive({});
81
- const baseStyle = computed(() => ({
82
- ...props.style,
83
- ...basePosition,
84
- }));
85
-
86
- const setBasePosition = () => {
87
- basePosition.position = 'fixed';
88
-
89
- if (props.fullscreen) {
90
- basePosition.width = '100%';
91
- basePosition.height = '100%';
92
- basePosition.top = 0;
93
- basePosition.left = 0;
94
- return;
95
- }
96
-
97
- const convertedWidth = removeUnit(props.width, 'horizontal');
98
- const convertedMinWidth = removeUnit(props.minWidth, 'horizontal');
99
- if (convertedWidth < convertedMinWidth) {
100
- console.warn('Since width is less than min-width, it is replaced by min-width.');
101
- basePosition.width = numberToUnit(props.minWidth);
102
- } else {
103
- basePosition.width = numberToUnit(props.width);
104
- }
105
-
106
- const convertedHeight = removeUnit(props.height, 'vertical');
107
- const convertedMinHeight = removeUnit(props.minHeight, 'vertical');
108
- if (convertedHeight < convertedMinHeight) {
109
- console.warn('Since height is less than min-height, it is replaced by min-height.');
110
- basePosition.height = numberToUnit(props.minHeight);
111
- } else {
112
- basePosition.height = numberToUnit(props.height);
113
- }
114
-
115
- basePosition.top = `calc((100% - ${basePosition.height}) / 2)`;
116
- basePosition.left = `calc((100% - ${basePosition.width}) / 2)`;
117
-
118
- if (removeUnit(props.width, 'horizontal') > window.innerWidth) {
119
- basePosition.left = 0;
120
- }
121
- if (removeUnit(props.height, 'vertical') > window.innerHeight) {
122
- basePosition.top = 0;
123
- }
124
- };
125
-
126
- // close window
127
- const closeWin = (from) => {
128
- if (from === 'layer' && !props.closeOnClickModal) {
129
- return;
130
- }
131
- emit('update:visible', false);
132
- };
133
-
134
- const changeBodyCls = (isVisible) => {
135
- const hideScrollWindowCnt = root?.getElementsByClassName('scroll-lock')?.length;
136
- const bodyElem = document.body;
137
-
138
- if (isVisible) { // window open
139
- if (props.hideScroll) {
140
- // hideScroll 시, body 우측 padding 추가 & overflow hidden class 추가
141
- if (!hideScrollWindowCnt) {
142
- const scrollWidth = getVScrollWidth();
143
- bodyElem.style.paddingRight = `${scrollWidth}px`;
144
- }
145
- bodyElem.classList.add('ev-window-scroll-lock');
146
- }
147
- } else if (props.hideScroll && hideScrollWindowCnt === 1) { // window close
148
- bodyElem.style.removeProperty('padding-right');
149
- bodyElem.classList.remove('ev-window-scroll-lock');
150
- }
151
- };
152
-
153
- setBasePosition();
154
-
155
- watch(
156
- () => props.visible,
157
- async (newVal) => {
158
- changeBodyCls(newVal);
159
- if (newVal) {
160
- await nextTick(() => {
161
- setBasePosition();
162
- });
163
- }
164
- },
165
- );
166
-
167
- return {
168
- windowRef,
169
- headerRef,
170
- isFullExpandWindow,
171
- maximizableIcon,
172
- baseStyle,
173
- closeWin,
174
- numberToUnit,
175
- removeUnit,
176
- };
177
- };
178
-
179
- const useMouseEvent = (param) => {
180
- const { props, emit } = getCurrentInstance();
181
- const {
182
- windowRef,
183
- headerRef,
184
- isFullExpandWindow,
185
- numberToUnit,
186
- removeUnit,
187
- } = param;
188
-
189
- const draggingMinSize = 50;
190
- const grabbingBorderSize = 5;
191
- const dragStyle = reactive({});
192
- const clickedInfo = reactive({
193
- state: '',
194
- pressedSpot: '',
195
- top: 0,
196
- left: 0,
197
- width: 0,
198
- height: 0,
199
- clientX: 0,
200
- clientY: 0,
201
- });
202
- const draggedInfo = reactive({
203
- top: 0,
204
- left: 0,
205
- });
206
- const grabbingBorderPosInfo = reactive({
207
- top: false,
208
- right: false,
209
- left: false,
210
- bottom: false,
211
- });
212
- const beforeExpandPosInfo = reactive({
213
- width: null,
214
- height: null,
215
- top: null,
216
- left: null,
217
- });
218
-
219
- const isInHeader = (x, y) => {
220
- if (x == null || y == null) {
221
- return false;
222
- }
223
-
224
- const rect = windowRef.value.getBoundingClientRect();
225
- const posX = +x - rect.left;
226
- const posY = +y - rect.top;
227
- const headerAreaStyleInfo = headerRef.value.style;
228
- const headerPaddingInfo = {
229
- top: removeUnit(headerAreaStyleInfo.paddingTop, 'vertical'),
230
- left: removeUnit(headerAreaStyleInfo.paddingLeft, 'horizontal'),
231
- right: removeUnit(headerAreaStyleInfo.paddingRight, 'horizontal'),
232
- };
233
- const startPosX = headerPaddingInfo.left;
234
- const endPosX = rect.width - headerPaddingInfo.right;
235
- const startPosY = headerPaddingInfo.top;
236
- const endPosY = startPosY + headerRef.value.offsetHeight;
237
-
238
- return posX > startPosX && posX < endPosX && posY > startPosY && posY < endPosY;
239
- };
240
-
241
- const setDragStyle = (paramObj) => {
242
- if (paramObj === null || typeof paramObj !== 'object') {
243
- return;
244
- }
245
-
246
- let top;
247
- let left;
248
- let width;
249
- let height;
250
- let tMinWidth;
251
- let tMinHeight;
252
- const windowEl = windowRef.value;
253
- const hasOwnProperty = Object.prototype.hasOwnProperty;
254
-
255
- if (hasOwnProperty.call(paramObj, 'top')) {
256
- top = paramObj.top;
257
- } else {
258
- top = clickedInfo.top;
259
- }
260
-
261
- if (hasOwnProperty.call(paramObj, 'left')) {
262
- left = paramObj.left;
263
- } else {
264
- left = clickedInfo.left;
265
- }
266
-
267
- if (hasOwnProperty.call(paramObj, 'width')) {
268
- width = paramObj.width;
269
- } else {
270
- width = windowEl.offsetWidth;
271
- }
272
-
273
- if (hasOwnProperty.call(paramObj, 'height')) {
274
- height = paramObj.height;
275
- } else {
276
- height = windowEl.offsetHeight;
277
- }
278
-
279
- if (hasOwnProperty.call(paramObj, 'minWidth')) {
280
- tMinWidth = paramObj.minWidth;
281
- } else {
282
- tMinWidth = props.minWidth;
283
- }
284
-
285
- if (hasOwnProperty.call(paramObj, 'minHeight')) {
286
- tMinHeight = paramObj.minHeight;
287
- } else {
288
- tMinHeight = props.minHeight;
289
- }
290
-
291
- width = removeUnit(width, 'horizontal') > removeUnit(tMinWidth, 'horizontal') ? width : tMinWidth;
292
- height = removeUnit(height, 'vertical') > removeUnit(tMinHeight, 'vertical') ? height : tMinHeight;
293
-
294
- dragStyle.top = numberToUnit(top);
295
- dragStyle.left = numberToUnit(left);
296
- dragStyle.width = numberToUnit(width);
297
- dragStyle.height = numberToUnit(height);
298
- dragStyle.minWidth = numberToUnit(tMinWidth);
299
- dragStyle.minHeight = numberToUnit(tMinHeight);
300
- };
301
-
302
- const changeMouseCursor = (e) => {
303
- if (!windowRef.value || clickedInfo.pressedSpot) {
304
- return;
305
- }
306
-
307
- if (props.resizable) {
308
- const rect = windowRef.value.getBoundingClientRect();
309
- const x = e.clientX - rect.left;
310
- const y = e.clientY - rect.top;
311
- const top = y < grabbingBorderSize;
312
- const left = x < grabbingBorderSize;
313
- const right = x >= (rect.width - grabbingBorderSize);
314
- const bottom = y >= (rect.height - grabbingBorderSize);
315
-
316
- if ((top && left) || (bottom && right)) {
317
- windowRef.value.style.cursor = 'nwse-resize';
318
- } else if ((top && right) || (bottom && left)) {
319
- windowRef.value.style.cursor = 'nesw-resize';
320
- } else if (right || left) {
321
- windowRef.value.style.cursor = 'ew-resize';
322
- } else if (bottom || top) {
323
- windowRef.value.style.cursor = 'ns-resize';
324
- } else if (props.draggable && isInHeader(e.clientX, e.clientY)) {
325
- windowRef.value.style.cursor = 'move';
326
- } else {
327
- windowRef.value.style.cursor = 'default';
328
- }
329
- } else if (props.draggable && isInHeader(e.clientX, e.clientY)) {
330
- windowRef.value.style.cursor = 'move';
331
- } else {
332
- windowRef.value.style.cursor = 'default';
333
- }
334
- };
335
-
336
- // window resize
337
- const resizeWindow = (e) => {
338
- const windowWidth = window.innerWidth;
339
- const windowHeight = window.innerHeight;
340
- const isTop = grabbingBorderPosInfo.top;
341
- const isLeft = grabbingBorderPosInfo.left;
342
- const isRight = grabbingBorderPosInfo.right;
343
- const isBottom = grabbingBorderPosInfo.bottom;
344
- const minWidth = removeUnit(props.minWidth, 'horizontal');
345
- const minHeight = removeUnit(props.minHeight, 'vertical');
346
- const clientX = e.clientX >= windowWidth ? windowWidth : e.clientX;
347
- let clientY = e.clientY >= windowHeight ? windowHeight : e.clientY;
348
- clientY = e.clientY > 0 ? clientY : 0;
349
- const diffX = clientX - clickedInfo.clientX;
350
- const diffY = clientY - clickedInfo.clientY;
351
-
352
- let top = clickedInfo.top;
353
- let left = clickedInfo.left;
354
- let width = clickedInfo.width;
355
- let height = clickedInfo.height;
356
- const maxTop = (top + clickedInfo.height) - minHeight;
357
- const maxLeft = (left + clickedInfo.width) - minWidth;
358
-
359
- if (isTop) {
360
- top = clickedInfo.top + diffY;
361
- height = clickedInfo.height - diffY;
362
-
363
- if (top > maxTop) {
364
- top = maxTop;
365
- }
366
- }
367
-
368
- if (isLeft) {
369
- left = clickedInfo.left + diffX;
370
- width = clickedInfo.width - diffX;
371
-
372
- if (left > maxLeft) {
373
- left = maxLeft;
374
- }
375
- }
376
-
377
- if (isRight) {
378
- width = clickedInfo.width + diffX;
379
- }
380
-
381
- if (isBottom) {
382
- height = clickedInfo.height + diffY;
383
- }
384
-
385
- width = Math.min(Math.max(width, minWidth), windowWidth);
386
- height = Math.min(Math.max(height, minHeight), windowHeight);
387
-
388
- const positionInfo = { top, left, width, height };
389
- setDragStyle(positionInfo);
390
- emit('resize', e, { ...positionInfo });
391
- };
392
-
393
- // 브라우저 상하 위치 제약
394
- const getValidTop = (windowHeight, top) => {
395
- let tempTop = top;
396
-
397
- if (tempTop < 0) { // 상
398
- tempTop = 0;
399
- } else if (tempTop > windowHeight - draggingMinSize) { // 하
400
- tempTop = Math.floor(windowHeight - draggingMinSize);
401
- }
402
- return tempTop;
403
- };
404
- // 브라우저 좌우 위치 제약
405
- const getValidLeft = (windowWidth, left) => {
406
- let tempLeft = left;
407
- if (tempLeft < -(clickedInfo.width - draggingMinSize)) { // 좌
408
- tempLeft = -Math.floor(clickedInfo.width - draggingMinSize);
409
- } else if (tempLeft > windowWidth - draggingMinSize) { // 우
410
- tempLeft = Math.floor(windowWidth - draggingMinSize);
411
- }
412
- return tempLeft;
413
- };
414
-
415
- // mousedown > mousemove: 마우스 드래그
416
- const dragging = (e) => {
417
- e.preventDefault();
418
- clickedInfo.state = 'mousedown-mousemove';
419
-
420
- // window header를 통해 mouseMove 됐을 경우
421
- if (props.draggable && clickedInfo.pressedSpot === 'header') {
422
- const windowWidth = document.documentElement.clientWidth;
423
- const windowHeight = document.documentElement.clientHeight;
424
- const diffTop = e.clientY - clickedInfo.clientY;
425
- const diffLeft = e.clientX - clickedInfo.clientX;
426
-
427
- let tempTop = clickedInfo.top + diffTop;
428
- let tempLeft = clickedInfo.left + diffLeft;
429
-
430
- tempTop = getValidTop(windowHeight, tempTop);
431
- tempLeft = getValidLeft(windowWidth, tempLeft);
432
-
433
- setDragStyle({
434
- top: `${tempTop}px`,
435
- left: `${tempLeft}px`,
436
- width: dragStyle.width ?? props.width,
437
- height: dragStyle.height ?? props.height,
438
- });
439
- } else if (props.resizable && clickedInfo.pressedSpot === 'border') {
440
- resizeWindow(e);
441
- }
442
-
443
- emit('mousedown-mousemove', e);
444
- };
445
-
446
- // mousedown > mouseup: 마우스 드래그 종료
447
- const endDrag = (e) => {
448
- clickedInfo.state = '';
449
- clickedInfo.pressedSpot = '';
450
-
451
- emit('mousedown-mouseup', e);
452
-
453
- window.removeEventListener('mousemove', dragging);
454
- window.removeEventListener('mouseup', endDrag);
455
- };
456
-
457
- // mousedown: 드래그 시작
458
- const startDrag = (e) => {
459
- if (!windowRef.value || (!props.resizable && !props.draggable)) {
460
- return;
461
- }
462
- let pressedSpot = '';
463
- if (props.resizable) {
464
- const clientRect = windowRef.value.getBoundingClientRect();
465
- const x = e.clientX - clientRect.left;
466
- const y = e.clientY - clientRect.top;
467
- const isGrabTop = y < grabbingBorderSize;
468
- const isGrabLeft = x < grabbingBorderSize;
469
- const isGrabRight = x >= (clientRect.width - grabbingBorderSize);
470
- const isGrabBottom = y >= (clientRect.height - grabbingBorderSize);
471
-
472
- grabbingBorderPosInfo.top = isGrabTop;
473
- grabbingBorderPosInfo.left = isGrabLeft;
474
- grabbingBorderPosInfo.right = isGrabRight;
475
- grabbingBorderPosInfo.bottom = isGrabBottom;
476
-
477
- if (isGrabTop || isGrabLeft || isGrabRight || isGrabBottom) {
478
- pressedSpot = 'border';
479
- }
480
- }
481
-
482
- if (pressedSpot !== 'border' && isInHeader(e.clientX, e.clientY)) {
483
- pressedSpot = 'header';
484
- }
485
-
486
- if (!pressedSpot
487
- || (!props.draggable && pressedSpot === 'header')
488
- || (!props.resizable && pressedSpot === 'border')
489
- ) {
490
- clickedInfo.state = 'mousedown';
491
- clickedInfo.pressedSpot = '';
492
- clickedInfo.top = windowRef.value.offsetTop;
493
- clickedInfo.left = windowRef.value.offsetLeft;
494
- clickedInfo.width = windowRef.value.offsetWidth;
495
- clickedInfo.height = windowRef.value.offsetHeight;
496
- clickedInfo.clientX = e.clientX;
497
- clickedInfo.clientY = e.clientY;
498
- emit('mousedown', { ...clickedInfo, ref: windowRef.value });
499
- return;
500
- }
501
-
502
- clickedInfo.state = 'mousedown';
503
- clickedInfo.pressedSpot = pressedSpot;
504
- clickedInfo.top = windowRef.value.offsetTop;
505
- clickedInfo.left = windowRef.value.offsetLeft;
506
- clickedInfo.width = windowRef.value.offsetWidth;
507
- clickedInfo.height = windowRef.value.offsetHeight;
508
- clickedInfo.clientX = e.clientX;
509
- clickedInfo.clientY = e.clientY;
510
-
511
- emit('mousedown', { ...clickedInfo, ref: windowRef.value });
512
-
513
- window.addEventListener('mousemove', dragging);
514
- window.addEventListener('mouseup', endDrag);
515
- };
516
-
517
- const moveMouse = (e) => {
518
- if (!props.draggable && !props.resizable) {
519
- return;
520
- }
521
- changeMouseCursor(e);
522
- };
523
-
524
- const clickExpandBtn = () => {
525
- isFullExpandWindow.value = !isFullExpandWindow.value;
526
- nextTick(() => {
527
- if (isFullExpandWindow.value) {
528
- beforeExpandPosInfo.top = windowRef.value.offsetTop;
529
- beforeExpandPosInfo.left = windowRef.value.offsetLeft;
530
- beforeExpandPosInfo.width = windowRef.value.offsetWidth;
531
- beforeExpandPosInfo.height = windowRef.value.offsetHeight;
532
-
533
- setDragStyle({
534
- top: 0,
535
- left: 0,
536
- width: document.body.clientWidth,
537
- height: document.body.clientHeight,
538
- });
539
- } else {
540
- setDragStyle({
541
- top: beforeExpandPosInfo.top,
542
- left: beforeExpandPosInfo.left,
543
- width: beforeExpandPosInfo.width,
544
- height: beforeExpandPosInfo.height,
545
- });
546
- }
547
-
548
- emit('expand', {
549
- top: beforeExpandPosInfo.top,
550
- left: beforeExpandPosInfo.left,
551
- width: beforeExpandPosInfo.width,
552
- height: beforeExpandPosInfo.height,
553
- });
554
- });
555
- };
556
-
557
- const initWindowInfo = () => {
558
- isFullExpandWindow.value = false;
559
-
560
- clickedInfo.state = '';
561
- clickedInfo.pressedSpot = '';
562
- clickedInfo.top = 0;
563
- clickedInfo.left = 0;
564
- clickedInfo.width = 0;
565
- clickedInfo.height = 0;
566
- clickedInfo.clientX = 0;
567
- clickedInfo.clientY = 0;
568
-
569
- draggedInfo.top = 0;
570
- draggedInfo.left = 0;
571
-
572
- grabbingBorderPosInfo.top = false;
573
- grabbingBorderPosInfo.left = false;
574
- grabbingBorderPosInfo.right = false;
575
- grabbingBorderPosInfo.bottom = false;
576
-
577
- beforeExpandPosInfo.top = null;
578
- beforeExpandPosInfo.left = null;
579
- beforeExpandPosInfo.width = null;
580
- beforeExpandPosInfo.height = null;
581
-
582
- Object.keys(dragStyle).forEach((key) => {
583
- delete dragStyle[key];
584
- });
585
- };
586
-
587
- watch(
588
- () => props.visible,
589
- (newVal) => {
590
- if (!newVal) {
591
- initWindowInfo();
592
- }
593
- },
594
- );
595
-
596
- return {
597
- dragStyle,
598
- startDrag,
599
- moveMouse,
600
- clickExpandBtn,
601
- };
602
- };
603
-
604
- const activeWindows = (() => {
605
- let windows = [];
606
- let sequence = 0;
607
-
608
- return {
609
- add(activeWindow) {
610
- if (activeWindow === null || activeWindow === undefined) return;
611
-
612
- activeWindow.sequence = sequence++;
613
- windows.push(activeWindow);
614
-
615
- // eslint-disable-next-line consistent-return
616
- return activeWindow.sequence;
617
- },
618
- remove(inactiveWindow) {
619
- if (inactiveWindow === null || inactiveWindow === undefined) return;
620
- windows = windows.filter(activeWindow => activeWindow.sequence !== inactiveWindow.sequence);
621
- },
622
-
623
- get windows() {
624
- return windows.slice();
625
- },
626
- getWindowBySequence(targetSequence) {
627
- return windows.find(activeWindow => activeWindow.sequence === targetSequence);
628
- },
629
-
630
- isEmpty() {
631
- return windows.length <= 0;
632
- },
633
- isFirstWindowOpen() {
634
- return sequence === 1;
635
- },
636
- };
637
- })();
638
-
639
- const zIndexService = (() => {
640
- const LOWER = 700;
641
- const UPPER = 750;
642
-
643
- const INCREMENT = 1;
644
- const PADDING = INCREMENT * 2;
645
-
646
- const UPPER_LIMIT = UPPER - PADDING;
647
-
648
- let current = LOWER;
649
-
650
- return {
651
- getNext() {
652
- if (current >= UPPER_LIMIT) {
653
- return UPPER_LIMIT;
654
- }
655
- current += INCREMENT;
656
- return current;
657
- },
658
- getNextOverLimit() {
659
- return UPPER_LIMIT + INCREMENT;
660
- },
661
- getPrevFrom(index) {
662
- const prev = current - (index * INCREMENT);
663
-
664
- if (prev <= LOWER) return LOWER;
665
- return prev;
666
- },
667
- isUpperLimitClose() {
668
- return current >= UPPER_LIMIT;
669
- },
670
- resetToLower() {
671
- current = LOWER;
672
- },
673
- getAllocableCount() {
674
- return Math.floor((UPPER_LIMIT - LOWER) / INCREMENT);
675
- },
676
- };
677
- })();
678
-
679
- const getZIndexFromElement = (element) => {
680
- const zIndex = window.getComputedStyle(element).getPropertyValue('z-index').trim();
681
-
682
- if (!zIndex || isNaN(zIndex)) return 700; // window 초기 z-index 값
683
-
684
- return parseInt(zIndex);
685
- };
686
-
687
- const getActiveWindowsOrderByZIndexAsc = () => {
688
- // zIndex 클수록, 최근에 열린 것일수록(sequence 클수록) 뒤에 위치
689
- const compareByZIndex = (window1, window2) => {
690
- if (window1.zIndex > window2.zIndex) return 1;
691
- if (window1.zIndex < window2.zIndex) return -1;
692
-
693
- if (window1.sequence > window2.sequence) return 1;
694
- return -1;
695
- };
696
-
697
- const activeWindowsSorted = Array.prototype.map.call(activeWindows.windows, activeWindow => ({
698
- ...activeWindow,
699
- zIndex: getZIndexFromElement(activeWindow.elem),
700
- })).sort(compareByZIndex);
701
-
702
- return activeWindowsSorted;
703
- };
704
-
705
- const useEscCloseAndFocusable = ({ closeWin, windowRef }) => {
706
- const { props } = getCurrentInstance();
707
-
708
- let sequence = null;
709
- let timer = null;
710
-
711
- // escClose 관련 로직 시작
712
- const addActiveWindow = () => {
713
- const windowSequence = activeWindows.add({
714
- sequence,
715
- closeWin,
716
- elem: windowRef.value,
717
- escClose: props.escClose,
718
- });
719
- return windowSequence;
720
- };
721
-
722
- const removeInactiveWindow = (inactiveWindow) => {
723
- activeWindows.remove(inactiveWindow);
724
- };
725
-
726
- const keydownEsc = (event) => {
727
- if (activeWindows.isEmpty()) return;
728
-
729
- const { code } = event;
730
- if (code !== 'Escape') return;
731
-
732
- const activeWindowsSorted = getActiveWindowsOrderByZIndexAsc();
733
- const topActiveWindow = activeWindowsSorted[activeWindowsSorted.length - 1];
734
-
735
- // 예시 상황) Nested에서 외부 Window의 escClose는 true이고, 내부 Window의 escClose는 false인 경우,
736
- // esc 눌러도 외부 Window는 닫히지 않고, 가장 상단에 있는 내부 Window가 수동으로 닫힌 후에 닫히도록 하기 위해
737
- if (!topActiveWindow.escClose) return;
738
-
739
- topActiveWindow.closeWin();
740
- };
741
-
742
- const setWindowActive = () => {
743
- sequence = addActiveWindow();
744
- // DOM의 dataset에 sequence 값 추가해 식별 가능하도록
745
- windowRef.value.dataset.sequence = sequence;
746
-
747
- if (activeWindows.isFirstWindowOpen()) {
748
- document.addEventListener('keydown', keydownEsc);
749
- }
750
- };
751
-
752
- const setWindowInactive = () => {
753
- const inactiveWindow = activeWindows.getWindowBySequence(sequence);
754
- removeInactiveWindow(inactiveWindow);
755
- };
756
- // escClose 관련 로직 끝
757
-
758
-
759
- // focusable 관련 로직 시작
760
- const setZIndexToWindow = ({ elem, zIndex }) => {
761
- // 모달인 경우에는 dim layer도 같이 z-index 높여준다.
762
- if (props.isModal) {
763
- const dimLayerElem = elem.parentElement.getElementsByClassName('ev-window-dim-layer')[0];
764
- dimLayerElem.style.zIndex = zIndex;
765
- }
766
-
767
- elem.style.zIndex = zIndex;
768
- };
769
-
770
- const assignZIndex = () => {
771
- // Window가 1번째로 열릴 때, z-index 값을 시작값으로 설정
772
- if (activeWindows.windows.length === 1) {
773
- zIndexService.resetToLower();
774
- }
775
-
776
- const nextZIndex = zIndexService.getNext();
777
- setZIndexToWindow({ elem: windowRef.value, zIndex: nextZIndex });
778
- };
779
-
780
- const sameAsCurrent = windowData => String(windowData.sequence)
781
- === windowRef.value.dataset.sequence;
782
-
783
- // 할당하려는 z-index 값이 상한일 때
784
- const reassignZIndex = () => {
785
- const activeWindowsZIndexAsc = getActiveWindowsOrderByZIndexAsc();
786
-
787
- const overCountLimit = activeWindows.windows.length > zIndexService.getAllocableCount();
788
- // 할당 가능한 z-index 수보다 많은 Window를 띄웠을 때
789
- if (overCountLimit) {
790
- const activeWindowsZIndexDesc = activeWindowsZIndexAsc.reverse();
791
-
792
- // z-index 기준 내림차순으로 정렬한 Window의 z-index 값을 UPPER에서 LOWER로 1씩 감소한 값 할당
793
- let interval = 0;
794
- activeWindowsZIndexDesc.forEach((activeWindow) => {
795
- if (sameAsCurrent(activeWindow)) return;
796
-
797
- const prevZIndex = zIndexService.getPrevFrom(interval++);
798
- setZIndexToWindow({ elem: activeWindow.elem, zIndex: prevZIndex });
799
- });
800
-
801
- // 가장 상단으로 와야하는 현재 Window의 z-index 값을 최대로
802
- const nextZIndex = zIndexService.getNextOverLimit();
803
- setZIndexToWindow({ elem: windowRef.value, zIndex: nextZIndex });
804
- } else {
805
- zIndexService.resetToLower();
806
-
807
- activeWindowsZIndexAsc.forEach((activeWindow) => {
808
- if (sameAsCurrent(activeWindow)) return;
809
-
810
- const nextZIndex = zIndexService.getNext();
811
- setZIndexToWindow({ elem: activeWindow.elem, zIndex: nextZIndex });
812
- });
813
-
814
- // 가장 상단으로 와야하는 현재 Window의 z-index 값을 최대로
815
- const nextZIndex = zIndexService.getNext();
816
- setZIndexToWindow({ elem: windowRef.value, zIndex: nextZIndex });
817
- }
818
- };
819
-
820
- const checkLimitAndSetZIndex = () => {
821
- if (zIndexService.isUpperLimitClose()) {
822
- reassignZIndex();
823
- } else {
824
- assignZIndex();
825
- }
826
- };
827
-
828
- const setFocus = () => {
829
- // X 버튼을 클릭했을 때
830
- if (!windowRef.value) return;
831
-
832
- // focusable prop이 false인 경우에는 z-index를 높이지 않는다.
833
- if (!props.focusable) return;
834
-
835
- const activeWindowsSorted = getActiveWindowsOrderByZIndexAsc();
836
- const topActiveWindow = activeWindowsSorted[activeWindowsSorted.length - 1];
837
-
838
- const isAlreadyTop = sameAsCurrent(topActiveWindow);
839
- if (isAlreadyTop) return;
840
-
841
- checkLimitAndSetZIndex();
842
- };
843
- // focusable 관련 로직 끝
844
-
845
-
846
- /*
847
- 실행 시점(=Window 열림):
848
- visible 초기값이 true일 때 watch를 실행시키지 않아 onMounted hook 사용
849
- */
850
- onMounted(() => {
851
- if (props.visible) {
852
- setWindowActive();
853
- timer = setTimeout(checkLimitAndSetZIndex, 0);
854
- }
855
- });
856
-
857
- /*
858
- 실행 시점(=Window 닫힘):
859
- 예시. 배열을 통해 Window 여러 개 띄울 때, 배열 원소 삭제로 인해 해당 Window가 닫히는 경우
860
- unmount가 발생해서 watch를 실행히시키지 않아 onBeforeUnmount hook 사용
861
- */
862
- onBeforeUnmount(() => {
863
- if (props.visible) {
864
- setWindowInactive();
865
- clearTimeout(timer);
866
- }
867
- });
868
-
869
- /*
870
- 실행 시점:
871
- 1. visible 값이 false -> true로 변했을 때(=Window 열림)
872
- 2. visible 값이 true -> false로 변했을 때(=Window 닫힙)
873
- */
874
- watch(
875
- () => props.visible,
876
- (visible) => {
877
- nextTick(() => {
878
- if (visible) {
879
- // visible 값이 false -> true로 변경되었을 때
880
- setWindowActive();
881
- timer = setTimeout(checkLimitAndSetZIndex, 0);
882
- } else {
883
- // visible 값이 true -> false로 변경되었을 때
884
- setWindowInactive();
885
- clearTimeout(timer);
886
- }
887
- });
888
- });
889
-
890
- watch(
891
- () => props.escClose,
892
- (escClose) => {
893
- if (!props.visible) return;
894
- const currentWindow = activeWindows.getWindowBySequence(sequence);
895
- if (currentWindow) currentWindow.escClose = escClose;
896
- },
897
- );
898
-
899
- return {
900
- setFocus,
901
- };
902
- };
903
-
904
- export {
905
- useModel,
906
- useMouseEvent,
907
- useEscCloseAndFocusable,
908
- };