UNPKG

@gooddata/react-components

Version:

GoodData.UI - A powerful JavaScript library for building analytical applications

156 lines (135 loc) 4.84 kB
// (C) 2020 GoodData Corporation import get = require("lodash/get"); import isEmpty = require("lodash/isEmpty"); import isFinite = require("lodash/isFinite"); import escape = require("lodash/escape"); import mapboxgl from "mapbox-gl"; import { ISeparators } from "@gooddata/numberjs"; import { TOOLTIP_MAX_WIDTH, isTooltipShownInFullScreen, formatValueForTooltip, getTooltipContentWidth, } from "../../visualizations/chart/tooltip"; import { DEFAULT_PUSHPIN_COLOR_VALUE, NULL_TOOLTIP_VALUE } from "../../../constants/geoChart"; import { IGeoConfig, IGeoTooltipItem } from "../../../interfaces/GeoChart"; import { parseGeoProperties } from "../../../helpers/geoChart/data"; function isTooltipItemValid(item: IGeoTooltipItem): boolean { if (!item) { return false; } const { title } = item; return Boolean(title); } function escapeAttributeValue(value: number | string): number | string { return isFinite(value) ? value : escape(String(value)); } function formatMeasure(item: IGeoTooltipItem, separators?: ISeparators): IGeoTooltipItem { const { title, value, format } = item; return { title, value: isFinite(value) ? formatValueForTooltip(value, format, separators) : NULL_TOOLTIP_VALUE, }; } function formatAttribute(item: IGeoTooltipItem): IGeoTooltipItem { const { value } = item; return { ...item, value: Boolean(value) ? escapeAttributeValue(value) : NULL_TOOLTIP_VALUE, }; } export function shouldShowTooltip(geoProperties: GeoJSON.GeoJsonProperties): boolean { if (isEmpty(geoProperties)) { return false; } const { locationName, color, size, segment } = geoProperties; return ( isTooltipItemValid(locationName) || isTooltipItemValid(size) || isTooltipItemValid(color) || isTooltipItemValid(segment) ); } export function getTooltipHtml( geoProperties: GeoJSON.GeoJsonProperties, tooltipStroke: string, maxWidth: number, separators?: ISeparators, ): string { const { locationName = {}, size = {}, color = {}, segment = {} } = geoProperties; const tooltipItems: string = [ formatAttribute(locationName), formatMeasure(size, separators), formatMeasure(color, separators), formatAttribute(segment), ] .map(getTooltipItemHtml) .join(""); return `<div class="gd-viz-tooltip" style="max-width:${maxWidth}px"> <span class="stroke gd-viz-tooltip-stroke" style="border-top-color: ${tooltipStroke}"></span> <div class="content gd-viz-tooltip-content">${tooltipItems}</div> </div>`; } function getTooltipItemHtml(item: IGeoTooltipItem): string { if (!isTooltipItemValid(item)) { return ""; } // value is escaped in formatAttribute or formatMeasure function const { title, value } = item; return `<div class="gd-viz-tooltip-item"> <span class="gd-viz-tooltip-title">${escape(title)}</span> <div class="gd-viz-tooltip-value-wraper"> <span class="gd-viz-tooltip-value">${value}</span> </div> </div>`; } export const handlePushpinMouseEnter = ( e: mapboxgl.EventData, chart: mapboxgl.Map, tooltip: mapboxgl.Popup, config: IGeoConfig, ) => { if (isTooltipDisabled(config)) { return; } const { separators } = config; const [feature] = e.features; const { properties } = feature; const parsedProps = parseGeoProperties(properties); if (!shouldShowTooltip(parsedProps)) { return; } chart.getCanvas().style.cursor = "pointer"; const coordinates = feature.geometry.coordinates.slice(); const tooltipStroke = get(parsedProps, "color.background", DEFAULT_PUSHPIN_COLOR_VALUE); const isFullScreenTooltip = isTooltipShownInFullScreen(); const chartWidth: number = chart.getCanvas().clientWidth; const maxTooltipContentWidth: number = getTooltipContentWidth( isFullScreenTooltip, chartWidth, TOOLTIP_MAX_WIDTH, ); const tooltipHtml = getTooltipHtml(parsedProps, tooltipStroke, maxTooltipContentWidth, separators); tooltip .setLngLat(coordinates) .setHTML(tooltipHtml) .setMaxWidth(`${maxTooltipContentWidth}px`) .addTo(chart); }; export const handlePushpinMouseLeave = ( _e: mapboxgl.EventData, chart: mapboxgl.Map, tooltip: mapboxgl.Popup, config: IGeoConfig, ) => { if (isTooltipDisabled(config)) { return; } chart.getCanvas().style.cursor = ""; tooltip.remove(); }; // Tooltips are now switched off in edit/export mode function isTooltipDisabled(config: IGeoConfig): boolean { const { viewport = {} } = config; return Boolean(viewport.frozen); }