evui 3.3.2 → 3.3.3

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "evui",
3
- "version": "3.3.2",
3
+ "version": "3.3.3",
4
4
  "description": "A EXEM Library project",
5
5
  "author": "exem <dev_client@ex-em.com>",
6
6
  "license": "MIT",
@@ -1,5 +1,6 @@
1
1
  <template>
2
2
  <button
3
+ ref="buttonRef"
3
4
  class="ev-button"
4
5
  :class="{
5
6
  disabled,
@@ -17,6 +18,8 @@
17
18
  </template>
18
19
 
19
20
  <script>
21
+ import { onMounted, ref } from 'vue';
22
+
20
23
  export default {
21
24
  name: 'EvButton',
22
25
  props: {
@@ -52,6 +55,19 @@ export default {
52
55
  emits: {
53
56
  click: null,
54
57
  },
58
+ setup(props) {
59
+ const buttonRef = ref(null);
60
+
61
+ onMounted(() => {
62
+ if (props.autoFocus) {
63
+ buttonRef.value.focus();
64
+ }
65
+ });
66
+
67
+ return {
68
+ buttonRef,
69
+ };
70
+ },
55
71
  };
56
72
  </script>
57
73
 
@@ -471,7 +471,7 @@ export default {
471
471
  setStore(props.rows);
472
472
  });
473
473
  onActivated(() => {
474
- updateVScroll();
474
+ onResize();
475
475
  });
476
476
  const ROW_INDEX = 0;
477
477
  const ROW_CHECK_INDEX = 1;
@@ -584,7 +584,10 @@ export default {
584
584
  watch(
585
585
  () => filterInfo.searchValue,
586
586
  (value) => {
587
- onSearch(value?.value ?? value);
587
+ const searchValue = value?.value ?? value;
588
+ if (searchValue) {
589
+ onSearch(searchValue);
590
+ }
588
591
  }, { immediate: true },
589
592
  );
590
593
  const isFilterButton = field => filterInfo.isFiltering && field !== 'db-icon' && field !== 'user-icon';
@@ -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 {
@@ -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(() => ({
@@ -70,24 +70,26 @@ export const scrollEvent = (params) => {
70
70
  const updateVScroll = () => {
71
71
  const store = stores.showTreeStore;
72
72
  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
- }
73
+ if (bodyEl) {
74
+ const rowHeight = resizeInfo.rowHeight;
75
+ const rowCount = bodyEl.clientHeight > rowHeight
76
+ ? Math.ceil(bodyEl.clientHeight / rowHeight) : store.length;
77
+ const totalScrollHeight = store.length * rowHeight;
78
+ let firstVisibleIndex = Math.floor(bodyEl.scrollTop / rowHeight);
79
+ if (firstVisibleIndex > store.length - 1) {
80
+ firstVisibleIndex = 0;
81
+ }
81
82
 
82
- const lastVisibleIndex = firstVisibleIndex + rowCount;
83
- const firstIndex = Math.max(firstVisibleIndex, 0);
84
- const lastIndex = lastVisibleIndex;
83
+ const lastVisibleIndex = firstVisibleIndex + rowCount;
84
+ const firstIndex = Math.max(firstVisibleIndex, 0);
85
+ const lastIndex = lastVisibleIndex;
85
86
 
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;
87
+ stores.viewStore = store.slice(firstIndex, lastIndex);
88
+ scrollInfo.hasVerticalScrollBar = rowCount < store.length;
89
+ scrollInfo.vScrollTopHeight = firstIndex * rowHeight;
90
+ scrollInfo.vScrollBottomHeight = totalScrollHeight - (stores.viewStore.length * rowHeight)
91
+ - scrollInfo.vScrollTopHeight;
92
+ }
91
93
  };
92
94
  /**
93
95
  * 수평 스크롤의 위치 계산 후 적용한다.
@@ -110,7 +112,7 @@ export const scrollEvent = (params) => {
110
112
  const isHorizontal = !(scrollLeft === lastLeft);
111
113
  const isVertical = !(scrollTop === lastTop);
112
114
 
113
- if (isVertical) {
115
+ if (isVertical && bodyEl.clientHeight) {
114
116
  updateVScroll();
115
117
  }
116
118
 
@@ -223,22 +225,25 @@ export const resizeEvent = (params) => {
223
225
  /**
224
226
  * grid resize 이벤트를 처리한다.
225
227
  */
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
- }
228
+ const onResize = () => {
229
+ nextTick(() => {
230
+ if (resizeInfo.adjust) {
231
+ stores.orderedColumns.map((column) => {
232
+ const item = column;
233
+
234
+ if (!props.columns[column.index].width && !item.resized) {
235
+ item.width = 0;
236
+ }
235
237
 
236
- return item;
237
- }, this);
238
- }
238
+ return item;
239
+ }, this);
240
+ }
239
241
 
240
- calculatedColumn();
241
- updateVScroll();
242
+ calculatedColumn();
243
+ if (elementInfo.body?.clientHeight) {
244
+ updateVScroll();
245
+ }
246
+ });
242
247
  };
243
248
  const onShow = (isVisible) => {
244
249
  if (isVisible) {
@@ -603,7 +608,7 @@ export const treeEvent = (params) => {
603
608
 
604
609
  nodeList.push(node);
605
610
 
606
- if (typeof parent !== 'undefined') {
611
+ if (!Object.hasOwnProperty.call(node, 'parent')) {
607
612
  node.parent = parent;
608
613
  }
609
614
  if (node.children) {
@@ -648,7 +653,7 @@ export const treeEvent = (params) => {
648
653
  };
649
654
 
650
655
  export const filterEvent = (params) => {
651
- const { checkInfo, stores, getConvertValue, calculatedColumn, updateVScroll } = params;
656
+ const { checkInfo, stores, getConvertValue, onResize } = params;
652
657
  const makeParentShow = (data) => {
653
658
  if (!data?.parent) {
654
659
  return;
@@ -735,8 +740,7 @@ export const filterEvent = (params) => {
735
740
  }
736
741
  const isCheck = store.length > 0 && store.every(n => n.checked === true);
737
742
  checkInfo.isHeaderChecked = isCheck;
738
- calculatedColumn();
739
- updateVScroll();
743
+ onResize();
740
744
  }, 500);
741
745
  };
742
746
  return { onSearch };