evui 3.1.38 → 3.1.42

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 (33) hide show
  1. package/dist/evui.common.js +2699 -970
  2. package/dist/evui.common.js.map +1 -1
  3. package/dist/evui.umd.js +2699 -970
  4. package/dist/evui.umd.js.map +1 -1
  5. package/dist/evui.umd.min.js +1 -1
  6. package/dist/evui.umd.min.js.map +1 -1
  7. package/package.json +1 -1
  8. package/src/components/calendar/Calendar.vue +194 -82
  9. package/src/components/calendar/uses.js +457 -138
  10. package/src/components/chart/chart.core.js +27 -23
  11. package/src/components/chart/element/element.bar.js +28 -20
  12. package/src/components/chart/element/element.line.js +13 -0
  13. package/src/components/chart/helpers/helpers.constant.js +27 -0
  14. package/src/components/chart/helpers/helpers.util.js +2 -2
  15. package/src/components/chart/plugins/plugins.interaction.js +5 -5
  16. package/src/components/chart/plugins/plugins.legend.js +6 -3
  17. package/src/components/chart/plugins/plugins.tooltip.js +14 -1
  18. package/src/components/chart/scale/scale.js +520 -56
  19. package/src/components/chart/scale/scale.linear.js +8 -0
  20. package/src/components/chart/scale/scale.logarithmic.js +8 -0
  21. package/src/components/chart/scale/scale.step.js +148 -69
  22. package/src/components/chart/scale/scale.time.category.js +8 -0
  23. package/src/components/chart/scale/scale.time.js +8 -0
  24. package/src/components/chart/uses.js +2 -2
  25. package/src/components/contextMenu/MenuList.vue +1 -1
  26. package/src/components/datePicker/DatePicker.vue +91 -29
  27. package/src/components/datePicker/uses.js +231 -21
  28. package/src/components/grid/Grid.vue +15 -10
  29. package/src/components/tabs/Tabs.vue +12 -11
  30. package/src/components/treeGrid/TreeGrid.vue +56 -2
  31. package/src/components/treeGrid/TreeGridNode.vue +10 -1
  32. package/src/components/treeGrid/treeGrid.toolbar.vue +26 -0
  33. package/src/components/treeGrid/uses.js +66 -6
@@ -1,3 +1,5 @@
1
+ import { defaultsDeep } from 'lodash-es';
2
+ import { PLOT_BAND_OPTION, PLOT_LINE_OPTION } from '@/components/chart/helpers/helpers.constant';
1
3
  import Scale from './scale';
2
4
  import Util from '../helpers/helpers.util';
3
5
 
