mdt-charts 1.13.2 → 1.14.0

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 (82) hide show
  1. package/README.md +1 -189
  2. package/lib/config/config.d.ts +28 -6
  3. package/lib/designer/designerConfig.d.ts +20 -2
  4. package/lib/engine/block/blockSvg.d.ts +3 -1
  5. package/lib/engine/block/blockSvg.js +8 -3
  6. package/lib/engine/block/defs.d.ts +7 -0
  7. package/lib/engine/block/defs.js +18 -0
  8. package/lib/engine/cardsNotation/card/cardService.js +2 -2
  9. package/lib/engine/elementHighlighter/elementHighlighter.js +2 -1
  10. package/lib/engine/features/axis/axis.js +6 -3
  11. package/lib/engine/features/axis/axisHelper.d.ts +2 -2
  12. package/lib/engine/features/axis/axisHelper.js +6 -11
  13. package/lib/engine/features/axis/axisLabelDomHelper.js +9 -11
  14. package/lib/engine/features/legend/legend.d.ts +17 -12
  15. package/lib/engine/features/legend/legend.js +38 -22
  16. package/lib/engine/features/legend/legendDomHelper.d.ts +8 -4
  17. package/lib/engine/features/legend/legendDomHelper.js +20 -8
  18. package/lib/engine/features/legend/legendEventsManager.d.ts +2 -2
  19. package/lib/engine/features/legend/legendEventsManager.js +5 -5
  20. package/lib/engine/features/legend/legendHelper.d.ts +6 -3
  21. package/lib/engine/features/legend/legendHelper.js +5 -7
  22. package/lib/engine/features/legend/legendMarkerCreator.d.ts +21 -0
  23. package/lib/engine/features/legend/legendMarkerCreator.js +88 -0
  24. package/lib/engine/features/legend/legendWidthCalculator.d.ts +16 -0
  25. package/lib/engine/features/legend/legendWidthCalculator.js +119 -0
  26. package/lib/engine/features/tolltip/tooltip.js +2 -5
  27. package/lib/engine/features/tolltip/tooltipDomHelper.d.ts +4 -4
  28. package/lib/engine/features/tolltip/tooltipDomHelper.js +13 -26
  29. package/lib/engine/helpers/domHelper.js +1 -1
  30. package/lib/engine/helpers/pipeline/Pipeline.d.ts +9 -0
  31. package/lib/engine/helpers/pipeline/Pipeline.js +37 -0
  32. package/lib/engine/intervalNotation/intervalManager.js +0 -2
  33. package/lib/engine/polarNotation/polarManager.js +3 -3
  34. package/lib/engine/twoDimensionalNotation/bar/bar.d.ts +16 -13
  35. package/lib/engine/twoDimensionalNotation/bar/bar.js +30 -18
  36. package/lib/engine/twoDimensionalNotation/bar/barHelper.d.ts +3 -0
  37. package/lib/engine/twoDimensionalNotation/bar/barHelper.js +9 -0
  38. package/lib/engine/twoDimensionalNotation/line/line.d.ts +22 -11
  39. package/lib/engine/twoDimensionalNotation/line/line.js +33 -17
  40. package/lib/engine/twoDimensionalNotation/line/lineGenerator.d.ts +15 -0
  41. package/lib/engine/twoDimensionalNotation/line/lineGenerator.js +27 -0
  42. package/lib/engine/twoDimensionalNotation/line/lineHelper.d.ts +18 -4
  43. package/lib/engine/twoDimensionalNotation/line/lineHelper.js +26 -16
  44. package/lib/engine/twoDimensionalNotation/twoDimensionalManager.js +13 -12
  45. package/lib/model/featuresModel/axisModel.d.ts +2 -1
  46. package/lib/model/featuresModel/axisModel.js +11 -1
  47. package/lib/model/featuresModel/legendModel/legendModel.d.ts +2 -1
  48. package/lib/model/featuresModel/legendModel/legendModel.js +5 -1
  49. package/lib/model/featuresModel/otherComponents.d.ts +2 -1
  50. package/lib/model/featuresModel/otherComponents.js +1 -1
  51. package/lib/model/featuresModel/scaleModel/scaleModel.d.ts +2 -1
  52. package/lib/model/featuresModel/scaleModel/scaleModel.js +4 -2
  53. package/lib/model/margin/marginModel.d.ts +6 -3
  54. package/lib/model/margin/marginModel.js +12 -8
  55. package/lib/model/margin/twoDim/twoDimMarginModel.d.ts +6 -3
  56. package/lib/model/margin/twoDim/twoDimMarginModel.js +30 -29
  57. package/lib/model/model.d.ts +56 -4
  58. package/lib/model/model.js +7 -1
  59. package/lib/model/modelBuilder.js +11 -6
  60. package/lib/model/modelInstance/configReader.d.ts +19 -0
  61. package/lib/model/modelInstance/configReader.js +35 -0
  62. package/lib/model/modelInstance/dataModel/dataModel.d.ts +2 -2
  63. package/lib/model/modelInstance/dataModel/dataModel.js +0 -1
  64. package/lib/model/modelInstance/dataModel/dataRepository.d.ts +6 -2
  65. package/lib/model/modelInstance/dataModel/dataRepository.js +15 -2
  66. package/lib/model/modelInstance/modelInstance.d.ts +2 -1
  67. package/lib/model/modelInstance/modelInstance.js +6 -4
  68. package/lib/model/notations/cards/cardsChangeService.js +2 -2
  69. package/lib/model/notations/cards/cardsModelService.js +1 -1
  70. package/lib/model/notations/intervalModel.js +4 -3
  71. package/lib/model/notations/polar/polarModel.js +6 -1
  72. package/lib/model/notations/twoDimensional/styles.d.ts +6 -0
  73. package/lib/model/notations/twoDimensional/styles.js +41 -0
  74. package/lib/model/notations/twoDimensionalModel.d.ts +5 -5
  75. package/lib/model/notations/twoDimensionalModel.js +13 -8
  76. package/lib/style/charts-main.css +3 -0
  77. package/lib/style/charts-main.less +3 -0
  78. package/package.json +5 -5
  79. package/lib/engine/contentManager.d.ts +0 -9
  80. package/lib/engine/contentManager.js +0 -29
  81. package/lib/model/modelInstance/canvasModel/marginModelService.d.ts +0 -11
  82. package/lib/model/modelInstance/canvasModel/marginModelService.js +0 -26
