@unovis/ts 1.5.0-alpha.7 → 1.5.0-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (70) hide show
  1. package/components/axis/config.d.ts +10 -1
  2. package/components/axis/config.js +1 -1
  3. package/components/axis/config.js.map +1 -1
  4. package/components/axis/index.d.ts +19 -19
  5. package/components/axis/index.js +63 -8
  6. package/components/axis/index.js.map +1 -1
  7. package/components/axis/style.d.ts +1 -0
  8. package/components/axis/style.js +7 -2
  9. package/components/axis/style.js.map +1 -1
  10. package/components/graph/config.d.ts +29 -5
  11. package/components/graph/config.js +3 -3
  12. package/components/graph/config.js.map +1 -1
  13. package/components/graph/index.d.ts +18 -6
  14. package/components/graph/index.js +230 -89
  15. package/components/graph/index.js.map +1 -1
  16. package/components/graph/modules/link/index.d.ts +2 -1
  17. package/components/graph/modules/link/index.js +36 -17
  18. package/components/graph/modules/link/index.js.map +1 -1
  19. package/components/graph/modules/node/index.d.ts +2 -1
  20. package/components/graph/modules/node/index.js +47 -23
  21. package/components/graph/modules/node/index.js.map +1 -1
  22. package/components/graph/modules/node/style.d.ts +2 -0
  23. package/components/graph/modules/node/style.js +34 -4
  24. package/components/graph/modules/node/style.js.map +1 -1
  25. package/components/graph/modules/panel/index.js +1 -0
  26. package/components/graph/modules/panel/index.js.map +1 -1
  27. package/components/graph/style.d.ts +1 -0
  28. package/components/graph/style.js +22 -1
  29. package/components/graph/style.js.map +1 -1
  30. package/components/graph/types.d.ts +8 -0
  31. package/components/graph/types.js +8 -2
  32. package/components/graph/types.js.map +1 -1
  33. package/components/leaflet-map/modules/map.js +2 -1
  34. package/components/leaflet-map/modules/map.js.map +1 -1
  35. package/components/scatter/index.d.ts +1 -0
  36. package/components/scatter/index.js +19 -12
  37. package/components/scatter/index.js.map +1 -1
  38. package/components/scatter/modules/point.js +1 -3
  39. package/components/scatter/modules/point.js.map +1 -1
  40. package/components/scatter/types.d.ts +2 -0
  41. package/components/topojson-map/config.js +2 -2
  42. package/components/topojson-map/config.js.map +1 -1
  43. package/components/topojson-map/index.js +22 -5
  44. package/components/topojson-map/index.js.map +1 -1
  45. package/containers/single-container/index.js +2 -2
  46. package/containers/single-container/index.js.map +1 -1
  47. package/containers/xy-container/index.js +2 -0
  48. package/containers/xy-container/index.js.map +1 -1
  49. package/core/container/config.d.ts +2 -4
  50. package/core/container/config.js.map +1 -1
  51. package/core/container/index.d.ts +2 -1
  52. package/core/container/index.js +20 -14
  53. package/core/container/index.js.map +1 -1
  54. package/data-models/graph.d.ts +2 -0
  55. package/data-models/graph.js +6 -0
  56. package/data-models/graph.js.map +1 -1
  57. package/index.d.ts +1 -4
  58. package/index.js +13 -5
  59. package/index.js.map +1 -1
  60. package/maps/world-simple.json.js +2430 -42
  61. package/package.json +1 -1
  62. package/types/graph.d.ts +2 -0
  63. package/types.js +1 -1
  64. package/utils/index.d.ts +12 -0
  65. package/utils/index.js +13 -0
  66. package/utils/index.js.map +1 -0
  67. package/utils/scale.js +4 -0
  68. package/utils/scale.js.map +1 -0
  69. package/utils/type.js +2 -0
  70. package/utils/type.js.map +1 -0
@@ -25,7 +25,13 @@ var GraphNodeShape;
25
25
  GraphNodeShape["Square"] = "square";
26
26
  GraphNodeShape["Hexagon"] = "hexagon";
27
27
  GraphNodeShape["Triangle"] = "triangle";
28
- })(GraphNodeShape || (GraphNodeShape = {}));
28
+ })(GraphNodeShape || (GraphNodeShape = {}));
29
+ var GraphNodeSelectionHighlightMode;
30
+ (function (GraphNodeSelectionHighlightMode) {
31
+ GraphNodeSelectionHighlightMode["None"] = "none";
32
+ GraphNodeSelectionHighlightMode["Greyout"] = "greyout";
33
+ GraphNodeSelectionHighlightMode["GreyoutNonConnected"] = "greyout-non-connected";
34
+ })(GraphNodeSelectionHighlightMode || (GraphNodeSelectionHighlightMode = {}));
29
35
 
30
- export { GraphLayoutType, GraphLinkArrowStyle, GraphLinkStyle, GraphNodeShape };
36
+ export { GraphLayoutType, GraphLinkArrowStyle, GraphLinkStyle, GraphNodeSelectionHighlightMode, GraphNodeShape };
31
37
  //# sourceMappingURL=types.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sources":["../../../src/components/graph/types.ts"],"sourcesContent":["// Types\nimport { Position } from 'types/position'\nimport { GraphInputLink, GraphInputNode, GraphNodeCore, GraphLinkCore } from 'types/graph'\nimport { Spacing } from 'types/spacing'\n\nexport type GraphNode<\n N extends GraphInputNode = GraphInputNode,\n L extends GraphInputLink = GraphInputLink,\n> = GraphNodeCore<N, L> & {\n x?: number;\n y?: number;\n\n _id?: number | string;\n _index?: number;\n _state?: {\n isDragged?: boolean;\n fx?: number;\n fy?: number;\n selected?: boolean;\n greyout?: boolean;\n };\n\n _panels?: GraphPanel<N, L>[];\n _isConnected?: boolean;\n}\n\nexport type GraphForceSimulationNode<\n N extends GraphInputNode = GraphInputNode,\n L extends GraphInputLink = GraphInputLink,\n> = GraphNode<N, L> & {\n fx?: number;\n fy?: number;\n}\n\nexport type GraphLink<\n N extends GraphInputNode = GraphInputNode,\n L extends GraphInputLink = GraphInputLink,\n> = GraphLinkCore<N, L> & {\n id?: number | string;\n source: number | string | GraphNode<N>;\n target: number | string | GraphNode<N>;\n\n _id?: number | string;\n _direction?: number;\n _index?: number;\n _neighbours?: number;\n\n _state?: {\n flowAnimTime?: number;\n hovered?: boolean;\n selected?: boolean;\n greyout?: boolean;\n };\n}\n\nexport enum GraphLayoutType {\n Circular = 'circular',\n Concentric = 'concentric',\n Parallel = 'parallel',\n ParallelHorizontal = 'parallel horizontal',\n Dagre = 'dagre',\n Force = 'force',\n Elk = 'elk',\n Precalculated = 'precalculated',\n}\n\nexport type GraphCircleLabel = {\n text: string;\n textColor?: string | null;\n color?: string | null;\n cursor?: string | null;\n fontSize?: string | null;\n radius?: number;\n}\n\nexport type GraphLinkLabel = GraphCircleLabel\n\nexport enum GraphLinkStyle {\n Dashed = 'dashed',\n Solid = 'solid',\n}\n\nexport enum GraphLinkArrowStyle {\n Single = 'single',\n Double = 'double',\n}\n\nexport enum GraphNodeShape {\n Circle = 'circle',\n Square = 'square',\n Hexagon = 'hexagon',\n Triangle = 'triangle',\n}\n\nexport type GraphPanelConfig = {\n /** Panel nodes references by unique ids */\n nodes: (string|number)[];\n /** Panel label */\n label?: string;\n /** Position of the label */\n labelPosition?: Position.Top | Position.Bottom | string;\n /** Color of the panel's border */\n borderColor?: string;\n /** Border width of the panel in pixels */\n borderWidth?: number;\n /** Inner padding */\n padding?: number | Spacing;\n /** Dashed outline showing that the panel is selected */\n dashedOutline?: boolean;\n /** Side icon symbol */\n sideIconSymbol?: string;\n /** Size of the icon as a CSS string. e.g.: `12pt` or `12px` */\n sideIconFontSize?: string;\n /** Color of the icon */\n sideIconSymbolColor?: string;\n /** Shape of the icon's background */\n sideIconShape?: GraphNodeShape | string;\n /** Size of the icon's background shape */\n sideIconShapeSize?: number;\n /** Stroke color of the icon's background shape */\n sideIconShapeStroke?: string;\n /** Cursor, when hovering over the icon */\n sideIconCursor?: string;\n}\n\nexport type GraphPanel<\n N extends GraphInputNode = GraphInputNode,\n L extends GraphInputLink = GraphInputLink,\n> = GraphPanelConfig & {\n _numNodes?: number;\n _x?: number;\n _y?: number;\n _width?: number;\n _height?: number;\n _disabled?: boolean;\n _padding?: Spacing;\n}\n\nexport type GraphNodeAnimationState = {\n endAngle: number;\n nodeIndex: number;\n nodeSize?: number;\n borderWidth?: number;\n}\n\nexport type GraphNodeAnimatedElement<T = SVGElement> = T & {\n _animState: GraphNodeAnimationState;\n}\n\nexport type GraphForceLayoutSettings<\n N extends GraphInputNode = GraphInputNode,\n L extends GraphInputLink = GraphInputLink,\n> = {\n /** Preferred Link Distance. Default: `60` */\n linkDistance?: number | ((l: GraphLink<N, L>, i: number) => number);\n /** Link Strength [0:1]. Default: `0.45` */\n linkStrength?: number | ((l: GraphLink<N, L>, i: number) => number);\n /** Charge Force (<0 repulsion, >0 attraction). Default: `-500` */\n charge?: number | ((l: GraphNode<N, L>, i: number) => number);\n /** X-centring force. Default: `0.15` */\n forceXStrength?: number;\n /** Y-centring force. Default: `0.25` */\n forceYStrength?: number;\n /** Number if simulation iterations. Default: automatic */\n numIterations?: number;\n /** Set to true if you want to fix the node positions after the simulation\n * Helpful when you want to update graph settings without re-calculating the layout.\n * Default: `false` */\n fixNodePositionAfterSimulation?: boolean;\n}\n\nexport type GraphElkLayoutSettings = Record<string, string>\n\n/**\n * Settings for configuring the layout of a Dagre graph.\n */\nexport type GraphDagreLayoutSetting = {\n /**\n * Direction for rank nodes. Can be TB, BT, LR, or RL, where T = top, B = bottom, L = left, and R = right.\n * Additional custom values can also be provided as a string.\n */\n rankdir?: 'TB' | 'BT' | 'LR' | 'RL' | string;\n\n /**\n * Alignment for rank nodes. Can be UL, UR, DL, or DR, where U = up, D = down, L = left, and R = right.\n * Additional custom values can also be provided as a string.\n */\n align?: 'UL' | 'UR' | 'DL' | 'DR' | string;\n\n /**\n * Number of pixels that separate nodes horizontally in the layout.\n */\n nodesep?: number;\n\n /**\n * Number of pixels that separate edges horizontally in the layout.\n */\n edgesep?: number;\n\n /**\n * Number of pixels between each rank in the layout.\n */\n ranksep?: number;\n\n /**\n * Number of pixels to use as a margin around the left and right of the graph.\n */\n marginx?: number;\n\n /**\n * Number of pixels to use as a margin around the top and bottom of the graph.\n */\n marginy?: number;\n\n /**\n * If set to 'greedy', uses a greedy heuristic for finding a feedback arc set for a graph.\n * A feedback arc set is a set of edges that can be removed to make a graph acyclic.\n */\n acyclicer?: 'greedy' | undefined;\n\n /**\n * Type of algorithm to assign a rank to each node in the input graph.\n * Possible values are 'network-simplex', 'tight-tree', or 'longest-path'.\n * Additional custom values can also be provided as a string.\n */\n ranker?: 'network-simplex' | 'tight-tree' | 'longest-path' | string;\n}\n\n"],"names":[],"mappings":"IAuDY,gBASX;AATD,CAAA,UAAY,eAAe,EAAA;AACzB,IAAA,eAAA,CAAA,UAAA,CAAA,GAAA,UAAqB,CAAA;AACrB,IAAA,eAAA,CAAA,YAAA,CAAA,GAAA,YAAyB,CAAA;AACzB,IAAA,eAAA,CAAA,UAAA,CAAA,GAAA,UAAqB,CAAA;AACrB,IAAA,eAAA,CAAA,oBAAA,CAAA,GAAA,qBAA0C,CAAA;AAC1C,IAAA,eAAA,CAAA,OAAA,CAAA,GAAA,OAAe,CAAA;AACf,IAAA,eAAA,CAAA,OAAA,CAAA,GAAA,OAAe,CAAA;AACf,IAAA,eAAA,CAAA,KAAA,CAAA,GAAA,KAAW,CAAA;AACX,IAAA,eAAA,CAAA,eAAA,CAAA,GAAA,eAA+B,CAAA;AACjC,CAAC,EATW,eAAe,KAAf,eAAe,GAS1B,EAAA,CAAA,CAAA,CAAA;IAaW,eAGX;AAHD,CAAA,UAAY,cAAc,EAAA;AACxB,IAAA,cAAA,CAAA,QAAA,CAAA,GAAA,QAAiB,CAAA;AACjB,IAAA,cAAA,CAAA,OAAA,CAAA,GAAA,OAAe,CAAA;AACjB,CAAC,EAHW,cAAc,KAAd,cAAc,GAGzB,EAAA,CAAA,CAAA,CAAA;IAEW,oBAGX;AAHD,CAAA,UAAY,mBAAmB,EAAA;AAC7B,IAAA,mBAAA,CAAA,QAAA,CAAA,GAAA,QAAiB,CAAA;AACjB,IAAA,mBAAA,CAAA,QAAA,CAAA,GAAA,QAAiB,CAAA;AACnB,CAAC,EAHW,mBAAmB,KAAnB,mBAAmB,GAG9B,EAAA,CAAA,CAAA,CAAA;IAEW,eAKX;AALD,CAAA,UAAY,cAAc,EAAA;AACxB,IAAA,cAAA,CAAA,QAAA,CAAA,GAAA,QAAiB,CAAA;AACjB,IAAA,cAAA,CAAA,QAAA,CAAA,GAAA,QAAiB,CAAA;AACjB,IAAA,cAAA,CAAA,SAAA,CAAA,GAAA,SAAmB,CAAA;AACnB,IAAA,cAAA,CAAA,UAAA,CAAA,GAAA,UAAqB,CAAA;AACvB,CAAC,EALW,cAAc,KAAd,cAAc,GAKzB,EAAA,CAAA,CAAA;;;;"}
