evui 3.4.56 → 3.4.58

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.4.56",
3
+ "version": "3.4.58",
4
4
  "description": "A EXEM Library project",
5
5
  "author": "exem <dev_client@ex-em.com>",
6
6
  "license": "MIT",
@@ -95,6 +95,7 @@
95
95
  const injectIsChartGroup = inject('isChartGroup', false);
96
96
  const injectBrushSeries = inject('brushSeries', { list: [], chartIdx: null });
97
97
  const injectGroupSelectedLabel = inject('groupSelectedLabel', null);
98
+ const injectGroupHoveredLabel = inject('groupHoveredLabel', null);
98
99
  const injectBrushIdx = inject('brushIdx', { start: 0, end: -1 });
99
100
  const injectEvChartPropsInGroup = inject('evChartPropsInGroup', []);
100
101
 
@@ -105,7 +106,7 @@
105
106
  selectSeriesInfo,
106
107
  getNormalizedData,
107
108
  getNormalizedOptions,
108
- } = useModel(injectGroupSelectedLabel);
109
+ } = useModel(injectGroupSelectedLabel, injectGroupHoveredLabel);
109
110
 
110
111
  const normalizedData = getNormalizedData(props.data);
111
112
  const normalizedOptions = getNormalizedOptions(props.options);
@@ -278,6 +279,19 @@
278
279
  });
279
280
  });
280
281
 
