evui 3.4.131 → 3.4.132

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.131",
3
+ "version": "3.4.132",
4
4
  "description": "A EXEM Library project",
5
5
  "author": "exem <dev_client@ex-em.com>",
6
6
  "license": "MIT",
@@ -206,15 +206,10 @@ const modules = {
206
206
  const { groups } = this.data;
207
207
  const { seriesList } = this;
208
208
 
209
- if (this.options.legend.virtualScroll) {
210
- if (this.useTable) {
211
- this.addLegendForGroups(groups, seriesList, true);
212
- this.addStandaloneLegends(seriesList, true);
213
- } else {
214
- this.renderVisibleLegendsFrameId = requestAnimationFrame(() => {
215
- this.renderVisibleLegends();
216
- });
217
- }
209
+ if (this.options.legend.virtualScroll && !this.useTable) {
210
+ this.renderVisibleLegendsFrameId = requestAnimationFrame(() => {
211
+ this.renderVisibleLegends();
212
+ });
218
213
  } else {
219
214
  this.addLegendForGroups(groups, seriesList, this.useTable);
220
215
  this.addStandaloneLegends(seriesList, this.useTable);
@@ -362,19 +357,116 @@ const modules = {
362
357
  }
363
358
 
364
359
  const classList = {
365
- container: `ev-chart-legend${this.useTable ? '--table__container' : '-container'}`,
360
+ container: `ev-chart-legend${this.useTable ? '--table__row' : '-container'}`,
366
361
  color: `ev-chart-legend${this.useTable ? '--table__color' : '-color'}`,
367
362
  name: `ev-chart-legend${this.useTable ? '--table__name' : '-name'}`,
368
363
  value: `ev-chart-legend${this.useTable ? '--table__value' : '-value'}`,
369
364
  };
370
365
 
366
+ /**
367
+ * callback for legendBoxDOM to show/hide clicked series
368
+ *
369
+ * @param {Element} _targetDOM - target DOM
370
+ * @param {string} _inactiveColor - inactive color
371
+ * @returns {void}
372
+ */
373
+ const inactiveDomAndSeries = (_targetDOM, _inactiveColor) => {
374
+ const _colorDOM = _targetDOM?.getElementsByClassName(classList.color)[0];
375
+ const _nameDOM = _targetDOM?.getElementsByClassName(classList.name)[0];
376
+ const _valueDOMList = _targetDOM?.getElementsByClassName(classList.value);
377
+ const _series = _targetDOM?.series;
378
+
379
+ _colorDOM.style.backgroundColor = _inactiveColor;
380
+ _colorDOM.style.borderColor = _inactiveColor;
381
+ _nameDOM.style.color = _inactiveColor;
382
+ _valueDOMList?.forEach((dom) => {
383
+ dom.style.color = _inactiveColor;
384
+ });
385
+
386
+ _series.show = false;
387
+ _targetDOM.dataset.inactive = true;
388
+ };
389
+
390
+ /**
391
+ * callback for legendBoxDOM to show/hide clicked series
392
+ *
393
+ * @param {Element} _targetDOM - target DOM
394
+ * @param {string} _activeColor - active color
395
+ * @returns {void}
396
+ */
397
+ const activeDomAndSeries = (_targetDOM, _activeColor) => {
398
+ let seriesColor;
399
+
400
+ const _colorDOM = _targetDOM?.getElementsByClassName(classList.color)[0];
401
+ const _nameDOM = _targetDOM?.getElementsByClassName(classList.name)[0];
402
+ const _valueDOMList = _targetDOM?.getElementsByClassName(classList.value);
403
+ const _series = _targetDOM?.series;
404
+
405
+ if (typeof _series.color !== 'string') {
406
+ seriesColor = _series.color[_series.color.length - 1][1];
407
+ } else {
408
+ seriesColor = _series.color;
409
+ }
410
+
411
+ if (_series.type === 'line' && _series.fill) {
412
+ _colorDOM.style.height = '8px';
413
+ _colorDOM.style.backgroundColor = Util.rgbaAdjustHalfOpacity(seriesColor);
414
+ _colorDOM.style.border = `1px solid ${seriesColor}`;
415
+ } else {
416
+ _colorDOM.style.backgroundColor = seriesColor;
417
+ }
418
+
419
+ _nameDOM.style.color = _activeColor;
420
+ _valueDOMList?.forEach((dom) => {
421
+ const style = this.options.legend.table?.columns[dom.dataset.type]?.style;
422
+ dom.style.color = style?.color ? style.color : _activeColor;
423
+ });
424
+
425
+ _series.show = true;
426
+ _targetDOM.dataset.inactive = false;
427
+ };
428
+
429
+ const hideAllSeries = () => {
430
+ const legendSeries = (() => {
431
+ if (this.data.groups.at(0)) {
432
+ return this.data.groups.at(0).slice().reverse()
433
+ .filter(sId => this.seriesList[sId].showLegend)
434
+ .map(sId => [sId, this.seriesList[sId]]);
435
+ }
436
+ return Object.entries(this.seriesList)
437
+ .filter(([, series]) => series.showLegend);
438
+ })();
439
+ legendSeries.forEach(([, s]) => {
440
+ s.show = false;
441
+ });
442
+ };
443
+ const showAllSeries = () => {
444
+ const legendSeries = (() => {
445
+ if (this.data.groups.at(0)) {
446
+ return this.data.groups.at(0).slice().reverse()
447
+ .filter(sId => this.seriesList[sId].showLegend)
448
+ .map(sId => [sId, this.seriesList[sId]]);
449
+ }
450
+ return Object.entries(this.seriesList)
451
+ .filter(([, series]) => series.showLegend);
452
+ })();
453
+ legendSeries.forEach(([, s]) => {
454
+ s.show = true;
455
+ });
456
+ };
457
+
371
458
  /**
372
459
  * callback for legendBoxDOM to show/hide clicked series
373
460
  *
374
461
  * @returns {undefined}
375
462
  */
463
+ /**
464
+ * 범례 박스 클릭 이벤트 핸들러
465
+ * 시리즈의 표시/숨김을 토글하고 범례의 시각적 상태를 변경
466
+ */
376
467
  this.onLegendBoxClick = (e) => {
377
468
  const { legend: opt } = this.options;
469
+
378
470
  if (opt?.stopClickEvt) {
379
471
  return;
380
472
  }
@@ -385,59 +477,63 @@ const modules = {
385
477
  return;
386
478
  }
387
479
 
388
- const series = targetDOM?.series;
389
-
390
480
  const colorDOM = targetDOM?.getElementsByClassName(classList.color)[0];
391
481
  const nameDOM = targetDOM?.getElementsByClassName(classList.name)[0];
392
- const valueDOMList = targetDOM?.getElementsByClassName(classList.value);
393
-
394
- const isActive = !targetDOM?.className.includes('inactive');
395
- if (isActive && this.seriesInfo.count === 1) {
396
- return;
397
- }
482
+ const isActive = targetDOM?.dataset.inactive === 'false';
398
483
 
399
484
  if (!colorDOM || !nameDOM) {
400
485
  return;
401
486
  }
402
487
 
403
- if (isActive) {
404
- this.seriesInfo.count--;
488
+ // clickMode active - 클릭시 활성화
489
+ if (opt.clickMode === 'active') {
490
+ const legendContainerDOMs = Array.from(
491
+ this.legendBoxDOM.getElementsByClassName(classList.container),
492
+ );
493
+ const isActiveAll = legendContainerDOMs.every(dom => dom.dataset.inactive === 'false');
405
494
 
406
- const inactiveColor = opt.inactive;
407
- colorDOM.style.backgroundColor = inactiveColor;
408
- colorDOM.style.borderColor = inactiveColor;
409
- nameDOM.style.color = inactiveColor;
410
- valueDOMList?.forEach((dom) => {
411
- dom.style.color = inactiveColor;
412
- });
413
- } else {
414
- this.seriesInfo.count++;
495
+ if (isActiveAll) {
496
+ legendContainerDOMs.forEach((dom) => {
497
+ inactiveDomAndSeries(dom, opt.inactive);
498
+ });
499
+ hideAllSeries();
500
+
501
+ activeDomAndSeries(targetDOM, opt.color);
502
+ this.seriesInfo.count = 1;
503
+ } else if (isActive) {
504
+ inactiveDomAndSeries(targetDOM, opt.inactive);
505
+ this.seriesInfo.count--;
506
+ } else if (!isActive) {
507
+ activeDomAndSeries(targetDOM, opt.color);
508
+ this.seriesInfo.count++;
509
+ }
415
510
 
416
- let seriesColor;
417
- if (typeof series.color !== 'string') {
418
- seriesColor = series.color[series.color.length - 1][1];
419
- } else {
420
- seriesColor = series.color;
511
+ const isInactiveAll = legendContainerDOMs.every(dom => dom.dataset.inactive === 'true');
512
+
513
+ if (isInactiveAll) {
514
+ legendContainerDOMs.forEach((dom) => {
515
+ activeDomAndSeries(dom, opt.color);
516
+ });
517
+ showAllSeries();
518
+ this.seriesInfo.count = legendContainerDOMs.length;
421
519
  }
520
+ }
422
521
 
423
- if (series.type === 'line' && series.fill) {
424
- colorDOM.style.height = '8px';
425
- colorDOM.style.backgroundColor = Util.rgbaAdjustHalfOpacity(seriesColor);
426
- colorDOM.style.border = `1px solid ${seriesColor}`;
427
- } else {
428
- colorDOM.style.backgroundColor = seriesColor;
522
+ // clickMode inactive - 클릭시 비활성화
523
+ if (opt.clickMode !== 'active') {
524
+ if (isActive && this.seriesInfo.count === 1) {
525
+ return;
429
526
  }
430
527
 
431
- nameDOM.style.color = opt.color;
432
- valueDOMList?.forEach((dom) => {
433
- const style = opt.table?.columns[dom.dataset.type]?.style;
434
- dom.style.color = style?.color ? style.color : opt.color;
435
- });
528
+ if (isActive) {
529
+ inactiveDomAndSeries(targetDOM, opt.inactive);
530
+ this.seriesInfo.count--;
531
+ } else {
532
+ activeDomAndSeries(targetDOM, opt.color);
533
+ this.seriesInfo.count++;
534
+ }
436
535
  }
437
536
 
438
- series.show = !series.show;
439
- targetDOM.classList.toggle('inactive');
440
-
441
537
  if (this.brushSeries) {
442
538
  const seriesList = [...this.brushSeries.list];
443
539
  seriesList[chartIdx] = this.seriesList;
@@ -515,6 +611,73 @@ const modules = {
515
611
  if (this.isInitLegend) {
516
612
  return;
517
613
  }
614
+ const classList = {
615
+ container: `ev-chart-legend${this.useTable ? '--table__row' : '-container'}`,
616
+ color: `ev-chart-legend${this.useTable ? '--table__color' : '-color'}`,
617
+ name: `ev-chart-legend${this.useTable ? '--table__name' : '-name'}`,
618
+ };
619
+
620
+ /**
621
+ * callback for legendBoxDOM to show/hide clicked series
622
+ *
623
+ * @param {Element} _targetDOM - target DOM
624
+ * @param {string} _inactiveColor - inactive color
625
+ * @returns {void}
626
+ */
627
+ const inactiveDomAndSeries = (_targetDOM, _inactiveColor) => {
628
+ const _colorDOM = _targetDOM?.getElementsByClassName(classList.color)[0];
629
+ const _nameDOM = _targetDOM?.getElementsByClassName(classList.name)[0];
630
+ const _series = Object.values(this.seriesList)[0];
631
+ const targetId = _targetDOM?.series?.cId;
632
+
633
+ _colorDOM.style.backgroundColor = _inactiveColor;
634
+ _colorDOM.style.borderColor = _inactiveColor;
635
+ _nameDOM.style.color = _inactiveColor;
636
+
637
+ const targetIndex = _series.colorState.findIndex(colorItem => colorItem.id === targetId);
638
+ if (targetIndex > -1) {
639
+ _series.colorState[targetIndex].show = false;
640
+ }
641
+
642
+ _targetDOM.dataset.inactive = true;
643
+ };
644
+
645
+ /**
646
+ * callback for legendBoxDOM to show/hide clicked series
647
+ *
648
+ * @param {Element} _targetDOM - target DOM
649
+ * @param {string} _activeColor - active color
650
+ * @returns {void}
651
+ */
652
+ const activeDomAndSeries = (_targetDOM, _activeColor) => {
653
+ const _colorDOM = _targetDOM?.getElementsByClassName(classList.color)[0];
654
+ const _nameDOM = _targetDOM?.getElementsByClassName(classList.name)[0];
655
+ const _series = Object.values(this.seriesList)[0];
656
+ const targetId = _targetDOM?.series?.cId;
657
+
658
+ _colorDOM.style.backgroundColor = _targetDOM?.series?.color;
659
+ _nameDOM.style.color = _activeColor;
660
+
661
+ const targetIndex = _series.colorState.findIndex(colorItem => colorItem.id === targetId);
662
+ if (targetIndex > -1) {
663
+ _series.colorState[targetIndex].show = true;
664
+ }
665
+
666
+ _targetDOM.dataset.inactive = false;
667
+ };
668
+
669
+ const hideAllSeries = () => {
670
+ const series = Object.values(this.seriesList)[0];
671
+ series.colorState.forEach((colorItem) => {
672
+ colorItem.show = false;
673
+ });
674
+ };
675
+ const showAllSeries = () => {
676
+ const series = Object.values(this.seriesList)[0];
677
+ series.colorState.forEach((colorItem) => {
678
+ colorItem.show = true;
679
+ });
680
+ };
518
681
 
519
682
  /**
520
683
  * callback for legendBoxDOM to show/hide clicked series
@@ -533,36 +696,57 @@ const modules = {
533
696
  return;
534
697
  }
535
698
 
536
- const colorDOM = targetDOM?.getElementsByClassName('ev-chart-legend-color')[0];
537
- const nameDOM = targetDOM?.getElementsByClassName('ev-chart-legend-name')[0];
538
- const targetId = targetDOM?.series?.cId;
539
- const isActive = !colorDOM?.className.includes('inactive');
699
+ const colorDOM = targetDOM?.getElementsByClassName(classList.color)[0];
700
+ const nameDOM = targetDOM?.getElementsByClassName(classList.name)[0];
701
+ const isActive = targetDOM?.dataset.inactive === 'false';
540
702
  const activeCount = series.colorState.filter(colorItem => colorItem.show).length;
541
703
 
542
- if (isActive && activeCount === 1) {
543
- return;
544
- }
545
-
546
704
  if (!colorDOM || !nameDOM) {
547
705
  return;
548
706
  }
549
707
 
550
- if (isActive) {
551
- colorDOM.style.backgroundColor = opt.inactive;
552
- colorDOM.style.borderColor = opt.inactive;
553
- nameDOM.style.color = opt.inactive;
554
- } else {
555
- colorDOM.style.backgroundColor = targetDOM?.series?.color;
556
- nameDOM.style.color = opt.color;
557
- }
708
+ // clickMode active - 클릭시 활성화
709
+ if (opt.clickMode === 'active') {
710
+ const legendContainerDOMs = Array.from(
711
+ this.legendBoxDOM.getElementsByClassName(classList.container),
712
+ );
713
+ const isActiveAll = legendContainerDOMs.every(dom => dom.dataset.inactive === 'false');
558
714
 
559
- const targetIndex = series.colorState.findIndex(colorItem => colorItem.id === targetId);
560
- if (targetIndex > -1) {
561
- series.colorState[targetIndex].show = !isActive;
715
+ if (isActiveAll) {
716
+ legendContainerDOMs.forEach((dom) => {
717
+ inactiveDomAndSeries(dom, opt.inactive);
718
+ });
719
+ hideAllSeries();
720
+
721
+ activeDomAndSeries(targetDOM, opt.color);
722
+ } else if (isActive) {
723
+ inactiveDomAndSeries(targetDOM, opt.inactive);
724
+ } else if (!isActive) {
725
+ activeDomAndSeries(targetDOM, opt.color);
726
+ }
727
+
728
+ const isInactiveAll = legendContainerDOMs.every(dom => dom.dataset.inactive === 'true');
729
+
730
+ if (isInactiveAll) {
731
+ legendContainerDOMs.forEach((dom) => {
732
+ activeDomAndSeries(dom, opt.color);
733
+ });
734
+ showAllSeries();
735
+ }
562
736
  }
563
737
 
564
- colorDOM.classList.toggle('inactive');
565
- nameDOM.classList.toggle('inactive');
738
+ // clickMode inactive - 클릭시 비활성화
739
+ if (opt.clickMode !== 'active') {
740
+ if (isActive && activeCount === 1) {
741
+ return;
742
+ }
743
+
744
+ if (isActive) {
745
+ inactiveDomAndSeries(targetDOM, opt.inactive);
746
+ } else {
747
+ activeDomAndSeries(targetDOM, opt.color);
748
+ }
749
+ }
566
750
 
567
751
  this.update({
568
752
  updateSeries: false,
@@ -791,13 +975,19 @@ const modules = {
791
975
  *
792
976
  * @returns {undefined}
793
977
  */
978
+ /**
979
+ * 새로운 범례 아이템을 생성하고 범례 영역에 추가
980
+ * @param {Object} series - 시리즈 정보 객체
981
+ */
794
982
  addLegend(series) {
795
983
  const opt = this.options.legend;
984
+
796
985
  const containerDOM = document.createElement('div');
797
986
  const colorDOM = document.createElement('span');
798
987
  const nameDOM = document.createElement('div');
799
988
 
800
- containerDOM.className = `ev-chart-legend-container ${!series.show ? ' inactive' : ''}`;
989
+ containerDOM.className = 'ev-chart-legend-container';
990
+ containerDOM.dataset.inactive = !series.show;
801
991
  containerDOM.series = series;
802
992
 
803
993
  colorDOM.className = 'ev-chart-legend-color';
@@ -808,7 +998,6 @@ const modules = {
808
998
 
809
999
  nameDOM.className = 'ev-chart-legend-name';
810
1000
 
811
- // set series color
812
1001
  let seriesColor;
813
1002
  if (!series.show) {
814
1003
  seriesColor = opt.inactive;
@@ -828,6 +1017,7 @@ const modules = {
828
1017
  }
829
1018
 
830
1019
  colorDOM.dataset.type = 'color';
1020
+
831
1021
  nameDOM.style.color = opt.color;
832
1022
  nameDOM.textContent = series.name;
833
1023
  nameDOM.setAttribute('title', series.name);
@@ -842,12 +1032,14 @@ const modules = {
842
1032
  } else {
843
1033
  containerDOM.style.width = '100%';
844
1034
  }
1035
+
845
1036
  containerDOM.style.height = `${this.legendItemHeight}px`;
846
1037
  containerDOM.style.display = 'inline-block';
847
1038
  containerDOM.style.overflow = 'hidden';
848
1039
  containerDOM.dataset.type = 'container';
849
1040
 
850
1041
  this.legendBoxDOM.insertBefore(containerDOM, this.legendBottomSpacer);
1042
+
851
1043
  if (series.show) {
852
1044
  this.seriesInfo.count++;
853
1045
  }
@@ -869,7 +1061,8 @@ const modules = {
869
1061
 
870
1062
  // create row
871
1063
  const rowDOM = document.createElement('tr');
872
- rowDOM.className = `ev-chart-legend--table__row ${!series.show ? ' inactive' : ''}`;
1064
+ rowDOM.className = 'ev-chart-legend--table__row';
1065
+ rowDOM.dataset.inactive = !series.show;
873
1066
  Util.setDOMStyle(rowDOM, opt.table?.style?.row);
874
1067
  rowDOM.series = series;
875
1068
  rowDOM.dataset.type = 'container';
@@ -39,6 +39,7 @@ const DEFAULT_OPTIONS = {
39
39
  height: 24,
40
40
  allowResize: false,
41
41
  virtualScroll: false,
42
+ clickMode: 'active',
42
43
  table: {
43
44
  use: false,
44
45
  columns: {
@@ -300,9 +300,11 @@ export const useDropdown = (param) => {
300
300
  if (props.filterable) {
301
301
  filterTextRef.value = '';
302
302
  }
303
- mv.value = val;
304
303
  isDropbox.value = false;
305
- changeMv();
304
+ if (mv.value !== val) {
305
+ mv.value = val;
306
+ changeMv();
307
+ }
306
308
  };
307
309
  const multipleClickItem = (val) => {
308
310
  if (props.filterable) {