evui 3.3.2 → 3.3.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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) => {
@@ -747,14 +751,12 @@ export const filterEvent = (params) => {
747
751
  }
748
752
  const store = stores.store;
749
753
  let checkedCount = 0;
750
- for (let ix = 0; ix < store.length; ix++) {
751
- if (checkInfo.checkedIndex.has(store[ix][ROW_INDEX])) {
752
- 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]) {
753
757
  checkedCount += 1;
754
- } else {
755
- store[ix][ROW_CHECK_INDEX] = false;
756
758
  }
757
- }
759
+ });
758
760
  if (store.length && store.length === checkedCount) {
759
761
  checkInfo.isHeaderChecked = true;
760
762
  } else {
@@ -48,7 +48,7 @@
48
48
  </template>
49
49
 
50
50
  <script>
51
- import { reactive, toRefs, onMounted, onUnmounted } from 'vue';
51
+ import { reactive, toRefs, onMounted, onBeforeUnmount } from 'vue';
52
52
 
53
53
  export default {
54
54
  name: 'EvMessage',
@@ -125,8 +125,9 @@ export default {
125
125
  startTimer();
126
126
  document.addEventListener('keydown', keydown);
127
127
  });
128
- onUnmounted(() => {
128
+ onBeforeUnmount(() => {
129
129
  document.removeEventListener('keydown', keydown);
130
+ clearTimer();
130
131
  });
131
132
  return {
132
133
  startTimer,
@@ -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, onBeforeUnmount } 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,18 +199,41 @@ 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) {
199
226
  document.removeEventListener('keydown', keydown);
200
227
  }
201
228
  });
229
+ onBeforeUnmount(() => {
230
+ document.removeEventListener('keydown', keydown);
231
+ });
202
232
  return {
203
233
  closeMsg,
204
234
  ...toRefs(state),
235
+ msgRef,
236
+ hasFocus,
205
237
  };
206
238
  },
207
239
  };
@@ -55,7 +55,7 @@
55
55
  </template>
56
56
 
57
57
  <script>
58
- import { reactive, toRefs, onMounted, onUnmounted } from 'vue';
58
+ import { reactive, toRefs, onMounted, onBeforeUnmount } from 'vue';
59
59
 
60
60
  export default {
61
61
  name: 'EvNotification',
@@ -153,8 +153,9 @@ export default {
153
153
  startTimer();
154
154
  document.addEventListener('keydown', keydown);
155
155
  });
156
- onUnmounted(() => {
156
+ onBeforeUnmount(() => {
157
157
  document.removeEventListener('keydown', keydown);
158
+ clearTimer();
158
159
  });
159
160
  return {
160
161
  startTimer,
@@ -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(() => ({
@@ -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 };