1
+ {"version":3,"file":"types.js","sources":["../../../src/components/graph/types.ts"],"sourcesContent":["// Types\nimport { Position } from 'types/position'\nimport { GraphInputLink, GraphInputNode, GraphNodeCore, GraphLinkCore } from 'types/graph'\nimport { Spacing } from 'types/spacing'\n\nexport type GraphNode<\n N extends GraphInputNode = GraphInputNode,\n L extends GraphInputLink = GraphInputLink,\n> = GraphNodeCore<N, L> & {\n x?: number;\n y?: number;\n\n _id?: number | string;\n _index?: number;\n _state?: {\n isDragged?: boolean;\n fx?: number;\n fy?: number;\n selected?: boolean;\n greyout?: boolean;\n brushed?: boolean;\n };\n\n _panels?: GraphPanel<N, L>[];\n _isConnected?: boolean;\n}\n\nexport type GraphForceSimulationNode<\n N extends GraphInputNode = GraphInputNode,\n L extends GraphInputLink = GraphInputLink,\n> = GraphNode<N, L> & {\n fx?: number;\n fy?: number;\n}\n\nexport type GraphLink<\n N extends GraphInputNode = GraphInputNode,\n L extends GraphInputLink = GraphInputLink,\n> = GraphLinkCore<N, L> & {\n id?: number | string;\n source: number | string | GraphNode<N>;\n target: number | string | GraphNode<N>;\n\n _id?: number | string;\n _direction?: number;\n _index?: number;\n _neighbours?: number;\n\n _state?: {\n flowAnimTime?: number;\n hovered?: boolean;\n selected?: boolean;\n greyout?: boolean;\n };\n}\n\nexport enum GraphLayoutType {\n Circular = 'circular',\n Concentric = 'concentric',\n Parallel = 'parallel',\n ParallelHorizontal = 'parallel horizontal',\n Dagre = 'dagre',\n Force = 'force',\n Elk = 'elk',\n Precalculated = 'precalculated',\n}\n\nexport type GraphCircleLabel = {\n text: string;\n textColor?: string | null;\n color?: string | null;\n cursor?: string | null;\n fontSize?: string | null;\n radius?: number;\n}\n\nexport type GraphLinkLabel = GraphCircleLabel\n\nexport enum GraphLinkStyle {\n Dashed = 'dashed',\n Solid = 'solid',\n}\n\nexport enum GraphLinkArrowStyle {\n Single = 'single',\n Double = 'double',\n}\n\nexport enum GraphNodeShape {\n Circle = 'circle',\n Square = 'square',\n Hexagon = 'hexagon',\n Triangle = 'triangle',\n}\n\nexport type GraphPanelConfig = {\n /** Panel nodes references by unique ids */\n nodes: (string|number)[];\n /** Panel label */\n label?: string;\n /** Position of the label */\n labelPosition?: Position.Top | Position.Bottom | string;\n /** Fill color of the panel */\n fillColor?: string;\n /** Color of the panel's border */\n borderColor?: string;\n /** Border width of the panel in pixels */\n borderWidth?: number;\n /** Inner padding */\n padding?: number | Spacing;\n /** Dashed outline showing that the panel is selected */\n dashedOutline?: boolean;\n /** Side icon symbol */\n sideIconSymbol?: string;\n /** Size of the icon as a CSS string. e.g.: `12pt` or `12px` */\n sideIconFontSize?: string;\n /** Color of the icon */\n sideIconSymbolColor?: string;\n /** Shape of the icon's background */\n sideIconShape?: GraphNodeShape | string;\n /** Size of the icon's background shape */\n sideIconShapeSize?: number;\n /** Stroke color of the icon's background shape */\n sideIconShapeStroke?: string;\n /** Cursor, when hovering over the icon */\n sideIconCursor?: string;\n}\n\nexport type GraphPanel<\n N extends GraphInputNode = GraphInputNode,\n L extends GraphInputLink = GraphInputLink,\n> = GraphPanelConfig & {\n _numNodes?: number;\n _x?: number;\n _y?: number;\n _width?: number;\n _height?: number;\n _disabled?: boolean;\n _padding?: Spacing;\n}\n\nexport type GraphNodeAnimationState = {\n endAngle: number;\n nodeIndex: number;\n nodeSize?: number;\n borderWidth?: number;\n}\n\nexport type GraphNodeAnimatedElement<T = SVGElement> = T & {\n _animState: GraphNodeAnimationState;\n}\n\nexport type GraphForceLayoutSettings<\n N extends GraphInputNode = GraphInputNode,\n L extends GraphInputLink = GraphInputLink,\n> = {\n /** Preferred Link Distance. Default: `60` */\n linkDistance?: number | ((l: GraphLink<N, L>, i: number) => number);\n /** Link Strength [0:1]. Default: `0.45` */\n linkStrength?: number | ((l: GraphLink<N, L>, i: number) => number);\n /** Charge Force (<0 repulsion, >0 attraction). Default: `-500` */\n charge?: number | ((l: GraphNode<N, L>, i: number) => number);\n /** X-centring force. Default: `0.15` */\n forceXStrength?: number;\n /** Y-centring force. Default: `0.25` */\n forceYStrength?: number;\n /** Number if simulation iterations. Default: automatic */\n numIterations?: number;\n /** Set to true if you want to fix the node positions after the simulation\n * Helpful when you want to update graph settings without re-calculating the layout.\n * Default: `false` */\n fixNodePositionAfterSimulation?: boolean;\n}\n\nexport type GraphElkLayoutSettings = Record<string, string>\n\n/**\n * Settings for configuring the layout of a Dagre graph.\n */\nexport type GraphDagreLayoutSetting = {\n /**\n * Direction for rank nodes. Can be TB, BT, LR, or RL, where T = top, B = bottom, L = left, and R = right.\n * Additional custom values can also be provided as a string.\n */\n rankdir?: 'TB' | 'BT' | 'LR' | 'RL' | string;\n\n /**\n * Alignment for rank nodes. Can be UL, UR, DL, or DR, where U = up, D = down, L = left, and R = right.\n * Additional custom values can also be provided as a string.\n */\n align?: 'UL' | 'UR' | 'DL' | 'DR' | string;\n\n /**\n * Number of pixels that separate nodes horizontally in the layout.\n */\n nodesep?: number;\n\n /**\n * Number of pixels that separate edges horizontally in the layout.\n */\n edgesep?: number;\n\n /**\n * Number of pixels between each rank in the layout.\n */\n ranksep?: number;\n\n /**\n * Number of pixels to use as a margin around the left and right of the graph.\n */\n marginx?: number;\n\n /**\n * Number of pixels to use as a margin around the top and bottom of the graph.\n */\n marginy?: number;\n\n /**\n * If set to 'greedy', uses a greedy heuristic for finding a feedback arc set for a graph.\n * A feedback arc set is a set of edges that can be removed to make a graph acyclic.\n */\n acyclicer?: 'greedy' | undefined;\n\n /**\n * Type of algorithm to assign a rank to each node in the input graph.\n * Possible values are 'network-simplex', 'tight-tree', or 'longest-path'.\n * Additional custom values can also be provided as a string.\n */\n ranker?: 'network-simplex' | 'tight-tree' | 'longest-path' | string;\n}\n\nexport enum GraphNodeSelectionHighlightMode {\n None = 'none',\n Greyout ='greyout',\n GreyoutNonConnected ='greyout-non-connected',\n}\n"],"names":[],"mappings":"IAwDY,gBASX;AATD,CAAA,UAAY,eAAe,EAAA;AACzB,IAAA,eAAA,CAAA,UAAA,CAAA,GAAA,UAAqB,CAAA;AACrB,IAAA,eAAA,CAAA,YAAA,CAAA,GAAA,YAAyB,CAAA;AACzB,IAAA,eAAA,CAAA,UAAA,CAAA,GAAA,UAAqB,CAAA;AACrB,IAAA,eAAA,CAAA,oBAAA,CAAA,GAAA,qBAA0C,CAAA;AAC1C,IAAA,eAAA,CAAA,OAAA,CAAA,GAAA,OAAe,CAAA;AACf,IAAA,eAAA,CAAA,OAAA,CAAA,GAAA,OAAe,CAAA;AACf,IAAA,eAAA,CAAA,KAAA,CAAA,GAAA,KAAW,CAAA;AACX,IAAA,eAAA,CAAA,eAAA,CAAA,GAAA,eAA+B,CAAA;AACjC,CAAC,EATW,eAAe,KAAf,eAAe,GAS1B,EAAA,CAAA,CAAA,CAAA;IAaW,eAGX;AAHD,CAAA,UAAY,cAAc,EAAA;AACxB,IAAA,cAAA,CAAA,QAAA,CAAA,GAAA,QAAiB,CAAA;AACjB,IAAA,cAAA,CAAA,OAAA,CAAA,GAAA,OAAe,CAAA;AACjB,CAAC,EAHW,cAAc,KAAd,cAAc,GAGzB,EAAA,CAAA,CAAA,CAAA;IAEW,oBAGX;AAHD,CAAA,UAAY,mBAAmB,EAAA;AAC7B,IAAA,mBAAA,CAAA,QAAA,CAAA,GAAA,QAAiB,CAAA;AACjB,IAAA,mBAAA,CAAA,QAAA,CAAA,GAAA,QAAiB,CAAA;AACnB,CAAC,EAHW,mBAAmB,KAAnB,mBAAmB,GAG9B,EAAA,CAAA,CAAA,CAAA;IAEW,eAKX;AALD,CAAA,UAAY,cAAc,EAAA;AACxB,IAAA,cAAA,CAAA,QAAA,CAAA,GAAA,QAAiB,CAAA;AACjB,IAAA,cAAA,CAAA,QAAA,CAAA,GAAA,QAAiB,CAAA;AACjB,IAAA,cAAA,CAAA,SAAA,CAAA,GAAA,SAAmB,CAAA;AACnB,IAAA,cAAA,CAAA,UAAA,CAAA,GAAA,UAAqB,CAAA;AACvB,CAAC,EALW,cAAc,KAAd,cAAc,GAKzB,EAAA,CAAA,CAAA,CAAA;IA0IW,gCAIX;AAJD,CAAA,UAAY,+BAA+B,EAAA;AACzC,IAAA,+BAAA,CAAA,MAAA,CAAA,GAAA,MAAa,CAAA;AACb,IAAA,+BAAA,CAAA,SAAA,CAAA,GAAA,SAAkB,CAAA;AAClB,IAAA,+BAAA,CAAA,qBAAA,CAAA,GAAA,uBAA4C,CAAA;AAC9C,CAAC,EAJW,+BAA+B,KAA/B,+BAA+B,GAI1C,EAAA,CAAA,CAAA;;;;"}
@@ -108,6 +108,7 @@ function setupMap(mapContainer, config) {
108
108
  // eslint-disable-next-line no-case-declarations
109
109
  const { getMaplibreGLLayer } = yield import('../renderer/mapboxgl-layer.js');
110
110
  layer = getMaplibreGLLayer(config, L, maplibre.default);
111
+ layer.addTo(leafletMap);
111
112
  maplibreMap = (_b = (_a = layer).getMaplibreMap) === null || _b === void 0 ? void 0 : _b.call(_a);
112
113
  select(mapContainer).on('wheel', (event) => {
113
114
  event.preventDefault();
@@ -116,9 +117,9 @@ function setupMap(mapContainer, config) {
116
117
  break;
117
118
  case LeafletMapRenderer.Raster:
118
119
  layer = L.tileLayer(style);
120
+ layer.addTo(leafletMap);
119
121
  break;
120
122
  }
121
- layer.addTo(leafletMap);
122
123
  // leaflet-mapbox-gl has a layer positioning issue on far zoom levels which leads to having wrong
123
124
  // map points projection. We constrain the view to prevent that.
124
125
  constraintMapView(leafletMap);
@@ -1 +1 @@
1
- {"version":3,"file":"map.js","sources":["../../../../src/components/leaflet-map/modules/map.ts"],"sourcesContent":["import type L from 'leaflet'\nimport { select, Selection } from 'd3-selection'\nimport type { GeoJSONSource, Map } from 'maplibre-gl'\nimport { feature } from 'topojson-client'\n\n// Types\nimport { GenericDataRecord } from 'types/data'\n\n// Config\nimport { LeafletMapConfigInterface } from '../config'\n\n// Local Types\n\n// Utils\nimport { constraintMapView, mapboxglWheelEventThrottled } from '../renderer/mapboxgl-utils'\n\n// Styles\nimport * as s from '../style'\nimport { LeafletMapRenderer } from '../types'\n\nexport const initialMapCenter: L.LatLngExpression = [36, 14]\nexport const initialMapZoom = 1.9\n\nexport function updateTopoJson<T extends GenericDataRecord> (maplibreMap: Map, config: LeafletMapConfigInterface<T>): void {\n const { topoJSONLayer } = config\n\n if (topoJSONLayer.sources) {\n const featureObject = topoJSONLayer.sources?.objects?.[topoJSONLayer.featureName]\n if (featureObject) {\n const mapSource = maplibreMap.getSource(topoJSONLayer.featureName) as GeoJSONSource\n const featureCollection = feature(topoJSONLayer.sources, featureObject)\n if (mapSource) {\n mapSource.setData(featureCollection)\n } else {\n maplibreMap.addSource(topoJSONLayer.featureName, { type: 'geojson', data: featureCollection })\n }\n }\n }\n\n const fillLayer = maplibreMap.getLayer(`${topoJSONLayer.featureName}-area`)\n if (topoJSONLayer.fillProperty) {\n if (!fillLayer) {\n maplibreMap.addLayer({\n id: `${topoJSONLayer.featureName}-area`,\n type: 'fill',\n source: topoJSONLayer.featureName,\n paint: {\n // eslint-disable-next-line @typescript-eslint/naming-convention\n 'fill-antialias': false,\n // eslint-disable-next-line @typescript-eslint/naming-convention\n 'fill-opacity': topoJSONLayer.fillOpacity,\n },\n })\n }\n maplibreMap.setPaintProperty(`${topoJSONLayer.featureName}-area`, 'fill-color', [\n 'case',\n ['!', ['has', topoJSONLayer.fillProperty]],\n 'rgba(255, 255, 255, 0)',\n ['get', topoJSONLayer.fillProperty],\n ])\n } else if (fillLayer) maplibreMap.removeLayer(`${topoJSONLayer.featureName}-area`)\n\n const strokeLayer = maplibreMap.getLayer(`${topoJSONLayer.featureName}-stroke`)\n if (topoJSONLayer.strokeProperty) {\n if (!strokeLayer) {\n maplibreMap.addLayer({\n id: `${topoJSONLayer.featureName}-stroke`,\n type: 'line',\n source: topoJSONLayer.featureName,\n paint: {\n // eslint-disable-next-line @typescript-eslint/naming-convention\n 'line-opacity': topoJSONLayer.strokeOpacity,\n // eslint-disable-next-line @typescript-eslint/naming-convention\n 'line-width': topoJSONLayer.strokeWidth,\n },\n })\n }\n maplibreMap.setPaintProperty(`${topoJSONLayer.featureName}-stroke`, 'line-color', [\n 'case',\n ['!', ['has', topoJSONLayer.strokeProperty]],\n 'rgba(255, 255, 255, 0)',\n ['get', topoJSONLayer.strokeProperty],\n ])\n } else if (strokeLayer) { maplibreMap.removeLayer(`${topoJSONLayer.featureName}-stroke`) }\n}\n\nexport async function setupMap<T extends GenericDataRecord> (mapContainer: HTMLElement, config: LeafletMapConfigInterface<T>): Promise<{\n leaflet: L.Map;\n layer: L.Layer;\n svgOverlay: Selection<SVGSVGElement, unknown, null, undefined>;\n svgGroup: Selection<SVGGElement, unknown, SVGElement, undefined>;\n}> {\n const { style, renderer, topoJSONLayer } = config\n const leaflet = await import('leaflet')\n const L = leaflet.default\n\n if (!style) {\n console.error('Unovis | Leaflet Map: Please provide style settings in the map configuration object')\n return\n }\n\n const leafletMap = L.map(mapContainer, {\n scrollWheelZoom: renderer === LeafletMapRenderer.Raster, // We define custom scroll event for MapboxGL to enabling smooth zooming\n zoomControl: false,\n zoomDelta: renderer === LeafletMapRenderer.Raster ? 1 : 0.5,\n zoomSnap: renderer === LeafletMapRenderer.Raster ? 1 : 0,\n attributionControl: true,\n center: initialMapCenter,\n zoom: initialMapZoom,\n minZoom: Math.sqrt(mapContainer.offsetWidth) / 17,\n maxZoom: 23,\n maxBounds: L.latLngBounds(\n [-75, -290],\n [85, 290]\n ),\n maxBoundsViscosity: 1,\n })\n\n for (const attr of config.attribution) {\n leafletMap.attributionControl.addAttribution(attr)\n }\n\n let layer: L.Layer | (L.Layer & { getMaplibreMap(): Map })\n let maplibreMap: Map = null\n\n switch (renderer) {\n case LeafletMapRenderer.MapLibre:\n // eslint-disable-next-line no-case-declarations\n const maplibre = await import('maplibre-gl')\n // eslint-disable-next-line no-case-declarations\n const { getMaplibreGLLayer } = await import('../renderer/mapboxgl-layer')\n layer = getMaplibreGLLayer(config, L, maplibre.default)\n maplibreMap = (layer as ReturnType<typeof getMaplibreGLLayer>).getMaplibreMap?.()\n\n select(mapContainer).on('wheel', (event: WheelEvent) => {\n event.preventDefault()\n mapboxglWheelEventThrottled(leafletMap, layer as (L.Layer & { getMaplibreMap(): Map }), event)\n })\n break\n case LeafletMapRenderer.Raster:\n layer = L.tileLayer(style as string)\n break\n }\n layer.addTo(leafletMap)\n\n // leaflet-mapbox-gl has a layer positioning issue on far zoom levels which leads to having wrong\n // map points projection. We constrain the view to prevent that.\n constraintMapView(leafletMap)\n\n if (maplibreMap && topoJSONLayer?.sources) {\n const canvas = maplibreMap.getCanvas()\n const canvasSelection = select(canvas).classed(s.mapboxglCanvas, true)\n const tilePaneSelection = select(leafletMap.getPanes().tilePane)\n\n maplibreMap.on('mousemove', (event) => {\n const layerName = `${topoJSONLayer.featureName}-area`\n const layer = maplibreMap.getLayer(layerName)\n if (!layer) return\n\n const features = maplibreMap.queryRenderedFeatures(event.point, { layers: [layerName] })\n tilePaneSelection.datum(features[0])\n canvasSelection.classed(s.onFeatureHover, Boolean(features[0]))\n })\n\n maplibreMap.on('load', () => {\n updateTopoJson(maplibreMap, config)\n })\n }\n\n const svgOverlay = select(leafletMap.getPanes().overlayPane).append('svg')\n const svgGroup = svgOverlay.append('g')\n\n return {\n leaflet: leafletMap,\n layer,\n svgOverlay,\n svgGroup,\n }\n}\n"],"names":["s.mapboxglCanvas","s.onFeatureHover"],"mappings":"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"}
1
+ {"version":3,"file":"map.js","sources":["../../../../src/components/leaflet-map/modules/map.ts"],"sourcesContent":["import type L from 'leaflet'\nimport { select, Selection } from 'd3-selection'\nimport type { GeoJSONSource, Map } from 'maplibre-gl'\nimport { feature } from 'topojson-client'\n\n// Types\nimport { GenericDataRecord } from 'types/data'\n\n// Config\nimport { LeafletMapConfigInterface } from '../config'\n\n// Local Types\n\n// Utils\nimport { constraintMapView, mapboxglWheelEventThrottled } from '../renderer/mapboxgl-utils'\n\n// Styles\nimport * as s from '../style'\nimport { LeafletMapRenderer } from '../types'\n\nexport const initialMapCenter: L.LatLngExpression = [36, 14]\nexport const initialMapZoom = 1.9\n\nexport function updateTopoJson<T extends GenericDataRecord> (maplibreMap: Map, config: LeafletMapConfigInterface<T>): void {\n const { topoJSONLayer } = config\n\n if (topoJSONLayer.sources) {\n const featureObject = topoJSONLayer.sources?.objects?.[topoJSONLayer.featureName]\n if (featureObject) {\n const mapSource = maplibreMap.getSource(topoJSONLayer.featureName) as GeoJSONSource\n const featureCollection = feature(topoJSONLayer.sources, featureObject)\n if (mapSource) {\n mapSource.setData(featureCollection)\n } else {\n maplibreMap.addSource(topoJSONLayer.featureName, { type: 'geojson', data: featureCollection })\n }\n }\n }\n\n const fillLayer = maplibreMap.getLayer(`${topoJSONLayer.featureName}-area`)\n if (topoJSONLayer.fillProperty) {\n if (!fillLayer) {\n maplibreMap.addLayer({\n id: `${topoJSONLayer.featureName}-area`,\n type: 'fill',\n source: topoJSONLayer.featureName,\n paint: {\n // eslint-disable-next-line @typescript-eslint/naming-convention\n 'fill-antialias': false,\n // eslint-disable-next-line @typescript-eslint/naming-convention\n 'fill-opacity': topoJSONLayer.fillOpacity,\n },\n })\n }\n maplibreMap.setPaintProperty(`${topoJSONLayer.featureName}-area`, 'fill-color', [\n 'case',\n ['!', ['has', topoJSONLayer.fillProperty]],\n 'rgba(255, 255, 255, 0)',\n ['get', topoJSONLayer.fillProperty],\n ])\n } else if (fillLayer) maplibreMap.removeLayer(`${topoJSONLayer.featureName}-area`)\n\n const strokeLayer = maplibreMap.getLayer(`${topoJSONLayer.featureName}-stroke`)\n if (topoJSONLayer.strokeProperty) {\n if (!strokeLayer) {\n maplibreMap.addLayer({\n id: `${topoJSONLayer.featureName}-stroke`,\n type: 'line',\n source: topoJSONLayer.featureName,\n paint: {\n // eslint-disable-next-line @typescript-eslint/naming-convention\n 'line-opacity': topoJSONLayer.strokeOpacity,\n // eslint-disable-next-line @typescript-eslint/naming-convention\n 'line-width': topoJSONLayer.strokeWidth,\n },\n })\n }\n maplibreMap.setPaintProperty(`${topoJSONLayer.featureName}-stroke`, 'line-color', [\n 'case',\n ['!', ['has', topoJSONLayer.strokeProperty]],\n 'rgba(255, 255, 255, 0)',\n ['get', topoJSONLayer.strokeProperty],\n ])\n } else if (strokeLayer) { maplibreMap.removeLayer(`${topoJSONLayer.featureName}-stroke`) }\n}\n\nexport async function setupMap<T extends GenericDataRecord> (mapContainer: HTMLElement, config: LeafletMapConfigInterface<T>): Promise<{\n leaflet: L.Map;\n layer: L.Layer;\n svgOverlay: Selection<SVGSVGElement, unknown, null, undefined>;\n svgGroup: Selection<SVGGElement, unknown, SVGElement, undefined>;\n}> {\n const { style, renderer, topoJSONLayer } = config\n const leaflet = await import('leaflet')\n const L = leaflet.default\n\n if (!style) {\n console.error('Unovis | Leaflet Map: Please provide style settings in the map configuration object')\n return\n }\n\n const leafletMap = L.map(mapContainer, {\n scrollWheelZoom: renderer === LeafletMapRenderer.Raster, // We define custom scroll event for MapboxGL to enabling smooth zooming\n zoomControl: false,\n zoomDelta: renderer === LeafletMapRenderer.Raster ? 1 : 0.5,\n zoomSnap: renderer === LeafletMapRenderer.Raster ? 1 : 0,\n attributionControl: true,\n center: initialMapCenter,\n zoom: initialMapZoom,\n minZoom: Math.sqrt(mapContainer.offsetWidth) / 17,\n maxZoom: 23,\n maxBounds: L.latLngBounds(\n [-75, -290],\n [85, 290]\n ),\n maxBoundsViscosity: 1,\n })\n\n for (const attr of config.attribution) {\n leafletMap.attributionControl.addAttribution(attr)\n }\n\n let layer: L.Layer | (L.Layer & { getMaplibreMap(): Map })\n let maplibreMap: Map = null\n\n switch (renderer) {\n case LeafletMapRenderer.MapLibre:\n // eslint-disable-next-line no-case-declarations\n const maplibre = await import('maplibre-gl')\n // eslint-disable-next-line no-case-declarations\n const { getMaplibreGLLayer } = await import('../renderer/mapboxgl-layer')\n layer = getMaplibreGLLayer(config, L, maplibre.default)\n layer.addTo(leafletMap)\n maplibreMap = (layer as ReturnType<typeof getMaplibreGLLayer>).getMaplibreMap?.()\n\n select(mapContainer).on('wheel', (event: WheelEvent) => {\n event.preventDefault()\n mapboxglWheelEventThrottled(leafletMap, layer as (L.Layer & { getMaplibreMap(): Map }), event)\n })\n break\n case LeafletMapRenderer.Raster:\n layer = L.tileLayer(style as string)\n layer.addTo(leafletMap)\n break\n }\n // leaflet-mapbox-gl has a layer positioning issue on far zoom levels which leads to having wrong\n // map points projection. We constrain the view to prevent that.\n constraintMapView(leafletMap)\n\n if (maplibreMap && topoJSONLayer?.sources) {\n const canvas = maplibreMap.getCanvas()\n const canvasSelection = select(canvas).classed(s.mapboxglCanvas, true)\n const tilePaneSelection = select(leafletMap.getPanes().tilePane)\n\n maplibreMap.on('mousemove', (event) => {\n const layerName = `${topoJSONLayer.featureName}-area`\n const layer = maplibreMap.getLayer(layerName)\n if (!layer) return\n\n const features = maplibreMap.queryRenderedFeatures(event.point, { layers: [layerName] })\n tilePaneSelection.datum(features[0])\n canvasSelection.classed(s.onFeatureHover, Boolean(features[0]))\n })\n\n maplibreMap.on('load', () => {\n updateTopoJson(maplibreMap, config)\n })\n }\n\n const svgOverlay = select(leafletMap.getPanes().overlayPane).append('svg')\n const svgGroup = svgOverlay.append('g')\n\n return {\n leaflet: leafletMap,\n layer,\n svgOverlay,\n svgGroup,\n }\n}\n"],"names":["s.mapboxglCanvas","s.onFeatureHover"],"mappings":"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"}
@@ -15,6 +15,7 @@ export declare class Scatter<Datum> extends XYComponentCore<Datum, ScatterConfig
15
15
  };
16
16
  private _pointData;
17
17
  private _points;
18
+ private _sizeScale;
18
19
  private _collideLabelsAnimFrameId;
19
20
  constructor(config?: ScatterConfigInterface<Datum>);
20
21
  setConfig(config: ScatterConfigInterface<Datum>): void;
@@ -1,7 +1,7 @@
1
1
  import { select } from 'd3-selection';
2
2
  import { min, max } from 'd3-array';
3
3
  import { XYComponentCore } from '../../core/xy-component/index.js';
4
- import { flatten, getValue, isNumber, getString, getExtent, isArray, getNumber } from '../../utils/data.js';
4
+ import { flatten, isNumber, getString, getExtent, isArray, getNumber, getValue } from '../../utils/data.js';
5
5
  import { getColor } from '../../utils/color.js';
6
6
  import { smartTransition } from '../../utils/d3.js';
7
7
  import { getCSSVariableValueInPixels } from '../../utils/misc.js';
@@ -43,15 +43,20 @@ class Scatter extends XYComponentCore {
43
43
  const xRangeEnd = this.xScale.range()[1];
44
44
  const fontSizePx = getCSSVariableValueInPixels('var(--vis-scatter-point-label-text-font-size)', this.element);
45
45
  const extent = pointDataFlat.reduce((ext, d) => {
46
- const labelPosition = getValue(d, this.config.labelPosition, d._point.pointIndex);
47
- const labelBBox = getEstimatedLabelBBox(d, labelPosition, this.xScale, this.yScale, fontSizePx);
48
46
  const x = this.xScale(d._point.xValue);
49
47
  const y = this.yScale(d._point.yValue);
50
48
  const r = d._point.sizePx / 2;
51
- ext.minX = Math.min(ext.minX, x - r, labelBBox.x);
52
- ext.maxX = Math.max(ext.maxX, x + r, labelBBox.x + labelBBox.width);
53
- ext.minY = Math.min(ext.minY, y - r, labelBBox.y);
54
- ext.maxY = Math.max(ext.maxY, y + r, labelBBox.y + labelBBox.height);
49
+ ext.minX = Math.min(ext.minX, x - r);
50
+ ext.maxX = Math.max(ext.maxX, x + r);
51
+ ext.minY = Math.min(ext.minY, y - r);
52
+ ext.maxY = Math.max(ext.maxY, y + r);
53
+ if (d._point.label) {
54
+ const labelBBox = getEstimatedLabelBBox(d, d._point.labelPosition, this.xScale, this.yScale, fontSizePx);
55
+ ext.minX = Math.min(ext.minX, labelBBox.x);
56
+ ext.maxX = Math.max(ext.maxX, labelBBox.x + labelBBox.width);
57
+ ext.minY = Math.min(ext.minY, labelBBox.y);
58
+ ext.maxY = Math.max(ext.maxY, labelBBox.y + labelBBox.height);
59
+ }
55
60
  return ext;
56
61
  }, {
57
62
  minX: Number.POSITIVE_INFINITY,
@@ -109,8 +114,9 @@ class Scatter extends XYComponentCore {
109
114
  _updateSizeScale() {
110
115
  var _a;
111
116
  const { config, datamodel } = this;
112
- config.sizeScale.domain(getExtent(datamodel.data, config.size));
113
- config.sizeScale.range((_a = config.sizeRange) !== null && _a !== void 0 ? _a : [0, 0]);
117
+ this._sizeScale = config.sizeScale.copy();
118
+ this._sizeScale.domain(getExtent(datamodel.data, config.size));
119
+ this._sizeScale.range((_a = config.sizeRange) !== null && _a !== void 0 ? _a : [0, 0]);
114
120
  }
115
121
  _getOnScreenData() {
116
122
  const { config, datamodel: { data } } = this;
@@ -118,7 +124,7 @@ class Scatter extends XYComponentCore {
118
124
  const yDomain = this.yScale.domain().map((d) => +d); // Convert Date to number
119
125
  const yAccessors = (isArray(config.y) ? config.y : [config.y]);
120
126
  const maxSizeValue = max(flatten(yAccessors.map((y, j) => data === null || data === void 0 ? void 0 : data.map(d => getNumber(d, config.size, j)))));
121
- const maxSizePx = config.sizeRange ? config.sizeScale(maxSizeValue) : maxSizeValue;
127
+ const maxSizePx = config.sizeRange ? this._sizeScale(maxSizeValue) : maxSizeValue;
122
128
  const maxSizeXDomain = this.xScale.invert(maxSizePx) - this.xScale.invert(0);
123
129
  const maxSizeYDomain = Math.abs(this.yScale.invert(maxSizePx) - this.yScale.invert(0));
124
130
  return yAccessors.map((y, j) => {
@@ -127,7 +133,7 @@ class Scatter extends XYComponentCore {
127
133
  const xValue = getNumber(d, config.x, i);
128
134
  const yValue = getNumber(d, y, j);
129
135
  const pointSize = getNumber(d, config.size, i);
130
- const pointSizeScaled = config.sizeRange ? config.sizeScale(pointSize) : pointSize;
136
+ const pointSizeScaled = config.sizeRange ? this._sizeScale(pointSize) : pointSize;
131
137
  const pointSizeXDomain = this.xScale.invert(pointSizeScaled) - this.xScale.invert(0);
132
138
  const pointSizeYDomain = Math.abs(this.yScale.invert(pointSizeScaled) - this.yScale.invert(0));
133
139
  if (((xValue - pointSizeXDomain / 2) >= (xDomain[0] - maxSizeXDomain / 2)) &&
@@ -143,7 +149,8 @@ class Scatter extends XYComponentCore {
143
149
  strokeWidthPx: getNumber(d, config.strokeWidth, j),
144
150
  shape: getString(d, config.shape, j),
145
151
  label: getString(d, config.label, j),
146
- labelColor: getColor(d, config.labelColor, j),
152
+ labelColor: getColor(d, config.labelColor, j, true),
153
+ labelPosition: getValue(d, config.labelPosition, i),
147
154
  cursor: getString(d, config.cursor, j),
148
155
  groupIndex: j,
149
156
  pointIndex: i,
@@ -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'\nimport { Position } from 'types/position'\n\n// Local Types\nimport { ScatterPointGroupNode, ScatterPoint } from './types'\n\n// Config\nimport { ScatterDefaultConfig, 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, ScatterConfigInterface<Datum>> {\n static selectors = s\n protected _defaultConfig = ScatterDefaultConfig as ScatterConfigInterface<Datum>\n public config: ScatterConfigInterface<Datum> = this._defaultConfig\n\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 as Position, 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.domain(getExtent(datamodel.data, config.size))\n config.sizeScale.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: number | Date) => +d) // Convert Date to number\n const yDomain = this.yScale.domain().map((d: number | Date) => +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: getColor(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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"}
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'\nimport { Position } from 'types/position'\nimport { ContinuousScale } from 'types/scale'\n\n// Local Types\nimport { ScatterPointGroupNode, ScatterPoint } from './types'\n\n// Config\nimport { ScatterDefaultConfig, 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\n\nexport class Scatter<Datum> extends XYComponentCore<Datum, ScatterConfigInterface<Datum>> {\n static selectors = s\n protected _defaultConfig = ScatterDefaultConfig as ScatterConfigInterface<Datum>\n public config: ScatterConfigInterface<Datum> = this._defaultConfig\n\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 _sizeScale: ContinuousScale\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 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)\n ext.maxX = Math.max(ext.maxX, x + r)\n ext.minY = Math.min(ext.minY, y - r)\n ext.maxY = Math.max(ext.maxY, y + r)\n\n if (d._point.label) {\n const labelBBox = getEstimatedLabelBBox(d, d._point.labelPosition, this.xScale, this.yScale, fontSizePx)\n ext.minX = Math.min(ext.minX, labelBBox.x)\n ext.maxX = Math.max(ext.maxX, labelBBox.x + labelBBox.width)\n ext.minY = Math.min(ext.minY, labelBBox.y)\n ext.maxY = Math.max(ext.maxY, labelBBox.y + labelBBox.height)\n }\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 this._sizeScale = config.sizeScale.copy()\n this._sizeScale.domain(getExtent(datamodel.data, config.size))\n this._sizeScale.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: number | Date) => +d) // Convert Date to number\n const yDomain = this.yScale.domain().map((d: number | Date) => +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 ? this._sizeScale(maxSizeValue) : maxSizeValue\n\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 ? this._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: getColor(d, config.labelColor, j, true),\n labelPosition: getValue(d, config.labelPosition, i) as Position,\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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"}
@@ -6,7 +6,6 @@ import { Symbol } from '../../../types/symbol.js';
6
6
  import { smartTransition } from '../../../utils/d3.js';
7
7
  import { isStringCSSVariable, getCSSVariableValue } from '../../../utils/misc.js';
8
8
  import { hexToBrightness } from '../../../utils/color.js';
9
- import { getValue } from '../../../utils/data.js';
10
9
  import { getCentralLabelFontSize, getLabelShift } from './utils.js';
11
10
 
12
11
  function createPoints(selection, xScale, yScale) {
@@ -20,7 +19,6 @@ function updatePoints(selection, config, xScale, yScale, duration) {
20
19
  const symbolGenerator = symbol();
21
20
  selection.each((d, index, elements) => {
22
21
  var _a, _b, _c, _d;
23
- const i = d._point.pointIndex;
24
22
  const group = select(elements[index]);
25
23
  const label = group.select('text');
26
24
  const path = group.select('path');
@@ -40,7 +38,7 @@ function updatePoints(selection, config, xScale, yScale, duration) {
40
38
  .style('stroke', pointStrokeColor)
41
39
  .style('stroke-width', `${pointStrokeWidth}px`);
42
40
  // Label
43
- const labelPosition = getValue(d, config.labelPosition, i);
41
+ const labelPosition = d._point.labelPosition;
44
42
  const isLabelPositionCenter = (labelPosition !== Position.Top) && (labelPosition !== Position.Bottom) &&
45
43
  (labelPosition !== Position.Left) && (labelPosition !== Position.Right);
46
44
  const pointLabelText = (_c = d._point.label) !== null && _c !== void 0 ? _c : '';
@@ -1 +1 @@
1
- {"version":3,"file":"point.js","sources":["../../../../src/components/scatter/modules/point.ts"],"sourcesContent":["import { select, Selection } from 'd3-selection'\nimport { symbol } from 'd3-shape'\nimport { color } from 'd3-color'\nimport { Position } from 'types/position'\nimport { Symbol, SymbolType } from 'types/symbol'\n\n// Utils\nimport { smartTransition } from 'utils/d3'\nimport { getCSSVariableValue, isStringCSSVariable } from 'utils/misc'\nimport { hexToBrightness } from 'utils/color'\nimport { getValue } from 'utils/data'\n\n// Types\nimport { ContinuousScale } from 'types/scale'\n\n// Config\nimport { ScatterConfigInterface } from '../config'\n\n// Local Types\nimport { ScatterPoint } from '../types'\n\n// Local Utils\nimport { getCentralLabelFontSize, getLabelShift } from './utils'\n\nexport function createPoints<Datum> (\n selection: Selection<SVGGElement, ScatterPoint<Datum>, SVGGElement, ScatterPoint<Datum>[]>,\n xScale: ContinuousScale,\n yScale: ContinuousScale\n): void {\n selection.attr('transform', d => `translate(${d._point.xValue},${d._point.yValue})`)\n selection.append('path').style('fill', d => d._point.color)\n selection.append('text')\n .style('pointer-events', 'none')\n\n selection.attr('transform', d => `translate(${xScale(d._point.xValue)},${yScale(d._point.yValue)}) scale(0)`)\n}\n\nexport function updatePoints<Datum> (\n selection: Selection<SVGGElement, ScatterPoint<Datum>, SVGGElement, ScatterPoint<Datum>[]>,\n config: ScatterConfigInterface<Datum>,\n xScale: ContinuousScale,\n yScale: ContinuousScale,\n duration: number\n): void {\n const symbolGenerator = symbol()\n\n selection.each((d, index, elements) => {\n const i = d._point.pointIndex\n const group: Selection<SVGGElement, ScatterPoint<Datum>, SVGGElement, ScatterPoint<Datum>[]> = select(elements[index])\n const label = group.select('text')\n const path = group.select('path')\n\n // Shape\n const pointDiameter = d._point.sizePx\n const pointColor = d._point.color\n const pointStrokeColor = d._point.strokeColor ?? null\n const pointStrokeWidth = d._point.strokeWidthPx ?? null\n path.attr('d', () => {\n const svgPath = d._point.shape ? symbolGenerator\n .size(Math.PI * pointDiameter * pointDiameter / 4)\n .type(Symbol[d._point.shape as SymbolType])() : null\n return svgPath\n })\n\n smartTransition(path, duration)\n .style('fill', pointColor)\n .style('stroke', pointStrokeColor)\n .style('stroke-width', `${pointStrokeWidth}px`)\n\n // Label\n const labelPosition = getValue(d, config.labelPosition, i) as `${Position}`\n const isLabelPositionCenter = (labelPosition !== Position.Top) && (labelPosition !== Position.Bottom) &&\n (labelPosition !== Position.Left) && (labelPosition !== Position.Right)\n const pointLabelText = d._point.label ?? ''\n const textLength = pointLabelText.length\n const centralLabelFontSize = getCentralLabelFontSize(pointDiameter, textLength)\n\n let labelColor = d._point.labelColor\n if (!labelColor && isLabelPositionCenter) {\n const c = pointColor || 'var(--vis-scatter-fill-color)'\n const hex = color(isStringCSSVariable(c) ? getCSSVariableValue(c, group.node()) : c)?.hex()\n const brightness = hexToBrightness(hex)\n labelColor = brightness > config.labelTextBrightnessRatio ? 'var(--vis-scatter-point-label-text-color-dark)' : 'var(--vis-scatter-point-label-text-color-light)'\n }\n\n const labelShift = getLabelShift(labelPosition, pointDiameter)\n label.html(pointLabelText)\n .attr('x', labelShift[0])\n .attr('y', labelShift[1])\n .style('font-size', isLabelPositionCenter ? centralLabelFontSize : null)\n .style('text-anchor', () => {\n switch (labelPosition) {\n case Position.Right: return null\n case Position.Left: return 'end'\n default: return 'middle'\n }\n })\n .style('dominant-baseline', () => {\n switch (labelPosition) {\n case Position.Top: return null\n case Position.Bottom: return 'hanging'\n default: return 'central'\n }\n })\n\n smartTransition(label, duration)\n .style('fill', labelColor)\n\n path.style('cursor', d._point.cursor)\n })\n\n smartTransition(selection, duration)\n .attr('transform', d => `translate(${xScale(d._point.xValue)},${yScale(d._point.yValue)}) scale(1)`)\n}\n\nexport function removePoints<Datum> (\n selection: Selection<SVGGElement, ScatterPoint<Datum>, SVGGElement, ScatterPoint<Datum>[]>,\n xScale: ContinuousScale,\n yScale: ContinuousScale,\n duration: number\n): void {\n smartTransition(selection, duration)\n .attr('transform', d => `translate(${xScale(d._point.xValue)},${yScale(d._point.yValue)}) scale(0)`)\n .remove()\n}\n\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"point.js","sources":["../../../../src/components/scatter/modules/point.ts"],"sourcesContent":["import { select, Selection } from 'd3-selection'\nimport { symbol } from 'd3-shape'\nimport { color } from 'd3-color'\nimport { Position } from 'types/position'\nimport { Symbol, SymbolType } from 'types/symbol'\n\n// Utils\nimport { smartTransition } from 'utils/d3'\nimport { getCSSVariableValue, isStringCSSVariable } from 'utils/misc'\nimport { hexToBrightness } from 'utils/color'\n\n// Types\nimport { ContinuousScale } from 'types/scale'\n\n// Config\nimport { ScatterConfigInterface } from '../config'\n\n// Local Types\nimport { ScatterPoint } from '../types'\n\n// Local Utils\nimport { getCentralLabelFontSize, getLabelShift } from './utils'\n\nexport function createPoints<Datum> (\n selection: Selection<SVGGElement, ScatterPoint<Datum>, SVGGElement, ScatterPoint<Datum>[]>,\n xScale: ContinuousScale,\n yScale: ContinuousScale\n): void {\n selection.attr('transform', d => `translate(${d._point.xValue},${d._point.yValue})`)\n selection.append('path').style('fill', d => d._point.color)\n selection.append('text')\n .style('pointer-events', 'none')\n\n selection.attr('transform', d => `translate(${xScale(d._point.xValue)},${yScale(d._point.yValue)}) scale(0)`)\n}\n\nexport function updatePoints<Datum> (\n selection: Selection<SVGGElement, ScatterPoint<Datum>, SVGGElement, ScatterPoint<Datum>[]>,\n config: ScatterConfigInterface<Datum>,\n xScale: ContinuousScale,\n yScale: ContinuousScale,\n duration: number\n): void {\n const symbolGenerator = symbol()\n\n selection.each((d, index, elements) => {\n const group: Selection<SVGGElement, ScatterPoint<Datum>, SVGGElement, ScatterPoint<Datum>[]> = select(elements[index])\n const label = group.select('text')\n const path = group.select('path')\n\n // Shape\n const pointDiameter = d._point.sizePx\n const pointColor = d._point.color\n const pointStrokeColor = d._point.strokeColor ?? null\n const pointStrokeWidth = d._point.strokeWidthPx ?? null\n path.attr('d', () => {\n const svgPath = d._point.shape ? symbolGenerator\n .size(Math.PI * pointDiameter * pointDiameter / 4)\n .type(Symbol[d._point.shape as SymbolType])() : null\n return svgPath\n })\n\n smartTransition(path, duration)\n .style('fill', pointColor)\n .style('stroke', pointStrokeColor)\n .style('stroke-width', `${pointStrokeWidth}px`)\n\n // Label\n const labelPosition = d._point.labelPosition\n const isLabelPositionCenter = (labelPosition !== Position.Top) && (labelPosition !== Position.Bottom) &&\n (labelPosition !== Position.Left) && (labelPosition !== Position.Right)\n const pointLabelText = d._point.label ?? ''\n const textLength = pointLabelText.length\n const centralLabelFontSize = getCentralLabelFontSize(pointDiameter, textLength)\n\n let labelColor = d._point.labelColor\n if (!labelColor && isLabelPositionCenter) {\n const c = pointColor || 'var(--vis-scatter-fill-color)'\n const hex = color(isStringCSSVariable(c) ? getCSSVariableValue(c, group.node()) : c)?.hex()\n const brightness = hexToBrightness(hex)\n labelColor = brightness > config.labelTextBrightnessRatio ? 'var(--vis-scatter-point-label-text-color-dark)' : 'var(--vis-scatter-point-label-text-color-light)'\n }\n\n const labelShift = getLabelShift(labelPosition, pointDiameter)\n label.html(pointLabelText)\n .attr('x', labelShift[0])\n .attr('y', labelShift[1])\n .style('font-size', isLabelPositionCenter ? centralLabelFontSize : null)\n .style('text-anchor', () => {\n switch (labelPosition) {\n case Position.Right: return null\n case Position.Left: return 'end'\n default: return 'middle'\n }\n })\n .style('dominant-baseline', () => {\n switch (labelPosition) {\n case Position.Top: return null\n case Position.Bottom: return 'hanging'\n default: return 'central'\n }\n })\n\n smartTransition(label, duration)\n .style('fill', labelColor)\n\n path.style('cursor', d._point.cursor)\n })\n\n smartTransition(selection, duration)\n .attr('transform', d => `translate(${xScale(d._point.xValue)},${yScale(d._point.yValue)}) scale(1)`)\n}\n\nexport function removePoints<Datum> (\n selection: Selection<SVGGElement, ScatterPoint<Datum>, SVGGElement, ScatterPoint<Datum>[]>,\n xScale: ContinuousScale,\n yScale: ContinuousScale,\n duration: number\n): void {\n smartTransition(selection, duration)\n .attr('transform', d => `translate(${xScale(d._point.xValue)},${yScale(d._point.yValue)}) scale(0)`)\n .remove()\n}\n\n"],"names":[],"mappings":"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"}
@@ -1,3 +1,4 @@
1
+ import { Position } from "../../types/position";
1
2
  import { SymbolType } from "../../types/symbol";
2
3
  export declare type ScatterPoint<D> = D & {
3
4
  _point: {
@@ -10,6 +11,7 @@ export declare type ScatterPoint<D> = D & {
10
11
  shape: SymbolType | string;
11
12
  label: string | null;
12
13
  labelColor: string | null;
14
+ labelPosition: Position | null;
13
15
  cursor: string | null;
14
16
  groupIndex: number;
15
17
  pointIndex: number;
@@ -1,7 +1,7 @@
1
1
  import { ComponentDefaultConfig } from '../../core/component/config.js';
2
- import { MapProjection, MapPointLabelPosition } from './types.js';
2
+ import { MapPointLabelPosition } from './types.js';
3
3
 
4
- const TopoJSONMapDefaultConfig = Object.assign(Object.assign({}, ComponentDefaultConfig), { projection: MapProjection.Kavrayskiy7(), duration: 1500, topojson: undefined, mapFeatureName: 'countries', mapFitToPoints: false, zoomExtent: [0.5, 6], zoomDuration: 400, disableZoom: false, zoomFactor: undefined, linkWidth: (d) => { var _a; return (_a = d.width) !== null && _a !== void 0 ? _a : 1; }, linkColor: (d) => { var _a; return (_a = d.color) !== null && _a !== void 0 ? _a : null; }, linkCursor: null, linkId: (d, i) => { var _a; return `${(_a = d.id) !== null && _a !== void 0 ? _a : i}`; }, linkSource: (d) => d.source, linkTarget: (d) => d.target, areaId: (d) => { var _a; return (_a = d.id) !== null && _a !== void 0 ? _a : ''; }, areaColor: (d) => { var _a; return (_a = d.color) !== null && _a !== void 0 ? _a : null; }, areaCursor: null, longitude: (d) => d.longitude, latitude: (d) => d.latitude, pointColor: (d) => { var _a; return (_a = d.color) !== null && _a !== void 0 ? _a : null; }, pointRadius: (d) => { var _a; return (_a = d.radius) !== null && _a !== void 0 ? _a : 8; }, pointStrokeWidth: (d) => { var _a; return (_a = d.strokeWidth) !== null && _a !== void 0 ? _a : 0; }, pointCursor: null, pointLabel: undefined, pointLabelPosition: MapPointLabelPosition.Bottom, pointLabelTextBrightnessRatio: 0.65, pointId: (d) => d.id, heatmapMode: false, heatmapModeBlurStdDeviation: 8, heatmapModeZoomLevelThreshold: 2.5 });
4
+ const TopoJSONMapDefaultConfig = Object.assign(Object.assign({}, ComponentDefaultConfig), { projection: undefined, duration: 1500, topojson: undefined, mapFeatureName: 'countries', mapFitToPoints: false, zoomExtent: [0.5, 6], zoomDuration: 400, disableZoom: false, zoomFactor: undefined, linkWidth: (d) => { var _a; return (_a = d.width) !== null && _a !== void 0 ? _a : 1; }, linkColor: (d) => { var _a; return (_a = d.color) !== null && _a !== void 0 ? _a : null; }, linkCursor: null, linkId: (d, i) => { var _a; return `${(_a = d.id) !== null && _a !== void 0 ? _a : i}`; }, linkSource: (d) => d.source, linkTarget: (d) => d.target, areaId: (d) => { var _a; return (_a = d.id) !== null && _a !== void 0 ? _a : ''; }, areaColor: (d) => { var _a; return (_a = d.color) !== null && _a !== void 0 ? _a : null; }, areaCursor: null, longitude: (d) => d.longitude, latitude: (d) => d.latitude, pointColor: (d) => { var _a; return (_a = d.color) !== null && _a !== void 0 ? _a : null; }, pointRadius: (d) => { var _a; return (_a = d.radius) !== null && _a !== void 0 ? _a : 8; }, pointStrokeWidth: (d) => { var _a; return (_a = d.strokeWidth) !== null && _a !== void 0 ? _a : 0; }, pointCursor: null, pointLabel: undefined, pointLabelPosition: MapPointLabelPosition.Bottom, pointLabelTextBrightnessRatio: 0.65, pointId: (d) => d.id, heatmapMode: false, heatmapModeBlurStdDeviation: 8, heatmapModeZoomLevelThreshold: 2.5 });
5
5
 
6
6
  export { TopoJSONMapDefaultConfig };
7
7
  //# sourceMappingURL=config.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"config.js","sources":["../../../src/components/topojson-map/config.ts"],"sourcesContent":["import { GeoProjection } from 'd3-geo'\nimport { ComponentConfigInterface, ComponentDefaultConfig } from 'core/component/config'\n\n// Types\nimport { ColorAccessor, NumericAccessor, StringAccessor } from 'types/accessor'\n\n// Local Types\nimport { MapProjection, MapPointLabelPosition } from './types'\n\nexport interface TopoJSONMapConfigInterface<\n AreaDatum,\n PointDatum = unknown,\n LinkDatum = unknown,\n> extends ComponentConfigInterface {\n // General\n /** MapProjection (aka D3's GeoProjection) instance. Default: `MapProjection.Kavrayskiy7()` */\n projection?: GeoProjection;\n /** Map data in the TopoJSON topology format. Default: `undefined` */\n topojson?: TopoJSON.Topology;\n /** Name of the map features to be displayed, e.g. 'countries' or 'counties'. Default: `countries` */\n mapFeatureName?: string;\n /** Set initial map fit to points instead of topojson features. Default: `false` */\n mapFitToPoints?: boolean;\n /** Initial zoom level. Default: `undefined` */\n zoomFactor?: number;\n /** Disable pan / zoom interactions. Default: `false` */\n disableZoom?: boolean;\n /** Zoom extent. Default: `[0.5, 6]` */\n zoomExtent?: number[];\n /** Zoom animation duration. Default: `400` */\n zoomDuration?: number;\n\n /** Link width value or accessor function. Default: `d => d.width ?? 1` */\n linkWidth?: NumericAccessor<LinkDatum>;\n /** Link color value or accessor function. Default: `d => d.color ?? null` */\n linkColor?: ColorAccessor<LinkDatum>;\n /** Link cursor value or accessor function. Default: `null` */\n linkCursor?: StringAccessor<LinkDatum>;\n /** Link id accessor function. Default: `d => d.id` */\n linkId?: StringAccessor<LinkDatum>;\n /** Link source accessor function. Default: `d => d.source` */\n linkSource?: ((l: LinkDatum) => number | string | PointDatum);\n /** Link target accessor function. Default: `d => d.target` */\n linkTarget?: ((l: LinkDatum) => number | string | PointDatum);\n\n /** Area id accessor function corresponding to the feature id from TopoJSON. Default: `d => d.id ?? ''` */\n areaId?: StringAccessor<AreaDatum>;\n /** Area color value or accessor function. Default: `d => d.color ?? null` */\n areaColor?: ColorAccessor<AreaDatum>;\n /** Area cursor value or accessor function. Default: `null` */\n areaCursor?: StringAccessor<AreaDatum>;\n\n /** Point color accessor. Default: `d => d.color ?? null` */\n pointColor?: ColorAccessor<PointDatum>;\n /** Point radius accessor. Default: `d => d.radius ?? 8` */\n pointRadius?: NumericAccessor<PointDatum>;\n /** Point stroke width accessor. Default: `d => d.strokeWidth ?? null` */\n pointStrokeWidth?: NumericAccessor<PointDatum>;\n /** Point cursor constant value or accessor function. Default: `null` */\n pointCursor?: StringAccessor<PointDatum>;\n /** Point longitude accessor function. Default: `d => d.longitude ?? null` */\n longitude?: NumericAccessor<PointDatum>;\n /** Point latitude accessor function. Default: `d => d.latitude ?? null` */\n latitude?: NumericAccessor<PointDatum>;\n /** Point label accessor function. Default: `undefined` */\n pointLabel?: StringAccessor<PointDatum>;\n /** Point label position. Default: `Position.Bottom` */\n pointLabelPosition?: MapPointLabelPosition;\n /** Point color brightness ratio for switching between dark and light text label color. Default: `0.65` */\n pointLabelTextBrightnessRatio?: number;\n /** Point id accessor function. Default: `d => d.id` */\n pointId?: ((d: PointDatum, i: number) => string);\n\n /** Enables blur and blending between neighbouring points. Default: `false` */\n heatmapMode?: boolean;\n /** Heatmap blur filter stdDeviation value. Default: `10` */\n heatmapModeBlurStdDeviation?: number;\n /** Zoom level at which the heatmap mode will be disabled. Default: `2.5` */\n heatmapModeZoomLevelThreshold?: number;\n}\n\nexport const TopoJSONMapDefaultConfig: TopoJSONMapConfigInterface<unknown, unknown, unknown> = {\n ...ComponentDefaultConfig,\n projection: MapProjection.Kavrayskiy7(),\n duration: 1500,\n topojson: undefined,\n mapFeatureName: 'countries',\n mapFitToPoints: false,\n\n zoomExtent: [0.5, 6],\n zoomDuration: 400,\n disableZoom: false,\n zoomFactor: undefined,\n\n linkWidth: (d: unknown): number => (d as { width: number }).width ?? 1,\n linkColor: (d: unknown): string => (d as { color: string }).color ?? null,\n linkCursor: null,\n linkId: (d: unknown, i: number | undefined): string => `${(d as { id: string }).id ?? i}`,\n linkSource: (d: unknown): (number | string | unknown) => (d as { source: string }).source,\n linkTarget: (d: unknown): (number | string | unknown) => (d as { target: string }).target,\n\n areaId: (d: unknown): string => (d as { id: string }).id ?? '',\n areaColor: (d: unknown): string => (d as { color: string }).color ?? null,\n areaCursor: null,\n\n longitude: (d: unknown): number => (d as { longitude: number }).longitude,\n latitude: (d: unknown): number => (d as { latitude: number }).latitude,\n pointColor: (d: unknown): string => (d as { color: string }).color ?? null,\n pointRadius: (d: unknown): number => (d as { radius: number }).radius ?? 8,\n pointStrokeWidth: (d: unknown): number => (d as { strokeWidth: number }).strokeWidth ?? 0,\n pointCursor: null,\n pointLabel: undefined,\n pointLabelPosition: MapPointLabelPosition.Bottom,\n pointLabelTextBrightnessRatio: 0.65,\n pointId: (d: unknown): string => (d as { id: string }).id,\n\n heatmapMode: false,\n heatmapModeBlurStdDeviation: 8,\n heatmapModeZoomLevelThreshold: 2.5,\n}\n\n"],"names":[],"mappings":";;;AAiFO,MAAM,wBAAwB,GAAA,MAAA,CAAA,MAAA,CAAA,MAAA,CAAA,MAAA,CAAA,EAAA,EAChC,sBAAsB,CAAA,EAAA,EACzB,UAAU,EAAE,aAAa,CAAC,WAAW,EAAE,EACvC,QAAQ,EAAE,IAAI,EACd,QAAQ,EAAE,SAAS,EACnB,cAAc,EAAE,WAAW,EAC3B,cAAc,EAAE,KAAK,EAErB,UAAU,EAAE,CAAC,GAAG,EAAE,CAAC,CAAC,EACpB,YAAY,EAAE,GAAG,EACjB,WAAW,EAAE,KAAK,EAClB,UAAU,EAAE,SAAS,EAErB,SAAS,EAAE,CAAC,CAAU,KAAa,EAAA,IAAA,EAAA,CAAA,CAAA,OAAA,MAAC,CAAuB,CAAC,KAAK,MAAA,IAAA,IAAA,EAAA,KAAA,KAAA,CAAA,GAAA,EAAA,GAAI,CAAC,CAAA,EAAA,EACtE,SAAS,EAAE,CAAC,CAAU,KAAY,EAAA,IAAA,EAAA,CAAA,CAAC,OAAA,CAAA,EAAA,GAAC,CAAuB,CAAC,KAAK,MAAI,IAAA,IAAA,EAAA,KAAA,KAAA,CAAA,GAAA,EAAA,GAAA,IAAI,CAAA,EAAA,EACzE,UAAU,EAAE,IAAI,EAChB,MAAM,EAAE,CAAC,CAAU,EAAE,CAAqB,KAAY,EAAA,IAAA,EAAA,CAAA,CAAC,OAAA,CAAA,EAAG,CAAC,EAAA,GAAA,CAAoB,CAAC,EAAE,mCAAI,CAAC,CAAA,CAAE,CAAA,EAAA,EACzF,UAAU,EAAE,CAAC,CAAU,KAAmC,CAAwB,CAAC,MAAM,EACzF,UAAU,EAAE,CAAC,CAAU,KAAmC,CAAwB,CAAC,MAAM,EAEzF,MAAM,EAAE,CAAC,CAAU,KAAa,EAAA,IAAA,EAAA,CAAA,CAAA,OAAA,MAAC,CAAoB,CAAC,EAAE,MAAA,IAAA,IAAA,EAAA,KAAA,KAAA,CAAA,GAAA,EAAA,GAAI,EAAE,CAAA,EAAA,EAC9D,SAAS,EAAE,CAAC,CAAU,KAAa,EAAA,IAAA,EAAA,CAAA,CAAA,OAAA,MAAC,CAAuB,CAAC,KAAK,MAAA,IAAA,IAAA,EAAA,KAAA,KAAA,CAAA,GAAA,EAAA,GAAI,IAAI,CAAA,EAAA,EACzE,UAAU,EAAE,IAAI,EAEhB,SAAS,EAAE,CAAC,CAAU,KAAc,CAA2B,CAAC,SAAS,EACzE,QAAQ,EAAE,CAAC,CAAU,KAAc,CAA0B,CAAC,QAAQ,EACtE,UAAU,EAAE,CAAC,CAAU,KAAa,EAAA,IAAA,EAAA,CAAA,CAAA,OAAA,CAAC,EAAA,GAAA,CAAuB,CAAC,KAAK,MAAA,IAAA,IAAA,EAAA,KAAA,KAAA,CAAA,GAAA,EAAA,GAAI,IAAI,CAAA,EAAA,EAC1E,WAAW,EAAE,CAAC,CAAU,KAAY,EAAA,IAAA,EAAA,CAAA,CAAC,OAAA,CAAA,EAAA,GAAC,CAAwB,CAAC,MAAM,MAAI,IAAA,IAAA,EAAA,KAAA,KAAA,CAAA,GAAA,EAAA,GAAA,CAAC,CAAA,EAAA,EAC1E,gBAAgB,EAAE,CAAC,CAAU,KAAa,EAAA,IAAA,EAAA,CAAA,CAAA,OAAA,CAAC,EAAA,GAAA,CAA6B,CAAC,WAAW,mCAAI,CAAC,CAAA,EAAA,EACzF,WAAW,EAAE,IAAI,EACjB,UAAU,EAAE,SAAS,EACrB,kBAAkB,EAAE,qBAAqB,CAAC,MAAM,EAChD,6BAA6B,EAAE,IAAI,EACnC,OAAO,EAAE,CAAC,CAAU,KAAc,CAAoB,CAAC,EAAE,EAEzD,WAAW,EAAE,KAAK,EAClB,2BAA2B,EAAE,CAAC,EAC9B,6BAA6B,EAAE,GAAG;;;;"}
1
+ {"version":3,"file":"config.js","sources":["../../../src/components/topojson-map/config.ts"],"sourcesContent":["import { GeoProjection } from 'd3-geo'\nimport { ComponentConfigInterface, ComponentDefaultConfig } from 'core/component/config'\n\n// Types\nimport { ColorAccessor, NumericAccessor, StringAccessor } from 'types/accessor'\n\n// Local Types\nimport { MapPointLabelPosition } from './types'\n\nexport interface TopoJSONMapConfigInterface<\n AreaDatum,\n PointDatum = unknown,\n LinkDatum = unknown,\n> extends ComponentConfigInterface {\n // General\n /** MapProjection (aka D3's GeoProjection) instance. Default: `MapProjection.Kavrayskiy7()` */\n projection?: GeoProjection;\n /** Map data in the TopoJSON topology format. Default: `undefined` */\n topojson?: TopoJSON.Topology;\n /** Name of the map features to be displayed, e.g. 'countries' or 'counties'. Default: `countries` */\n mapFeatureName?: string;\n /** Set initial map fit to points instead of topojson features. Default: `false` */\n mapFitToPoints?: boolean;\n /** Initial zoom level. Default: `undefined` */\n zoomFactor?: number;\n /** Disable pan / zoom interactions. Default: `false` */\n disableZoom?: boolean;\n /** Zoom extent. Default: `[0.5, 6]` */\n zoomExtent?: number[];\n /** Zoom animation duration. Default: `400` */\n zoomDuration?: number;\n\n /** Link width value or accessor function. Default: `d => d.width ?? 1` */\n linkWidth?: NumericAccessor<LinkDatum>;\n /** Link color value or accessor function. Default: `d => d.color ?? null` */\n linkColor?: ColorAccessor<LinkDatum>;\n /** Link cursor value or accessor function. Default: `null` */\n linkCursor?: StringAccessor<LinkDatum>;\n /** Link id accessor function. Default: `d => d.id` */\n linkId?: StringAccessor<LinkDatum>;\n /** Link source accessor function. Default: `d => d.source` */\n linkSource?: ((l: LinkDatum) => number | string | PointDatum);\n /** Link target accessor function. Default: `d => d.target` */\n linkTarget?: ((l: LinkDatum) => number | string | PointDatum);\n\n /** Area id accessor function corresponding to the feature id from TopoJSON. Default: `d => d.id ?? ''` */\n areaId?: StringAccessor<AreaDatum>;\n /** Area color value or accessor function. Default: `d => d.color ?? null` */\n areaColor?: ColorAccessor<AreaDatum>;\n /** Area cursor value or accessor function. Default: `null` */\n areaCursor?: StringAccessor<AreaDatum>;\n\n /** Point color accessor. Default: `d => d.color ?? null` */\n pointColor?: ColorAccessor<PointDatum>;\n /** Point radius accessor. Default: `d => d.radius ?? 8` */\n pointRadius?: NumericAccessor<PointDatum>;\n /** Point stroke width accessor. Default: `d => d.strokeWidth ?? null` */\n pointStrokeWidth?: NumericAccessor<PointDatum>;\n /** Point cursor constant value or accessor function. Default: `null` */\n pointCursor?: StringAccessor<PointDatum>;\n /** Point longitude accessor function. Default: `d => d.longitude ?? null` */\n longitude?: NumericAccessor<PointDatum>;\n /** Point latitude accessor function. Default: `d => d.latitude ?? null` */\n latitude?: NumericAccessor<PointDatum>;\n /** Point label accessor function. Default: `undefined` */\n pointLabel?: StringAccessor<PointDatum>;\n /** Point label position. Default: `Position.Bottom` */\n pointLabelPosition?: MapPointLabelPosition;\n /** Point color brightness ratio for switching between dark and light text label color. Default: `0.65` */\n pointLabelTextBrightnessRatio?: number;\n /** Point id accessor function. Default: `d => d.id` */\n pointId?: ((d: PointDatum, i: number) => string);\n\n /** Enables blur and blending between neighbouring points. Default: `false` */\n heatmapMode?: boolean;\n /** Heatmap blur filter stdDeviation value. Default: `10` */\n heatmapModeBlurStdDeviation?: number;\n /** Zoom level at which the heatmap mode will be disabled. Default: `2.5` */\n heatmapModeZoomLevelThreshold?: number;\n}\n\nexport const TopoJSONMapDefaultConfig: TopoJSONMapConfigInterface<unknown, unknown, unknown> = {\n ...ComponentDefaultConfig,\n projection: undefined,\n duration: 1500,\n topojson: undefined,\n mapFeatureName: 'countries',\n mapFitToPoints: false,\n\n zoomExtent: [0.5, 6],\n zoomDuration: 400,\n disableZoom: false,\n zoomFactor: undefined,\n\n linkWidth: (d: unknown): number => (d as { width: number }).width ?? 1,\n linkColor: (d: unknown): string => (d as { color: string }).color ?? null,\n linkCursor: null,\n linkId: (d: unknown, i: number | undefined): string => `${(d as { id: string }).id ?? i}`,\n linkSource: (d: unknown): (number | string | unknown) => (d as { source: string }).source,\n linkTarget: (d: unknown): (number | string | unknown) => (d as { target: string }).target,\n\n areaId: (d: unknown): string => (d as { id: string }).id ?? '',\n areaColor: (d: unknown): string => (d as { color: string }).color ?? null,\n areaCursor: null,\n\n longitude: (d: unknown): number => (d as { longitude: number }).longitude,\n latitude: (d: unknown): number => (d as { latitude: number }).latitude,\n pointColor: (d: unknown): string => (d as { color: string }).color ?? null,\n pointRadius: (d: unknown): number => (d as { radius: number }).radius ?? 8,\n pointStrokeWidth: (d: unknown): number => (d as { strokeWidth: number }).strokeWidth ?? 0,\n pointCursor: null,\n pointLabel: undefined,\n pointLabelPosition: MapPointLabelPosition.Bottom,\n pointLabelTextBrightnessRatio: 0.65,\n pointId: (d: unknown): string => (d as { id: string }).id,\n\n heatmapMode: false,\n heatmapModeBlurStdDeviation: 8,\n heatmapModeZoomLevelThreshold: 2.5,\n}\n\n"],"names":[],"mappings":";;;AAiFO,MAAM,wBAAwB,GAAA,MAAA,CAAA,MAAA,CAAA,MAAA,CAAA,MAAA,CAAA,EAAA,EAChC,sBAAsB,CAAA,EAAA,EACzB,UAAU,EAAE,SAAS,EACrB,QAAQ,EAAE,IAAI,EACd,QAAQ,EAAE,SAAS,EACnB,cAAc,EAAE,WAAW,EAC3B,cAAc,EAAE,KAAK,EAErB,UAAU,EAAE,CAAC,GAAG,EAAE,CAAC,CAAC,EACpB,YAAY,EAAE,GAAG,EACjB,WAAW,EAAE,KAAK,EAClB,UAAU,EAAE,SAAS,EAErB,SAAS,EAAE,CAAC,CAAU,KAAa,EAAA,IAAA,EAAA,CAAA,CAAA,OAAA,CAAC,EAAA,GAAA,CAAuB,CAAC,KAAK,MAAA,IAAA,IAAA,EAAA,KAAA,KAAA,CAAA,GAAA,EAAA,GAAI,CAAC,CAAA,EAAA,EACtE,SAAS,EAAE,CAAC,CAAU,KAAY,EAAA,IAAA,EAAA,CAAA,CAAC,OAAA,CAAA,EAAA,GAAC,CAAuB,CAAC,KAAK,MAAA,IAAA,IAAA,EAAA,KAAA,KAAA,CAAA,GAAA,EAAA,GAAI,IAAI,CAAA,EAAA,EACzE,UAAU,EAAE,IAAI,EAChB,MAAM,EAAE,CAAC,CAAU,EAAE,CAAqB,KAAa,EAAA,IAAA,EAAA,CAAA,CAAA,OAAA,CAAG,EAAA,CAAA,EAAA,GAAC,CAAoB,CAAC,EAAE,MAAA,IAAA,IAAA,EAAA,KAAA,KAAA,CAAA,GAAA,EAAA,GAAI,CAAC,CAAE,CAAA,CAAA,EAAA,EACzF,UAAU,EAAE,CAAC,CAAU,KAAmC,CAAwB,CAAC,MAAM,EACzF,UAAU,EAAE,CAAC,CAAU,KAAmC,CAAwB,CAAC,MAAM,EAEzF,MAAM,EAAE,CAAC,CAAU,KAAY,EAAA,IAAA,EAAA,CAAA,CAAC,OAAA,CAAA,EAAA,GAAC,CAAoB,CAAC,EAAE,MAAI,IAAA,IAAA,EAAA,KAAA,KAAA,CAAA,GAAA,EAAA,GAAA,EAAE,CAAA,EAAA,EAC9D,SAAS,EAAE,CAAC,CAAU,KAAY,EAAA,IAAA,EAAA,CAAA,CAAC,OAAA,CAAA,EAAA,GAAC,CAAuB,CAAC,KAAK,MAAI,IAAA,IAAA,EAAA,KAAA,KAAA,CAAA,GAAA,EAAA,GAAA,IAAI,CAAA,EAAA,EACzE,UAAU,EAAE,IAAI,EAEhB,SAAS,EAAE,CAAC,CAAU,KAAc,CAA2B,CAAC,SAAS,EACzE,QAAQ,EAAE,CAAC,CAAU,KAAc,CAA0B,CAAC,QAAQ,EACtE,UAAU,EAAE,CAAC,CAAU,KAAY,EAAA,IAAA,EAAA,CAAA,CAAC,OAAA,CAAA,EAAA,GAAC,CAAuB,CAAC,KAAK,MAAI,IAAA,IAAA,EAAA,KAAA,KAAA,CAAA,GAAA,EAAA,GAAA,IAAI,CAAA,EAAA,EAC1E,WAAW,EAAE,CAAC,CAAU,KAAa,EAAA,IAAA,EAAA,CAAA,CAAA,OAAA,CAAC,EAAA,GAAA,CAAwB,CAAC,MAAM,MAAI,IAAA,IAAA,EAAA,KAAA,KAAA,CAAA,GAAA,EAAA,GAAA,CAAC,CAAA,EAAA,EAC1E,gBAAgB,EAAE,CAAC,CAAU,KAAa,EAAA,IAAA,EAAA,CAAA,CAAA,OAAA,CAAC,EAAA,GAAA,CAA6B,CAAC,WAAW,mCAAI,CAAC,CAAA,EAAA,EACzF,WAAW,EAAE,IAAI,EACjB,UAAU,EAAE,SAAS,EACrB,kBAAkB,EAAE,qBAAqB,CAAC,MAAM,EAChD,6BAA6B,EAAE,IAAI,EACnC,OAAO,EAAE,CAAC,CAAU,KAAc,CAAoB,CAAC,EAAE,EAEzD,WAAW,EAAE,KAAK,EAClB,2BAA2B,EAAE,CAAC,EAC9B,6BAA6B,EAAE,GAAG;;;;"}
@@ -9,7 +9,7 @@ import { isNumber, getString, getNumber, clamp } from '../../utils/data.js';
9
9
  import { smartTransition } from '../../utils/d3.js';
10
10
  import { getColor, hexToBrightness } from '../../utils/color.js';
11
11
  import { isStringCSSVariable, getCSSVariableValue } from '../../utils/misc.js';
12
- import { MapPointLabelPosition } from './types.js';
12
+ import { MapProjection, MapPointLabelPosition } from './types.js';
13
13
  import { TopoJSONMapDefaultConfig } from './config.js';
14
14
  import { getLonLat, arc } from './utils.js';
15
15
  import * as style from './style.js';
@@ -54,10 +54,14 @@ class TopoJSONMap extends ComponentCore {
54
54
  this.datamodel.linkSource = config.linkSource;
55
55
  this.datamodel.linkTarget = config.linkTarget;
56
56
  this.datamodel.data = data;
57
+ // If there was a data change and mapFitToPoints is enabled, we will need to re-fit the map
58
+ this._firstRender = this._firstRender || config.mapFitToPoints;
57
59
  }
58
60
  setConfig(config) {
61
+ var _a;
59
62
  super.setConfig(config);
60
- const newProjection = this.config.projection;
63
+ // Setting the default here instead of defaultConfig to prevent mutation from other TopoJSONMap instances
64
+ const newProjection = (_a = this.config.projection) !== null && _a !== void 0 ? _a : MapProjection.Kavrayskiy7();
61
65
  if (this._projection) {
62
66
  newProjection.scale(this._projection.scale()).translate(this._projection.translate());
63
67
  }
@@ -180,7 +184,8 @@ class TopoJSONMap extends ComponentCore {
180
184
  .attr('transform', d => {
181
185
  const pos = this._projection(getLonLat(d, config.longitude, config.latitude));
182
186
  return `translate(${pos[0]},${pos[1]})`;
183
- });
187
+ })
188
+ .style('opacity', 0);
184
189
  pointsEnter.append('circle').attr('class', pointCircle)
185
190
  .attr('r', 0)
186
191
  .style('fill', (d, i) => getColor(d, config.pointColor, i))
@@ -194,7 +199,8 @@ class TopoJSONMap extends ComponentCore {
194
199
  const pos = this._projection(getLonLat(d, config.longitude, config.latitude));
195
200
  return `translate(${pos[0]},${pos[1]})`;
196
201
  })
197
- .style('cursor', d => getString(d, config.pointCursor));
202
+ .style('cursor', d => getString(d, config.pointCursor))
203
+ .style('opacity', 1);
198
204
  smartTransition(pointsMerged.select(`.${pointCircle}`), duration)
199
205
  .attr('r', d => getNumber(d, config.pointRadius) / this._currentZoomLevel)
200
206
  .style('fill', (d, i) => getColor(d, config.pointColor, i))
@@ -244,6 +250,7 @@ class TopoJSONMap extends ComponentCore {
244
250
  const pointData = points || datamodel.points;
245
251
  if (pointData.length === 0)
246
252
  return;
253
+ this.fitView();
247
254
  const featureCollection = {
248
255
  type: 'FeatureCollection',
249
256
  features: [{
@@ -265,8 +272,18 @@ class TopoJSONMap extends ComponentCore {
265
272
  [this._width * (1 - pad), this._height * (1 - pad)],
266
273
  ], featureCollection);
267
274
  const maxScale = config.zoomExtent[1] * this._initialScale;
268
- if (this._projection.scale() > maxScale)
275
+ const fittedScale = this._projection.scale();
276
+ if (fittedScale > maxScale) {
277
+ const fittedTranslate = this._projection.translate();
278
+ const scaleRatio = maxScale / fittedScale;
269
279
  this._projection.scale(maxScale);
280
+ this._projection.translate([
281
+ this._width / 2 - (this._width / 2 - fittedTranslate[0]) * scaleRatio,
282
+ this._height / 2 - (this._height / 2 - fittedTranslate[1]) * scaleRatio,
283
+ ]);
284
+ }
285
+ // If we don't update the center, the next zoom will be centered around the previous value
286
+ this._center = this._projection.translate();
270
287
  this._applyZoom();
271
288
  }
272
289
  _applyZoom() {