@@ -73,90 +75,159 @@ class StepScale extends Scale {
73
75
  const offsetCounterPoint = aPos[this.units.rectOffsetCounter(this.position)];
74
76
  const maxWidth = chartRect.chartWidth / (this.labels.length + 2);
75
77
 
76
- // label font 설정
77
- ctx.font = Util.getLabelStyle(this.labelStyle);
78
+ if (this.labelStyle?.show) {
79
+ // label font 설정
80
+ ctx.font = Util.getLabelStyle(this.labelStyle);
78
81
 
79
- if (this.type === 'x') {
80
- ctx.textAlign = 'center';
81
- ctx.textBaseline = this.position === 'top' ? 'bottom' : 'top';
82
- } else {
83
- ctx.textAlign = this.position === 'left' ? 'right' : 'left';
84
- ctx.textBaseline = 'middle';
85
- }
82
+ if (this.type === 'x') {
83
+ ctx.textAlign = 'center';
84
+ ctx.textBaseline = this.position === 'top' ? 'bottom' : 'top';
85
+ } else {
86
+ ctx.textAlign = this.position === 'left' ? 'right' : 'left';
87
+ ctx.textBaseline = 'middle';
88
+ }
86
89
 
87
- ctx.fillStyle = this.labelStyle.color;
88
- ctx.lineWidth = 1;
89
- const aliasPixel = Util.aliasPixel(ctx.lineWidth);
90
-
91
- ctx.beginPath();
92
- ctx.strokeStyle = this.axisLineColor;
93
- if (this.type === 'x') {
94
- ctx.moveTo(startPoint, offsetPoint + aliasPixel);
95
- ctx.lineTo(endPoint, offsetPoint + aliasPixel);
96
- } else {
97
- ctx.moveTo(offsetPoint + aliasPixel, startPoint);
98
- ctx.lineTo(offsetPoint + aliasPixel, endPoint);
99
- }
100
- ctx.stroke();
90
+ ctx.fillStyle = this.labelStyle.color;
91
+ ctx.lineWidth = 1;
92
+ const aliasPixel = Util.aliasPixel(ctx.lineWidth);
101
93
 
102
- if (steps === 0) {
103
- return;
104
- }
94
+ ctx.beginPath();
95
+ ctx.strokeStyle = this.axisLineColor;
96
+ if (this.type === 'x') {
97
+ ctx.moveTo(startPoint, offsetPoint + aliasPixel);
98
+ ctx.lineTo(endPoint, offsetPoint + aliasPixel);
99
+ } else {
100
+ ctx.moveTo(offsetPoint + aliasPixel, startPoint);
101
+ ctx.lineTo(offsetPoint + aliasPixel, endPoint);
102
+ }
103
+ ctx.stroke();
105
104
 
106
- const labelGap = (endPoint - startPoint) / labels.length;
107
- let labelCenter = null;
108
- let linePosition = null;
105
+ if (steps === 0) {
106
+ return;
107
+ }
109
108
 
110
- ctx.beginPath();
111
- ctx.strokeStyle = this.gridLineColor;
109
+ const labelGap = (endPoint - startPoint) / labels.length;
110
+ let labelCenter = null;
111
+ let linePosition = null;
112
112
 
113
- let labelText;
114
- let labelPoint;
113
+ ctx.beginPath();
114
+ ctx.strokeStyle = this.gridLineColor;
115
115
 
116
- labels.forEach((item, index) => {
117
- labelCenter = Math.round(startPoint + (labelGap * index));
118
- linePosition = labelCenter + aliasPixel;
119
- labelText = this.getLabelFormat(item, maxWidth);
116
+ let labelText;
117
+ let labelPoint;
120
118
 
121
- if (this.type === 'x') {
122
- labelPoint = this.position === 'top' ? offsetPoint - 10 : offsetPoint + 10;
123
- ctx.fillText(labelText, labelCenter + (labelGap / 2), labelPoint);
124
- if (this.options?.selectItem?.showLabelTip && hitInfo?.label && !this.options?.horizontal) {
125
- const selectedLabel = hitInfo.label;
126
- if (selectedLabel === labelText) {
127
- const height = Math.round(ctx.measureText(this.labelStyle?.fontSize).width);
128
- Util.showLabelTip({
129
- ctx: this.ctx,
130
- width: Math.round(ctx.measureText(selectedLabel).width) + 10,
131
- height,
132
- x: labelCenter + (labelGap / 2),
133
- y: labelPoint + (height - 2),
134
- borderRadius: 2,
135
- arrowSize: 3,
136
- text: labelText,
137
- backgroundColor: this.options?.selectItem?.labelTipStyle?.backgroundColor,
138
- textColor: this.options?.selectItem?.labelTipStyle?.textColor,
139
- });
119
+ labels.forEach((item, index) => {
120
+ labelCenter = Math.round(startPoint + (labelGap * index));
121
+ linePosition = labelCenter + aliasPixel;
122
+ labelText = this.getLabelFormat(item, maxWidth);
123
+
124
+ if (this.type === 'x') {
125
+ labelPoint = this.position === 'top' ? offsetPoint - 10 : offsetPoint + 10;
126
+ ctx.fillText(labelText, labelCenter + (labelGap / 2), labelPoint);
127
+
128
+ if (this.options?.selectItem?.showLabelTip
129
+ && hitInfo?.label
130
+ && !this.options?.horizontal
131
+ ) {
132
+ const selectedLabel = hitInfo.label;
133
+ if (selectedLabel === labelText) {
134
+ const height = Math.round(ctx.measureText(this.labelStyle?.fontSize).width);
135
+ Util.showLabelTip({
136
+ ctx: this.ctx,
137
+ width: Math.round(ctx.measureText(selectedLabel).width) + 10,
138
+ height,
139
+ x: labelCenter + (labelGap / 2),
140
+ y: labelPoint + (height - 2),
141
+ borderRadius: 2,
142
+ arrowSize: 3,
143
+ text: labelText,
144
+ backgroundColor: this.options?.selectItem?.labelTipStyle?.backgroundColor,
145
+ textColor: this.options?.selectItem?.labelTipStyle?.textColor,
146
+ });
147
+ }
148
+ }
149
+
150
+ if (index > 0 && this.showGrid) {
151
+ ctx.moveTo(linePosition, offsetPoint);
152
+ ctx.lineTo(linePosition, offsetCounterPoint);
153
+ }
154
+ } else {
155
+ labelPoint = this.position === 'left' ? offsetPoint - 10 : offsetPoint + 10;
156
+ ctx.fillText(labelText, labelPoint, labelCenter + (labelGap / 2));
157
+
158
+ if (index > 0 && this.showGrid) {
159
+ ctx.moveTo(offsetPoint, linePosition);
160
+ ctx.lineTo(offsetCounterPoint, linePosition);
140
161
  }
141
162
  }
163
+ ctx.stroke();
164
+ });
165
+
166
+ ctx.closePath();
167
+ }
168
+
169
+ // draw plot lines and plot bands
170
+ if (this.plotBands?.length || this.plotLines?.length) {
171
+ const padding = Util.aliasPixel(ctx.lineWidth) + 1;
172
+ const minX = aPos.x1 + padding;
173
+ const maxX = aPos.x2;
174
+ const minY = aPos.y1 + padding;
175
+ const maxY = aPos.y2;
176
+ const labelGap = (endPoint - startPoint) / (this.labelStyle.show ? labels.length : 1);
142
177
 
143
- if (index > 0 && this.showGrid) {
144
- ctx.moveTo(linePosition, offsetPoint);
145
- ctx.lineTo(linePosition, offsetCounterPoint);
178
+ this.plotBands?.forEach((plotBand) => {
179
+ if (!plotBand.from && !plotBand.to) {
180
+ return;
146
181
  }
147
- } else {
148
- labelPoint = this.position === 'left' ? offsetPoint - 10 : offsetPoint + 10;
149
- ctx.fillText(labelText, labelPoint, labelCenter + (labelGap / 2));
150
182
 
151
- if (index > 0 && this.showGrid) {
152
- ctx.moveTo(offsetPoint, linePosition);
153
- ctx.lineTo(offsetCounterPoint, linePosition);
183
+ const mergedPlotBandOpt = defaultsDeep({}, plotBand, PLOT_BAND_OPTION);
184
+ const { from = 0, to = labels.length, label: labelOpt } = mergedPlotBandOpt;
185
+ const fromPos = Math.round(startPoint + (labelGap * from));
186
+ const toPos = Math.round(startPoint + (labelGap * to));
187
+
188
+ this.setPlotBandStyle(mergedPlotBandOpt);
189
+
190
+ if (this.type === 'x') {
191
+ this.drawXPlotBand(fromPos, toPos, minX, maxX, minY, maxY);
192
+ } else {
193
+ this.drawYPlotBand(fromPos, toPos, minX, maxX, minY, maxY);
154
194
  }
155
- }
156
- ctx.stroke();
157
- });
158
195
 
159
- ctx.closePath();
196
+ if (labelOpt.show) {
197
+ const labelOptions = this.getNormalizedLabelOptions(chartRect, labelOpt);
198
+ const textXY = this.getPlotBandLabelPosition(fromPos, toPos, labelOptions, maxX, minY);
199
+ this.drawPlotLabel(labelOptions, textXY);
200
+ }
201
+
202
+ ctx.restore();
203
+ });
204
+
205
+ this.plotLines?.forEach((plotLine) => {
206
+ if (!plotLine.value) {
207
+ return;
208
+ }
209
+
210
+ const mergedPlotLineOpt = defaultsDeep({}, plotLine, PLOT_LINE_OPTION);
211
+ const { value, label: labelOpt } = mergedPlotLineOpt;
212
+ const dataPos = Math.round(startPoint + (labelGap * value)) + (labelGap / 2);
213
+
214
+ this.setPlotLineStyle(mergedPlotLineOpt);
215
+
216
+ if (this.type === 'x') {
217
+ this.drawXPlotLine(dataPos, minX, maxX, minY, maxY);
218
+ } else {
219
+ this.drawYPlotLine(dataPos, minX, maxX, minY, maxY);
220
+ }
221
+
222
+ if (labelOpt.show) {
223
+ const labelOptions = this.getNormalizedLabelOptions(chartRect, labelOpt);
224
+ const textXY = this.getPlotLineLabelPosition(dataPos, labelOptions, maxX, minY);
225
+ this.drawPlotLabel(labelOptions, textXY);
226
+ }
227
+
228
+ ctx.restore();
229
+ });
230
+ }
160
231
  }
161
232
 
162
233
  /**
@@ -167,6 +238,14 @@ class StepScale extends Scale {
167
238
  * @returns {string} formatted label
168
239
  */
169
240
  getLabelFormat(value, maxWidth) {
241
+ if (this.formatter) {
242
+ const formattedLabel = this.formatter(value);
243
+
244
+ if (typeof formattedLabel === 'string') {
245
+ return formattedLabel;
246
+ }
247
+ }
248
+
170
249
  return this.labelStyle.fitWidth ? this.fittingString(value, maxWidth) : value;
171
250
  }
172
251
 
@@ -17,6 +17,14 @@ class TimeCategoryScale extends Scale {
17
17
  * @returns {string} formatted label
18
18
  */
19
19
  getLabelFormat(value) {
20
+ if (this.formatter) {
21
+ const formattedLabel = this.formatter(value);
22
+
23
+ if (typeof formattedLabel === 'string') {
24
+ return formattedLabel;
25
+ }
26
+ }
27
+
20
28
  return dayjs(value).format(this.timeFormat);
21
29
  }
22
30
 
@@ -10,6 +10,14 @@ class TimeScale extends Scale {
10
10
  * @returns {string} formatted label
11
11
  */
12
12
  getLabelFormat(value) {
13
+ if (this.formatter) {
14
+ const formattedLabel = this.formatter(value);
15
+
16
+ if (typeof formattedLabel === 'string') {
17
+ return formattedLabel;
18
+ }
19
+ }
20
+
13
21
  return dayjs(value).format(this.timeFormat);
14
22
  }
15
23
 
@@ -81,9 +81,9 @@ const DEFAULT_OPTIONS = {
81
81
  tipTextColor: '#FFFFFF',
82
82
  },
83
83
  dragSelection: {
84
- use: true,
84
+ use: false,
85
85
  keepDisplay: true,
86
- fillColor: '#38acec',
86
+ fillColor: '#38ACEC',
87
87
  opacity: 0.65,
88
88
  },
89
89
  };
@@ -6,7 +6,7 @@
6
6
  :key="`${item.value}_${idx}`"
7
7
  class="ev-menu-li"
8
8
  :class="{ disabled: item.disabled }"
9
- @click="[item.click && !item.disabled ? item.click() : (() => {})()
9
+ @click="[item.click && !item.disabled ? item.click(item) : (() => {})()
10
10
  , hideAll(item.children)]"
11
11
  @mouseenter="!item.disabled ? mouseenterLi($event, item.children) : (() => {})()"
12
12
  >
@@ -4,10 +4,10 @@
4
4
  v-clickoutside="clickOutsideDropbox"
5
5
  class="ev-date-picker"
6
6
  :class="{
7
- disabled,
7
+ disabled : $props.disabled,
8
8
  }"
9
9
  >
10
- <template v-if="mode === 'date' || mode === 'dateTime'">
10
+ <template v-if="$props.mode === 'date' || $props.mode === 'dateTime'">
11
11
  <span class="ev-date-picker-prefix-icon">
12
12
  <i class="ev-icon-calendar" />
13
13
  </span>
@@ -15,8 +15,8 @@
15
15
  v-model.trim="currentValue"
16
16
  type="text"
17
17
  class="ev-input"
18
- :placeholder="placeholder"
19
- :disabled="disabled"
18
+ :placeholder="$props.placeholder"
19
+ :disabled="$props.disabled"
20
20
  @click="clickSelectInput"
21
21
  @keydown.enter.prevent="validateValue(currentValue)"
22
22
  @change="validateValue(currentValue)"
@@ -31,23 +31,23 @@
31
31
  type="text"
32
32
  class="ev-input readonly"
33
33
  readonly
34
- :placeholder="placeholder"
35
- :disabled="disabled"
34
+ :placeholder="$props.placeholder"
35
+ :disabled="$props.disabled"
36
36
  @click="clickSelectInput"
37
37
  />
38
38
  <template
39
- v-if="mode === 'dateMulti'
40
- && (options.multiType === 'date' || !options.tagShorten)"
39
+ v-if="$props.mode === 'dateMulti'
40
+ && ($props.options.multiType === 'date' || !$props.options.tagShorten)"
41
41
  >
42
42
  <div
43
43
  v-for="(item, idx) in mv"
44
44
  :key="`${item}_${idx}`"
45
45
  class="ev-select-tag"
46
- :class="{ num: options.multiType !== 'date' }"
46
+ :class="{ num: $props.options.multiType !== 'date' }"
47
47
  >
48
48
  <span class="ev-tag-name"> {{ item }} </span>
49
49
  <span
50
- v-if="options.multiType === 'date'"
50
+ v-if="$props.options.multiType === 'date'"
51
51
  class="ev-tag-suffix"
52
52
  @click.stop="[removeMv(item), changeDropboxPosition()]"
53
53
  >
@@ -68,7 +68,7 @@
68
68
  </template>
69
69
  </div>
70
70
  </template>
71
- <template v-if="clearable">
71
+ <template v-if="$props.clearable">
72
72
  <span
73
73
  v-show="isClearableIcon"
74
74
  class="ev-input-suffix"
@@ -82,17 +82,38 @@
82
82
  v-if="isDropbox"
83
83
  ref="dropbox"
84
84
  class="ev-date-picker-dropdown"
85
- :class="mode"
85
+ :class="$props.mode"
86
86
  :style="dropboxPosition"
87
87
  >
88
- <ev-calendar
89
- key="fromCalendar"
90
- v-model="mv"
91
- :mode="mode"
92
- :month-notation="monthNotation"
93
- :day-of-the-week-notation="dayOfTheWeekNotation"
94
- :options="options"
88
+ <div
89
+ v-if="usedShortcuts.length"
90
+ class="ev-date-picker-dropbox__button-layout">
91
+ <ev-button-group>
92
+ <ev-button
93
+ v-for="button in usedShortcuts"
94
+ :key="button.key"
95
+ :type="button.isActive ? 'primary' : 'default'"
96
+ @click="clickShortcut(button.key)"
97
+ >
98
+ {{ button.label }}
99
+ </ev-button>
100
+ </ev-button-group>
101
+ </div>
102
+ <div
103
+ v-if="usedShortcuts.length"
104
+ class="ev-date-picker-dropbox__divider"
95
105
  />
106
+ <div
107
+ :class="{ 'ev-date-picker-dropbox__calendar':usedShortcuts.length }">
108
+ <ev-calendar
109
+ key="fromCalendar"
110
+ v-model="mv"
111
+ :mode="$props.mode"
112
+ :month-notation="$props.monthNotation"
113
+ :day-of-the-week-notation="$props.dayOfTheWeekNotation"
114
+ :options="$props.options"
115
+ />
116
+ </div>
96
117
  </div>
97
118
  </div>
98
119
  </div>
@@ -100,7 +121,7 @@
100
121
 
101
122
  <script>
102
123
  import { datePickerClickoutside as clickoutside } from '@/directives/clickoutside';
103
- import { useModel, useDropdown } from './uses';
124
+ import { useModel, useDropdown, useShortcuts } from './uses';
104
125
 
105
126
  export default {
106
127
  name: 'EvDatePicker',
@@ -116,7 +137,8 @@ export default {
116
137
  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]/);
117
138
  if (Array.isArray(value)) {
118
139
  return value.every(v => !!(!v
119
- || (v.length === 10 && dateReg.exec(v))));
140
+ || (v.length === 10 && dateReg.exec(v)))
141
+ || (v.length === 19 && dateTimeReg.exec(v)));
120
142
  }
121
143
  return !!(!value
122
144
  || (value.length === 10 && dateReg.exec(value))
@@ -138,7 +160,7 @@ export default {
138
160
  mode: {
139
161
  type: String,
140
162
  default: 'date',
141
- validator: value => ['date', 'dateTime', 'dateMulti', 'dateRange']
163
+ validator: value => ['date', 'dateTime', 'dateMulti', 'dateRange', 'dateTimeRange']
142
164
  .indexOf(value) !== -1,
143
165
  },
144
166
  monthNotation: {
@@ -160,11 +182,20 @@ export default {
160
182
  limit: 1,
161
183
  tagShorten: false,
162
184
  }),
163
- validator: ({ multiType, multiDayLimit, disabledDate, tagShorten }) =>
164
- (multiType ? ['weekday', 'week', 'date'].indexOf(multiType) !== -1 : true)
185
+ validator: ({ multiType, multiDayLimit, disabledDate, tagShorten, timeFormat }) => {
186
+ const timeReg = new RegExp(/(HH|2[0-3]|[01][0-9]):(mm|[0-5][0-9]):(ss|[0-5][0-9])/);
187
+ return (multiType ? ['weekday', 'week', 'date'].indexOf(multiType) !== -1 : true)
165
188
  && (multiDayLimit ? typeof multiDayLimit === 'number' && multiDayLimit > 0 : true)
166
189
  && (disabledDate ? typeof disabledDate === 'function' : true)
167
- && (tagShorten !== undefined ? typeof tagShorten === 'boolean' : true),
190
+ && (tagShorten !== undefined ? typeof tagShorten === 'boolean' : true)
191
+ && Array.isArray(timeFormat)
192
+ ? timeFormat.every(v => !!(!v || timeReg.exec(v)))
193
+ : !!(!timeFormat || (timeReg.exec(timeFormat)));
194
+ },
195
+ },
196
+ shortcuts: {
197
+ type: Array,
198
+ default: () => [],
168
199
  },
169
200
  },
170
201
  emits: {
@@ -190,10 +221,20 @@ export default {
190
221
  clickSelectInput,
191
222
  clickOutsideDropbox,
192
223
  changeDropboxPosition,
193
- } = useDropdown({
224
+ } = useDropdown();
225
+
226
+ const {
227
+ usedShortcuts,
228
+ clickShortcut,
229
+ setActiveShortcut,
230
+ } = useShortcuts({
231
+ mv,
194
232
  currentValue,
233
+ clickOutsideDropbox,
195
234
  });
196
235
 
236
+ setActiveShortcut();
237
+
197
238
  return {
198
239
  mv,
199
240
  currentValue,
@@ -211,6 +252,9 @@ export default {
211
252
  clickSelectInput,
212
253
  clickOutsideDropbox,
213
254
  changeDropboxPosition,
255
+
256
+ usedShortcuts,
257
+ clickShortcut,
214
258
  };
215
259
  },
216
260
  };
@@ -329,8 +373,26 @@ export default {
329
373
  }
330
374
  }
331
375
 
332
- .ev-date-picker-dropbox-wrapper {
333
- height: 0;
334
- z-index: 100;
376
+ .ev-date-picker-dropbox {
377
+ &-wrapper {
378
+ height: 0;
379
+ z-index: 100;
380
+ }
381
+
382
+ &__button-layout {
383
+ margin: 5px;
384
+ }
385
+
386
+ &__divider {
387
+ width: 100%;
388
+ height: 2px;
389
+ margin: 8px 0;
390
+ background-color: #E5E5E5;
391
+ }
392
+
393
+ &__calendar {
394
+ height: 100%;
395
+ margin: 5px;
396
+ }
335
397
  }
336
398
  </style>