@@ -1,46 +1,58 @@
1
+ import { select } from "d3-selection";
1
2
  import { ColorReader } from "../../colorReader/colorReader";
2
3
  import { SelectionCondition } from "../../helpers/domHelper";
3
4
  import { LegendDomHelper } from "./legendDomHelper";
4
5
  import { LegendEventsManager } from "./legendEventsManager";
5
6
  import { LegendHelper } from "./legendHelper";
7
+ import { LegendMarkerCreator } from "./legendMarkerCreator";
6
8
  export class Legend {
7
- static render(block, data, options, model) {
9
+ constructor() {
10
+ this.markerCreator = new LegendMarkerCreator();
11
+ }
12
+ static get() {
13
+ return new Legend();
14
+ }
15
+ render(block, data, options, model) {
8
16
  if (options.legend.position !== 'off') {
9
17
  const legendObject = this.renderObject(block, options.legend.position, model.otherComponents.legendBlock, model.blockCanvas.size);
10
- this.setContent(block, data, options, legendObject);
18
+ this.setContent(block, data, options, legendObject, model.otherComponents.legendBlock);
11
19
  }
12
20
  }
13
- static update(block, data, model) {
14
- if (model.options.type != "card" && model.options.legend.position !== 'off') {
21
+ update(block, data, model) {
22
+ if (model.options.legend.position !== 'off') {
15
23
  const legendObject = this.getObject(block);
16
24
  const legendCoordinate = LegendHelper.getLegendCoordinateByPosition(model.options.legend.position, model.otherComponents.legendBlock, model.blockCanvas.size);
17
25
  this.fillCoordinate(legendObject, legendCoordinate);
18
26
  this.removeContent(legendObject);
19
- this.setContent(block, data, model.options, legendObject);
27
+ this.setContent(block, data, model.options, legendObject, model.otherComponents.legendBlock);
20
28
  }
21
29
  }
22
- static updateColors(block, options) {
30
+ updateColors(block, options) {
23
31
  if (options.type === "polar" && ColorReader.isNeedReadFromData(options.charts[0]))
24
32
  return;
25
33
  const legendObject = this.getObject(block);
26
34
  const colors = LegendHelper.getMarksColor(options);
27
35
  const itemWrappers = legendObject
28
- .selectAll(`.${this.itemClass}`);
29
- LegendDomHelper.setItemsColors(itemWrappers, colors);
36
+ .selectAll(`.${Legend.itemClass}`);
37
+ const markerCreator = this.markerCreator;
38
+ itemWrappers.each(function (d, i) {
39
+ const selection = select(this);
40
+ markerCreator.updateColorForItem(selection, Object.assign(Object.assign({}, d), { color: colors[i % colors.length] }));
41
+ });
30
42
  }
31
43
  static getItemsByKeys(block, keys, condition = SelectionCondition.Include) {
32
44
  return block
33
45
  .getSvg()
34
46
  .selectAll(`.${this.itemClass}`)
35
47
  .filter(d => {
36
- const index = keys.findIndex(k => k === d);
48
+ const index = keys.findIndex(k => k === d.textContent);
37
49
  return condition === SelectionCondition.Include ? index !== -1 : index === -1;
38
50
  });
39
51
  }
40
- static setContent(block, data, options, legendObject) {
52
+ setContent(block, data, options, legendObject, legendBlockModel) {
41
53
  const items = LegendHelper.getLegendItemsContent(options, data);
42
54
  const colors = LegendHelper.getMarksColor(options, data[options.data.dataSource]);
43
- const renderingOptions = LegendHelper.getContentRenderingOptions(options.type, options.legend.position);
55
+ const renderingOptions = LegendHelper.getContentRenderingOptions(options.type, options.legend.position, legendBlockModel);
44
56
  const itemBlocks = this.renderContent(legendObject, items, colors, renderingOptions);
45
57
  if (options.type === 'polar') {
46
58
  LegendEventsManager.setListeners(block, options.data.keyField.name, itemBlocks, options.selectable);
@@ -49,7 +61,7 @@ export class Legend {
49
61
  LegendDomHelper.setItemsTitles(itemBlocks);
50
62
  }
51
63
  }
52
- static renderObject(block, legendPosition, legendBlockModel, blockSize) {
64
+ renderObject(block, legendPosition, legendBlockModel, blockSize) {
53
65
  const legendObject = block.getSvg()
54
66
  .append('foreignObject')
55
67
  .attr('class', Legend.objectClass);
@@ -57,35 +69,38 @@ export class Legend {
57
69
  this.fillCoordinate(legendObject, legendCoordinate);
58
70
  return legendObject;
59
71
  }
60
- static renderContent(foreignObject, items, colorPalette, options) {
72
+ renderContent(foreignObject, items, colorPalette, options) {
61
73
  const wrapper = foreignObject.append('xhtml:div');
62
74
  wrapper.classed(options.wrapperClasses.join(" "), true);
63
75
  const itemWrappers = wrapper
64
- .selectAll(`.${this.itemClass}`)
76
+ .selectAll(`.${Legend.itemClass}`)
65
77
  .data(items)
66
78
  .enter()
67
79
  .append('div');
68
80
  itemWrappers.classed(options.itemsOptions.wrapperClasses.join(" "), true);
81
+ const markerCreator = this.markerCreator;
69
82
  itemWrappers
70
- .append('span')
71
- .classed(options.itemsOptions.markerClass, true);
72
- LegendDomHelper.setItemsColors(itemWrappers, colorPalette);
83
+ .each(function (d, i) {
84
+ const selection = select(this);
85
+ const markers = markerCreator.create(selection, Object.assign(Object.assign({}, d), { color: colorPalette[i % colorPalette.length] }));
86
+ markers.classed(options.itemsOptions.markerClass, true);
87
+ });
73
88
  itemWrappers
74
89
  .append('span')
75
90
  .attr('class', options.itemsOptions.labelClass)
76
- .text(d => d);
91
+ .text(d => d.textContent);
77
92
  if (options.shouldCropLabels)
78
93
  LegendDomHelper.cropRowLabels(foreignObject, itemWrappers);
79
94
  return itemWrappers;
80
95
  }
81
- static getObject(block) {
96
+ getObject(block) {
82
97
  return block.getSvg()
83
98
  .select(`foreignObject.${Legend.objectClass}`);
84
99
  }
85
- static removeContent(legendObject) {
100
+ removeContent(legendObject) {
86
101
  legendObject.select(`.${Legend.legendBlockClass}`).remove();
87
102
  }
88
- static fillCoordinate(legendBlock, coordinate) {
103
+ fillCoordinate(legendBlock, coordinate) {
89
104
  legendBlock
90
105
  .attr('x', coordinate.x)
91
106
  .attr('y', coordinate.y)
@@ -96,5 +111,6 @@ export class Legend {
96
111
  Legend.objectClass = 'legend-object';
97
112
  Legend.labelClass = 'legend-label';
98
113
  Legend.itemClass = 'legend-item';
99
- Legend.markerClass = 'legend-circle';
114
+ Legend.markerClass = 'legend-marker';
115
+ Legend.markerCircle = 'legend-circle';
100
116
  Legend.legendBlockClass = 'legend-block';
@@ -1,8 +1,12 @@
1
1
  import { BaseType, Selection } from "d3-selection";
2
+ import { ChartLegendEngineModel } from "./legendHelper";
3
+ import { StaticLegendBlockCanvas } from "../../../designer/designerConfig";
4
+ export declare type LegendItemSelection = Selection<HTMLDivElement, ChartLegendEngineModel, BaseType, unknown>;
2
5
  export declare class LegendDomHelper {
3
- static setItemsTitles(items: Selection<HTMLDivElement, string, BaseType, unknown>): void;
4
- static setItemsColors(items: Selection<HTMLDivElement, string, BaseType, unknown>, colorPalette: string[]): void;
5
- static cropRowLabels(legendBlock: Selection<SVGForeignObjectElement, unknown, HTMLElement, any>, items: Selection<HTMLDivElement, string, BaseType, unknown>): void;
6
- private static getItemsLeftMargins;
6
+ static setItemsTitles(items: LegendItemSelection): void;
7
+ static decreaseRowLabels(legendBlock: Selection<SVGForeignObjectElement, unknown, HTMLElement, any>, items: LegendItemSelection, staticLegend: StaticLegendBlockCanvas): void;
8
+ /** @deprecated */
9
+ static cropRowLabels(legendBlock: Selection<SVGForeignObjectElement, unknown, HTMLElement, any>, items: LegendItemSelection): void;
10
+ private static getItemsRightMargins;
7
11
  private static getItemsWidth;
8
12
  }
@@ -2,17 +2,29 @@ import { DomHelper } from "../../helpers/domHelper";
2
2
  import { Helper } from "../../helpers/helper";
3
3
  import { Legend } from "./legend";
4
4
  import { LegendHelper } from "./legendHelper";
5
+ import { getNewLegendItemWidths } from "./legendWidthCalculator";
5
6
  export class LegendDomHelper {
6
7
  static setItemsTitles(items) {
7
- items.attr('title', d => d);
8
+ items.attr('title', d => d.textContent);
8
9
  }
9
- static setItemsColors(items, colorPalette) {
10
- items.select(`.${Legend.markerClass}`)
11
- .style('background-color', (d, i) => colorPalette[i % colorPalette.length]);
10
+ static decreaseRowLabels(legendBlock, items, staticLegend) {
11
+ let itemsRightMargins = this.getItemsRightMargins(items);
12
+ const itemConfig = [];
13
+ items.nodes().forEach((node, i) => {
14
+ itemConfig.push({ width: node.getBoundingClientRect().width, marginLeft: 0, marginRight: itemsRightMargins[i] });
15
+ });
16
+ const newWidths = getNewLegendItemWidths({
17
+ items: itemConfig,
18
+ wrapper: { maxRowsAmount: staticLegend.maxLinesAmount, width: legendBlock.node().getBoundingClientRect().width }
19
+ });
20
+ items.nodes().forEach((node, i) => {
21
+ node.style.width = `${newWidths[i]}px`;
22
+ });
12
23
  }
24
+ /** @deprecated */
13
25
  static cropRowLabels(legendBlock, items) {
14
26
  const maxWidth = legendBlock.node().getBoundingClientRect().width;
15
- let itemsLeftMargins = this.getItemsLeftMargins(items);
27
+ let itemsLeftMargins = this.getItemsRightMargins(items);
16
28
  let itemsWidth = this.getItemsWidth(items);
17
29
  let sumOfItemsWidth = LegendHelper.getSumOfItemsWidths(itemsWidth, itemsLeftMargins);
18
30
  const maxItemWidth = LegendHelper.getMaxItemWidth(legendBlock.attr('width'), itemsLeftMargins, 'row');
@@ -27,7 +39,7 @@ export class LegendDomHelper {
27
39
  : textBlock.textContent;
28
40
  labelText = labelText.substr(0, labelText.length - 1);
29
41
  textBlock.textContent = labelText + '...';
30
- itemsLeftMargins = this.getItemsLeftMargins(items);
42
+ itemsLeftMargins = this.getItemsRightMargins(items);
31
43
  itemsWidth = this.getItemsWidth(items);
32
44
  sumOfItemsWidth = LegendHelper.getSumOfItemsWidths(itemsWidth, itemsLeftMargins);
33
45
  if (labelText.length === 0) {
@@ -39,8 +51,8 @@ export class LegendDomHelper {
39
51
  index++;
40
52
  }
41
53
  }
42
- static getItemsLeftMargins(items) {
43
- return items.nodes().map(node => Helper.getPXValueFromString(DomHelper.getCssPropertyValue(node, 'margin-left')));
54
+ static getItemsRightMargins(items) {
55
+ return items.nodes().map(node => Helper.getPXValueFromString(DomHelper.getCssPropertyValue(node, 'margin-right')));
44
56
  }
45
57
  static getItemsWidth(items) {
46
58
  return items.nodes().map(node => node.getBoundingClientRect().width);
@@ -1,12 +1,12 @@
1
- import { BaseType, Selection } from "d3-selection";
2
1
  import { Block } from "../../block/block";
2
+ import { LegendItemSelection } from "./legendDomHelper";
3
3
  export declare class LegendEventsManager {
4
4
  /**
5
5
  * @param block
6
6
  * @param keyFieldName
7
7
  * @param legendItems айтемы легенды полара, которые привязаны к ключам
8
8
  */
9
- static setListeners(block: Block, keyFieldName: string, legendItems: Selection<HTMLDivElement, string, BaseType, unknown>, selectable: boolean): void;
9
+ static setListeners(block: Block, keyFieldName: string, legendItems: LegendItemSelection, selectable: boolean): void;
10
10
  private static setHoverListeners;
11
11
  private static setClickListeners;
12
12
  }
@@ -15,7 +15,7 @@ export class LegendEventsManager {
15
15
  static setHoverListeners(block, keyFieldName, legendItems) {
16
16
  const arcItems = Donut.getAllArcGroups(block);
17
17
  legendItems.on('mousemove', function (e, keyValue) {
18
- arcItems.filter((row) => row.data[keyFieldName] === keyValue)
18
+ arcItems.filter((row) => row.data[keyFieldName] === keyValue.textContent)
19
19
  .dispatch('mousemove', {
20
20
  bubbles: false,
21
21
  cancelable: true,
@@ -26,21 +26,21 @@ export class LegendEventsManager {
26
26
  });
27
27
  });
28
28
  legendItems.on('mouseover', function (e, keyValue) {
29
- arcItems.filter((row) => row.data[keyFieldName] === keyValue)
29
+ arcItems.filter((row) => row.data[keyFieldName] === keyValue.textContent)
30
30
  .dispatch('mouseover');
31
31
  ElementHighlighter.toggleActivityStyle(select(this), true);
32
32
  });
33
33
  legendItems.on('mouseleave', function (e, keyValue) {
34
- arcItems.filter((row) => row.data[keyFieldName] === keyValue)
34
+ arcItems.filter((row) => row.data[keyFieldName] === keyValue.textContent)
35
35
  .dispatch('mouseleave');
36
- if (!block.filterEventManager.isSelected(keyValue) && block.filterEventManager.getSelectedKeys().length > 0)
36
+ if (!block.filterEventManager.isSelected(keyValue.textContent) && block.filterEventManager.getSelectedKeys().length > 0)
37
37
  ElementHighlighter.toggleActivityStyle(select(this), false);
38
38
  });
39
39
  }
40
40
  static setClickListeners(block, keyFieldName, legendItems) {
41
41
  const arcItems = Donut.getAllArcGroups(block);
42
42
  legendItems.on('click', (e, keyValue) => {
43
- arcItems.filter((row) => row.data[keyFieldName] === keyValue)
43
+ arcItems.filter((row) => row.data[keyFieldName] === keyValue.textContent)
44
44
  .dispatch('click', { bubbles: false, cancelable: true, detail: { multySelect: e.ctrlKey || e.metaKey } });
45
45
  });
46
46
  }
@@ -1,6 +1,6 @@
1
1
  import { ChartNotation, MdtChartsDataRow, MdtChartsDataSource, Size } from "../../../config/config";
2
2
  import { LegendItemsDirection } from "../../../model/featuresModel/legendModel/legendCanvasModel";
3
- import { IntervalOptionsModel, LegendBlockModel, LegendPosition, Orient, PolarOptionsModel, TwoDimensionalOptionsModel } from "../../../model/model";
3
+ import { ChartLegendModel, IntervalOptionsModel, LegendBlockModel, LegendPosition, Orient, PolarOptionsModel, TwoDimensionalOptionsModel } from "../../../model/model";
4
4
  import { LegendContentRenderingOptions } from "./legend";
5
5
  import { LegendHelperService } from "./legendHelperService";
6
6
  export interface LegendCoordinate {
@@ -9,12 +9,15 @@ export interface LegendCoordinate {
9
9
  height: number;
10
10
  width: number;
11
11
  }
12
+ export interface ChartLegendEngineModel extends ChartLegendModel {
13
+ textContent: string;
14
+ }
12
15
  export declare class LegendHelper {
13
16
  static service: LegendHelperService;
14
- static getLegendItemsContent(options: TwoDimensionalOptionsModel | PolarOptionsModel | IntervalOptionsModel, data: MdtChartsDataSource): string[];
17
+ static getLegendItemsContent(options: TwoDimensionalOptionsModel | PolarOptionsModel, data: MdtChartsDataSource): ChartLegendEngineModel[];
15
18
  static getMarksColor(options: TwoDimensionalOptionsModel | PolarOptionsModel | IntervalOptionsModel, dataRows?: MdtChartsDataRow[]): string[];
16
19
  static getMaxItemWidth(legendBlockWidth: string, marginsLeft: number[], itemsDirection: LegendItemsDirection): number;
17
20
  static getSumOfItemsWidths(itemsWidth: number[], marginsLeft: number[]): number;
18
21
  static getLegendCoordinateByPosition(legendPosition: Orient, legendBlockModel: LegendBlockModel, blockSize: Size): LegendCoordinate;
19
- static getContentRenderingOptions(chartNotation: ChartNotation, legendPosition: LegendPosition): LegendContentRenderingOptions;
22
+ static getContentRenderingOptions(chartNotation: ChartNotation, legendPosition: LegendPosition, legendBlockModel: LegendBlockModel): LegendContentRenderingOptions;
20
23
  }
@@ -6,15 +6,12 @@ export class LegendHelper {
6
6
  if (options.type === '2d') {
7
7
  let texts = [];
8
8
  options.charts.forEach(chart => {
9
- texts = texts.concat(chart.data.valueFields.map(field => field.title));
9
+ texts = texts.concat(chart.data.valueFields.map(field => (Object.assign(Object.assign({}, chart.legend), { textContent: field.title }))));
10
10
  });
11
11
  return texts;
12
12
  }
13
- else if (options.type === 'polar') {
14
- return data[options.data.dataSource].map((record) => record[options.data.keyField.name]);
15
- }
16
- else if (options.type === 'interval') {
17
- return options.charts.map(chart => chart.data.valueField1.name);
13
+ if (options.type === "polar") {
14
+ return data[options.data.dataSource].map((record) => (Object.assign(Object.assign({}, options.charts[0].legend), { textContent: record[options.data.keyField.name] })));
18
15
  }
19
16
  }
20
17
  static getMarksColor(options, dataRows) {
@@ -74,7 +71,7 @@ export class LegendHelper {
74
71
  coordinate.y = blockSize.height - legendModel.size - legendModel.margin.bottom;
75
72
  return coordinate;
76
73
  }
77
- static getContentRenderingOptions(chartNotation, legendPosition) {
74
+ static getContentRenderingOptions(chartNotation, legendPosition, legendBlockModel) {
78
75
  const itemsDirection = this.service.getLegendItemsDirection(legendPosition);
79
76
  return {
80
77
  wrapperClasses: [
@@ -84,6 +81,7 @@ export class LegendHelper {
84
81
  this.service.getWrapperClassByWrappingItems(legendPosition, chartNotation)
85
82
  ],
86
83
  shouldCropLabels: chartNotation === "2d",
84
+ blockModel: legendBlockModel,
87
85
  itemsOptions: {
88
86
  markerClass: Legend.markerClass,
89
87
  labelClass: this.service.getLegendLabelClassByPosition(legendPosition, chartNotation, Legend.labelClass),
@@ -0,0 +1,21 @@
1
+ import { BaseType, Selection } from "d3-selection";
2
+ import { ChartLegendModel } from "../../../model/model";
3
+ interface MarkerCreationOptions extends ChartLegendModel {
4
+ color: string;
5
+ }
6
+ declare type MarkerParentSelection = Selection<BaseType, any, BaseType, any>;
7
+ export declare class LegendMarkerCreator {
8
+ create(selection: MarkerParentSelection, options: MarkerCreationOptions): Selection<BaseType, ChartLegendModel, BaseType, unknown>;
9
+ updateColorForItem(selection: MarkerParentSelection, options: MarkerCreationOptions): void;
10
+ }
11
+ export interface MarkerCreator {
12
+ renderMarker(selection: MarkerParentSelection, color: string): Selection<BaseType, ChartLegendModel, BaseType, unknown>;
13
+ updateColors(selection: MarkerParentSelection, color: string): void;
14
+ }
15
+ interface MakerCreatorCustomOptions {
16
+ default?: {
17
+ cssClass: string;
18
+ };
19
+ }
20
+ export declare function getMarkerCreator(options: ChartLegendModel, customOptions?: MakerCreatorCustomOptions): MarkerCreator;
21
+ export {};
@@ -0,0 +1,88 @@
1
+ import { Legend } from "./legend";
2
+ import { HatchPatternDef } from "../../block/defs";
3
+ import { applyLineDash } from "../../twoDimensionalNotation/line/lineHelper";
4
+ export class LegendMarkerCreator {
5
+ create(selection, options) {
6
+ const creator = getMarkerCreator(options);
7
+ return creator.renderMarker(selection, options.color);
8
+ }
9
+ updateColorForItem(selection, options) {
10
+ const creator = getMarkerCreator(options);
11
+ creator.updateColors(selection, options.color);
12
+ }
13
+ }
14
+ export function getMarkerCreator(options, customOptions) {
15
+ var _a;
16
+ if (options.markerShape === "bar")
17
+ return new BarMarkerCreator(options.barViewOptions);
18
+ if (options.markerShape === "line")
19
+ return new LineMarkerCreator(options.lineViewOptions);
20
+ return new DefaultMarkerCreator((_a = customOptions === null || customOptions === void 0 ? void 0 : customOptions.default) === null || _a === void 0 ? void 0 : _a.cssClass);
21
+ }
22
+ class DefaultMarkerCreator {
23
+ constructor(cssClass = Legend.markerCircle) {
24
+ this.cssClass = cssClass;
25
+ }
26
+ renderMarker(selection, color) {
27
+ return selection.append('span').style('background-color', color).classed(this.cssClass, true);
28
+ }
29
+ updateColors(selection, color) {
30
+ selection.select(`.${this.cssClass}`).style('background-color', color);
31
+ }
32
+ }
33
+ class SvgMarkerCreator {
34
+ renderSvg(selection) {
35
+ return selection.append('svg')
36
+ .style("display", "inline-block")
37
+ .style("height", '10px')
38
+ .classed(Legend.markerClass, true);
39
+ }
40
+ }
41
+ class BarMarkerCreator extends SvgMarkerCreator {
42
+ constructor(options) {
43
+ super();
44
+ this.options = options;
45
+ }
46
+ renderMarker(selection, color) {
47
+ const svg = this.renderSvg(selection).style("width", this.options.width);
48
+ const bars = svg
49
+ .append('rect')
50
+ .attr('x', 0)
51
+ .attr('y', 0)
52
+ .attr('height', 10)
53
+ .attr('width', this.options.width)
54
+ .style('fill', color);
55
+ if (this.options.hatch.on) {
56
+ bars.style('mask', HatchPatternDef.getMaskValue());
57
+ }
58
+ return bars;
59
+ }
60
+ updateColors(selection, color) {
61
+ selection.select('svg rect').style('fill', color);
62
+ }
63
+ }
64
+ class LineMarkerCreator extends SvgMarkerCreator {
65
+ constructor(options) {
66
+ super();
67
+ this.options = options;
68
+ }
69
+ renderMarker(selection, color) {
70
+ const svg = this.renderSvg(selection).style("width", this.options.width);
71
+ const line = svg
72
+ .append('line')
73
+ .style('stroke', 'red')
74
+ .classed("line", true)
75
+ .attr('x1', 0)
76
+ .attr('x2', this.options.width)
77
+ .attr('y1', 5)
78
+ .attr('y2', 5)
79
+ .style('stroke', color);
80
+ if (this.options.dashedStyles.on) {
81
+ applyLineDash(line, this.options.dashedStyles.dashSize, this.options.dashedStyles.gapSize);
82
+ }
83
+ return line;
84
+ }
85
+ updateColors(selection, color) {
86
+ selection.select('svg line').style('stroke', color);
87
+ }
88
+ }
@@ -0,0 +1,16 @@
1
+ declare type SizePx = number;
2
+ interface WidthCalculatorConfig {
3
+ wrapper: LegendWrapperConfig;
4
+ items: LegendItemConfig[];
5
+ }
6
+ export declare function getNewLegendItemWidths(config: WidthCalculatorConfig): SizePx[];
7
+ interface LegendWrapperConfig {
8
+ maxRowsAmount: number;
9
+ width: SizePx;
10
+ }
11
+ export interface LegendItemConfig {
12
+ marginLeft: SizePx;
13
+ marginRight: SizePx;
14
+ width: SizePx;
15
+ }
16
+ export {};
@@ -0,0 +1,119 @@
1
+ export function getNewLegendItemWidths(config) {
2
+ const wrapper = new LegendWrapper(config.wrapper);
3
+ const collection = new LegendItemCollection(config.items.map(i => new LegendItem(i)));
4
+ return getNewWidths(collection, wrapper);
5
+ }
6
+ function getNewWidths(collection, wrapper) {
7
+ let extra = collection.getTotalWidth() - wrapper.getMaxWidth();
8
+ if (extra <= 0) {
9
+ return fixWidthsByLinePos(collection, wrapper);
10
+ }
11
+ const avgWidth = (wrapper.getMaxWidth() - collection.getTotalMarginSizes()) / collection.getItemsAmount();
12
+ const biggerThanAvg = collection.getItemsWithWidthBiggerThan(avgWidth);
13
+ let avgExtra = extra / biggerThanAvg.length;
14
+ biggerThanAvg.forEach((item, index) => {
15
+ const avgDiff = item.getCurrentWidth() - avgWidth;
16
+ const decreaseBy = avgDiff < avgExtra ? avgDiff : avgExtra;
17
+ item.decreaseBy(decreaseBy);
18
+ extra -= decreaseBy;
19
+ avgExtra = extra / (biggerThanAvg.length - index - 1);
20
+ });
21
+ return fixWidthsByLinePos(collection, wrapper);
22
+ }
23
+ function fixWidthsByLinePos(collection, wrapper) {
24
+ const byRows = [];
25
+ let currentRow = [];
26
+ collection.items.forEach((item, i) => {
27
+ const currentRowSum = currentRow.reduce((acc, i) => acc + i.getCurrentTotalWidth(), 0);
28
+ if (currentRowSum + item.getWidthWithoutRightMargin() <= wrapper.getWidthOfOneLine()) {
29
+ currentRow.push(item);
30
+ }
31
+ else {
32
+ byRows.push(new LegendItemCollection(currentRow));
33
+ currentRow = [item];
34
+ }
35
+ if (i === collection.items.length - 1)
36
+ byRows.push(new LegendItemCollection(currentRow));
37
+ });
38
+ if (byRows.length <= wrapper.getMaxRowsCount())
39
+ return collection.getActualWidths();
40
+ const result = [];
41
+ for (let i = 0; i < byRows.length - 1; i++) {
42
+ const top = byRows[i];
43
+ const bottom = byRows[i + 1];
44
+ const topFreeSpace = wrapper.getWidthOfOneLine() - top.getTotalWidth();
45
+ const firstOfBottom = bottom.getFirstItem();
46
+ if (topFreeSpace / firstOfBottom.getCurrentTotalWidth() > 0.51 || i === byRows.length - 2) {
47
+ const fromBottom = bottom.shift();
48
+ top.push(fromBottom);
49
+ result.push(...getNewWidths(top, new LegendWrapper({ maxRowsAmount: 1, width: wrapper.getWidthOfOneLine() })));
50
+ }
51
+ }
52
+ return result;
53
+ }
54
+ class LegendWrapper {
55
+ constructor(config) {
56
+ this.config = config;
57
+ }
58
+ getMaxWidth() {
59
+ return this.config.width * this.config.maxRowsAmount;
60
+ }
61
+ getWidthOfOneLine() {
62
+ return this.config.width;
63
+ }
64
+ getMaxRowsCount() {
65
+ return this.config.maxRowsAmount;
66
+ }
67
+ }
68
+ class LegendItem {
69
+ constructor(config) {
70
+ this.config = config;
71
+ this.width = this.config.width;
72
+ }
73
+ getCurrentTotalWidth() {
74
+ return this.width + this.getTotalMarginSize();
75
+ }
76
+ getWidthWithoutRightMargin() {
77
+ return this.width + this.config.marginLeft;
78
+ }
79
+ decreaseBy(by) {
80
+ this.width -= by;
81
+ }
82
+ getCurrentWidth() {
83
+ return this.width;
84
+ }
85
+ getTotalMarginSize() {
86
+ return this.config.marginLeft + this.config.marginRight;
87
+ }
88
+ }
89
+ class LegendItemCollection {
90
+ constructor(items) {
91
+ this.items = items;
92
+ }
93
+ getTotalWidth() {
94
+ return this.items.reduce((acc, item) => acc + item.getCurrentTotalWidth(), 0);
95
+ }
96
+ getActualWidths() {
97
+ return this.items.map(item => item.getCurrentWidth());
98
+ }
99
+ getTotalMarginSizes() {
100
+ return this.items.reduce((acc, item) => acc + item.getTotalMarginSize(), 0);
101
+ }
102
+ getItemsAmount() {
103
+ return this.items.length;
104
+ }
105
+ getItemsWithWidthBiggerThan(thanWidth) {
106
+ return this.items
107
+ .filter(item => item.getCurrentWidth() > thanWidth)
108
+ .sort((a, b) => a.getCurrentWidth() - b.getCurrentWidth());
109
+ }
110
+ getFirstItem() {
111
+ return this.items[0];
112
+ }
113
+ shift() {
114
+ return this.items.shift();
115
+ }
116
+ push(item) {
117
+ this.items.push(item);
118
+ }
119
+ }
@@ -76,7 +76,7 @@ export class Tooltip {
76
76
  const tipBox = TipBox.renderOrGet(block, args.margin, args.blockSize);
77
77
  let currentKey = null;
78
78
  tipBox.on('mousemove', function (e) {
79
- var _a, _b;
79
+ var _a;
80
80
  const keyValue = e.detail.keyValue || TipBoxHelper.getKeyValueByPointer(pointer(e, this), args.chartOrientation, args.margin, args.blockSize, args.scales.key, args.scaleKeyModel.type);
81
81
  if (args.tooltipSettings.position === 'followCursor') {
82
82
  const tooltipCoordinate = TooltipHelper.getTooltipCursorCoordinate(e.detail.pointer || pointer(e, this), block.getSvg().node().getBoundingClientRect(), tooltipBlock.getEl().node().getBoundingClientRect());
@@ -85,9 +85,7 @@ export class Tooltip {
85
85
  if (!currentKey || currentKey !== keyValue) {
86
86
  TooltipComponentsManager.showComponent(tooltipBlock.getEl());
87
87
  if (args.type === '2d')
88
- TooltipDomHelper.fillForMulty2DCharts(tooltipContent, args.charts.filter(ch => ch.tooltip.show), data, args.dataOptions, keyValue, (_a = args.tooltipOptions) === null || _a === void 0 ? void 0 : _a.html);
89
- else
90
- TooltipDomHelper.fillForIntervalChart(tooltipContent, args.charts.filter(ch => ch.tooltip.show), data, args.dataOptions, keyValue, (_b = args.tooltipOptions) === null || _b === void 0 ? void 0 : _b.html);
88
+ TooltipDomHelper.fillForMulti2DCharts(tooltipContent, args.charts.filter(ch => ch.tooltip.show), data, args.dataOptions, keyValue, (_a = args.tooltipOptions) === null || _a === void 0 ? void 0 : _a.html);
91
89
  if (args.tooltipSettings.position === 'fixed') {
92
90
  const tooltipCoordinate = TooltipHelper.getTooltipFixedCoordinate(args.scales.key, args.margin, keyValue, block.getSvg().node().getBoundingClientRect(), tooltipContent.node().getBoundingClientRect(), args.keyAxisOrient, window.innerWidth, window.innerHeight);
93
91
  TooltipComponentsManager.setLineTooltipCoordinate(tooltipBlock, tooltipCoordinate, args.chartOrientation, block.transitionManager.durations.tooltipSlide);
@@ -95,7 +93,6 @@ export class Tooltip {
95
93
  const tooltipLineAttributes = TooltipHelper.getTooltipLineAttributes(args.scales.key, args.margin, keyValue, args.chartOrientation, args.blockSize);
96
94
  TooltipComponentsManager.setTooltipLineAttributes(tooltipLine, tooltipLineAttributes, block.transitionManager.durations.tooltipSlide);
97
95
  TooltipComponentsManager.showComponent(tooltipLine);
98
- //TODO: append highlight for interval / Extract this highlighting in method
99
96
  if (args.type === '2d') {
100
97
  args.charts.forEach(chart => {
101
98
  const elements = DomHelper.get2DChartElements(block, chart);
@@ -1,6 +1,6 @@
1
1
  import { Selection, BaseType } from 'd3-selection';
2
2
  import { MdtChartsDataSource, TooltipHtml } from "../../../config/config";
3
- import { IntervalChartModel, OptionsModelData, PolarChartModel, TwoDimensionalChartModel } from "../../../model/model";
3
+ import { OptionsModelData, PolarChartModel, TwoDimensionalChartModel } from "../../../model/model";
4
4
  import { Size } from "../../../config/config";
5
5
  export interface TooltipLineAttributes {
6
6
  x1: number;
@@ -16,10 +16,9 @@ export declare class TooltipDomHelper {
16
16
  private static readonly groupClass;
17
17
  private static readonly headClass;
18
18
  private static readonly textItemClass;
19
- private static readonly maxContentWidth;
20
- static fillForMulty2DCharts(contentBlock: Selection<HTMLElement, unknown, BaseType, unknown>, charts: TwoDimensionalChartModel[], data: MdtChartsDataSource, dataOptions: OptionsModelData, keyValue: string, htmlHandler?: TooltipHtml): void;
19
+ private static readonly tooltipLegendDefaultMarker;
20
+ static fillForMulti2DCharts(contentBlock: Selection<HTMLElement, unknown, BaseType, unknown>, charts: TwoDimensionalChartModel[], data: MdtChartsDataSource, dataOptions: OptionsModelData, keyValue: string, htmlHandler?: TooltipHtml): void;
21
21
  static fillForPolarChart(contentBlock: Selection<HTMLElement, unknown, BaseType, unknown>, chart: PolarChartModel, data: MdtChartsDataSource, dataOptions: OptionsModelData, keyValue: string, markColor: string, htmlHandler?: TooltipHtml): void;
22
- static fillForIntervalChart(contentBlock: Selection<HTMLElement, unknown, BaseType, unknown>, charts: IntervalChartModel[], data: MdtChartsDataSource, dataOptions: OptionsModelData, keyValue: string, htmlHandler?: TooltipHtml): void;
23
22
  static getRecalcedCoordinateByArrow(coordinate: [number, number], tooltipBlock: Selection<HTMLElement, unknown, HTMLElement, any>, blockSize: Size, tooltipArrow: Selection<BaseType, unknown, HTMLElement, any>, translateX?: number, translateY?: number): [number, number];
24
23
  private static renderHead;
25
24
  private static fillValuesContent;
@@ -27,4 +26,5 @@ export declare class TooltipDomHelper {
27
26
  private static setTooltipArrowCoordinate;
28
27
  private static fillContentByFunction;
29
28
  private static setWhiteSpaceForTextBlocks;
29
+ private static getMarkerCreator;
30
30
  }