282
+ watch(() => injectGroupHoveredLabel?.value, (newHoveredLabel) => {
283
+ if (!newHoveredLabel) {
284
+ return;
285
+ }
286
+ if (props.options.syncHover !== false) {
287
+ if (newHoveredLabel.label == null) {
288
+ evChart.overlayClear();
289
+ } else {
290
+ evChart.drawSyncedIndicator(newHoveredLabel);
291
+ }
292
+ }
293
+ }, { deep: true, flush: 'post' });
294
+
281
295
  onMounted(async () => {
282
296
  if (injectEvChartPropsInGroup?.value) {
283
297
  injectEvChartPropsInGroup.value.push(props);
@@ -170,6 +170,10 @@ class EvChart {
170
170
  this.chartRect = this.getChartRect();
171
171
  }
172
172
 
173
+ drawSyncedIndicator({ horizontal, label, mousePosition }) {
174
+ this.drawSyncedIndicator({ horizontal, label, mousePosition });
175
+ }
176
+
173
177
  /**
174
178
  * To draw canvas chart, it processes several sequential jobs
175
179
  * @param {any} [hitInfo=undefined] from mousemove callback (object or object[] of undefined)
@@ -61,6 +61,12 @@ const modules = {
61
61
 
62
62
  if (indicator.use && type !== 'pie' && type !== 'scatter' && type !== 'heatMap') {
63
63
  this.drawIndicator(offset, indicator.color);
64
+ const label = this.getTimeLabel(offset);
65
+ args.hoveredLabel = {
66
+ horizontal: this.options.horizontal,
67
+ label,
68
+ mousePosition: [e.clientX, e.clientY],
69
+ };
64
70
  }
65
71
 
66
72
  if (typeof this.listeners['mouse-move'] === 'function') {
@@ -92,6 +98,7 @@ const modules = {
92
98
  if (tooltip.use) {
93
99
  this.tooltipClear();
94
100
  }
101
+ this.listeners['mouse-leave']();
95
102
  };
96
103
 
97
104
  /**
@@ -1,5 +1,6 @@
1
1
  import { convertToPercent } from '@/common/utils';
2
2
  import debounce from '@/common/utils.debounce';
3
+ import { inRange } from 'lodash-es';
3
4
  import Canvas from '../helpers/helpers.canvas';
4
5
  import Util from '../helpers/helpers.util';
5
6
 
@@ -778,6 +779,94 @@ const modules = {
778
779
  ctx.closePath();
779
780
  }
780
781
  },
782
+ /**
783
+ * Get hovered axis label with mousemove
784
+ * @param {object} offset mousemove callback
785
+ *
786
+ * @returns {number | null} hovered axis label
787
+ */
788
+ getTimeLabel(offset) {
789
+ const options = this.options;
790
+
791
+ if (
792
+ options.syncHover === false
793
+ || (!options.horizontal && !options.axesX.every(({ type }) => type === 'time'))
794
+ || (options.horizontal && !options.axesY.every(({ type }) => type === 'time'))) {
795
+ return null;
796
+ }
797
+
798
+ const fromTime = +this.data.labels?.[0];
799
+ const toTime = +this.data.labels?.[this.data.labels.length - 1];
800
+ if (fromTime == null || toTime == null) {
801
+ return null;
802
+ }
803
+
804
+ const [offsetX, offsetY] = offset;
805
+ const graphPos = {
806
+ x1: this.chartRect.x1 + this.labelOffset.left,
807
+ x2: this.chartRect.x2 - this.labelOffset.right,
808
+ y1: this.chartRect.y1 + this.labelOffset.top,
809
+ y2: this.chartRect.y2 - this.labelOffset.bottom,
810
+ };
811
+
812
+ if (options.horizontal) {
813
+ const chartHeight = graphPos.y2 - graphPos.y1;
814
+ const hoverYAxis = offsetY - graphPos.y1;
815
+ const hoverTime = ((hoverYAxis * (toTime - fromTime)) / chartHeight) + fromTime;
816
+ return Math.round(hoverTime);
817
+ }
818
+ const chartWidth = graphPos.x2 - graphPos.x1;
819
+ const hoverXAxis = offsetX - graphPos.x1;
820
+ const hoverTime = ((hoverXAxis * (toTime - fromTime)) / chartWidth) + fromTime;
821
+ return Math.round(hoverTime);
822
+ },
823
+ /**
824
+ * Draw chart indicator with other grouped chart's mousemove
825
+ * @param {object} hoveredLabel chart direction and hovered axis label
826
+ *
827
+ * @returns {undefined}
828
+ */
829
+ drawSyncedIndicator({ horizontal, label, mousePosition }) {
830
+ if (!mousePosition || !!horizontal !== !!this.options.horizontal) {
831
+ return;
832
+ }
833
+ if (
834
+ this.options.syncHover === false
835
+ || (!horizontal && !this.options.axesX.every(({ type }) => type === 'time'))
836
+ || (horizontal && !this.options.axesY.every(({ type }) => type === 'time'))) {
837
+ return;
838
+ }
839
+ const fromTime = +this.data.labels?.[0];
840
+ const toTime = +this.data.labels?.[this.data.labels.length - 1];
841
+ if (fromTime == null || toTime == null) {
842
+ return;
843
+ }
844
+ const [clientX, clientY] = mousePosition;
845
+ const { top, bottom, left, right } = this.chartDOM.getBoundingClientRect();
846
+
847
+ const isHoveredChart = inRange(clientX, left, right) && inRange(clientY, bottom, top);
848
+ if (isHoveredChart) {
849
+ return;
850
+ }
851
+
852
+ this.overlayClear();
853
+ const graphPos = {
854
+ x1: this.chartRect.x1 + this.labelOffset.left,
855
+ x2: this.chartRect.x2 - this.labelOffset.right,
856
+ y1: this.chartRect.y1 + this.labelOffset.top,
857
+ y2: this.chartRect.y2 - this.labelOffset.bottom,
858
+ };
859
+
860
+ if (horizontal) {
861
+ const chartHeight = graphPos.y2 - graphPos.y1;
862
+ const offsetY = (chartHeight * (label - fromTime)) / (toTime - fromTime) + graphPos.y1;
863
+ this.drawIndicator([graphPos.x2, offsetY], this.options.indicator.color);
864
+ } else {
865
+ const chartWidth = graphPos.x2 - graphPos.x1;
866
+ const offsetX = (chartWidth * (label - fromTime)) / (toTime - fromTime) + graphPos.x1;
867
+ this.drawIndicator([offsetX, graphPos.y2], this.options.indicator.color);
868
+ }
869
+ },
781
870
 
782
871
  /**
783
872
  * Clear tooltip canvas
@@ -253,7 +253,7 @@ const DEFAULT_DATA = {
253
253
  data: {},
254
254
  };
255
255
 
256
- export const useModel = (injectGroupSelectedLabel) => {
256
+ export const useModel = (injectGroupSelectedLabel, injectGroupHoveredLabel) => {
257
257
  const { props, emit } = getCurrentInstance();
258
258
 
259
259
  const getNormalizedOptions = (options) => {
@@ -338,9 +338,17 @@ export const useModel = (injectGroupSelectedLabel) => {
338
338
  emit('drag-select', e);
339
339
  },
340
340
  'mouse-move': async (e) => {
341
+ if (injectGroupHoveredLabel?.value) {
342
+ injectGroupHoveredLabel.value = e.hoveredLabel;
343
+ }
341
344
  await nextTick();
342
345
  emit('mouse-move', e);
343
346
  },
347
+ 'mouse-leave': () => {
348
+ if (injectGroupHoveredLabel?.value) {
349
+ injectGroupHoveredLabel.value.label = null;
350
+ }
351
+ },
344
352
  };
345
353
 
346
354
  return {
@@ -18,7 +18,7 @@
18
18
  </template>
19
19
 
20
20
  <script>
21
- import { onMounted, watch, provide, toRef, computed } from 'vue';
21
+ import { onMounted, ref, watch, provide, toRef, computed } from 'vue';
22
22
  import evChartToolbar from '../chart/ChartToolbar';
23
23
  import { useGroupModel } from './uses';
24
24
  import { useZoomModel } from '../chart/uses';
@@ -50,6 +50,7 @@ export default {
50
50
  'update:groupSelectedLabel',
51
51
  'update:zoomStartIdx',
52
52
  'update:zoomEndIdx',
53
+ 'update:groupHoveredLabel',
53
54
  ],
54
55
  setup(props, { emit }) {
55
56
  const {
@@ -70,6 +71,18 @@ export default {
70
71
  set: val => emit('update:groupSelectedLabel', val),
71
72
  });
72
73
  provide('groupSelectedLabel', groupSelectedLabel);
74
+ const groupHoveredLabel = ref(null);
75
+ provide('groupHoveredLabel', groupHoveredLabel);
76
+
77
+ watch(() => props.options.syncHover, (newSyncHover) => {
78
+ if (newSyncHover) {
79
+ groupHoveredLabel.value = { label: '', horizontal: false };
80
+ } else {
81
+ groupHoveredLabel.value = null;
82
+ }
83
+ }, {
84
+ immediate: true,
85
+ });
73
86
 
74
87
  const {
75
88
  evChartZoomOptions,
@@ -1234,7 +1234,7 @@ export default {
1234
1234
  stores.orderedColumns.map((column) => {
1235
1235
  const item = column;
1236
1236
 
1237
- if (!props.columns[column.index].width && !item.resized) {
1237
+ if (!props.columns[column.index]?.width && !item.resized) {
1238
1238
  item.width = 0;
1239
1239
  }
1240
1240
 
@@ -798,7 +798,7 @@ export default {
798
798
  stores.orderedColumns.map((column) => {
799
799
  const item = column;
800
800
 
801
- if (!props.columns[column.index].width && !item.resized) {
801
+ if (!props.columns[column.index]?.width && !item.resized) {
802
802
  item.width = 0;
803
803
  }
804
804
 
@@ -279,7 +279,7 @@ export const resizeEvent = (params) => {
279
279
  stores.orderedColumns.forEach((column) => {
280
280
  const item = column;
281
281
 
282
- if (!props.columns[column.index].width && !item.resized) {
282
+ if (!props.columns[column.index]?.width && !item.resized) {
283
283
  item.width = 0;
284
284
  }
285
285