@gooddata/sdk-ui-geo 11.41.0-alpha.0 → 11.41.0-alpha.2

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.
@@ -1,12 +1,7 @@
1
1
  // (C) 2026 GoodData Corporation
2
2
  import { useMemo } from "react";
3
- import { defineMessages } from "react-intl";
4
3
  import { useTooltipLookupExecutions } from "@gooddata/sdk-ui-vis-commons";
5
4
  import { getLayerAdapter } from "../../layers/registry/adapterRegistry.js";
6
- const customTooltipMessages = defineMessages({
7
- noData: { id: "richText.no_data" },
8
- multipleItems: { id: "richText.multiple_data" },
9
- });
10
5
  const EMPTY_RESULT = { tooltipLookups: new Map() };
11
6
  function planTooltipExecutions(layerExecutions, layerDataViews, backend, workspace, config, execConfig, intl) {
12
7
  const planned = [];
@@ -43,7 +38,6 @@ function planTooltipExecutions(layerExecutions, layerDataViews, backend, workspa
43
38
  planned.push({
44
39
  key: record.layerId,
45
40
  execution: built.execution,
46
- meta: built.meta,
47
41
  context: built.buildFeatureKey,
48
42
  });
49
43
  }
@@ -67,11 +61,7 @@ export function useLayersTooltipData(params) {
67
61
  // eslint-disable-next-line react-hooks/exhaustive-deps
68
62
  }, [tooltipEnabled, layerExecutions, layerDataViews, backend, workspace, tooltipContent]);
69
63
  const separators = config?.separators;
70
- const localizedStrings = useMemo(() => ({
71
- noData: `(${intl.formatMessage(customTooltipMessages.noData)})`,
72
- multipleItems: `(${intl.formatMessage(customTooltipMessages.multipleItems)})`,
73
- }), [intl]);
74
- const lookupResults = useTooltipLookupExecutions(planned, separators, localizedStrings);
64
+ const lookupResults = useTooltipLookupExecutions(planned, separators);
75
65
  // Lookup-table construction is downstream of the cancelable promise so a
76
66
  // separators-only change rebuilds the cached strings without a backend call.
77
67
  // No stale-guard needed here: `useTooltipLookupExecutions` clears its result
@@ -112,7 +112,7 @@ function buildAreaTooltipExecution(layer, context, mainDefinition) {
112
112
  }
113
113
  return buildKeySegment(areaAttrId, areaUri);
114
114
  };
115
- return { ...built, buildFeatureKey };
115
+ return { execution: built, buildFeatureKey };
116
116
  }
