@unovis/ts 1.2.1-beta.1 → 1.2.1-beta.25

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 (71) hide show
  1. package/components/axis/config.d.ts +6 -0
  2. package/components/axis/config.js +2 -0
  3. package/components/axis/config.js.map +1 -1
  4. package/components/axis/index.js +5 -3
  5. package/components/axis/index.js.map +1 -1
  6. package/components/axis/style.js +3 -2
  7. package/components/axis/style.js.map +1 -1
  8. package/components/bullet-legend/config.d.ts +5 -2
  9. package/components/bullet-legend/config.js +2 -0
  10. package/components/bullet-legend/config.js.map +1 -1
  11. package/components/bullet-legend/index.js +6 -16
  12. package/components/bullet-legend/index.js.map +1 -1
  13. package/components/bullet-legend/modules/shape.d.ts +6 -0
  14. package/components/bullet-legend/modules/shape.js +58 -0
  15. package/components/bullet-legend/modules/shape.js.map +1 -0
  16. package/components/bullet-legend/style.js +6 -9
  17. package/components/bullet-legend/style.js.map +1 -1
  18. package/components/bullet-legend/types.d.ts +5 -0
  19. package/components/bullet-legend/types.js +7 -0
  20. package/components/bullet-legend/types.js.map +1 -1
  21. package/components/chord-diagram/config.d.ts +6 -0
  22. package/components/chord-diagram/config.js +2 -0
  23. package/components/chord-diagram/config.js.map +1 -1
  24. package/components/chord-diagram/index.d.ts +1 -0
  25. package/components/chord-diagram/index.js +22 -12
  26. package/components/chord-diagram/index.js.map +1 -1
  27. package/components/chord-diagram/modules/link.js +6 -5
  28. package/components/chord-diagram/modules/link.js.map +1 -1
  29. package/components/chord-diagram/style.d.ts +2 -2
  30. package/components/chord-diagram/style.js +21 -18
  31. package/components/chord-diagram/style.js.map +1 -1
  32. package/components/chord-diagram/types.d.ts +2 -2
  33. package/components/chord-diagram/types.js.map +1 -1
  34. package/components/nested-donut/index.js +15 -10
  35. package/components/nested-donut/index.js.map +1 -1
  36. package/components/nested-donut/modules/arc.js +2 -1
  37. package/components/nested-donut/modules/arc.js.map +1 -1
  38. package/components/nested-donut/modules/label.js +9 -6
  39. package/components/nested-donut/modules/label.js.map +1 -1
  40. package/components/nested-donut/types.d.ts +1 -0
  41. package/components/nested-donut/types.js.map +1 -1
  42. package/components/scatter/config.d.ts +3 -0
  43. package/components/scatter/config.js +1 -0
  44. package/components/scatter/config.js.map +1 -1
  45. package/components/scatter/index.d.ts +1 -1
  46. package/components/scatter/index.js +9 -4
  47. package/components/scatter/index.js.map +1 -1
  48. package/containers/single-container/index.d.ts +3 -2
  49. package/containers/single-container/index.js +6 -2
  50. package/containers/single-container/index.js.map +1 -1
  51. package/containers/xy-container/config.d.ts +7 -5
  52. package/containers/xy-container/config.js +1 -1
  53. package/containers/xy-container/config.js.map +1 -1
  54. package/containers/xy-container/index.d.ts +8 -7
  55. package/containers/xy-container/index.js +20 -13
  56. package/containers/xy-container/index.js.map +1 -1
  57. package/core/container/index.d.ts +5 -4
  58. package/core/container/index.js +7 -1
  59. package/core/container/index.js.map +1 -1
  60. package/index.js +2 -1
  61. package/index.js.map +1 -1
  62. package/package.json +1 -1
  63. package/types/text.d.ts +3 -3
  64. package/types/text.js.map +1 -1
  65. package/types.js +1 -1
  66. package/utils/color.d.ts +7 -3
  67. package/utils/color.js +18 -2
  68. package/utils/color.js.map +1 -1
  69. package/utils/text.d.ts +1 -0
  70. package/utils/text.js +22 -10
  71. package/utils/text.js.map +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"arc.js","sources":["../../../../src/components/nested-donut/modules/arc.ts"],"sourcesContent":["import { Selection } from 'd3-selection'\nimport { Transition } from 'd3-transition'\nimport { interpolate } from 'd3-interpolate'\nimport { Arc } from 'd3-shape'\n\n// Utils\nimport { getColor } from 'utils/color'\nimport { smartTransition } from 'utils/d3'\n\n// Local Types\nimport { NestedDonutSegment } from '../types'\n\n// Config\nimport { NestedDonutConfig } from '../config'\n\ntype AnimState = { x0: number; x1: number; y0: number; y1: number }\nexport interface ArcNode extends SVGElement {\n _animState?: AnimState;\n}\n\nexport function createArc<Datum> (\n selection: Selection<SVGPathElement, NestedDonutSegment<Datum>, SVGGElement, unknown>,\n config: NestedDonutConfig<Datum>\n): void {\n selection\n .style('fill', d => getColor(d, config.segmentColor) ?? d._state?.fill)\n .style('opacity', 0)\n .each((d, i, els) => {\n const arcNode: ArcNode = els[i]\n const angleCenter = (d.x0 + d.x1) / 2\n const angleHalfWidth = (d.x1 - d.x0) / 2\n arcNode._animState = {\n x0: angleCenter - angleHalfWidth,\n x1: angleCenter + angleHalfWidth,\n y0: d.y0,\n y1: d.y1,\n }\n })\n}\n\nexport function updateArc<Datum> (\n selection: Selection<SVGPathElement, NestedDonutSegment<Datum>, SVGGElement, unknown>,\n config: NestedDonutConfig<Datum>,\n arcGen: Arc<any, AnimState>,\n duration: number\n): void {\n selection\n .style('transition', `fill ${duration}ms`) // Animate color with CSS because we're using CSS-variables\n .style('fill', d => getColor(d, config.segmentColor) ?? d._state?.fill)\n\n if (duration) {\n const transition = smartTransition(selection, duration)\n .style('opacity', 1) as Transition<SVGPathElement, NestedDonutSegment<Datum>, SVGGElement, ArcNode>\n\n transition.attrTween('d', (d, i, els) => {\n const arcNode: ArcNode = els[i]\n const nextAnimState = { x0: d.x0, x1: d.x1, y0: d.y0, y1: d.y1 }\n const datum = interpolate(arcNode._animState, nextAnimState)\n return (t: number): string => {\n arcNode._animState = datum(t)\n return arcGen(arcNode._animState)\n }\n })\n } else {\n selection.attr('d', arcGen)\n .style('opacity', 1)\n }\n}\n\nexport function removeArc<Datum> (\n selection: Selection<SVGPathElement, NestedDonutSegment<Datum>, SVGGElement, unknown>,\n duration: number\n): void {\n smartTransition(selection, duration)\n .style('opacity', 0)\n .remove()\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"arc.js","sources":["../../../../src/components/nested-donut/modules/arc.ts"],"sourcesContent":["import { Selection } from 'd3-selection'\nimport { Transition } from 'd3-transition'\nimport { interpolate } from 'd3-interpolate'\nimport { Arc } from 'd3-shape'\n\n// Utils\nimport { getColor } from 'utils/color'\nimport { smartTransition } from 'utils/d3'\n\n// Local Types\nimport { NestedDonutSegment } from '../types'\n\n// Config\nimport { NestedDonutConfig } from '../config'\n\ntype AnimState = { x0: number; x1: number; y0: number; y1: number }\nexport interface ArcNode extends SVGElement {\n _animState?: AnimState;\n}\n\nexport function createArc<Datum> (\n selection: Selection<SVGPathElement, NestedDonutSegment<Datum>, SVGGElement, unknown>,\n config: NestedDonutConfig<Datum>\n): void {\n selection\n .style('fill', d => getColor(d, config.segmentColor) ?? d._state?.fill)\n .style('opacity', 0)\n .each((d, i, els) => {\n const arcNode: ArcNode = els[i]\n const angleCenter = (d.x0 + d.x1) / 2\n const angleHalfWidth = (d.x1 - d.x0) / 2\n arcNode._animState = {\n x0: angleCenter - angleHalfWidth,\n x1: angleCenter + angleHalfWidth,\n y0: d.y0,\n y1: d.y1,\n }\n })\n}\n\nexport function updateArc<Datum> (\n selection: Selection<SVGPathElement, NestedDonutSegment<Datum>, SVGGElement, unknown>,\n config: NestedDonutConfig<Datum>,\n arcGen: Arc<any, AnimState>,\n duration: number\n): void {\n selection\n .style('transition', `fill ${duration}ms`) // Animate color with CSS because we're using CSS-variables\n .style('fill', d => d._state.fill)\n .style('fill-opacity', d => d._state.fillOpacity)\n\n if (duration) {\n const transition = smartTransition(selection, duration)\n .style('opacity', 1) as Transition<SVGPathElement, NestedDonutSegment<Datum>, SVGGElement, ArcNode>\n\n transition.attrTween('d', (d, i, els) => {\n const arcNode: ArcNode = els[i]\n const nextAnimState = { x0: d.x0, x1: d.x1, y0: d.y0, y1: d.y1 }\n const datum = interpolate(arcNode._animState, nextAnimState)\n return (t: number): string => {\n arcNode._animState = datum(t)\n return arcGen(arcNode._animState)\n }\n })\n } else {\n selection.attr('d', arcGen)\n .style('opacity', 1)\n }\n}\n\nexport function removeArc<Datum> (\n selection: Selection<SVGPathElement, NestedDonutSegment<Datum>, SVGGElement, unknown>,\n duration: number\n): void {\n smartTransition(selection, duration)\n .style('opacity', 0)\n .remove()\n}\n"],"names":[],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  import { select } from 'd3-selection';
2
2
  import { color } from 'd3-color';
3
- import { getColor, hexToBrightness } from '../../../utils/color.js';
3
+ import { getHexValue, rgbaToRgb, rgbToBrightness, getColor } from '../../../utils/color.js';
4
4
  import { smartTransition } from '../../../utils/d3.js';
5
5
  import { getString } from '../../../utils/data.js';
6
6
  import { getCSSVariableValueInPixels } from '../../../utils/misc.js';
@@ -9,11 +9,14 @@ import { wrapSVGText } from '../../../utils/text.js';
9
9
  import { NestedDonutSegmentLabelAlignment } from '../types.js';
10
10
  import { variables } from '../style.js';
11
11
 
12
- function getLabelFillColor(d, config) {
12
+ function getLabelFillColor(d, element) {
13
13
  var _a;
14
- const c = (_a = getColor(d, config.segmentColor)) !== null && _a !== void 0 ? _a : d._state.fill;
15
- const colorParsed = color(c);
16
- const brightness = colorParsed ? hexToBrightness(colorParsed.hex()) : 0;
14
+ const c = (_a = color(d._state.fill)) !== null && _a !== void 0 ? _a : color(getHexValue(d._state.fill, element));
15
+ const rgb = c === null || c === void 0 ? void 0 : c.rgb();
16
+ // If shading, we adjust segment color before calculating brightness ratio
17
+ const colorParsed = rgb && d._state.fillOpacity
18
+ ? rgbaToRgb(`rgba(${rgb.r},${rgb.g},${rgb.b},${d._state.fillOpacity})`, getHexValue(cssvar(variables.nestedDonutBackgroundColor), element)) : rgb;
19
+ const brightness = colorParsed ? rgbToBrightness(colorParsed) : 0;
17
20
  return cssvar(brightness > 0.65 ? variables.nestedDonutSegmentLabelTextColorLight : variables.nestedDonutSegmentLabelTextColorDark);
18
21
  }
19
22
  function getLabelTransform(d, arcGen) {
@@ -51,7 +54,7 @@ function updateLabel(selection, config, arcGen, duration) {
51
54
  selection
52
55
  .text(d => { var _a; return (_a = getString(d, config.segmentLabel)) !== null && _a !== void 0 ? _a : d.data.key; })
53
56
  .style('transition', `fill ${duration}ms`)
54
- .style('fill', d => { var _a; return (_a = getColor(d, config.segmentLabelColor)) !== null && _a !== void 0 ? _a : getLabelFillColor(d, config); })
57
+ .style('fill', (d, i, els) => { var _a; return (_a = getColor(d, config.segmentLabelColor)) !== null && _a !== void 0 ? _a : getLabelFillColor(d, els[i]); })
55
58
  .each((d, i, els) => {
56
59
  const bounds = getLabelBounds(d);
57
60
  const label = select(els[i]).call(wrapSVGText, bounds.width);
@@ -1 +1 @@
1
- {"version":3,"file":"label.js","sources":["../../../../src/components/nested-donut/modules/label.ts"],"sourcesContent":["import { Selection, select } from 'd3-selection'\nimport { color } from 'd3-color'\nimport { Arc } from 'd3-shape'\n\n// Utils\nimport { getColor, hexToBrightness } from 'utils/color'\nimport { smartTransition } from 'utils/d3'\nimport { getString } from 'utils/data'\nimport { getCSSVariableValueInPixels } from 'utils/misc'\nimport { cssvar } from 'utils/style'\nimport { wrapSVGText } from 'utils/text'\n\n// Config\nimport { NestedDonutConfig } from '../config'\n\n// Local Types\nimport { NestedDonutSegment, NestedDonutSegmentLabelAlignment } from '../types'\n\n// Styles\nimport { variables } from '../style'\n\nfunction getLabelFillColor<Datum> (\n d: NestedDonutSegment<Datum>,\n config: NestedDonutConfig<Datum>\n): string {\n const c = getColor(d, config.segmentColor) ?? d._state.fill\n const colorParsed = color(c)\n const brightness = colorParsed ? hexToBrightness(colorParsed.hex()) : 0\n return cssvar(brightness > 0.65 ? variables.nestedDonutSegmentLabelTextColorLight : variables.nestedDonutSegmentLabelTextColorDark)\n}\n\nfunction getLabelTransform<Datum> (\n d: NestedDonutSegment<Datum>,\n arcGen: Arc<unknown, NestedDonutSegment<Datum>>\n): string {\n const translate = `translate(${arcGen.centroid(d)})`\n const degree = 180 / Math.PI * (arcGen.startAngle()(d) + arcGen.endAngle()(d)) / 2 - 90\n switch (d._layer.labelAlignment) {\n case NestedDonutSegmentLabelAlignment.Along:\n return `${translate} rotate(${degree + 90})`\n case NestedDonutSegmentLabelAlignment.Perpendicular:\n return `${translate} rotate(${degree > 90 ? degree - 180 : degree})`\n default:\n return `${translate}`\n }\n}\n\nfunction getLabelBounds<Datum> (\n d: NestedDonutSegment<Datum>\n): { width: number; height: number } {\n const arcWidth = d.y1 - d.y0\n const arcLength = d._layer._innerRadius * (d.x1 - d.x0)\n const bandwidth = Math.max(Math.abs(Math.cos(d.x0 + (d.x1 - d.x0) / 2 - Math.PI / 2) * arcWidth), arcWidth)\n switch (d._layer.labelAlignment) {\n case NestedDonutSegmentLabelAlignment.Perpendicular:\n return { width: arcWidth, height: arcLength }\n case NestedDonutSegmentLabelAlignment.Along:\n return { width: arcLength, height: arcWidth }\n case NestedDonutSegmentLabelAlignment.Straight:\n return { width: bandwidth, height: bandwidth }\n }\n}\n\nexport function createLabel<Datum> (\n selection: Selection<SVGTextElement, NestedDonutSegment<Datum>, SVGGElement, unknown>,\n arcGen: Arc<unknown, NestedDonutSegment<Datum>>\n): void {\n selection\n .attr('transform', d => getLabelTransform(d, arcGen))\n .style('visibility', null)\n .style('opacity', 0)\n}\n\n\nexport function updateLabel<Datum> (\n selection: Selection<SVGTextElement, NestedDonutSegment<Datum>, SVGGElement, unknown>,\n config: NestedDonutConfig<Datum>,\n arcGen: Arc<unknown, NestedDonutSegment<Datum>>,\n duration: number\n): void {\n selection\n .text(d => getString(d, config.segmentLabel) ?? d.data.key)\n .style('transition', `fill ${duration}ms`)\n .style('fill', d => getColor(d, config.segmentLabelColor) ?? getLabelFillColor(d, config))\n .each((d, i, els) => {\n const bounds = getLabelBounds(d)\n const label = select(els[i]).call(wrapSVGText, bounds.width)\n\n const { width, height } = label.node().getBBox()\n\n if (config.hideOverflowingSegmentLabels && (width > bounds.width || height > bounds.height) && 'hidden') {\n label.attr('visibility', 'hidden')\n } else {\n const fontSize = getCSSVariableValueInPixels(cssvar(variables.nestedDonutSegmentLabelFontSize), els[i])\n const len = label.selectChildren().size() - 1\n label.attr('dy', -fontSize / 2 * len)\n }\n })\n\n smartTransition(selection, duration)\n .attr('transform', d => getLabelTransform(d, arcGen))\n .style('opacity', 1)\n}\n\nexport function removeLabel<Datum> (\n selection: Selection<SVGTextElement, NestedDonutSegment<Datum>, SVGGElement, unknown>,\n duration: number\n): void {\n smartTransition(selection, duration)\n .style('opacity', 0)\n .remove()\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"label.js","sources":["../../../../src/components/nested-donut/modules/label.ts"],"sourcesContent":["import { Selection, select } from 'd3-selection'\nimport { color } from 'd3-color'\nimport { Arc } from 'd3-shape'\n\n// Utils\nimport { getColor, getHexValue, rgbaToRgb, rgbToBrightness } from 'utils/color'\nimport { smartTransition } from 'utils/d3'\nimport { getString } from 'utils/data'\nimport { getCSSVariableValueInPixels } from 'utils/misc'\nimport { cssvar } from 'utils/style'\nimport { wrapSVGText } from 'utils/text'\n\n// Config\nimport { NestedDonutConfig } from '../config'\n\n// Local Types\nimport { NestedDonutSegment, NestedDonutSegmentLabelAlignment } from '../types'\n\n// Styles\nimport { variables } from '../style'\n\nfunction getLabelFillColor<Datum> (\n d: NestedDonutSegment<Datum>,\n element: SVGElement\n): string {\n const c = color(d._state.fill) ?? color(getHexValue(d._state.fill, element))\n const rgb = c?.rgb()\n\n // If shading, we adjust segment color before calculating brightness ratio\n const colorParsed = rgb && d._state.fillOpacity\n ? rgbaToRgb(\n `rgba(${rgb.r},${rgb.g},${rgb.b},${d._state.fillOpacity})`,\n getHexValue(cssvar(variables.nestedDonutBackgroundColor), element)\n ) : rgb\n\n const brightness = colorParsed ? rgbToBrightness(colorParsed) : 0\n return cssvar(brightness > 0.65 ? variables.nestedDonutSegmentLabelTextColorLight : variables.nestedDonutSegmentLabelTextColorDark)\n}\n\nfunction getLabelTransform<Datum> (\n d: NestedDonutSegment<Datum>,\n arcGen: Arc<unknown, NestedDonutSegment<Datum>>\n): string {\n const translate = `translate(${arcGen.centroid(d)})`\n const degree = 180 / Math.PI * (arcGen.startAngle()(d) + arcGen.endAngle()(d)) / 2 - 90\n switch (d._layer.labelAlignment) {\n case NestedDonutSegmentLabelAlignment.Along:\n return `${translate} rotate(${degree + 90})`\n case NestedDonutSegmentLabelAlignment.Perpendicular:\n return `${translate} rotate(${degree > 90 ? degree - 180 : degree})`\n default:\n return `${translate}`\n }\n}\n\nfunction getLabelBounds<Datum> (\n d: NestedDonutSegment<Datum>\n): { width: number; height: number } {\n const arcWidth = d.y1 - d.y0\n const arcLength = d._layer._innerRadius * (d.x1 - d.x0)\n const bandwidth = Math.max(Math.abs(Math.cos(d.x0 + (d.x1 - d.x0) / 2 - Math.PI / 2) * arcWidth), arcWidth)\n switch (d._layer.labelAlignment) {\n case NestedDonutSegmentLabelAlignment.Perpendicular:\n return { width: arcWidth, height: arcLength }\n case NestedDonutSegmentLabelAlignment.Along:\n return { width: arcLength, height: arcWidth }\n case NestedDonutSegmentLabelAlignment.Straight:\n return { width: bandwidth, height: bandwidth }\n }\n}\n\nexport function createLabel<Datum> (\n selection: Selection<SVGTextElement, NestedDonutSegment<Datum>, SVGGElement, unknown>,\n arcGen: Arc<unknown, NestedDonutSegment<Datum>>\n): void {\n selection\n .attr('transform', d => getLabelTransform(d, arcGen))\n .style('visibility', null)\n .style('opacity', 0)\n}\n\n\nexport function updateLabel<Datum> (\n selection: Selection<SVGTextElement, NestedDonutSegment<Datum>, SVGGElement, unknown>,\n config: NestedDonutConfig<Datum>,\n arcGen: Arc<unknown, NestedDonutSegment<Datum>>,\n duration: number\n): void {\n selection\n .text(d => getString(d, config.segmentLabel) ?? d.data.key)\n .style('transition', `fill ${duration}ms`)\n .style('fill', (d, i, els) => getColor(d, config.segmentLabelColor) ?? getLabelFillColor(d, els[i]))\n .each((d, i, els) => {\n const bounds = getLabelBounds(d)\n const label = select(els[i]).call(wrapSVGText, bounds.width)\n\n const { width, height } = label.node().getBBox()\n\n if (config.hideOverflowingSegmentLabels && (width > bounds.width || height > bounds.height) && 'hidden') {\n label.attr('visibility', 'hidden')\n } else {\n const fontSize = getCSSVariableValueInPixels(cssvar(variables.nestedDonutSegmentLabelFontSize), els[i])\n const len = label.selectChildren().size() - 1\n label.attr('dy', -fontSize / 2 * len)\n }\n })\n\n smartTransition(selection, duration)\n .attr('transform', d => getLabelTransform(d, arcGen))\n .style('opacity', 1)\n}\n\nexport function removeLabel<Datum> (\n selection: Selection<SVGTextElement, NestedDonutSegment<Datum>, SVGGElement, unknown>,\n duration: number\n): void {\n smartTransition(selection, duration)\n .style('opacity', 0)\n .remove()\n}\n"],"names":[],"mappings":"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"}
@@ -10,6 +10,7 @@ export declare type NestedDonutSegment<Datum> = HierarchyRectangularNode<NestedD
10
10
  _index?: number;
11
11
  _state?: {
12
12
  fill?: string;
13
+ fillOpacity?: number | null;
13
14
  };
14
15
  };
15
16
  export declare enum NestedDonutDirection {
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sources":["../../../src/components/nested-donut/types.ts"],"sourcesContent":["import { HierarchyRectangularNode } from 'd3-hierarchy'\n\nexport type NestedDonutSegmentDatum<Datum> = {\n key: string;\n root: string;\n values: Datum[];\n}\n\nexport type NestedDonutSegment<Datum> = HierarchyRectangularNode<NestedDonutSegmentDatum<Datum>> & {\n _id: string;\n _layer: NestedDonutLayer;\n _index?: number;\n _state?: {\n fill?: string;\n };\n}\n\nexport enum NestedDonutDirection {\n Inwards = 'inwards',\n Outwards = 'outwards',\n}\n\nexport enum NestedDonutSegmentLabelAlignment {\n Along = 'along',\n Perpendicular = 'perpendicular',\n Straight = 'straight',\n}\n\nexport type NestedDonutLayerSettings = {\n backgroundColor?: string;\n labelAlignment?: NestedDonutSegmentLabelAlignment;\n width?: number | string;\n}\n\nexport type NestedDonutLayer = NestedDonutLayerSettings & {\n _id: number;\n _innerRadius: number;\n _outerRadius: number;\n}\n\n"],"names":[],"mappings":"IAiBY,qBAGX;AAHD,CAAA,UAAY,oBAAoB,EAAA;AAC9B,IAAA,oBAAA,CAAA,SAAA,CAAA,GAAA,SAAmB,CAAA;AACnB,IAAA,oBAAA,CAAA,UAAA,CAAA,GAAA,UAAqB,CAAA;AACvB,CAAC,EAHW,oBAAoB,KAApB,oBAAoB,GAG/B,EAAA,CAAA,CAAA,CAAA;IAEW,iCAIX;AAJD,CAAA,UAAY,gCAAgC,EAAA;AAC1C,IAAA,gCAAA,CAAA,OAAA,CAAA,GAAA,OAAe,CAAA;AACf,IAAA,gCAAA,CAAA,eAAA,CAAA,GAAA,eAA+B,CAAA;AAC/B,IAAA,gCAAA,CAAA,UAAA,CAAA,GAAA,UAAqB,CAAA;AACvB,CAAC,EAJW,gCAAgC,KAAhC,gCAAgC,GAI3C,EAAA,CAAA,CAAA;;;;"}
1
+ {"version":3,"file":"types.js","sources":["../../../src/components/nested-donut/types.ts"],"sourcesContent":["import { HierarchyRectangularNode } from 'd3-hierarchy'\n\nexport type NestedDonutSegmentDatum<Datum> = {\n key: string;\n root: string;\n values: Datum[];\n}\n\nexport type NestedDonutSegment<Datum> = HierarchyRectangularNode<NestedDonutSegmentDatum<Datum>> & {\n _id: string;\n _layer: NestedDonutLayer;\n _index?: number;\n _state?: {\n fill?: string;\n fillOpacity?: number | null;\n };\n}\n\nexport enum NestedDonutDirection {\n Inwards = 'inwards',\n Outwards = 'outwards',\n}\n\nexport enum NestedDonutSegmentLabelAlignment {\n Along = 'along',\n Perpendicular = 'perpendicular',\n Straight = 'straight',\n}\n\nexport type NestedDonutLayerSettings = {\n backgroundColor?: string;\n labelAlignment?: NestedDonutSegmentLabelAlignment;\n width?: number | string;\n}\n\nexport type NestedDonutLayer = NestedDonutLayerSettings & {\n _id: number;\n _innerRadius: number;\n _outerRadius: number;\n}\n\n"],"names":[],"mappings":"IAkBY,qBAGX;AAHD,CAAA,UAAY,oBAAoB,EAAA;AAC9B,IAAA,oBAAA,CAAA,SAAA,CAAA,GAAA,SAAmB,CAAA;AACnB,IAAA,oBAAA,CAAA,UAAA,CAAA,GAAA,UAAqB,CAAA;AACvB,CAAC,EAHW,oBAAoB,KAApB,oBAAoB,GAG/B,EAAA,CAAA,CAAA,CAAA;IAEW,iCAIX;AAJD,CAAA,UAAY,gCAAgC,EAAA;AAC1C,IAAA,gCAAA,CAAA,OAAA,CAAA,GAAA,OAAe,CAAA;AACf,IAAA,gCAAA,CAAA,eAAA,CAAA,GAAA,eAA+B,CAAA;AAC/B,IAAA,gCAAA,CAAA,UAAA,CAAA,GAAA,UAAqB,CAAA;AACvB,CAAC,EAJW,gCAAgC,KAAhC,gCAAgC,GAI3C,EAAA,CAAA,CAAA;;;;"}
@@ -24,6 +24,8 @@ export interface ScatterConfigInterface<Datum> extends XYComponentConfigInterfac
24
24
  label?: StringAccessor<Datum>;
25
25
  /** Label color. Default: `undefined` */
26
26
  labelColor?: ColorAccessor<Datum>;
27
+ /** Hide overlapping labels. Default: `true` */
28
+ labelHideOverlapping?: boolean;
27
29
  /** Optional point cursor. Default: `null` */
28
30
  cursor?: StringAccessor<Datum>;
29
31
  /** Point color brightness ratio for switching between dark and light text label color. Default: `0.65` */
@@ -43,6 +45,7 @@ export declare class ScatterConfig<Datum> extends XYComponentConfig<Datum> imple
43
45
  label: any;
44
46
  labelColor: any;
45
47
  labelPosition: Position;
48
+ labelHideOverlapping: boolean;
46
49
  cursor: any;
47
50
  labelTextBrightnessRatio: number;
48
51
  strokeColor: ScatterConfigInterface<Datum>['strokeColor'];
@@ -14,6 +14,7 @@ class ScatterConfig extends XYComponentConfig {
14
14
  this.label = undefined;
15
15
  this.labelColor = undefined;
16
16
  this.labelPosition = Position.Bottom;
17
+ this.labelHideOverlapping = true;
17
18
  this.cursor = null;
18
19
  this.labelTextBrightnessRatio = 0.65;
19
20
  this.strokeColor = undefined;
@@ -1 +1 @@
1
- {"version":3,"file":"config.js","sources":["../../../src/components/scatter/config.ts"],"sourcesContent":["import { ScalePower } from 'd3-scale'\n// Core\nimport { XYComponentConfigInterface, XYComponentConfig } from 'core/xy-component/config'\n\n// Types\nimport { Scale, ContinuousScale } from 'types/scale'\nimport { SymbolType } from 'types/symbol'\nimport { ColorAccessor, GenericAccessor, NumericAccessor, StringAccessor } from 'types/accessor'\nimport { Position } from 'types/position'\n\nexport interface ScatterConfigInterface<Datum> extends XYComponentConfigInterface<Datum> {\n /**\n * Size of the scatter plot marker (e.g. diameter if `SymbolType.Circle` is used for `shape`) in pixels.\n * Can be a constant value or an accessor function. But if `sizeRange` is set, then the values will be treated\n * as an input to `sizeScale`, and the resulting size will be different.\n * Default: `10`\n */\n size?: NumericAccessor<Datum>;\n /** Size scale to be used if the `sizeRange` was set. Default: `Scale.scaleSqrt()` */\n sizeScale?: ContinuousScale;\n /** Size range in the format of `[number, number]` to rescale the input values. Default: `undefined` */\n sizeRange?: [number, number];\n /** Shape of the scatter point. Accessor function or constant value: `SymbolType.Circle`, `SymbolType.Cross`, `SymbolType.Diamond`, `SymbolType.Square`,\n * `SymbolType.Star`, `SymbolType.Triangle` or `SymbolType.Wye`.\n * Default: `SymbolType.Circle` */\n shape?: ((d: Datum, i?: number, ...any) => (SymbolType | string)) | SymbolType | string;\n /** Label accessor function or string. Default: `undefined` */\n label?: StringAccessor<Datum>;\n /** Label color. Default: `undefined` */\n labelColor?: ColorAccessor<Datum>;\n /** Optional point cursor. Default: `null` */\n cursor?: StringAccessor<Datum>;\n /** Point color brightness ratio for switching between dark and light text label color. Default: `0.65` */\n labelTextBrightnessRatio?: number;\n /** Label position. Default: `Position.Bottom` */\n labelPosition?: GenericAccessor<Position | string, Datum>;\n /** Point stroke color. Default: `undefined` */\n strokeColor?: ColorAccessor<Datum>;\n /** Point stroke width. Default: `undefined` */\n strokeWidth?: NumericAccessor<Datum>;\n}\n\nexport class ScatterConfig<Datum> extends XYComponentConfig<Datum> implements ScatterConfigInterface<Datum> {\n size = 10\n sizeScale: ScalePower<number, number> = Scale.scaleSqrt()\n sizeRange = undefined\n shape = SymbolType.Circle\n label = undefined\n labelColor = undefined\n labelPosition = Position.Bottom\n cursor = null\n labelTextBrightnessRatio = 0.65\n strokeColor: ScatterConfigInterface<Datum>['strokeColor'] = undefined\n strokeWidth: ScatterConfigInterface<Datum>['strokeWidth'] = undefined\n}\n"],"names":[],"mappings":";;;;;AACA;AAyCM,MAAO,aAAqB,SAAQ,iBAAwB,CAAA;AAAlE,IAAA,WAAA,GAAA;;QACE,IAAI,CAAA,IAAA,GAAG,EAAE,CAAA;AACT,QAAA,IAAA,CAAA,SAAS,GAA+B,KAAK,CAAC,SAAS,EAAE,CAAA;QACzD,IAAS,CAAA,SAAA,GAAG,SAAS,CAAA;AACrB,QAAA,IAAA,CAAA,KAAK,GAAG,UAAU,CAAC,MAAM,CAAA;QACzB,IAAK,CAAA,KAAA,GAAG,SAAS,CAAA;QACjB,IAAU,CAAA,UAAA,GAAG,SAAS,CAAA;AACtB,QAAA,IAAA,CAAA,aAAa,GAAG,QAAQ,CAAC,MAAM,CAAA;QAC/B,IAAM,CAAA,MAAA,GAAG,IAAI,CAAA;QACb,IAAwB,CAAA,wBAAA,GAAG,IAAI,CAAA;QAC/B,IAAW,CAAA,WAAA,GAAiD,SAAS,CAAA;QACrE,IAAW,CAAA,WAAA,GAAiD,SAAS,CAAA;KACtE;AAAA;;;;"}
1
+ {"version":3,"file":"config.js","sources":["../../../src/components/scatter/config.ts"],"sourcesContent":["import { ScalePower } from 'd3-scale'\n// Core\nimport { XYComponentConfigInterface, XYComponentConfig } from 'core/xy-component/config'\n\n// Types\nimport { Scale, ContinuousScale } from 'types/scale'\nimport { SymbolType } from 'types/symbol'\nimport { ColorAccessor, GenericAccessor, NumericAccessor, StringAccessor } from 'types/accessor'\nimport { Position } from 'types/position'\n\nexport interface ScatterConfigInterface<Datum> extends XYComponentConfigInterface<Datum> {\n /**\n * Size of the scatter plot marker (e.g. diameter if `SymbolType.Circle` is used for `shape`) in pixels.\n * Can be a constant value or an accessor function. But if `sizeRange` is set, then the values will be treated\n * as an input to `sizeScale`, and the resulting size will be different.\n * Default: `10`\n */\n size?: NumericAccessor<Datum>;\n /** Size scale to be used if the `sizeRange` was set. Default: `Scale.scaleSqrt()` */\n sizeScale?: ContinuousScale;\n /** Size range in the format of `[number, number]` to rescale the input values. Default: `undefined` */\n sizeRange?: [number, number];\n /** Shape of the scatter point. Accessor function or constant value: `SymbolType.Circle`, `SymbolType.Cross`, `SymbolType.Diamond`, `SymbolType.Square`,\n * `SymbolType.Star`, `SymbolType.Triangle` or `SymbolType.Wye`.\n * Default: `SymbolType.Circle` */\n shape?: ((d: Datum, i?: number, ...any) => (SymbolType | string)) | SymbolType | string;\n /** Label accessor function or string. Default: `undefined` */\n label?: StringAccessor<Datum>;\n /** Label color. Default: `undefined` */\n labelColor?: ColorAccessor<Datum>;\n /** Hide overlapping labels. Default: `true` */\n labelHideOverlapping?: boolean;\n /** Optional point cursor. Default: `null` */\n cursor?: StringAccessor<Datum>;\n /** Point color brightness ratio for switching between dark and light text label color. Default: `0.65` */\n labelTextBrightnessRatio?: number;\n /** Label position. Default: `Position.Bottom` */\n labelPosition?: GenericAccessor<Position | string, Datum>;\n /** Point stroke color. Default: `undefined` */\n strokeColor?: ColorAccessor<Datum>;\n /** Point stroke width. Default: `undefined` */\n strokeWidth?: NumericAccessor<Datum>;\n}\n\nexport class ScatterConfig<Datum> extends XYComponentConfig<Datum> implements ScatterConfigInterface<Datum> {\n size = 10\n sizeScale: ScalePower<number, number> = Scale.scaleSqrt()\n sizeRange = undefined\n shape = SymbolType.Circle\n label = undefined\n labelColor = undefined\n labelPosition = Position.Bottom\n labelHideOverlapping = true\n cursor = null\n labelTextBrightnessRatio = 0.65\n strokeColor: ScatterConfigInterface<Datum>['strokeColor'] = undefined\n strokeWidth: ScatterConfigInterface<Datum>['strokeWidth'] = undefined\n}\n"],"names":[],"mappings":";;;;;AACA;AA2CM,MAAO,aAAqB,SAAQ,iBAAwB,CAAA;AAAlE,IAAA,WAAA,GAAA;;QACE,IAAI,CAAA,IAAA,GAAG,EAAE,CAAA;AACT,QAAA,IAAA,CAAA,SAAS,GAA+B,KAAK,CAAC,SAAS,EAAE,CAAA;QACzD,IAAS,CAAA,SAAA,GAAG,SAAS,CAAA;AACrB,QAAA,IAAA,CAAA,KAAK,GAAG,UAAU,CAAC,MAAM,CAAA;QACzB,IAAK,CAAA,KAAA,GAAG,SAAS,CAAA;QACjB,IAAU,CAAA,UAAA,GAAG,SAAS,CAAA;AACtB,QAAA,IAAA,CAAA,aAAa,GAAG,QAAQ,CAAC,MAAM,CAAA;QAC/B,IAAoB,CAAA,oBAAA,GAAG,IAAI,CAAA;QAC3B,IAAM,CAAA,MAAA,GAAG,IAAI,CAAA;QACb,IAAwB,CAAA,wBAAA,GAAG,IAAI,CAAA;QAC/B,IAAW,CAAA,WAAA,GAAiD,SAAS,CAAA;QACrE,IAAW,CAAA,WAAA,GAAiD,SAAS,CAAA;KACtE;AAAA;;;;"}
@@ -20,7 +20,7 @@ export declare class Scatter<Datum> extends XYComponentCore<Datum, ScatterConfig
20
20
  setData(data: Datum[]): void;
21
21
  get bleed(): Spacing;
22
22
  _render(customDuration?: number): void;
23
- private _collideLabels;
23
+ private _resolveLabelOverlap;
24
24
  private _updateSizeScale;
25
25
  private _getOnScreenData;
26
26
  private _onPointMouseOver;
@@ -92,9 +92,14 @@ class Scatter extends XYComponentCore {
92
92
  updatePoints(this._points, config, this.xScale, this.yScale, duration);
93
93
  removePoints(points.exit(), this.xScale, this.yScale, duration);
94
94
  // Take care of overlapping labels
95
- this._collideLabels();
95
+ this._resolveLabelOverlap();
96
96
  }
97
- _collideLabels() {
97
+ _resolveLabelOverlap() {
98
+ if (!this.config.labelHideOverlapping) {
99
+ const label = this._points.selectAll('text');
100
+ label.attr('opacity', null);
101
+ return;
102
+ }
98
103
  cancelAnimationFrame(this._collideLabelsAnimFrameId);
99
104
  this._collideLabelsAnimFrameId = requestAnimationFrame(() => {
100
105
  collideLabels(this._points, this.config, this.xScale, this.yScale);
@@ -154,13 +159,13 @@ class Scatter extends XYComponentCore {
154
159
  if (pointNode)
155
160
  pointNode._forceShowLabel = true;
156
161
  point.raise();
157
- this._collideLabels();
162
+ this._resolveLabelOverlap();
158
163
  }
159
164
  _onPointMouseOut(d, event) {
160
165
  const pointNode = select(event.target).node();
161
166
  if (pointNode)
162
167
  delete pointNode._forceShowLabel;
163
- this._collideLabels();
168
+ this._resolveLabelOverlap();
164
169
  }
165
170
  }
166
171
  Scatter.selectors = style;
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../../../src/components/scatter/index.ts"],"sourcesContent":["import { Selection, select } from 'd3-selection'\nimport { max, min } from 'd3-array'\n\n// Core\nimport { XYComponentCore } from 'core/xy-component'\n\n// Utils\nimport { isNumber, getExtent, getNumber, getString, isArray, flatten, getValue } from 'utils/data'\nimport { getColor } from 'utils/color'\nimport { smartTransition } from 'utils/d3'\nimport { getCSSVariableValueInPixels } from 'utils/misc'\n\n// Types\nimport { Spacing } from 'types/spacing'\nimport { SymbolType } from 'types/symbol'\nimport { NumericAccessor } from 'types/accessor'\n\n// Local Types\nimport { ScatterPointGroupNode, ScatterPoint } from './types'\n\n// Config\nimport { ScatterConfig, ScatterConfigInterface } from './config'\n\n// Modules\nimport { createPoints, updatePoints, removePoints } from './modules/point'\nimport { collideLabels, getEstimatedLabelBBox } from './modules/utils'\n\n// Styles\nimport * as s from './style'\n\nexport class Scatter<Datum> extends XYComponentCore<Datum, ScatterConfig<Datum>, ScatterConfigInterface<Datum>> {\n static selectors = s\n config: ScatterConfig<Datum> = new ScatterConfig()\n events = {\n [Scatter.selectors.point]: {\n mouseenter: this._onPointMouseOver.bind(this),\n mouseleave: this._onPointMouseOut.bind(this),\n },\n }\n\n private _pointData: ScatterPoint<Datum>[][] = []\n private _points: Selection<SVGGElement, ScatterPoint<Datum>, SVGGElement, ScatterPoint<Datum>[]>\n private _collideLabelsAnimFrameId: ReturnType<typeof requestAnimationFrame>\n\n constructor (config?: ScatterConfigInterface<Datum>) {\n super()\n if (config) this.setConfig(config)\n }\n\n setConfig (config: ScatterConfigInterface<Datum>): void {\n super.setConfig(config)\n this._updateSizeScale()\n }\n\n setData (data: Datum[]): void {\n super.setData(data)\n this._updateSizeScale()\n }\n\n get bleed (): Spacing {\n this._pointData = this._getOnScreenData()\n const pointDataFlat: ScatterPoint<Datum>[] = flatten(this._pointData)\n\n const yRangeStart = min(this.yScale.range())\n const yRangeEnd = max(this.yScale.range())\n const xRangeStart = this.xScale.range()[0]\n const xRangeEnd = this.xScale.range()[1]\n\n const fontSizePx = getCSSVariableValueInPixels('var(--vis-scatter-point-label-text-font-size)', this.element)\n\n const extent = pointDataFlat.reduce((ext, d) => {\n const labelPosition = getValue(d, this.config.labelPosition, d._point.pointIndex)\n const labelBBox = getEstimatedLabelBBox(d, labelPosition, this.xScale, this.yScale, fontSizePx)\n const x = this.xScale(d._point.xValue)\n const y = this.yScale(d._point.yValue)\n const r = d._point.sizePx / 2\n\n ext.minX = Math.min(ext.minX, x - r, labelBBox.x)\n ext.maxX = Math.max(ext.maxX, x + r, labelBBox.x + labelBBox.width)\n ext.minY = Math.min(ext.minY, y - r, labelBBox.y)\n ext.maxY = Math.max(ext.maxY, y + r, labelBBox.y + labelBBox.height)\n return ext\n }, {\n minX: Number.POSITIVE_INFINITY,\n maxX: Number.NEGATIVE_INFINITY,\n minY: Number.POSITIVE_INFINITY,\n maxY: Number.NEGATIVE_INFINITY,\n })\n\n const coeff = 1.2 // Multiplier to take into account subsequent scale range changes and shape irregularities\n const top = extent.minY < yRangeStart ? coeff * (yRangeStart - extent.minY) : 0\n const bottom = extent.maxY > yRangeEnd ? coeff * (extent.maxY - yRangeEnd) : 0\n const left = extent.minX < xRangeStart ? coeff * (xRangeStart - extent.minX) : 0\n const right = extent.maxX > xRangeEnd ? coeff * (extent.maxX - xRangeEnd) : 0\n\n return { top, bottom, left, right }\n }\n\n _render (customDuration?: number): void {\n const { config } = this\n const duration = isNumber(customDuration) ? customDuration : config.duration\n\n // Groups\n const pointGroups = this.g\n .selectAll<SVGGElement, ScatterPoint<Datum>[]>(`.${s.pointGroup}`)\n .data(this._pointData)\n\n const pointGroupsEnter = pointGroups\n .enter()\n .append('g')\n .attr('class', s.pointGroup)\n\n const pointGroupsMerged = pointGroupsEnter.merge(pointGroups)\n smartTransition(pointGroupsMerged, duration)\n .style('opacity', 1)\n\n const pointGroupExit = pointGroups.exit().attr('class', s.pointGroupExit)\n smartTransition(pointGroupExit, duration).style('opacity', 0).remove()\n\n // Points\n const points = pointGroupsMerged\n .selectAll<SVGGElement, ScatterPoint<Datum>>(`.${s.point}`)\n .data(\n d => d,\n d => `${getString(d, config.id, d._point.pointIndex) ?? d._point.pointIndex}`\n )\n\n const pointsEnter = points.enter().append('g')\n .attr('class', s.point)\n createPoints(pointsEnter, this.xScale, this.yScale)\n\n this._points = pointsEnter.merge(points)\n updatePoints(this._points, config, this.xScale, this.yScale, duration)\n\n removePoints(points.exit<ScatterPoint<Datum>>(), this.xScale, this.yScale, duration)\n\n // Take care of overlapping labels\n this._collideLabels()\n }\n\n private _collideLabels (): void {\n cancelAnimationFrame(this._collideLabelsAnimFrameId)\n this._collideLabelsAnimFrameId = requestAnimationFrame(() => {\n collideLabels(this._points, this.config, this.xScale, this.yScale)\n })\n }\n\n private _updateSizeScale (): void {\n const { config, datamodel } = this\n\n config.sizeScale\n .domain(getExtent(datamodel.data, config.size))\n .range(config.sizeRange ?? [0, 0])\n }\n\n private _getOnScreenData (): ScatterPoint<Datum>[][] {\n const { config, datamodel: { data } } = this\n\n const xDomain = this.xScale.domain().map(d => +d) // Convert Date to number\n const yDomain = this.yScale.domain().map(d => +d) // Convert Date to number\n const yAccessors = (isArray(config.y) ? config.y : [config.y]) as NumericAccessor<Datum>[]\n\n const maxSizeValue = max<number>(flatten(yAccessors.map((y, j) => data?.map(d => getNumber(d, config.size, j)))))\n const maxSizePx = config.sizeRange ? config.sizeScale(maxSizeValue) : maxSizeValue\n const maxSizeXDomain = (this.xScale.invert(maxSizePx) as number) - (this.xScale.invert(0) as number)\n const maxSizeYDomain = Math.abs((this.yScale.invert(maxSizePx) as number) - (this.yScale.invert(0) as number))\n\n return yAccessors.map((y, j) => {\n return data?.reduce<ScatterPoint<Datum>[]>((acc, d, i) => {\n const xValue = getNumber(d, config.x, i)\n const yValue = getNumber(d, y, j)\n const pointSize = getNumber(d, config.size, i)\n const pointSizeScaled = config.sizeRange ? config.sizeScale(pointSize) : pointSize\n const pointSizeXDomain = (this.xScale.invert(pointSizeScaled) as number) - (this.xScale.invert(0) as number)\n const pointSizeYDomain = Math.abs((this.yScale.invert(pointSizeScaled) as number) - (this.yScale.invert(0) as number))\n\n if (\n ((xValue - pointSizeXDomain / 2) >= (xDomain[0] - maxSizeXDomain / 2)) &&\n ((xValue + pointSizeXDomain / 2) <= (xDomain[1] + maxSizeXDomain / 2)) &&\n ((yValue - pointSizeYDomain / 2) >= (yDomain[0] - maxSizeYDomain / 2)) &&\n ((yValue + pointSizeYDomain / 2) <= (yDomain[1] + maxSizeYDomain / 2))\n ) {\n acc.push({\n ...d,\n _point: {\n xValue: xValue,\n yValue: yValue,\n sizePx: pointSizeScaled,\n color: getColor(d, config.color, j),\n strokeColor: getColor(d, config.strokeColor, j, true),\n strokeWidthPx: getNumber(d, config.strokeWidth, j),\n shape: getString(d, config.shape, j) as SymbolType,\n label: getString(d, config.label, j),\n labelColor: getValue(d, config.labelColor, j),\n cursor: getString(d, config.cursor, j),\n groupIndex: j,\n pointIndex: i,\n },\n })\n }\n\n return acc\n }, []) ?? []\n })\n }\n\n private _onPointMouseOver (d: ScatterPoint<Datum>, event: MouseEvent): void {\n const point = select(event.target as SVGGElement)\n const pointNode = point.node() as ScatterPointGroupNode | null\n if (pointNode) pointNode._forceShowLabel = true\n\n point.raise()\n this._collideLabels()\n }\n\n private _onPointMouseOut (d: ScatterPoint<Datum>, event: MouseEvent): void {\n const pointNode = select(event.target as SVGGElement).node() as ScatterPointGroupNode | null\n if (pointNode) delete pointNode._forceShowLabel\n\n this._collideLabels()\n }\n}\n"],"names":["s.pointGroup","pointGroupExit","s.pointGroupExit","s.point","s"],"mappings":";;;;;;;;;;;;;AA8BM,MAAO,OAAe,SAAQ,eAA2E,CAAA;AAc7G,IAAA,WAAA,CAAa,MAAsC,EAAA;AACjD,QAAA,KAAK,EAAE,CAAA;AAbT,QAAA,IAAA,CAAA,MAAM,GAAyB,IAAI,aAAa,EAAE,CAAA;AAClD,QAAA,IAAA,CAAA,MAAM,GAAG;AACP,YAAA,CAAC,OAAO,CAAC,SAAS,CAAC,KAAK,GAAG;gBACzB,UAAU,EAAE,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC,IAAI,CAAC;gBAC7C,UAAU,EAAE,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC;AAC7C,aAAA;SACF,CAAA;QAEO,IAAU,CAAA,UAAA,GAA4B,EAAE,CAAA;AAM9C,QAAA,IAAI,MAAM;AAAE,YAAA,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAA;KACnC;AAED,IAAA,SAAS,CAAE,MAAqC,EAAA;AAC9C,QAAA,KAAK,CAAC,SAAS,CAAC,MAAM,CAAC,CAAA;QACvB,IAAI,CAAC,gBAAgB,EAAE,CAAA;KACxB;AAED,IAAA,OAAO,CAAE,IAAa,EAAA;AACpB,QAAA,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAA;QACnB,IAAI,CAAC,gBAAgB,EAAE,CAAA;KACxB;AAED,IAAA,IAAI,KAAK,GAAA;AACP,QAAA,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,gBAAgB,EAAE,CAAA;QACzC,MAAM,aAAa,GAA0B,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,CAAA;QAErE,MAAM,WAAW,GAAG,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,CAAA;QAC5C,MAAM,SAAS,GAAG,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,CAAA;QAC1C,MAAM,WAAW,GAAG,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,CAAA;QAC1C,MAAM,SAAS,GAAG,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,CAAA;QAExC,MAAM,UAAU,GAAG,2BAA2B,CAAC,+CAA+C,EAAE,IAAI,CAAC,OAAO,CAAC,CAAA;QAE7G,MAAM,MAAM,GAAG,aAAa,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC,KAAI;AAC7C,YAAA,MAAM,aAAa,GAAG,QAAQ,CAAC,CAAC,EAAE,IAAI,CAAC,MAAM,CAAC,aAAa,EAAE,CAAC,CAAC,MAAM,CAAC,UAAU,CAAC,CAAA;AACjF,YAAA,MAAM,SAAS,GAAG,qBAAqB,CAAC,CAAC,EAAE,aAAa,EAAE,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,UAAU,CAAC,CAAA;AAC/F,YAAA,MAAM,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAA;AACtC,YAAA,MAAM,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAA;YACtC,MAAM,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAA;AAE7B,YAAA,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC,EAAE,SAAS,CAAC,CAAC,CAAC,CAAA;YACjD,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC,EAAE,SAAS,CAAC,CAAC,GAAG,SAAS,CAAC,KAAK,CAAC,CAAA;AACnE,YAAA,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC,EAAE,SAAS,CAAC,CAAC,CAAC,CAAA;YACjD,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC,EAAE,SAAS,CAAC,CAAC,GAAG,SAAS,CAAC,MAAM,CAAC,CAAA;AACpE,YAAA,OAAO,GAAG,CAAA;AACZ,SAAC,EAAE;YACD,IAAI,EAAE,MAAM,CAAC,iBAAiB;YAC9B,IAAI,EAAE,MAAM,CAAC,iBAAiB;YAC9B,IAAI,EAAE,MAAM,CAAC,iBAAiB;YAC9B,IAAI,EAAE,MAAM,CAAC,iBAAiB;AAC/B,SAAA,CAAC,CAAA;AAEF,QAAA,MAAM,KAAK,GAAG,GAAG,CAAA;QACjB,MAAM,GAAG,GAAG,MAAM,CAAC,IAAI,GAAG,WAAW,GAAG,KAAK,IAAI,WAAW,GAAG,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;QAC/E,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,GAAG,SAAS,GAAG,KAAK,IAAI,MAAM,CAAC,IAAI,GAAG,SAAS,CAAC,GAAG,CAAC,CAAA;QAC9E,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,GAAG,WAAW,GAAG,KAAK,IAAI,WAAW,GAAG,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;QAChF,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,GAAG,SAAS,GAAG,KAAK,IAAI,MAAM,CAAC,IAAI,GAAG,SAAS,CAAC,GAAG,CAAC,CAAA;QAE7E,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,CAAA;KACpC;AAED,IAAA,OAAO,CAAE,cAAuB,EAAA;AAC9B,QAAA,MAAM,EAAE,MAAM,EAAE,GAAG,IAAI,CAAA;AACvB,QAAA,MAAM,QAAQ,GAAG,QAAQ,CAAC,cAAc,CAAC,GAAG,cAAc,GAAG,MAAM,CAAC,QAAQ,CAAA;;AAG5E,QAAA,MAAM,WAAW,GAAG,IAAI,CAAC,CAAC;AACvB,aAAA,SAAS,CAAqC,CAAI,CAAA,EAAAA,UAAY,EAAE,CAAC;AACjE,aAAA,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,CAAA;QAExB,MAAM,gBAAgB,GAAG,WAAW;AACjC,aAAA,KAAK,EAAE;aACP,MAAM,CAAC,GAAG,CAAC;AACX,aAAA,IAAI,CAAC,OAAO,EAAEA,UAAY,CAAC,CAAA;QAE9B,MAAM,iBAAiB,GAAG,gBAAgB,CAAC,KAAK,CAAC,WAAW,CAAC,CAAA;AAC7D,QAAA,eAAe,CAAC,iBAAiB,EAAE,QAAQ,CAAC;AACzC,aAAA,KAAK,CAAC,SAAS,EAAE,CAAC,CAAC,CAAA;AAEtB,QAAA,MAAMC,gBAAc,GAAG,WAAW,CAAC,IAAI,EAAE,CAAC,IAAI,CAAC,OAAO,EAAEC,cAAgB,CAAC,CAAA;AACzE,QAAA,eAAe,CAACD,gBAAc,EAAE,QAAQ,CAAC,CAAC,KAAK,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,MAAM,EAAE,CAAA;;QAGtE,MAAM,MAAM,GAAG,iBAAiB;AAC7B,aAAA,SAAS,CAAmC,CAAI,CAAA,EAAAE,KAAO,EAAE,CAAC;AAC1D,aAAA,IAAI,CACH,CAAC,IAAI,CAAC,EACN,CAAC,cAAI,OAAA,CAAA,EAAG,MAAA,SAAS,CAAC,CAAC,EAAE,MAAM,CAAC,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,UAAU,CAAC,MAAA,IAAA,IAAA,EAAA,KAAA,KAAA,CAAA,GAAA,EAAA,GAAI,CAAC,CAAC,MAAM,CAAC,UAAU,EAAE,CAAA,EAAA,CAC9E,CAAA;QAEH,MAAM,WAAW,GAAG,MAAM,CAAC,KAAK,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC;AAC3C,aAAA,IAAI,CAAC,OAAO,EAAEA,KAAO,CAAC,CAAA;QACzB,YAAY,CAAC,WAAW,EAAE,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,CAAA;QAEnD,IAAI,CAAC,OAAO,GAAG,WAAW,CAAC,KAAK,CAAC,MAAM,CAAC,CAAA;AACxC,QAAA,YAAY,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAA;AAEtE,QAAA,YAAY,CAAC,MAAM,CAAC,IAAI,EAAuB,EAAE,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAA;;QAGpF,IAAI,CAAC,cAAc,EAAE,CAAA;KACtB;IAEO,cAAc,GAAA;AACpB,QAAA,oBAAoB,CAAC,IAAI,CAAC,yBAAyB,CAAC,CAAA;AACpD,QAAA,IAAI,CAAC,yBAAyB,GAAG,qBAAqB,CAAC,MAAK;AAC1D,YAAA,aAAa,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,CAAA;AACpE,SAAC,CAAC,CAAA;KACH;IAEO,gBAAgB,GAAA;;AACtB,QAAA,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,GAAG,IAAI,CAAA;AAElC,QAAA,MAAM,CAAC,SAAS;aACb,MAAM,CAAC,SAAS,CAAC,SAAS,CAAC,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC;AAC9C,aAAA,KAAK,CAAC,CAAA,EAAA,GAAA,MAAM,CAAC,SAAS,MAAA,IAAA,IAAA,EAAA,KAAA,KAAA,CAAA,GAAA,EAAA,GAAI,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAA;KACrC;IAEO,gBAAgB,GAAA;QACtB,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,EAAE,IAAI,EAAE,EAAE,GAAG,IAAI,CAAA;QAE5C,MAAM,OAAO,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;QACjD,MAAM,OAAO,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;QACjD,MAAM,UAAU,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAA6B,CAAA;AAE1F,QAAA,MAAM,YAAY,GAAG,GAAG,CAAS,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,IAAI,aAAJ,IAAI,KAAA,KAAA,CAAA,GAAA,KAAA,CAAA,GAAJ,IAAI,CAAE,GAAG,CAAC,CAAC,IAAI,SAAS,CAAC,CAAC,EAAE,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;AACjH,QAAA,MAAM,SAAS,GAAG,MAAM,CAAC,SAAS,GAAG,MAAM,CAAC,SAAS,CAAC,YAAY,CAAC,GAAG,YAAY,CAAA;AAClF,QAAA,MAAM,cAAc,GAAI,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,SAAS,CAAY,GAAI,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAY,CAAA;QACpG,MAAM,cAAc,GAAG,IAAI,CAAC,GAAG,CAAE,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,SAAS,CAAY,GAAI,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAY,CAAC,CAAA;QAE9G,OAAO,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,KAAI;;AAC7B,YAAA,OAAO,MAAA,IAAI,KAAA,IAAA,IAAJ,IAAI,KAAA,KAAA,CAAA,GAAA,KAAA,CAAA,GAAJ,IAAI,CAAE,MAAM,CAAwB,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,KAAI;AACvD,gBAAA,MAAM,MAAM,GAAG,SAAS,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,CAAA;gBACxC,MAAM,MAAM,GAAG,SAAS,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAA;AACjC,gBAAA,MAAM,SAAS,GAAG,SAAS,CAAC,CAAC,EAAE,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,CAAA;AAC9C,gBAAA,MAAM,eAAe,GAAG,MAAM,CAAC,SAAS,GAAG,MAAM,CAAC,SAAS,CAAC,SAAS,CAAC,GAAG,SAAS,CAAA;AAClF,gBAAA,MAAM,gBAAgB,GAAI,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,eAAe,CAAY,GAAI,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAY,CAAA;gBAC5G,MAAM,gBAAgB,GAAG,IAAI,CAAC,GAAG,CAAE,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,eAAe,CAAY,GAAI,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAY,CAAC,CAAA;AAEtH,gBAAA,IACE,CAAC,CAAC,MAAM,GAAG,gBAAgB,GAAG,CAAC,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,cAAc,GAAG,CAAC,CAAC;AACrE,qBAAC,CAAC,MAAM,GAAG,gBAAgB,GAAG,CAAC,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,cAAc,GAAG,CAAC,CAAC,CAAC;AACtE,qBAAC,CAAC,MAAM,GAAG,gBAAgB,GAAG,CAAC,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,cAAc,GAAG,CAAC,CAAC,CAAC;AACtE,qBAAC,CAAC,MAAM,GAAG,gBAAgB,GAAG,CAAC,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,cAAc,GAAG,CAAC,CAAC,CAAC,EACtE;AACA,oBAAA,GAAG,CAAC,IAAI,CAAA,MAAA,CAAA,MAAA,CAAA,MAAA,CAAA,MAAA,CAAA,EAAA,EACH,CAAC,CAAA,EAAA,EACJ,MAAM,EAAE;AACN,4BAAA,MAAM,EAAE,MAAM;AACd,4BAAA,MAAM,EAAE,MAAM;AACd,4BAAA,MAAM,EAAE,eAAe;4BACvB,KAAK,EAAE,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC;AACnC,4BAAA,WAAW,EAAE,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC,WAAW,EAAE,CAAC,EAAE,IAAI,CAAC;4BACrD,aAAa,EAAE,SAAS,CAAC,CAAC,EAAE,MAAM,CAAC,WAAW,EAAE,CAAC,CAAC;4BAClD,KAAK,EAAE,SAAS,CAAC,CAAC,EAAE,MAAM,CAAC,KAAK,EAAE,CAAC,CAAe;4BAClD,KAAK,EAAE,SAAS,CAAC,CAAC,EAAE,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC;4BACpC,UAAU,EAAE,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC,UAAU,EAAE,CAAC,CAAC;4BAC7C,MAAM,EAAE,SAAS,CAAC,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC;AACtC,4BAAA,UAAU,EAAE,CAAC;AACb,4BAAA,UAAU,EAAE,CAAC;AACd,yBAAA,EAAA,CAAA,CACD,CAAA;AACH,iBAAA;AAED,gBAAA,OAAO,GAAG,CAAA;AACZ,aAAC,EAAE,EAAE,CAAC,MAAA,IAAA,IAAA,EAAA,KAAA,KAAA,CAAA,GAAA,EAAA,GAAI,EAAE,CAAA;AACd,SAAC,CAAC,CAAA;KACH;IAEO,iBAAiB,CAAE,CAAsB,EAAE,KAAiB,EAAA;QAClE,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,MAAqB,CAAC,CAAA;AACjD,QAAA,MAAM,SAAS,GAAG,KAAK,CAAC,IAAI,EAAkC,CAAA;AAC9D,QAAA,IAAI,SAAS;AAAE,YAAA,SAAS,CAAC,eAAe,GAAG,IAAI,CAAA;QAE/C,KAAK,CAAC,KAAK,EAAE,CAAA;QACb,IAAI,CAAC,cAAc,EAAE,CAAA;KACtB;IAEO,gBAAgB,CAAE,CAAsB,EAAE,KAAiB,EAAA;QACjE,MAAM,SAAS,GAAG,MAAM,CAAC,KAAK,CAAC,MAAqB,CAAC,CAAC,IAAI,EAAkC,CAAA;AAC5F,QAAA,IAAI,SAAS;YAAE,OAAO,SAAS,CAAC,eAAe,CAAA;QAE/C,IAAI,CAAC,cAAc,EAAE,CAAA;KACtB;;AA7LM,OAAS,CAAA,SAAA,GAAGC,KAAC;;;;"}
1
+ {"version":3,"file":"index.js","sources":["../../../src/components/scatter/index.ts"],"sourcesContent":["import { Selection, select } from 'd3-selection'\nimport { max, min } from 'd3-array'\n\n// Core\nimport { XYComponentCore } from 'core/xy-component'\n\n// Utils\nimport { isNumber, getExtent, getNumber, getString, isArray, flatten, getValue } from 'utils/data'\nimport { getColor } from 'utils/color'\nimport { smartTransition } from 'utils/d3'\nimport { getCSSVariableValueInPixels } from 'utils/misc'\n\n// Types\nimport { Spacing } from 'types/spacing'\nimport { SymbolType } from 'types/symbol'\nimport { NumericAccessor } from 'types/accessor'\n\n// Local Types\nimport { ScatterPointGroupNode, ScatterPoint } from './types'\n\n// Config\nimport { ScatterConfig, ScatterConfigInterface } from './config'\n\n// Modules\nimport { createPoints, updatePoints, removePoints } from './modules/point'\nimport { collideLabels, getEstimatedLabelBBox } from './modules/utils'\n\n// Styles\nimport * as s from './style'\n\nexport class Scatter<Datum> extends XYComponentCore<Datum, ScatterConfig<Datum>, ScatterConfigInterface<Datum>> {\n static selectors = s\n config: ScatterConfig<Datum> = new ScatterConfig()\n events = {\n [Scatter.selectors.point]: {\n mouseenter: this._onPointMouseOver.bind(this),\n mouseleave: this._onPointMouseOut.bind(this),\n },\n }\n\n private _pointData: ScatterPoint<Datum>[][] = []\n private _points: Selection<SVGGElement, ScatterPoint<Datum>, SVGGElement, ScatterPoint<Datum>[]>\n private _collideLabelsAnimFrameId: ReturnType<typeof requestAnimationFrame>\n\n constructor (config?: ScatterConfigInterface<Datum>) {\n super()\n if (config) this.setConfig(config)\n }\n\n setConfig (config: ScatterConfigInterface<Datum>): void {\n super.setConfig(config)\n this._updateSizeScale()\n }\n\n setData (data: Datum[]): void {\n super.setData(data)\n this._updateSizeScale()\n }\n\n get bleed (): Spacing {\n this._pointData = this._getOnScreenData()\n const pointDataFlat: ScatterPoint<Datum>[] = flatten(this._pointData)\n\n const yRangeStart = min(this.yScale.range())\n const yRangeEnd = max(this.yScale.range())\n const xRangeStart = this.xScale.range()[0]\n const xRangeEnd = this.xScale.range()[1]\n\n const fontSizePx = getCSSVariableValueInPixels('var(--vis-scatter-point-label-text-font-size)', this.element)\n\n const extent = pointDataFlat.reduce((ext, d) => {\n const labelPosition = getValue(d, this.config.labelPosition, d._point.pointIndex)\n const labelBBox = getEstimatedLabelBBox(d, labelPosition, this.xScale, this.yScale, fontSizePx)\n const x = this.xScale(d._point.xValue)\n const y = this.yScale(d._point.yValue)\n const r = d._point.sizePx / 2\n\n ext.minX = Math.min(ext.minX, x - r, labelBBox.x)\n ext.maxX = Math.max(ext.maxX, x + r, labelBBox.x + labelBBox.width)\n ext.minY = Math.min(ext.minY, y - r, labelBBox.y)\n ext.maxY = Math.max(ext.maxY, y + r, labelBBox.y + labelBBox.height)\n return ext\n }, {\n minX: Number.POSITIVE_INFINITY,\n maxX: Number.NEGATIVE_INFINITY,\n minY: Number.POSITIVE_INFINITY,\n maxY: Number.NEGATIVE_INFINITY,\n })\n\n const coeff = 1.2 // Multiplier to take into account subsequent scale range changes and shape irregularities\n const top = extent.minY < yRangeStart ? coeff * (yRangeStart - extent.minY) : 0\n const bottom = extent.maxY > yRangeEnd ? coeff * (extent.maxY - yRangeEnd) : 0\n const left = extent.minX < xRangeStart ? coeff * (xRangeStart - extent.minX) : 0\n const right = extent.maxX > xRangeEnd ? coeff * (extent.maxX - xRangeEnd) : 0\n\n return { top, bottom, left, right }\n }\n\n _render (customDuration?: number): void {\n const { config } = this\n const duration = isNumber(customDuration) ? customDuration : config.duration\n\n // Groups\n const pointGroups = this.g\n .selectAll<SVGGElement, ScatterPoint<Datum>[]>(`.${s.pointGroup}`)\n .data(this._pointData)\n\n const pointGroupsEnter = pointGroups\n .enter()\n .append('g')\n .attr('class', s.pointGroup)\n\n const pointGroupsMerged = pointGroupsEnter.merge(pointGroups)\n smartTransition(pointGroupsMerged, duration)\n .style('opacity', 1)\n\n const pointGroupExit = pointGroups.exit().attr('class', s.pointGroupExit)\n smartTransition(pointGroupExit, duration).style('opacity', 0).remove()\n\n // Points\n const points = pointGroupsMerged\n .selectAll<SVGGElement, ScatterPoint<Datum>>(`.${s.point}`)\n .data(\n d => d,\n d => `${getString(d, config.id, d._point.pointIndex) ?? d._point.pointIndex}`\n )\n\n const pointsEnter = points.enter().append('g')\n .attr('class', s.point)\n createPoints(pointsEnter, this.xScale, this.yScale)\n\n this._points = pointsEnter.merge(points)\n updatePoints(this._points, config, this.xScale, this.yScale, duration)\n\n removePoints(points.exit<ScatterPoint<Datum>>(), this.xScale, this.yScale, duration)\n\n // Take care of overlapping labels\n this._resolveLabelOverlap()\n }\n\n private _resolveLabelOverlap (): void {\n if (!this.config.labelHideOverlapping) {\n const label = this._points.selectAll<SVGTextElement, ScatterPoint<Datum>>('text')\n label.attr('opacity', null)\n return\n }\n\n cancelAnimationFrame(this._collideLabelsAnimFrameId)\n this._collideLabelsAnimFrameId = requestAnimationFrame(() => {\n collideLabels(this._points, this.config, this.xScale, this.yScale)\n })\n }\n\n private _updateSizeScale (): void {\n const { config, datamodel } = this\n\n config.sizeScale\n .domain(getExtent(datamodel.data, config.size))\n .range(config.sizeRange ?? [0, 0])\n }\n\n private _getOnScreenData (): ScatterPoint<Datum>[][] {\n const { config, datamodel: { data } } = this\n\n const xDomain = this.xScale.domain().map(d => +d) // Convert Date to number\n const yDomain = this.yScale.domain().map(d => +d) // Convert Date to number\n const yAccessors = (isArray(config.y) ? config.y : [config.y]) as NumericAccessor<Datum>[]\n\n const maxSizeValue = max<number>(flatten(yAccessors.map((y, j) => data?.map(d => getNumber(d, config.size, j)))))\n const maxSizePx = config.sizeRange ? config.sizeScale(maxSizeValue) : maxSizeValue\n const maxSizeXDomain = (this.xScale.invert(maxSizePx) as number) - (this.xScale.invert(0) as number)\n const maxSizeYDomain = Math.abs((this.yScale.invert(maxSizePx) as number) - (this.yScale.invert(0) as number))\n\n return yAccessors.map((y, j) => {\n return data?.reduce<ScatterPoint<Datum>[]>((acc, d, i) => {\n const xValue = getNumber(d, config.x, i)\n const yValue = getNumber(d, y, j)\n const pointSize = getNumber(d, config.size, i)\n const pointSizeScaled = config.sizeRange ? config.sizeScale(pointSize) : pointSize\n const pointSizeXDomain = (this.xScale.invert(pointSizeScaled) as number) - (this.xScale.invert(0) as number)\n const pointSizeYDomain = Math.abs((this.yScale.invert(pointSizeScaled) as number) - (this.yScale.invert(0) as number))\n\n if (\n ((xValue - pointSizeXDomain / 2) >= (xDomain[0] - maxSizeXDomain / 2)) &&\n ((xValue + pointSizeXDomain / 2) <= (xDomain[1] + maxSizeXDomain / 2)) &&\n ((yValue - pointSizeYDomain / 2) >= (yDomain[0] - maxSizeYDomain / 2)) &&\n ((yValue + pointSizeYDomain / 2) <= (yDomain[1] + maxSizeYDomain / 2))\n ) {\n acc.push({\n ...d,\n _point: {\n xValue: xValue,\n yValue: yValue,\n sizePx: pointSizeScaled,\n color: getColor(d, config.color, j),\n strokeColor: getColor(d, config.strokeColor, j, true),\n strokeWidthPx: getNumber(d, config.strokeWidth, j),\n shape: getString(d, config.shape, j) as SymbolType,\n label: getString(d, config.label, j),\n labelColor: getValue(d, config.labelColor, j),\n cursor: getString(d, config.cursor, j),\n groupIndex: j,\n pointIndex: i,\n },\n })\n }\n\n return acc\n }, []) ?? []\n })\n }\n\n private _onPointMouseOver (d: ScatterPoint<Datum>, event: MouseEvent): void {\n const point = select(event.target as SVGGElement)\n const pointNode = point.node() as ScatterPointGroupNode | null\n if (pointNode) pointNode._forceShowLabel = true\n\n point.raise()\n this._resolveLabelOverlap()\n }\n\n private _onPointMouseOut (d: ScatterPoint<Datum>, event: MouseEvent): void {\n const pointNode = select(event.target as SVGGElement).node() as ScatterPointGroupNode | null\n if (pointNode) delete pointNode._forceShowLabel\n\n this._resolveLabelOverlap()\n }\n}\n"],"names":["s.pointGroup","pointGroupExit","s.pointGroupExit","s.point","s"],"mappings":"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"}
@@ -12,8 +12,9 @@ export declare class SingleContainer<Data> extends ContainerCore {
12
12
  updateComponent(componentConfig: ComponentConfigInterface, preventRender?: boolean): void;
13
13
  update(containerConfig: SingleContainerConfigInterface<Data>, componentConfig?: ComponentConfigInterface, data?: Data): void;
14
14
  getFitWidthScale(): number;
15
- _render(duration?: number): void;
15
+ protected _preRender(): void;
16
+ protected _render(duration?: number): void;
16
17
  render(duration?: any): void;
17
- _onResize(): void;
18
+ protected _onResize(): void;
18
19
  destroy(): void;
19
20
  }
@@ -32,7 +32,7 @@ class SingleContainer extends ContainerCore {
32
32
  }
33
33
  updateContainer(containerConfig, preventRender) {
34
34
  super.updateContainer(containerConfig);
35
- this.removeAllChildren();
35
+ this._removeAllChildren();
36
36
  this.component = containerConfig.component;
37
37
  if (containerConfig.sizing)
38
38
  this.component.sizing = containerConfig.sizing;
@@ -68,10 +68,13 @@ class SingleContainer extends ContainerCore {
68
68
  const componentWidth = extendedSizeComponent.getWidth() + config.margin.left + config.margin.right;
69
69
  return this.width / componentWidth;
70
70
  }
71
+ _preRender() {
72
+ super._preRender();
73
+ this.component.setSize(this.width, this.height, this.containerWidth, this.containerHeight);
74
+ }
71
75
  _render(duration) {
72
76
  const { config, component } = this;
73
77
  super._render(duration);
74
- component.setSize(this.width, this.height, this.containerWidth, this.containerHeight);
75
78
  component.g.attr('transform', `translate(${config.margin.left},${config.margin.top})`);
76
79
  component.render(duration);
77
80
  if (config.tooltip)
@@ -109,6 +112,7 @@ class SingleContainer extends ContainerCore {
109
112
  // Schedule the actual rendering in the next frame
110
113
  cancelAnimationFrame(this._requestedAnimationFrame);
111
114
  this._requestedAnimationFrame = requestAnimationFrame(() => {
115
+ this._preRender();
112
116
  this._render(duration);
113
117
  });
114
118
  }
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../../../src/containers/single-container/index.ts"],"sourcesContent":["// Global CSS variables (side effects import)\nimport 'styles/index'\n\n// Core\nimport { ContainerCore } from 'core/container'\nimport { ComponentCore } from 'core/component'\nimport { ComponentConfigInterface } from 'core/component/config'\n\n// Utils\nimport { smartTransition } from 'utils/d3'\n\n// Types\nimport { Sizing, ExtendedSizeComponent } from 'types/component'\n\n// Config\nimport { SingleContainerConfig, SingleContainerConfigInterface } from './config'\n\nexport class SingleContainer<Data> extends ContainerCore {\n component: ComponentCore<Data>\n config: SingleContainerConfig<Data> = new SingleContainerConfig()\n\n constructor (element: HTMLElement, config?: SingleContainerConfigInterface<Data>, data?: Data) {\n super(element)\n\n if (config) {\n this.updateContainer(config, true)\n this.component = config.component\n }\n\n if (data) {\n this.setData(data, true)\n }\n\n // Render if component exists and has data\n if (this.component?.datamodel.data) this.render()\n }\n\n public setData (data: Data, preventRender?: boolean): void {\n const { config } = this\n\n if (this.component) this.component.setData(data)\n if (!preventRender) this.render()\n config.tooltip?.hide()\n }\n\n public updateContainer (containerConfig: SingleContainerConfigInterface<Data>, preventRender?: boolean): void {\n super.updateContainer(containerConfig)\n this.removeAllChildren()\n\n this.component = containerConfig.component\n if (containerConfig.sizing) this.component.sizing = containerConfig.sizing\n this.element.appendChild(this.component.element)\n\n const tooltip = containerConfig.tooltip\n if (tooltip) {\n if (!tooltip.hasContainer()) tooltip.setContainer(this._container)\n tooltip.setComponents([this.component])\n }\n\n if (!preventRender) this.render()\n }\n\n public updateComponent (componentConfig: ComponentConfigInterface, preventRender?: boolean): void {\n this.component.setConfig(componentConfig)\n if (!preventRender) this.render()\n }\n\n public update (\n containerConfig: SingleContainerConfigInterface<Data>,\n componentConfig?: ComponentConfigInterface,\n data?: Data\n ): void {\n if (containerConfig) this.updateContainer(containerConfig, true)\n if (componentConfig) this.updateComponent(componentConfig, true)\n if (data) this.setData(data, true)\n this.render()\n }\n\n public getFitWidthScale (): number {\n const { config, component } = this\n\n const extendedSizeComponent = component as ExtendedSizeComponent\n if (!extendedSizeComponent.getWidth) return 1\n\n const componentWidth = extendedSizeComponent.getWidth() + config.margin.left + config.margin.right\n return this.width / componentWidth\n }\n\n _render (duration?: number): void {\n const { config, component } = this\n super._render(duration)\n\n component.setSize(this.width, this.height, this.containerWidth, this.containerHeight)\n component.g.attr('transform', `translate(${config.margin.left},${config.margin.top})`)\n component.render(duration)\n\n if (config.tooltip) config.tooltip.update()\n }\n\n // Re-defining the `render()` function to handle different sizing techniques (`Sizing.Extend` and `Sizing.FitWidth`)\n // Not calling `super.render()` because we don't want it to interfere with setting the SVG size here.\n render (duration = this.config.duration): void {\n const { config, component } = this\n\n if (config.sizing === Sizing.Extend || config.sizing === Sizing.FitWidth) {\n const fitToWidth = config.sizing === Sizing.FitWidth\n const extendedSizeComponent = component as ExtendedSizeComponent\n\n const componentWidth = extendedSizeComponent.getWidth() + config.margin.left + config.margin.right\n const componentHeight = extendedSizeComponent.getHeight() + config.margin.top + config.margin.bottom\n const scale = fitToWidth ? this.getFitWidthScale() : 1\n\n const currentWidth = this.svg.attr('width')\n const currentHeight = this.svg.attr('height')\n const scaledWidth = componentWidth * scale\n const scaledHeight = componentHeight * scale\n const animated = currentWidth || currentHeight\n\n smartTransition(this.svg, animated ? duration : 0)\n .attr('width', scaledWidth)\n .attr('height', scaledHeight)\n .attr('viewBox', `${0} ${0} ${componentWidth} ${fitToWidth ? scaledHeight : componentHeight}`)\n .attr('preserveAspectRatio', 'xMinYMin')\n } else {\n this.svg\n .attr('width', this.config.width || this.containerWidth)\n .attr('height', this.config.height || this.containerHeight)\n }\n\n // Set up Resize Observer\n if (!this._resizeObserver) this._setUpResizeObserver()\n\n // Schedule the actual rendering in the next frame\n cancelAnimationFrame(this._requestedAnimationFrame)\n this._requestedAnimationFrame = requestAnimationFrame(() => {\n this._render(duration)\n })\n }\n\n _onResize (): void {\n const { config } = this\n super._onResize()\n config.tooltip?.hide()\n }\n\n public destroy (): void {\n const { component, config } = this\n super.destroy()\n\n component?.destroy()\n config.tooltip?.destroy()\n }\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sources":["../../../src/containers/single-container/index.ts"],"sourcesContent":["// Global CSS variables (side effects import)\nimport 'styles/index'\n\n// Core\nimport { ContainerCore } from 'core/container'\nimport { ComponentCore } from 'core/component'\nimport { ComponentConfigInterface } from 'core/component/config'\n\n// Utils\nimport { smartTransition } from 'utils/d3'\n\n// Types\nimport { Sizing, ExtendedSizeComponent } from 'types/component'\n\n// Config\nimport { SingleContainerConfig, SingleContainerConfigInterface } from './config'\n\nexport class SingleContainer<Data> extends ContainerCore {\n component: ComponentCore<Data>\n config: SingleContainerConfig<Data> = new SingleContainerConfig()\n\n constructor (element: HTMLElement, config?: SingleContainerConfigInterface<Data>, data?: Data) {\n super(element)\n\n if (config) {\n this.updateContainer(config, true)\n this.component = config.component\n }\n\n if (data) {\n this.setData(data, true)\n }\n\n // Render if component exists and has data\n if (this.component?.datamodel.data) this.render()\n }\n\n public setData (data: Data, preventRender?: boolean): void {\n const { config } = this\n\n if (this.component) this.component.setData(data)\n if (!preventRender) this.render()\n config.tooltip?.hide()\n }\n\n public updateContainer (containerConfig: SingleContainerConfigInterface<Data>, preventRender?: boolean): void {\n super.updateContainer(containerConfig)\n this._removeAllChildren()\n\n this.component = containerConfig.component\n if (containerConfig.sizing) this.component.sizing = containerConfig.sizing\n this.element.appendChild(this.component.element)\n\n const tooltip = containerConfig.tooltip\n if (tooltip) {\n if (!tooltip.hasContainer()) tooltip.setContainer(this._container)\n tooltip.setComponents([this.component])\n }\n\n if (!preventRender) this.render()\n }\n\n public updateComponent (componentConfig: ComponentConfigInterface, preventRender?: boolean): void {\n this.component.setConfig(componentConfig)\n if (!preventRender) this.render()\n }\n\n public update (\n containerConfig: SingleContainerConfigInterface<Data>,\n componentConfig?: ComponentConfigInterface,\n data?: Data\n ): void {\n if (containerConfig) this.updateContainer(containerConfig, true)\n if (componentConfig) this.updateComponent(componentConfig, true)\n if (data) this.setData(data, true)\n this.render()\n }\n\n public getFitWidthScale (): number {\n const { config, component } = this\n\n const extendedSizeComponent = component as ExtendedSizeComponent\n if (!extendedSizeComponent.getWidth) return 1\n\n const componentWidth = extendedSizeComponent.getWidth() + config.margin.left + config.margin.right\n return this.width / componentWidth\n }\n\n protected _preRender (): void {\n super._preRender()\n this.component.setSize(this.width, this.height, this.containerWidth, this.containerHeight)\n }\n\n protected _render (duration?: number): void {\n const { config, component } = this\n super._render(duration)\n\n component.g.attr('transform', `translate(${config.margin.left},${config.margin.top})`)\n component.render(duration)\n\n if (config.tooltip) config.tooltip.update()\n }\n\n // Re-defining the `render()` function to handle different sizing techniques (`Sizing.Extend` and `Sizing.FitWidth`)\n // Not calling `super.render()` because we don't want it to interfere with setting the SVG size here.\n public render (duration = this.config.duration): void {\n const { config, component } = this\n\n if (config.sizing === Sizing.Extend || config.sizing === Sizing.FitWidth) {\n const fitToWidth = config.sizing === Sizing.FitWidth\n const extendedSizeComponent = component as ExtendedSizeComponent\n\n const componentWidth = extendedSizeComponent.getWidth() + config.margin.left + config.margin.right\n const componentHeight = extendedSizeComponent.getHeight() + config.margin.top + config.margin.bottom\n const scale = fitToWidth ? this.getFitWidthScale() : 1\n\n const currentWidth = this.svg.attr('width')\n const currentHeight = this.svg.attr('height')\n const scaledWidth = componentWidth * scale\n const scaledHeight = componentHeight * scale\n const animated = currentWidth || currentHeight\n\n smartTransition(this.svg, animated ? duration : 0)\n .attr('width', scaledWidth)\n .attr('height', scaledHeight)\n .attr('viewBox', `${0} ${0} ${componentWidth} ${fitToWidth ? scaledHeight : componentHeight}`)\n .attr('preserveAspectRatio', 'xMinYMin')\n } else {\n this.svg\n .attr('width', this.config.width || this.containerWidth)\n .attr('height', this.config.height || this.containerHeight)\n }\n\n // Set up Resize Observer\n if (!this._resizeObserver) this._setUpResizeObserver()\n\n // Schedule the actual rendering in the next frame\n cancelAnimationFrame(this._requestedAnimationFrame)\n this._requestedAnimationFrame = requestAnimationFrame(() => {\n this._preRender()\n this._render(duration)\n })\n }\n\n protected _onResize (): void {\n const { config } = this\n super._onResize()\n config.tooltip?.hide()\n }\n\n public destroy (): void {\n const { component, config } = this\n super.destroy()\n\n component?.destroy()\n config.tooltip?.destroy()\n }\n}\n"],"names":[],"mappings":"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"}
@@ -69,10 +69,12 @@ export interface XYContainerConfigInterface<Datum> extends ContainerConfigInterf
69
69
  /** Crosshair component. Default: `undefined` */
70
70
  crosshair?: Crosshair<Datum> | undefined;
71
71
  /** Prevents the chart domain from being empty (when domain's min and max values are equal).
72
- * That usually happens when all the data values are the same.
73
- * Setting to `true` will automatically extend the domain by `+1` when needed.
74
- * Default: `true` */
75
- preventEmptyDomain?: boolean;
72
+ * That usually happens when all the data values are equal or when there's no data.
73
+ * Setting to `true` will automatically extend the domain by `+1` when the domain is empty (domain start equals domain end).
74
+ * Setting to `null` will extend the empty domain, but only when there's no data.
75
+ * Setting to `false` will keep the domain as is.
76
+ * Default: `null` */
77
+ preventEmptyDomain?: boolean | null;
76
78
  /** Sets the Y scale domain based on the current X scale domain (not the whole dataset). Default: `false` */
77
79
  scaleByDomain?: boolean;
78
80
  }
@@ -94,6 +96,6 @@ export declare class XYContainerConfig<Datum> extends ContainerConfig implements
94
96
  yDomainMaxConstraint: any;
95
97
  yRange: any;
96
98
  yDirection: Direction;
97
- preventEmptyDomain: boolean;
99
+ preventEmptyDomain: any;
98
100
  scaleByDomain: boolean;
99
101
  }
@@ -21,7 +21,7 @@ class XYContainerConfig extends ContainerConfig {
21
21
  this.yDomainMaxConstraint = undefined;
22
22
  this.yRange = undefined;
23
23
  this.yDirection = Direction.North;
24
- this.preventEmptyDomain = true;
24
+ this.preventEmptyDomain = null;
25
25
  this.scaleByDomain = false;
26
26
  }
27
27
  }
@@ -1 +1 @@
1
- {"version":3,"file":"config.js","sources":["../../../src/containers/xy-container/config.ts"],"sourcesContent":["// Core\nimport { XYComponentCore } from 'core/xy-component'\nimport { ContainerConfig, ContainerConfigInterface } from 'core/container/config'\nimport { Tooltip } from 'components/tooltip'\n\n// Components\nimport { Axis } from 'components/axis'\nimport { Crosshair } from 'components/crosshair'\n\n// Types\nimport { ContinuousScale } from 'types/scale'\nimport { Direction } from 'types/direction'\n\nexport interface XYContainerConfigInterface<Datum> extends ContainerConfigInterface {\n /** An array of visualization components. Default: `[]` */\n components?: XYComponentCore<Datum>[];\n\n /** Scale for X dimension, e.g. Scale.scaleLinear().\n * If set, this value will override the components' xScale and they will have a single shared xScale instance.\n * By default the components have their own scale instances but their `domain` and `range` values are synchronized.\n * Default: `undefined` */\n xScale?: ContinuousScale;\n /** Scale domain (data extent) for X dimension. By default this value is calculated automatically based on data. */\n xDomain?: [number | undefined, number | undefined];\n /** Constraint the minimum value of the X scale domain. Useful when the data is plotted along the X axis.\n * For example, imagine that you have a chart with dynamic data that has negative values. When values are small\n * (let's say in the range of [-0.01, 0]), you might still want the chart to display some meaningful value range (e.g. [-1, 0]). That can\n * be achieved by setting `xDomainMinConstraint` to `[undefined, -1]`. In addition to that, if you want to cut off the\n * values that are too low (let's say lower than -100), you can set the constraint to `[-100, -1]`\n * Default: `undefined` */\n xDomainMinConstraint?: [number | undefined, number | undefined];\n /** Constraint the minimum value of the X scale domain. Useful when the data is plotted along the X axis.\n * For example, imagine that you have a chart with dynamic data. When values are small\n * (let's say < 0.01), you might still want the chart to display some meaningful value range (e.g. [0, 1]). That can\n * be achieved by setting `xDomainMaxConstraint` to `[1, undefined]`. In addition to that, if you want to cut off the\n * values that are too high (let's say higher than 100), you can set the constraint to `[1, 100]`\n * Default: `undefined` */\n xDomainMaxConstraint?: [number | undefined, number | undefined];\n /** Force set the X scale range (in the screen space). By default the range is calculated automatically based on the\n * chart's set up */\n xRange?: [number, number];\n\n /** Scale for Y dimension, e.g. Scale.scaleLinear().\n * If set, this value will override the components' yScale and they will have a single shared yScale instance.\n * By default the components have their own scale instances but their `domain` and `range` values are synchronized.\n * Default: `undefined` */\n yScale?: ContinuousScale;\n /** Scale domain (data extent) for Y dimension. By default this value is calculated automatically based on data. */\n yDomain?: [number | undefined, number | undefined];\n /** Constraint the minimum value of the Y scale domain.\n * For example, imagine that you have a chart with dynamic data that has negative values. When values are small\n * (let's say in the range of [-0.01, 0]), you might still want the chart to display some meaningful value range (e.g. [-1, 0]). That can\n * be achieved by setting `yDomainMinConstraint` to `[undefined, -1]`. In addition to that, if you want to cut off the\n * values that are too low (let's say lower than -100), you can set the constraint to `[-100, -1]`\n * Default: `undefined` */\n yDomainMinConstraint?: [number | undefined, number | undefined];\n /** Constraint the minimum value of the Y scale domain.\n * For example, imagine that you have a chart with dynamic data. When values are small\n * (let's say < 0.01), you might still want the chart to display some meaningful value range (e.g. [0, 1]). That can\n * be achieved by setting `yDomainMaxConstraint` to `[1, undefined]`. In addition to that, if you want to cut off the\n * values that are too high (let's say higher than 100), you can set the constraint to `[1, 100]`\n * Default: `undefined` */\n yDomainMaxConstraint?: [number | undefined, number | undefined];\n /** Force set the Y scale range (in the screen space). By default the range is calculated automatically based on the\n * chart's set up */\n yRange?: [number, number];\n /** Y Axis direction. Default: `Direction.North` */\n yDirection?: Direction.South | Direction.North | string;\n\n /** X Axis component instance. Default: `undefined` */\n xAxis?: Axis<Datum>;\n /** Y Axis component instance. Default: `undefined` */\n yAxis?: Axis<Datum>;\n /** Enables automatic calculation of chart margins based on the size of the axes. Default: `true` */\n autoMargin?: boolean;\n /** Tooltip component. Default: `undefined` */\n tooltip?: Tooltip | undefined;\n /** Crosshair component. Default: `undefined` */\n crosshair?: Crosshair<Datum> | undefined;\n /** Prevents the chart domain from being empty (when domain's min and max values are equal).\n * That usually happens when all the data values are the same.\n * Setting to `true` will automatically extend the domain by `+1` when needed.\n * Default: `true` */\n preventEmptyDomain?: boolean;\n /** Sets the Y scale domain based on the current X scale domain (not the whole dataset). Default: `false` */\n scaleByDomain?: boolean;\n}\n\nexport class XYContainerConfig<Datum> extends ContainerConfig implements XYContainerConfigInterface<Datum> {\n components = []\n tooltip: Tooltip = undefined\n crosshair: Crosshair<Datum> = undefined\n xAxis: Axis<Datum> = undefined\n yAxis: Axis<Datum> = undefined\n autoMargin = true\n\n xScale = undefined\n xDomain = undefined\n xDomainMinConstraint = undefined\n xDomainMaxConstraint = undefined\n xRange = undefined\n\n yScale = undefined\n yDomain = undefined\n yDomainMinConstraint = undefined\n yDomainMaxConstraint = undefined\n yRange = undefined\n yDirection = Direction.North\n\n preventEmptyDomain = true\n scaleByDomain = false\n}\n"],"names":[],"mappings":";;;AAwFM,MAAO,iBAAyB,SAAQ,eAAe,CAAA;AAA7D,IAAA,WAAA,GAAA;;QACE,IAAU,CAAA,UAAA,GAAG,EAAE,CAAA;QACf,IAAO,CAAA,OAAA,GAAY,SAAS,CAAA;QAC5B,IAAS,CAAA,SAAA,GAAqB,SAAS,CAAA;QACvC,IAAK,CAAA,KAAA,GAAgB,SAAS,CAAA;QAC9B,IAAK,CAAA,KAAA,GAAgB,SAAS,CAAA;QAC9B,IAAU,CAAA,UAAA,GAAG,IAAI,CAAA;QAEjB,IAAM,CAAA,MAAA,GAAG,SAAS,CAAA;QAClB,IAAO,CAAA,OAAA,GAAG,SAAS,CAAA;QACnB,IAAoB,CAAA,oBAAA,GAAG,SAAS,CAAA;QAChC,IAAoB,CAAA,oBAAA,GAAG,SAAS,CAAA;QAChC,IAAM,CAAA,MAAA,GAAG,SAAS,CAAA;QAElB,IAAM,CAAA,MAAA,GAAG,SAAS,CAAA;QAClB,IAAO,CAAA,OAAA,GAAG,SAAS,CAAA;QACnB,IAAoB,CAAA,oBAAA,GAAG,SAAS,CAAA;QAChC,IAAoB,CAAA,oBAAA,GAAG,SAAS,CAAA;QAChC,IAAM,CAAA,MAAA,GAAG,SAAS,CAAA;AAClB,QAAA,IAAA,CAAA,UAAU,GAAG,SAAS,CAAC,KAAK,CAAA;QAE5B,IAAkB,CAAA,kBAAA,GAAG,IAAI,CAAA;QACzB,IAAa,CAAA,aAAA,GAAG,KAAK,CAAA;KACtB;AAAA;;;;"}
1
+ {"version":3,"file":"config.js","sources":["../../../src/containers/xy-container/config.ts"],"sourcesContent":["// Core\nimport { XYComponentCore } from 'core/xy-component'\nimport { ContainerConfig, ContainerConfigInterface } from 'core/container/config'\nimport { Tooltip } from 'components/tooltip'\n\n// Components\nimport { Axis } from 'components/axis'\nimport { Crosshair } from 'components/crosshair'\n\n// Types\nimport { ContinuousScale } from 'types/scale'\nimport { Direction } from 'types/direction'\n\nexport interface XYContainerConfigInterface<Datum> extends ContainerConfigInterface {\n /** An array of visualization components. Default: `[]` */\n components?: XYComponentCore<Datum>[];\n\n /** Scale for X dimension, e.g. Scale.scaleLinear().\n * If set, this value will override the components' xScale and they will have a single shared xScale instance.\n * By default the components have their own scale instances but their `domain` and `range` values are synchronized.\n * Default: `undefined` */\n xScale?: ContinuousScale;\n /** Scale domain (data extent) for X dimension. By default this value is calculated automatically based on data. */\n xDomain?: [number | undefined, number | undefined];\n /** Constraint the minimum value of the X scale domain. Useful when the data is plotted along the X axis.\n * For example, imagine that you have a chart with dynamic data that has negative values. When values are small\n * (let's say in the range of [-0.01, 0]), you might still want the chart to display some meaningful value range (e.g. [-1, 0]). That can\n * be achieved by setting `xDomainMinConstraint` to `[undefined, -1]`. In addition to that, if you want to cut off the\n * values that are too low (let's say lower than -100), you can set the constraint to `[-100, -1]`\n * Default: `undefined` */\n xDomainMinConstraint?: [number | undefined, number | undefined];\n /** Constraint the minimum value of the X scale domain. Useful when the data is plotted along the X axis.\n * For example, imagine that you have a chart with dynamic data. When values are small\n * (let's say < 0.01), you might still want the chart to display some meaningful value range (e.g. [0, 1]). That can\n * be achieved by setting `xDomainMaxConstraint` to `[1, undefined]`. In addition to that, if you want to cut off the\n * values that are too high (let's say higher than 100), you can set the constraint to `[1, 100]`\n * Default: `undefined` */\n xDomainMaxConstraint?: [number | undefined, number | undefined];\n /** Force set the X scale range (in the screen space). By default the range is calculated automatically based on the\n * chart's set up */\n xRange?: [number, number];\n\n /** Scale for Y dimension, e.g. Scale.scaleLinear().\n * If set, this value will override the components' yScale and they will have a single shared yScale instance.\n * By default the components have their own scale instances but their `domain` and `range` values are synchronized.\n * Default: `undefined` */\n yScale?: ContinuousScale;\n /** Scale domain (data extent) for Y dimension. By default this value is calculated automatically based on data. */\n yDomain?: [number | undefined, number | undefined];\n /** Constraint the minimum value of the Y scale domain.\n * For example, imagine that you have a chart with dynamic data that has negative values. When values are small\n * (let's say in the range of [-0.01, 0]), you might still want the chart to display some meaningful value range (e.g. [-1, 0]). That can\n * be achieved by setting `yDomainMinConstraint` to `[undefined, -1]`. In addition to that, if you want to cut off the\n * values that are too low (let's say lower than -100), you can set the constraint to `[-100, -1]`\n * Default: `undefined` */\n yDomainMinConstraint?: [number | undefined, number | undefined];\n /** Constraint the minimum value of the Y scale domain.\n * For example, imagine that you have a chart with dynamic data. When values are small\n * (let's say < 0.01), you might still want the chart to display some meaningful value range (e.g. [0, 1]). That can\n * be achieved by setting `yDomainMaxConstraint` to `[1, undefined]`. In addition to that, if you want to cut off the\n * values that are too high (let's say higher than 100), you can set the constraint to `[1, 100]`\n * Default: `undefined` */\n yDomainMaxConstraint?: [number | undefined, number | undefined];\n /** Force set the Y scale range (in the screen space). By default the range is calculated automatically based on the\n * chart's set up */\n yRange?: [number, number];\n /** Y Axis direction. Default: `Direction.North` */\n yDirection?: Direction.South | Direction.North | string;\n\n /** X Axis component instance. Default: `undefined` */\n xAxis?: Axis<Datum>;\n /** Y Axis component instance. Default: `undefined` */\n yAxis?: Axis<Datum>;\n /** Enables automatic calculation of chart margins based on the size of the axes. Default: `true` */\n autoMargin?: boolean;\n /** Tooltip component. Default: `undefined` */\n tooltip?: Tooltip | undefined;\n /** Crosshair component. Default: `undefined` */\n crosshair?: Crosshair<Datum> | undefined;\n /** Prevents the chart domain from being empty (when domain's min and max values are equal).\n * That usually happens when all the data values are equal or when there's no data.\n * Setting to `true` will automatically extend the domain by `+1` when the domain is empty (domain start equals domain end).\n * Setting to `null` will extend the empty domain, but only when there's no data.\n * Setting to `false` will keep the domain as is.\n * Default: `null` */\n preventEmptyDomain?: boolean | null;\n /** Sets the Y scale domain based on the current X scale domain (not the whole dataset). Default: `false` */\n scaleByDomain?: boolean;\n}\n\nexport class XYContainerConfig<Datum> extends ContainerConfig implements XYContainerConfigInterface<Datum> {\n components = []\n tooltip: Tooltip = undefined\n crosshair: Crosshair<Datum> = undefined\n xAxis: Axis<Datum> = undefined\n yAxis: Axis<Datum> = undefined\n autoMargin = true\n\n xScale = undefined\n xDomain = undefined\n xDomainMinConstraint = undefined\n xDomainMaxConstraint = undefined\n xRange = undefined\n\n yScale = undefined\n yDomain = undefined\n yDomainMinConstraint = undefined\n yDomainMaxConstraint = undefined\n yRange = undefined\n yDirection = Direction.North\n\n preventEmptyDomain = null\n scaleByDomain = false\n}\n"],"names":[],"mappings":";;;AA0FM,MAAO,iBAAyB,SAAQ,eAAe,CAAA;AAA7D,IAAA,WAAA,GAAA;;QACE,IAAU,CAAA,UAAA,GAAG,EAAE,CAAA;QACf,IAAO,CAAA,OAAA,GAAY,SAAS,CAAA;QAC5B,IAAS,CAAA,SAAA,GAAqB,SAAS,CAAA;QACvC,IAAK,CAAA,KAAA,GAAgB,SAAS,CAAA;QAC9B,IAAK,CAAA,KAAA,GAAgB,SAAS,CAAA;QAC9B,IAAU,CAAA,UAAA,GAAG,IAAI,CAAA;QAEjB,IAAM,CAAA,MAAA,GAAG,SAAS,CAAA;QAClB,IAAO,CAAA,OAAA,GAAG,SAAS,CAAA;QACnB,IAAoB,CAAA,oBAAA,GAAG,SAAS,CAAA;QAChC,IAAoB,CAAA,oBAAA,GAAG,SAAS,CAAA;QAChC,IAAM,CAAA,MAAA,GAAG,SAAS,CAAA;QAElB,IAAM,CAAA,MAAA,GAAG,SAAS,CAAA;QAClB,IAAO,CAAA,OAAA,GAAG,SAAS,CAAA;QACnB,IAAoB,CAAA,oBAAA,GAAG,SAAS,CAAA;QAChC,IAAoB,CAAA,oBAAA,GAAG,SAAS,CAAA;QAChC,IAAM,CAAA,MAAA,GAAG,SAAS,CAAA;AAClB,QAAA,IAAA,CAAA,UAAU,GAAG,SAAS,CAAC,KAAK,CAAA;QAE5B,IAAkB,CAAA,kBAAA,GAAG,IAAI,CAAA;QACzB,IAAa,CAAA,aAAA,GAAG,KAAK,CAAA;KACtB;AAAA;;;;"}
@@ -22,13 +22,14 @@ export declare class XYContainer<Datum> extends ContainerCore {
22
22
  updateContainer(containerConfig: XYContainerConfigInterface<Datum>, preventRender?: boolean): void;
23
23
  updateComponents(componentConfigs: XYConfigInterface<Datum>[], preventRender?: boolean): void;
24
24
  update(containerConfig: XYContainerConfigInterface<Datum>, componentConfigs?: XYComponentConfigInterface<Datum>[], data?: Datum[]): void;
25
- _render(customDuration?: number): void;
26
- updateScales<T extends XYComponentCore<Datum>>(...components: T[]): void;
27
- _setScales<T extends XYComponentCore<Datum>>(...components: T[]): void;
28
- _updateScalesDomain<T extends XYComponentCore<Datum>>(...components: T[]): void;
29
- _updateScalesRange<T extends XYComponentCore<Datum>>(...components: T[]): void;
30
- _renderAxes(duration: number): void;
31
- _setAutoMargin(): void;
25
+ protected _preRender(): void;
26
+ protected _render(customDuration?: number): void;
27
+ private _updateScales;
28
+ private _setScales;
29
+ private _updateScalesDomain;
30
+ private _updateScalesRange;
31
+ private _renderAxes;
32
+ private _setAutoMargin;
32
33
  private _getMargin;
33
34
  destroy(): void;
34
35
  }
@@ -84,7 +84,7 @@ class XYContainer extends ContainerCore {
84
84
  }
85
85
  updateContainer(containerConfig, preventRender) {
86
86
  super.updateContainer(containerConfig);
87
- this.removeAllChildren();
87
+ this._removeAllChildren();
88
88
  // If there were any new components added we need to pass them data
89
89
  this.setData(this.datamodel.data, true);
90
90
  // Set up the axes
@@ -130,7 +130,7 @@ class XYContainer extends ContainerCore {
130
130
  c.setConfig(componentConfigs[i]);
131
131
  }
132
132
  });
133
- this.updateScales(...this.components, config.xAxis, config.yAxis, config.crosshair);
133
+ this._updateScales(...this.components, config.xAxis, config.yAxis, config.crosshair);
134
134
  if (!preventRender)
135
135
  this.render();
136
136
  }
@@ -143,18 +143,22 @@ class XYContainer extends ContainerCore {
143
143
  this.updateComponents(componentConfigs, true);
144
144
  this.render();
145
145
  }
146
- _render(customDuration) {
147
- var _a, _b, _c;
146
+ _preRender() {
148
147
  const { config } = this;
149
- super._render();
148
+ super._preRender();
150
149
  // Calculate extra margin required to fit the axes
151
150
  if (config.autoMargin) {
152
151
  this._setAutoMargin();
153
152
  }
153
+ // Update Scales of all the components at once to calculate required paddings and sync them
154
+ this._updateScales(...this.components, config.xAxis, config.yAxis, config.crosshair);
155
+ }
156
+ _render(customDuration) {
157
+ var _a, _b, _c;
158
+ const { config } = this;
159
+ super._render();
154
160
  // Get chart total margin after auto margin calculations
155
161
  const margin = this._getMargin();
156
- // Update Scales of all the components at once to calculate required paddings and sync them
157
- this.updateScales(...this.components, config.xAxis, config.yAxis, config.crosshair);
158
162
  // Render components
159
163
  for (const c of this.components) {
160
164
  c.g.attr('transform', `translate(${margin.left},${margin.top})`)
@@ -194,7 +198,7 @@ class XYContainer extends ContainerCore {
194
198
  }
195
199
  this._firstRender = false;
196
200
  }
197
- updateScales(...components) {
201
+ _updateScales(...components) {
198
202
  const c = clean(components || this.components);
199
203
  this._setScales(...c);
200
204
  this._updateScalesDomain(...c);
@@ -214,12 +218,11 @@ class XYContainer extends ContainerCore {
214
218
  const { config } = this;
215
219
  if (!components)
216
220
  return;
221
+ const componentsWithDomain = components.filter(c => !c.config.excludeFromDomainCalculation);
217
222
  // Loop over all the dimensions
218
223
  Object.values(ScaleDimension).forEach((dimension) => {
219
224
  var _a, _b, _c, _d, _e, _f, _g, _h;
220
- const [min, max] = extent(merge(components
221
- .filter(c => !c.config.excludeFromDomainCalculation)
222
- .map(c => c.getDataExtent(dimension, config.scaleByDomain)))); // Components with undefined dimension accessors will return [undefined, undefined] but d3.extent will take care of that
225
+ const [min, max] = extent(merge(componentsWithDomain.map(c => c.getDataExtent(dimension, config.scaleByDomain)))); // Components with undefined dimension accessors will return [undefined, undefined] but d3.extent will take care of that
223
226
  const configuredDomain = dimension === ScaleDimension.Y ? config.yDomain : config.xDomain;
224
227
  const configuredDomainMinConstraint = dimension === ScaleDimension.Y ? config.yDomainMinConstraint : config.xDomainMinConstraint;
225
228
  const configuredDomainMaxConstraint = dimension === ScaleDimension.Y ? config.yDomainMaxConstraint : config.xDomainMaxConstraint;
@@ -229,8 +232,12 @@ class XYContainer extends ContainerCore {
229
232
  clamp(domainMin, (_e = configuredDomainMinConstraint === null || configuredDomainMinConstraint === void 0 ? void 0 : configuredDomainMinConstraint[0]) !== null && _e !== void 0 ? _e : Number.NEGATIVE_INFINITY, (_f = configuredDomainMinConstraint === null || configuredDomainMinConstraint === void 0 ? void 0 : configuredDomainMinConstraint[1]) !== null && _f !== void 0 ? _f : Number.POSITIVE_INFINITY),
230
233
  clamp(domainMax, (_g = configuredDomainMaxConstraint === null || configuredDomainMaxConstraint === void 0 ? void 0 : configuredDomainMaxConstraint[0]) !== null && _g !== void 0 ? _g : Number.NEGATIVE_INFINITY, (_h = configuredDomainMaxConstraint === null || configuredDomainMaxConstraint === void 0 ? void 0 : configuredDomainMaxConstraint[1]) !== null && _h !== void 0 ? _h : Number.POSITIVE_INFINITY),
231
234
  ];
232
- if (config.preventEmptyDomain && (domain[0] === domain[1]) && isFinite(domain[0])) {
233
- domain[1] = domain[0] + 1;
235
+ // Extend the domain if there is no data provided or preventEmptyDomain was explicitly set to `true`
236
+ if (domain[0] === domain[1]) {
237
+ const hasDataProvided = componentsWithDomain.some(c => { var _a; return ((_a = c.datamodel.data) === null || _a === void 0 ? void 0 : _a.length) > 0; });
238
+ if (config.preventEmptyDomain || (config.preventEmptyDomain === null && !hasDataProvided)) {
239
+ domain[1] = domain[0] + 1;
240
+ }
234
241
  }
235
242
  components.forEach(c => c.setScaleDomain(dimension, domain));
236
243
  });