evui 3.3.0 → 3.3.4

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.
@@ -1,4 +1,4 @@
1
- import { getCurrentInstance } from 'vue';
1
+ import { getCurrentInstance, nextTick } from 'vue';
2
2
  import { isEqual, uniqBy } from 'lodash-es';
3
3
  import { numberWithComma } from '@/common/utils';
4
4
 
@@ -75,23 +75,25 @@ export const scrollEvent = (params) => {
75
75
  const updateVScroll = () => {
76
76
  const bodyEl = elementInfo.body;
77
77
  const rowHeight = resizeInfo.rowHeight;
78
- const rowCount = bodyEl.clientHeight > rowHeight
79
- ? Math.ceil(bodyEl.clientHeight / rowHeight) : stores.store.length;
80
- const totalScrollHeight = stores.store.length * rowHeight;
81
- let firstVisibleIndex = Math.floor(bodyEl.scrollTop / rowHeight);
82
- if (firstVisibleIndex > stores.store.length - 1) {
83
- firstVisibleIndex = 0;
84
- }
78
+ if (bodyEl) {
79
+ const rowCount = bodyEl.clientHeight > rowHeight
80
+ ? Math.ceil(bodyEl.clientHeight / rowHeight) : stores.store.length;
81
+ const totalScrollHeight = stores.store.length * rowHeight;
82
+ let firstVisibleIndex = Math.floor(bodyEl.scrollTop / rowHeight);
83
+ if (firstVisibleIndex > stores.store.length - 1) {
84
+ firstVisibleIndex = 0;
85
+ }
85
86
 
86
- const lastVisibleIndex = firstVisibleIndex + rowCount;
87
- const firstIndex = Math.max(firstVisibleIndex, 0);
88
- const lastIndex = lastVisibleIndex;
87
+ const lastVisibleIndex = firstVisibleIndex + rowCount;
88
+ const firstIndex = Math.max(firstVisibleIndex, 0);
89
+ const lastIndex = lastVisibleIndex;
89
90
 
90
- stores.viewStore = stores.store.slice(firstIndex, lastIndex);
91
- scrollInfo.hasVerticalScrollBar = rowCount < stores.store.length;
92
- scrollInfo.vScrollTopHeight = firstIndex * rowHeight;
93
- scrollInfo.vScrollBottomHeight = totalScrollHeight - (stores.viewStore.length * rowHeight)
94
- - scrollInfo.vScrollTopHeight;
91
+ stores.viewStore = stores.store.slice(firstIndex, lastIndex);
92
+ scrollInfo.hasVerticalScrollBar = rowCount < stores.store.length;
93
+ scrollInfo.vScrollTopHeight = firstIndex * rowHeight;
94
+ scrollInfo.vScrollBottomHeight = totalScrollHeight - (stores.viewStore.length * rowHeight)
95
+ - scrollInfo.vScrollTopHeight;
96
+ }
95
97
  };
96
98
  /**
97
99
  * 수평 스크롤의 위치 계산 후 적용한다.
@@ -114,7 +116,7 @@ export const scrollEvent = (params) => {
114
116
  const isHorizontal = !(scrollLeft === lastLeft);
115
117
  const isVertical = !(scrollTop === lastTop);
116
118
 
117
- if (isVertical && bodyEl.clientHeight) {
119
+ if (isVertical && bodyEl?.clientHeight) {
118
120
  updateVScroll();
119
121
  }
120
122
 
@@ -223,22 +225,24 @@ export const resizeEvent = (params) => {
223
225
  * grid resize 이벤트를 처리한다.
224
226
  */
225
227
  const onResize = () => {
226
- if (resizeInfo.adjust) {
227
- stores.orderedColumns.map((column) => {
228
- const item = column;
228
+ nextTick(() => {
229
+ if (resizeInfo.adjust) {
230
+ stores.orderedColumns.map((column) => {
231
+ const item = column;
229
232
 
230
- if (!props.columns[column.index].width && !item.resized) {
231
- item.width = 0;
232
- }
233
+ if (!props.columns[column.index].width && !item.resized) {
234
+ item.width = 0;
235
+ }
233
236
 
234
- return item;
235
- }, this);
236
- }
237
+ return item;
238
+ }, this);
239
+ }
237
240
 
238
- calculatedColumn();
239
- if (elementInfo.body?.clientHeight) {
240
- updateVScroll();
241
- }
241
+ calculatedColumn();
242
+ if (elementInfo.body?.clientHeight) {
243
+ updateVScroll();
244
+ }
245
+ });
242
246
  };
243
247
 
244
248
  const onShow = (isVisible) => {
@@ -496,21 +500,32 @@ export const sortEvent = (params) => {
496
500
  const index = getColumnIndex(sortInfo.sortField);
497
501
  const type = props.columns[index]?.type || 'string';
498
502
  const sortFn = sortInfo.sortOrder === 'desc' ? setDesc : setAsc;
499
- if (type === 'string') {
500
- stores.store.sort((a, b) => {
501
- if (typeof a[ROW_DATA_INDEX][index] === 'string') {
502
- return sortFn(a[ROW_DATA_INDEX][index]?.toLowerCase(),
503
- b[ROW_DATA_INDEX][index]?.toLowerCase());
504
- }
505
- return 0;
506
- });
507
- } else {
508
- stores.store.sort((a, b) => {
509
- if (typeof a[ROW_DATA_INDEX][index] === 'number') {
510
- return sortFn(a[ROW_DATA_INDEX][index], b[ROW_DATA_INDEX][index]);
511
- }
512
- return 0;
513
- });
503
+ switch (type) {
504
+ case 'string':
505
+ stores.store.sort((a, b) => {
506
+ if (typeof a[ROW_DATA_INDEX][index] === 'string') {
507
+ return sortFn(a[ROW_DATA_INDEX][index]?.toLowerCase(),
508
+ b[ROW_DATA_INDEX][index]?.toLowerCase());
509
+ }
510
+ return 0;
511
+ });
512
+ break;
513
+ case 'stringNumber':
514
+ stores.store.sort((a, b) => {
515
+ if (typeof a[ROW_DATA_INDEX][index] === 'string' || typeof a[ROW_DATA_INDEX][index] === 'number') {
516
+ return sortFn(Number(a[ROW_DATA_INDEX][index]), Number(b[ROW_DATA_INDEX][index]));
517
+ }
518
+ return 0;
519
+ });
520
+ break;
521
+ default:
522
+ stores.store.sort((a, b) => {
523
+ if (typeof a[ROW_DATA_INDEX][index] === 'number' || typeof a[ROW_DATA_INDEX][index] === 'boolean') {
524
+ return sortFn(a[ROW_DATA_INDEX][index], b[ROW_DATA_INDEX][index]);
525
+ }
526
+ return 0;
527
+ });
528
+ break;
514
529
  }
515
530
  };
516
531
  return { onSort, setSort };
@@ -736,14 +751,12 @@ export const filterEvent = (params) => {
736
751
  }
737
752
  const store = stores.store;
738
753
  let checkedCount = 0;
739
- for (let ix = 0; ix < store.length; ix++) {
740
- if (checkInfo.checkedIndex.has(store[ix][ROW_INDEX])) {
741
- store[ix][ROW_CHECK_INDEX] = true;
754
+ store.forEach((row) => {
755
+ row[ROW_CHECK_INDEX] = checkInfo.checkedRows.includes(row[ROW_DATA_INDEX]);
756
+ if (row[ROW_CHECK_INDEX]) {
742
757
  checkedCount += 1;
743
- } else {
744
- store[ix][ROW_CHECK_INDEX] = false;
745
758
  }
746
- }
759
+ });
747
760
  if (store.length && store.length === checkedCount) {
748
761
  checkInfo.isHeaderChecked = true;
749
762
  } else {
@@ -14,11 +14,12 @@
14
14
  ref="msgRef"
15
15
  class="ev-message-box"
16
16
  :class="{
17
- [`type-${type}`]: !!type,
18
- 'show-close': showClose,
19
- 'has-icon': !!iconClass,
20
- 'has-title': !!title,
21
- }"
17
+ [`type-${type}`]: !!type,
18
+ 'show-close': showClose,
19
+ 'has-icon': !!iconClass,
20
+ 'has-title': !!title,
21
+ }"
22
+ tabindex="-1"
22
23
  >
23
24
  <span
24
25
  v-if="iconClass"
@@ -52,6 +53,7 @@
52
53
  v-if="showCancelBtn"
53
54
  size="small"
54
55
  class="ev-message-box-cancel"
56
+ :auto-focus="hasFocus('cancelBtn')"
55
57
  @click="closeMsg('cancel')"
56
58
  >
57
59
  {{ cancelBtnText }}
@@ -61,6 +63,7 @@
61
63
  type="primary"
62
64
  size="small"
63
65
  class="ev-message-box-confirm"
66
+ :auto-focus="hasFocus('confirmBtn')"
64
67
  @click="closeMsg('ok')"
65
68
  >
66
69
  {{ confirmBtnText }}
@@ -80,7 +83,7 @@
80
83
  </template>
81
84
 
82
85
  <script>
83
- import { reactive, toRefs, watch, onMounted } from 'vue';
86
+ import { reactive, toRefs, watch, onMounted, ref } from 'vue';
84
87
  import EvButton from '@/components/button/Button.vue';
85
88
 
86
89
  export default {
@@ -142,8 +145,14 @@ export default {
142
145
  type: Function,
143
146
  default: null,
144
147
  },
148
+ focusable: {
149
+ type: Boolean,
150
+ default: false,
151
+ },
145
152
  },
146
153
  setup(props) {
154
+ const msgRef = ref(null);
155
+
147
156
  const state = reactive({
148
157
  isShow: true,
149
158
  iconClass: '',
@@ -190,9 +199,27 @@ export default {
190
199
  }
191
200
  };
192
201
 
202
+ const hasFocus = (type) => {
203
+ if (!props.focusable) return false;
204
+
205
+ switch (type) {
206
+ case 'confirmBtn':
207
+ return props.showConfirmBtn;
208
+ case 'cancelBtn':
209
+ return !props.showConfirmBtn && props.showCancelBtn;
210
+ case 'messagebox':
211
+ return !props.showConfirmBtn && !props.showCancelBtn;
212
+ default:
213
+ return false;
214
+ }
215
+ };
216
+
193
217
  onMounted(() => {
194
218
  setState();
195
219
  document.addEventListener('keydown', keydown);
220
+ if (hasFocus('messagebox')) {
221
+ msgRef.value.focus();
222
+ }
196
223
  });
197
224
  watch(() => state.isShow, (val) => {
198
225
  if (!val) {
@@ -202,6 +229,8 @@ export default {
202
229
  return {
203
230
  closeMsg,
204
231
  ...toRefs(state),
232
+ msgRef,
233
+ hasFocus,
205
234
  };
206
235
  },
207
236
  };
@@ -332,13 +332,13 @@ export default {
332
332
 
333
333
  const {
334
334
  onSearch,
335
- } = filterEvent({ checkInfo, stores, getConvertValue, calculatedColumn, updateVScroll });
335
+ } = filterEvent({ checkInfo, stores, getConvertValue, onResize });
336
336
 
337
337
  onMounted(() => {
338
338
  stores.treeStore = setTreeNodeStore();
339
339
  });
340
340
  onActivated(() => {
341
- updateVScroll();
341
+ onResize();
342
342
  });
343
343
  watch(
344
344
  () => props.checked,
@@ -377,7 +377,6 @@ export default {
377
377
  stores.treeRows = newData;
378
378
  stores.treeStore = setTreeNodeStore();
379
379
  onResize();
380
- updateVScroll();
381
380
  }, { deep: true },
382
381
  );
383
382
  watch(
@@ -400,7 +399,10 @@ export default {
400
399
  watch(
401
400
  () => searchValue.value,
402
401
  (value) => {
403
- onSearch(value?.value ?? value);
402
+ const searchWord = value?.value ?? value;
403
+ if (searchWord) {
404
+ onSearch(searchWord);
405
+ }
404
406
  }, { immediate: true },
405
407
  );
406
408
  const gridStyle = computed(() => ({
@@ -198,7 +198,7 @@
198
198
  text-align: right;
199
199
  }
200
200
  &.string,
201
- &.stringnumber {
201
+ &.stringNumber {
202
202
  text-align: left;
203
203
  }
204
204
  &.center {
@@ -1,4 +1,5 @@
1
1
  import { getCurrentInstance, nextTick } from 'vue';
2
+ import { cloneDeep } from 'lodash-es';
2
3
  import { numberWithComma } from '@/common/utils';
3
4
 
4
5
  export const commonFunctions = () => {
@@ -70,24 +71,26 @@ export const scrollEvent = (params) => {
70
71
  const updateVScroll = () => {
71
72
  const store = stores.showTreeStore;
72
73
  const bodyEl = elementInfo.body;
73
- const rowHeight = resizeInfo.rowHeight;
74
- const rowCount = bodyEl.clientHeight > rowHeight
75
- ? Math.ceil(bodyEl.clientHeight / rowHeight) : store.length;
76
- const totalScrollHeight = store.length * rowHeight;
77
- let firstVisibleIndex = Math.floor(bodyEl.scrollTop / rowHeight);
78
- if (firstVisibleIndex > store.length - 1) {
79
- firstVisibleIndex = 0;
80
- }
74
+ if (bodyEl) {
75
+ const rowHeight = resizeInfo.rowHeight;
76
+ const rowCount = bodyEl.clientHeight > rowHeight
77
+ ? Math.ceil(bodyEl.clientHeight / rowHeight) : store.length;
78
+ const totalScrollHeight = store.length * rowHeight;
79
+ let firstVisibleIndex = Math.floor(bodyEl.scrollTop / rowHeight);
80
+ if (firstVisibleIndex > store.length - 1) {
81
+ firstVisibleIndex = 0;
82
+ }
81
83
 
82
- const lastVisibleIndex = firstVisibleIndex + rowCount;
83
- const firstIndex = Math.max(firstVisibleIndex, 0);
84
- const lastIndex = lastVisibleIndex;
84
+ const lastVisibleIndex = firstVisibleIndex + rowCount;
85
+ const firstIndex = Math.max(firstVisibleIndex, 0);
86
+ const lastIndex = lastVisibleIndex;
85
87
 
86
- stores.viewStore = store.slice(firstIndex, lastIndex);
87
- scrollInfo.hasVerticalScrollBar = rowCount < store.length;
88
- scrollInfo.vScrollTopHeight = firstIndex * rowHeight;
89
- scrollInfo.vScrollBottomHeight = totalScrollHeight - (stores.viewStore.length * rowHeight)
90
- - scrollInfo.vScrollTopHeight;
88
+ stores.viewStore = store.slice(firstIndex, lastIndex);
89
+ scrollInfo.hasVerticalScrollBar = rowCount < store.length;
90
+ scrollInfo.vScrollTopHeight = firstIndex * rowHeight;
91
+ scrollInfo.vScrollBottomHeight = totalScrollHeight - (stores.viewStore.length * rowHeight)
92
+ - scrollInfo.vScrollTopHeight;
93
+ }
91
94
  };
92
95
  /**
93
96
  * 수평 스크롤의 위치 계산 후 적용한다.
@@ -110,7 +113,7 @@ export const scrollEvent = (params) => {
110
113
  const isHorizontal = !(scrollLeft === lastLeft);
111
114
  const isVertical = !(scrollTop === lastTop);
112
115
 
113
- if (isVertical) {
116
+ if (isVertical && bodyEl.clientHeight) {
114
117
  updateVScroll();
115
118
  }
116
119
 
@@ -223,22 +226,25 @@ export const resizeEvent = (params) => {
223
226
  /**
224
227
  * grid resize 이벤트를 처리한다.
225
228
  */
226
- const onResize = async () => {
227
- await nextTick();
228
- if (resizeInfo.adjust) {
229
- stores.orderedColumns.map((column) => {
230
- const item = column;
231
-
232
- if (!props.columns[column.index].width && !item.resized) {
233
- item.width = 0;
234
- }
229
+ const onResize = () => {
230
+ nextTick(() => {
231
+ if (resizeInfo.adjust) {
232
+ stores.orderedColumns.map((column) => {
233
+ const item = column;
234
+
235
+ if (!props.columns[column.index].width && !item.resized) {
236
+ item.width = 0;
237
+ }
235
238
 
236
- return item;
237
- }, this);
238
- }
239
+ return item;
240
+ }, this);
241
+ }
239
242
 
240
- calculatedColumn();
241
- updateVScroll();
243
+ calculatedColumn();
244
+ if (elementInfo.body?.clientHeight) {
245
+ updateVScroll();
246
+ }
247
+ });
242
248
  };
243
249
  const onShow = (isVisible) => {
244
250
  if (isVisible) {
@@ -603,11 +609,12 @@ export const treeEvent = (params) => {
603
609
 
604
610
  nodeList.push(node);
605
611
 
606
- if (typeof parent !== 'undefined') {
612
+ if (!Object.hasOwnProperty.call(node, 'parent')) {
607
613
  node.parent = parent;
608
614
  }
609
615
  if (node.children) {
610
616
  node.hasChild = true;
617
+ node.children = cloneDeep(node.children);
611
618
  node.children.forEach(child =>
612
619
  setNodeData({
613
620
  node: child,
@@ -648,7 +655,7 @@ export const treeEvent = (params) => {
648
655
  };
649
656
 
650
657
  export const filterEvent = (params) => {
651
- const { checkInfo, stores, getConvertValue, calculatedColumn, updateVScroll } = params;
658
+ const { checkInfo, stores, getConvertValue, onResize } = params;
652
659
  const makeParentShow = (data) => {
653
660
  if (!data?.parent) {
654
661
  return;
@@ -735,8 +742,7 @@ export const filterEvent = (params) => {
735
742
  }
736
743
  const isCheck = store.length > 0 && store.every(n => n.checked === true);
737
744
  checkInfo.isHeaderChecked = isCheck;
738
- calculatedColumn();
739
- updateVScroll();
745
+ onResize();
740
746
  }, 500);
741
747
  };
742
748
  return { onSearch };
@@ -433,8 +433,8 @@ const useMouseEvent = (param) => {
433
433
  setDragStyle({
434
434
  top: `${tempTop}px`,
435
435
  left: `${tempLeft}px`,
436
- width: props.width,
437
- height: props.height,
436
+ width: dragStyle.width ?? props.width,
437
+ height: dragStyle.height ?? props.height,
438
438
  });
439
439
  } else if (props.resizable && clickedInfo.pressedSpot === 'border') {
440
440
  resizeWindow(e);