117
117
  export const areaAdapter = {
118
118
  type: "area",
@@ -1,4 +1,5 @@
1
1
  // (C) 2025-2026 GoodData Corporation
2
+ import { buildTooltipLocalizedStrings } from "@gooddata/sdk-ui-vis-commons";
2
3
  import { buildCustomTooltipPieces, composeTooltipBody } from "../../common/customTooltipSection.js";
3
4
  import { dedupeAttributePayloadsByAttrId, formatAttributeHtml, formatMeasureHtml, getTooltipProperties, parseTooltipPayload, } from "../../common/tooltipUtils.js";
4
5
  function escapeHtml(str) {
@@ -20,9 +21,7 @@ function buildAreaTooltipHtml(rawProperties, locationName, color, segment, strok
20
21
  const measureItem = formatMeasureHtml(color, separators, tooltipFormatConfig);
21
22
  const items = [...attributeItems, ...(measureItem ? [measureItem] : [])];
22
23
  const defaultItemsHtml = items.join("");
23
- const fallbackText = `(${intl.formatMessage({ id: "richText.no_fetch" })})`;
24
- const noDataLabel = `(${intl.formatMessage({ id: "richText.no_data" })})`;
25
- const customPieces = buildCustomTooltipPieces(rawProperties, customConfig, referenceMaps, separators, fallbackText, noDataLabel, tooltipLookup);
24
+ const customPieces = buildCustomTooltipPieces(rawProperties, customConfig, referenceMaps, separators, buildTooltipLocalizedStrings(intl), tooltipLookup);
26
25
  // Suppress the tooltip entirely only when there's nothing to show in
27
26
  // either the default or the custom section.
28
27
  if (items.length === 0 && !customPieces.sectionHtml) {
@@ -1,5 +1,5 @@
1
1
  import { type IAttribute, type IExecutionDefinition } from "@gooddata/sdk-model";
2
- import { type IResolvedReferenceValues, type ITooltipExecutionBundle } from "@gooddata/sdk-ui-vis-commons";
2
+ import { type IResolvedReferenceValues, type ITooltipExecution } from "@gooddata/sdk-ui-vis-commons";
3
3
  import { type JsonValue } from "../../utils/guards.js";
4
4
  /**
5
5
  * Returns the lookup key for a hovered feature in the same format
@@ -12,7 +12,8 @@ export type BuildFeatureKey = (properties: GeoJSON.GeoJsonProperties) => string
12
12
  /**
13
13
  * @internal
14
14
  */
15
- export interface IGeoLayerCustomTooltipExecution extends ITooltipExecutionBundle {
15
+ export interface IGeoLayerCustomTooltipExecution {
16
+ execution: ITooltipExecution;
16
17
  buildFeatureKey: BuildFeatureKey;
17
18
  }
18
19
  /**
@@ -1,5 +1,5 @@
1
1
  import { type ISeparators } from "@gooddata/sdk-model";
2
- import { type ICustomTooltipConfig } from "@gooddata/sdk-ui-vis-commons";
2
+ import { type ICustomTooltipConfig, type ITooltipLocalizedStrings } from "@gooddata/sdk-ui-vis-commons";
3
3
  import { type ITooltipReferenceMaps } from "../registry/adapterTypes.js";
4
4
  import { type IGeoLayerTooltipLookup } from "./customTooltipExecution.js";
5
5
  interface ICustomTooltipPieces {
@@ -16,7 +16,7 @@ interface ICustomTooltipPieces {
16
16
  *
17
17
  * @internal
18
18
  */
19
- export declare function buildCustomTooltipPieces(properties: GeoJSON.GeoJsonProperties, customConfig: ICustomTooltipConfig | undefined, referenceMaps: ITooltipReferenceMaps | undefined, separators: ISeparators | undefined, fallbackText: string, noDataLabel: string, tooltipLookup?: IGeoLayerTooltipLookup): ICustomTooltipPieces;
19
+ export declare function buildCustomTooltipPieces(properties: GeoJSON.GeoJsonProperties, customConfig: ICustomTooltipConfig | undefined, referenceMaps: ITooltipReferenceMaps | undefined, separators: ISeparators | undefined, localizedStrings: ITooltipLocalizedStrings, tooltipLookup?: IGeoLayerTooltipLookup): ICustomTooltipPieces;
20
20
  /**
21
21
  * Splice custom-tooltip pieces into the default tooltip body.
22
22
  *
@@ -1,5 +1,5 @@
1
1
  // (C) 2026 GoodData Corporation
2
- import { composeCustomTooltipSectionHtml } from "@gooddata/sdk-ui-vis-commons";
2
+ import { composeCustomTooltipSectionHtml, } from "@gooddata/sdk-ui-vis-commons";
3
3
  import { resolveReferencesFromGeoFeature } from "./resolveReferencesFromGeoFeature.js";
4
4
  /**
5
5
  * Build the custom-tooltip section + separator HTML pieces for a hovered feature.
@@ -9,12 +9,12 @@ import { resolveReferencesFromGeoFeature } from "./resolveReferencesFromGeoFeatu
9
9
  *
10
10
  * @internal
11
11
  */
12
- export function buildCustomTooltipPieces(properties, customConfig, referenceMaps, separators, fallbackText, noDataLabel, tooltipLookup) {
12
+ export function buildCustomTooltipPieces(properties, customConfig, referenceMaps, separators, localizedStrings, tooltipLookup) {
13
13
  if (!customConfig?.enabled || !customConfig.content) {
14
14
  return { sectionHtml: "", separatorHtml: "" };
15
15
  }
16
16
  // In-chart values from the rendered feature's properties.
17
- const pointLocal = resolveReferencesFromGeoFeature(properties, referenceMaps, separators, noDataLabel);
17
+ const pointLocal = resolveReferencesFromGeoFeature(properties, referenceMaps, separators);
18
18
  // External values from the precomputed lookup (refs not on the feature).
19
19
  let externalValues = {};
20
20
  if (tooltipLookup) {
@@ -23,7 +23,7 @@ export function buildCustomTooltipPieces(properties, customConfig, referenceMaps
23
23
  externalValues = tooltipLookup.lookup.get(featureKey) ?? {};
24
24
  }
25
25
  }
26
- const sectionHtml = composeCustomTooltipSectionHtml(customConfig.content, pointLocal, externalValues, fallbackText);
26
+ const sectionHtml = composeCustomTooltipSectionHtml(customConfig.content, pointLocal, externalValues, localizedStrings);
27
27
  // Replace mode shows only the custom section, so no separator is needed.
28
28
  const separatorHtml = customConfig.placement === "replace" ? "" : `<div class="gd-viz-tooltip-custom-separator"></div>`;
29
29
  return { sectionHtml, separatorHtml };
@@ -17,4 +17,4 @@ import { type ITooltipReferenceMaps } from "../registry/adapterTypes.js";
17
17
  *
18
18
  * @internal
19
19
  */
20
- export declare function resolveReferencesFromGeoFeature(properties: GeoJSON.GeoJsonProperties, referenceMaps: ITooltipReferenceMaps | undefined, separators: ISeparators | undefined, noDataLabel: string): IResolvedReferenceValues;
20
+ export declare function resolveReferencesFromGeoFeature(properties: GeoJSON.GeoJsonProperties, referenceMaps: ITooltipReferenceMaps | undefined, separators: ISeparators | undefined): IResolvedReferenceValues;
@@ -1,5 +1,5 @@
1
1
  // (C) 2026 GoodData Corporation
2
- import { ClientFormatterFacade } from "@gooddata/number-formatter";
2
+ import { labelKey, labelReference, measureReference, metricKey, } from "@gooddata/sdk-ui-vis-commons";
3
3
  import { getTooltipProperties, parseTooltipPayload } from "./tooltipUtils.js";
4
4
  /**
5
5
  * Builds the resolver lookup table for a hovered GeoJSON feature.
@@ -17,7 +17,7 @@ import { getTooltipProperties, parseTooltipPayload } from "./tooltipUtils.js";
17
17
  *
18
18
  * @internal
19
19
  */
20
- export function resolveReferencesFromGeoFeature(properties, referenceMaps, separators, noDataLabel) {
20
+ export function resolveReferencesFromGeoFeature(properties, referenceMaps, separators) {
21
21
  const values = {};
22
22
  if (!properties) {
23
23
  return values;
@@ -29,19 +29,19 @@ export function resolveReferencesFromGeoFeature(properties, referenceMaps, separ
29
29
  if (!payload?.attrId || payload.value === undefined) {
30
30
  return;
31
31
  }
32
- const text = String(payload.value);
33
- const displayFormKey = `label/${payload.attrId}`;
32
+ const status = labelReference(String(payload.value));
33
+ const displayFormKey = labelKey(payload.attrId);
34
34
  if (values[displayFormKey] === undefined) {
35
- values[displayFormKey] = text;
35
+ values[displayFormKey] = status;
36
36
  }
37
37
  // When `attrId` and the parent attribute id are equal, `attributeKey`
38
38
  // collapses onto `displayFormKey` and the second write is a no-op
39
39
  // under first-wins — no self-equality check needed.
40
40
  const attributeId = attributeIdByDisplayFormId[payload.attrId];
41
41
  if (attributeId) {
42
- const attributeKey = `label/${attributeId}`;
42
+ const attributeKey = labelKey(attributeId);
43
43
  if (values[attributeKey] === undefined) {
44
- values[attributeKey] = text;
44
+ values[attributeKey] = status;
45
45
  }
46
46
  }
47
47
  };
@@ -53,29 +53,14 @@ export function resolveReferencesFromGeoFeature(properties, referenceMaps, separ
53
53
  if (!ldmId) {
54
54
  return;
55
55
  }
56
- const key = `metric/${ldmId}`;
56
+ const key = metricKey(ldmId);
57
57
  if (values[key] !== undefined) {
58
58
  return; // first-wins precedence
59
59
  }
60
+ // Geo payloads (via JSON) can be non-numeric/NaN; normalize to null (→ "No data") first.
60
61
  const rawValue = payload.value;
61
- if (typeof rawValue !== "number" || !Number.isFinite(rawValue)) {
62
- // Null / undefined / NaN on the rendered feature — emit the no-data
63
- // sentinel so the custom section reads "(No data)" instead of falling
64
- // through to the resolution-failure fallback text.
65
- values[key] = noDataLabel;
66
- return;
67
- }
68
- // Use the raw formatted value without HTML escaping. The resolved
69
- // content goes through `markdownToHtml`, which escapes once at render
70
- // time — pre-escaping here would produce double-escaped output (`&` →
71
- // `&amp;amp;`). Matches Highcharts' `resolveReferencesFromPoint`.
72
- if (payload.format) {
73
- const { formattedValue } = ClientFormatterFacade.formatValue(rawValue, payload.format, separators);
74
- values[key] = formattedValue;
75
- }
76
- else {
77
- values[key] = String(rawValue);
78
- }
62
+ const numeric = typeof rawValue === "number" && Number.isFinite(rawValue) ? rawValue : null;
63
+ values[key] = measureReference(numeric, payload.format, separators);
79
64
  };
80
65
  // Walk in default-tooltip render order so `{metric/foo}` resolves to the
81
66
  // value users see above the custom section when the same metric appears
@@ -234,7 +234,7 @@ function buildPushpinTooltipExecution(layer, context, mainDefinition) {
234
234
  }
235
235
  return joinKeySegments(parts);
236
236
  };
237
- return { ...built, buildFeatureKey };
237
+ return { execution: built, buildFeatureKey };
238
238
  }
239
239
  export const pushpinAdapter = {
240
240
  type: "pushpin",
@@ -1,5 +1,6 @@
1
1
  // (C) 2025-2026 GoodData Corporation
2
2
  import { escape, isEmpty } from "lodash-es";
3
+ import { buildTooltipLocalizedStrings } from "@gooddata/sdk-ui-vis-commons";
3
4
  import { getTooltipContentWidth } from "../../../map/style/tooltipFormatting.js";
4
5
  import { isGeoJsonPoint, isLngLatTuple, isRecord, } from "../../../utils/guards.js";
5
6
  import { buildCustomTooltipPieces, composeTooltipBody } from "../../common/customTooltipSection.js";
@@ -124,9 +125,7 @@ export function getTooltipHtml(geoProperties, tooltipStroke, maxWidth, separator
124
125
  ]
125
126
  .filter((item) => item !== null)
126
127
  .join("");
127
- const fallbackText = `(${intl.formatMessage({ id: "richText.no_fetch" })})`;
128
- const noDataLabel = `(${intl.formatMessage({ id: "richText.no_data" })})`;
129
- const customPieces = buildCustomTooltipPieces(geoProperties, customConfig, referenceMaps, separators, fallbackText, noDataLabel, tooltipLookup);
128
+ const customPieces = buildCustomTooltipPieces(geoProperties, customConfig, referenceMaps, separators, buildTooltipLocalizedStrings(intl), tooltipLookup);
130
129
  const itemsBody = composeTooltipBody(tooltipItems, customPieces, customConfig?.placement);
131
130
  const strokeHtml = showStroke
132
131
  ? `<span class="gd-viz-tooltip-stroke" style="border-top-color: ${tooltipStroke}"></span>`
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gooddata/sdk-ui-geo",
3
- "version": "11.41.0-alpha.0",
3
+ "version": "11.41.0-alpha.2",
4
4
  "description": "GoodData.UI SDK - Geo Charts",
5
5
  "license": "MIT",
6
6
  "author": "GoodData Corporation",
@@ -43,12 +43,12 @@
43
43
  "ts-invariant": "0.10.3",
44
44
  "tslib": "2.8.1",
45
45
  "uuid": "11.1.0",
46
- "@gooddata/sdk-model": "11.41.0-alpha.0",
47
- "@gooddata/sdk-backend-spi": "11.41.0-alpha.0",
48
- "@gooddata/sdk-ui": "11.41.0-alpha.0",
49
- "@gooddata/sdk-ui-theme-provider": "11.41.0-alpha.0",
50
- "@gooddata/sdk-ui-kit": "11.41.0-alpha.0",
51
- "@gooddata/sdk-ui-vis-commons": "11.41.0-alpha.0"
46
+ "@gooddata/sdk-backend-spi": "11.41.0-alpha.2",
47
+ "@gooddata/sdk-model": "11.41.0-alpha.2",
48
+ "@gooddata/sdk-ui": "11.41.0-alpha.2",
49
+ "@gooddata/sdk-ui-theme-provider": "11.41.0-alpha.2",
50
+ "@gooddata/sdk-ui-kit": "11.41.0-alpha.2",
51
+ "@gooddata/sdk-ui-vis-commons": "11.41.0-alpha.2"
52
52
  },
53
53
  "devDependencies": {
54
54
  "@microsoft/api-documenter": "^7.17.0",
@@ -91,10 +91,10 @@
91
91
  "typescript": "5.9.3",
92
92
  "vitest": "4.1.8",
93
93
  "vitest-dom": "0.1.1",
94
- "@gooddata/eslint-config": "11.41.0-alpha.0",
95
- "@gooddata/oxlint-config": "11.41.0-alpha.0",
96
- "@gooddata/sdk-backend-mockingbird": "11.41.0-alpha.0",
97
- "@gooddata/stylelint-config": "11.41.0-alpha.0"
94
+ "@gooddata/eslint-config": "11.41.0-alpha.2",
95
+ "@gooddata/oxlint-config": "11.41.0-alpha.2",
96
+ "@gooddata/sdk-backend-mockingbird": "11.41.0-alpha.2",
97
+ "@gooddata/stylelint-config": "11.41.0-alpha.2"
98
98
  },
99
99
  "peerDependencies": {
100
100
  "react": "^18.0.0 || ^19.0.0",