@carto/ps-react-ui 4.6.2 → 4.6.3

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,5 +1,10 @@
1
1
  import { describe, it, expect } from 'vitest'
2
- import { niceNum } from './option-builders'
2
+ import type { CallbackDataParams } from 'echarts/types/dist/shared'
3
+ import {
4
+ niceNum,
5
+ buildSeriesLabelConfig,
6
+ buildHistogramSeriesLabelConfig,
7
+ } from './option-builders'
3
8
 
4
9
  describe('niceNum', () => {
5
10
  it('should return 0 for 0', () => {
@@ -38,3 +43,102 @@ describe('niceNum', () => {
38
43
  expect(niceNum(1)).toBe(1)
39
44
  })
40
45
  })
46
+
47
+ describe('buildSeriesLabelConfig', () => {
48
+ it('should return empty object when no formatter provided', () => {
49
+ expect(buildSeriesLabelConfig()).toEqual({})
50
+ expect(buildSeriesLabelConfig(undefined)).toEqual({})
51
+ })
52
+
53
+ it('should return label config with formatter when formatter provided', () => {
54
+ const formatter = (v: number) => `$${v}`
55
+ const result = buildSeriesLabelConfig(formatter)
56
+ expect(result).toHaveProperty('label')
57
+ expect((result as { label: { formatter: unknown } }).label).toHaveProperty(
58
+ 'formatter',
59
+ )
60
+ })
61
+
62
+ it('should format value from dataset params using y encode key', () => {
63
+ const formatter = (v: number) => `$${v}`
64
+ const result = buildSeriesLabelConfig(formatter, 'y')
65
+ const label = (
66
+ result as {
67
+ label: { formatter: (p: Partial<CallbackDataParams>) => string }
68
+ }
69
+ ).label
70
+ const params = {
71
+ encode: { y: [1] },
72
+ dimensionNames: ['category', 'amount'],
73
+ value: { category: 'A', amount: 42 },
74
+ }
75
+ expect(label.formatter(params as unknown as CallbackDataParams)).toBe('$42')
76
+ })
77
+
78
+ it('should format value from dataset params using x encode key', () => {
79
+ const formatter = (v: number) => `${v}%`
80
+ const result = buildSeriesLabelConfig(formatter, 'x')
81
+ const label = (
82
+ result as {
83
+ label: { formatter: (p: Partial<CallbackDataParams>) => string }
84
+ }
85
+ ).label
86
+ const params = {
87
+ encode: { x: [1] },
88
+ dimensionNames: ['name', 'value'],
89
+ value: { name: 'Foo', value: 75 },
90
+ }
91
+ expect(label.formatter(params as unknown as CallbackDataParams)).toBe('75%')
92
+ })
93
+
94
+ it('should return empty string when encode index is undefined', () => {
95
+ const formatter = (v: number) => `$${v}`
96
+ const result = buildSeriesLabelConfig(formatter, 'y')
97
+ const label = (
98
+ result as {
99
+ label: { formatter: (p: Partial<CallbackDataParams>) => string }
100
+ }
101
+ ).label
102
+ const params = {
103
+ encode: {},
104
+ dimensionNames: ['category', 'amount'],
105
+ value: { category: 'A', amount: 42 },
106
+ }
107
+ expect(label.formatter(params as unknown as CallbackDataParams)).toBe('')
108
+ })
109
+ })
110
+
111
+ describe('buildHistogramSeriesLabelConfig', () => {
112
+ it('should return empty object when no formatter provided', () => {
113
+ expect(buildHistogramSeriesLabelConfig()).toEqual({})
114
+ expect(buildHistogramSeriesLabelConfig(undefined)).toEqual({})
115
+ })
116
+
117
+ it('should format raw numeric value', () => {
118
+ const formatter = (v: number) => `${v} units`
119
+ const result = buildHistogramSeriesLabelConfig(formatter)
120
+ const label = (
121
+ result as {
122
+ label: { formatter: (p: Partial<CallbackDataParams>) => string }
123
+ }
124
+ ).label
125
+ const params = { value: 100 }
126
+ expect(label.formatter(params as unknown as CallbackDataParams)).toBe(
127
+ '100 units',
128
+ )
129
+ })
130
+
131
+ it('should stringify non-numeric values', () => {
132
+ const formatter = (v: number) => `${v} units`
133
+ const result = buildHistogramSeriesLabelConfig(formatter)
134
+ const label = (
135
+ result as {
136
+ label: { formatter: (p: Partial<CallbackDataParams>) => string }
137
+ }
138
+ ).label
139
+ const params = { value: 'text' }
140
+ expect(label.formatter(params as unknown as CallbackDataParams)).toBe(
141
+ 'text',
142
+ )
143
+ })
144
+ })
@@ -225,3 +225,59 @@ export function createTooltipFormatter(
225
225
  return tooltip(name, formattedValues.join(''))
226
226
  }
227
227
  }
228
+
229
+ /**
230
+ * Builds a series `label` config that applies formatter to the data value
231
+ * extracted from a dataset row using ECharts encode/dimensionNames.
232
+ *
233
+ * Does not set `show` — labels remain hidden by default per ECharts defaults.
234
+ *
235
+ * @param formatter - Optional numeric value formatter
236
+ * @param encodeKey - The encode dimension key to extract ('y' for vertical charts, 'x' for horizontal)
237
+ */
238
+ export function buildSeriesLabelConfig(
239
+ formatter?: (value: number) => string,
240
+ encodeKey = 'y',
241
+ ): { label: { formatter: (params: CallbackDataParams) => string } } | object {
242
+ if (!formatter) return {}
243
+
244
+ return {
245
+ label: {
246
+ formatter: (params: CallbackDataParams) => {
247
+ const encodeIndex = params.encode?.[encodeKey]?.[0]
248
+ if (encodeIndex === undefined) return ''
249
+ const dimName = params.dimensionNames?.[encodeIndex]
250
+ const row = params.value as Record<string, string | number>
251
+ const value = dimName ? row[dimName] : undefined
252
+ return typeof value === 'number'
253
+ ? formatter(value)
254
+ : String(value ?? '')
255
+ },
256
+ },
257
+ }
258
+ }
259
+
260
+ /**
261
+ * Builds a series `label` config that applies formatter to a raw numeric value.
262
+ * Used by histogram where series data is number[] (not datasets).
263
+ *
264
+ * Does not set `show` — labels remain hidden by default per ECharts defaults.
265
+ *
266
+ * @param formatter - Optional numeric value formatter
267
+ */
268
+ export function buildHistogramSeriesLabelConfig(
269
+ formatter?: (value: number) => string,
270
+ ): { label: { formatter: (params: CallbackDataParams) => string } } | object {
271
+ if (!formatter) return {}
272
+
273
+ return {
274
+ label: {
275
+ formatter: (params: CallbackDataParams) => {
276
+ const value = params.value as number
277
+ return typeof value === 'number'
278
+ ? formatter(value)
279
+ : String(value ?? '')
280
+ },
281
+ },
282
+ }
283
+ }
@@ -1,49 +0,0 @@
1
- function t({
2
- theme: o
3
- }) {
4
- return {
5
- grid: {
6
- left: parseInt(o.spacing(1)),
7
- top: parseInt(o.spacing(3)),
8
- right: parseInt(o.spacing(1)),
9
- bottom: parseInt(o.spacing(4)),
10
- containLabel: !0
11
- },
12
- toolbox: {
13
- show: !1
14
- },
15
- tooltip: {
16
- axisPointer: {
17
- type: "shadow",
18
- shadowStyle: {
19
- color: "rgba(44,48,50, 0.08)"
20
- }
21
- },
22
- backgroundColor: o.palette.grey[900],
23
- borderWidth: 0,
24
- padding: [parseInt(o.spacing(1)), parseInt(o.spacing(1))],
25
- textStyle: {
26
- color: o.palette.common.white,
27
- fontSize: 11,
28
- fontFamily: o.typography.caption.fontFamily
29
- },
30
- trigger: "axis"
31
- },
32
- legend: {
33
- type: "scroll",
34
- bottom: 0
35
- },
36
- axisPointer: {
37
- lineStyle: {
38
- color: o.palette.grey[400]
39
- }
40
- },
41
- xAxis: {},
42
- yAxis: {},
43
- color: [o.palette.secondary.main, ...Object.values(o.palette.qualitative?.bold ?? {})]
44
- };
45
- }
46
- export {
47
- t as g
48
- };
49
- //# sourceMappingURL=options-D9wflre6.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"options-D9wflre6.js","sources":["../src/widgets/echart/options.ts"],"sourcesContent":["import type { EchartOptionsProps, EchartWidgetOptionProps } from './types'\n\n/**\n * Returns the shared base ECharts options used across all EChart-based widgets (bar, pie, histogram, etc.).\n *\n * @remarks\n * Configures grid spacing, tooltip styling, legend, axis pointer, and the default color palette\n * derived from the MUI theme.\n */\nexport function getCommonOptions({\n theme,\n}: EchartWidgetOptionProps<unknown>): EchartOptionsProps {\n return {\n grid: {\n left: parseInt(theme.spacing(1)),\n top: parseInt(theme.spacing(3)),\n right: parseInt(theme.spacing(1)),\n bottom: parseInt(theme.spacing(4)),\n containLabel: true,\n },\n toolbox: {\n show: false,\n },\n tooltip: {\n axisPointer: {\n type: 'shadow',\n shadowStyle: {\n color: 'rgba(44,48,50, 0.08)',\n },\n },\n backgroundColor: theme.palette.grey[900],\n borderWidth: 0,\n padding: [parseInt(theme.spacing(1)), parseInt(theme.spacing(1))],\n textStyle: {\n color: theme.palette.common.white,\n fontSize: 11,\n fontFamily: theme.typography.caption.fontFamily,\n },\n trigger: 'axis',\n },\n legend: {\n type: 'scroll',\n bottom: 0,\n },\n axisPointer: {\n lineStyle: {\n color: theme.palette.grey[400],\n },\n },\n xAxis: {},\n yAxis: {},\n color: [\n theme.palette.secondary.main,\n ...Object.values(\n (theme.palette as { qualitative?: { bold?: Record<string, string> } })\n .qualitative?.bold ?? {},\n ),\n ],\n }\n}\n"],"names":["getCommonOptions","theme","grid","left","parseInt","spacing","top","right","bottom","containLabel","toolbox","show","tooltip","axisPointer","type","shadowStyle","color","backgroundColor","palette","grey","borderWidth","padding","textStyle","common","white","fontSize","fontFamily","typography","caption","trigger","legend","lineStyle","xAxis","yAxis","secondary","main","Object","values","qualitative","bold"],"mappings":"AASO,SAASA,EAAiB;AAAA,EAC/BC,OAAAA;AACgC,GAAuB;AACvD,SAAO;AAAA,IACLC,MAAM;AAAA,MACJC,MAAMC,SAASH,EAAMI,QAAQ,CAAC,CAAC;AAAA,MAC/BC,KAAKF,SAASH,EAAMI,QAAQ,CAAC,CAAC;AAAA,MAC9BE,OAAOH,SAASH,EAAMI,QAAQ,CAAC,CAAC;AAAA,MAChCG,QAAQJ,SAASH,EAAMI,QAAQ,CAAC,CAAC;AAAA,MACjCI,cAAc;AAAA,IAAA;AAAA,IAEhBC,SAAS;AAAA,MACPC,MAAM;AAAA,IAAA;AAAA,IAERC,SAAS;AAAA,MACPC,aAAa;AAAA,QACXC,MAAM;AAAA,QACNC,aAAa;AAAA,UACXC,OAAO;AAAA,QAAA;AAAA,MACT;AAAA,MAEFC,iBAAiBhB,EAAMiB,QAAQC,KAAK,GAAG;AAAA,MACvCC,aAAa;AAAA,MACbC,SAAS,CAACjB,SAASH,EAAMI,QAAQ,CAAC,CAAC,GAAGD,SAASH,EAAMI,QAAQ,CAAC,CAAC,CAAC;AAAA,MAChEiB,WAAW;AAAA,QACTN,OAAOf,EAAMiB,QAAQK,OAAOC;AAAAA,QAC5BC,UAAU;AAAA,QACVC,YAAYzB,EAAM0B,WAAWC,QAAQF;AAAAA,MAAAA;AAAAA,MAEvCG,SAAS;AAAA,IAAA;AAAA,IAEXC,QAAQ;AAAA,MACNhB,MAAM;AAAA,MACNN,QAAQ;AAAA,IAAA;AAAA,IAEVK,aAAa;AAAA,MACXkB,WAAW;AAAA,QACTf,OAAOf,EAAMiB,QAAQC,KAAK,GAAG;AAAA,MAAA;AAAA,IAC/B;AAAA,IAEFa,OAAO,CAAA;AAAA,IACPC,OAAO,CAAA;AAAA,IACPjB,OAAO,CACLf,EAAMiB,QAAQgB,UAAUC,MACxB,GAAGC,OAAOC,OACPpC,EAAMiB,QACJoB,aAAaC,QAAQ,CAAA,CAC1B,CAAC;AAAA,EAAA;AAGP;"}
@@ -1,118 +0,0 @@
1
- function u(t) {
2
- if (t === 0) return 0;
3
- const e = Math.abs(t), n = Math.pow(10, Math.floor(Math.log10(e))), i = Math.ceil(e / n) * n;
4
- return t < 0 ? -i : i;
5
- }
6
- function d({
7
- hasLegend: t,
8
- labelFormatter: e
9
- }) {
10
- return {
11
- show: t,
12
- icon: "circle",
13
- left: 0,
14
- bottom: 0,
15
- orient: "horizontal",
16
- type: "scroll",
17
- ...e && {
18
- formatter: (n) => String(e(n))
19
- }
20
- };
21
- }
22
- function x(t, e) {
23
- return {
24
- ...!t && {
25
- bottom: parseInt(e.spacing(3))
26
- },
27
- ...t && {
28
- bottom: parseInt(e.spacing(7))
29
- }
30
- };
31
- }
32
- function y(t) {
33
- return function(e, n, i, o, a) {
34
- const l = {
35
- top: parseInt(t.spacing(0.5))
36
- };
37
- return a.contentSize[0] < a.viewSize[0] - e[0] ? l.left = e[0] : l.right = a.viewSize[0] - e[0], l;
38
- };
39
- }
40
- function m(t) {
41
- if (t)
42
- return (e) => t(e);
43
- }
44
- function b(t, e) {
45
- const n = t && !Array.isArray(t), i = t, o = e && n ? (a) => String(e(a)) : void 0;
46
- return {
47
- ...i,
48
- axisLabel: {
49
- ...typeof i.axisLabel == "object" && i.axisLabel ? i.axisLabel : {},
50
- formatter: o
51
- }
52
- };
53
- }
54
- function F(t, e) {
55
- let n = m(e);
56
- const i = t && !Array.isArray(t), o = t;
57
- return (!i || o.type !== "value") && (n = void 0), {
58
- ...o,
59
- axisLabel: {
60
- ...typeof o.axisLabel == "object" && o.axisLabel ? o.axisLabel : {},
61
- formatter: n
62
- }
63
- };
64
- }
65
- function v(t) {
66
- return (e) => {
67
- const n = Array.isArray(e) ? e : [e], i = (r, s) => `<div style="margin: 0px 0 0;line-height:1;">${r ? `<div style="font-size:11px;color:#FFFFFF;font-weight:400;line-height:1; margin-bottom: 10px">${r}</div>` : ""}<div style="margin: 0;line-height:1;">${s}</div><div style="clear:both"></div></div>`, o = n.map((r) => {
68
- const {
69
- name: s,
70
- seriesName: c,
71
- marker: f,
72
- value: h
73
- } = t(r, n);
74
- return {
75
- name: s,
76
- seriesName: c,
77
- marker: f,
78
- value: h
79
- };
80
- }), a = o[0]?.name ?? "", p = a || n.length > 1 ? "margin: 10px 0 0;line-height:1;" : "margin: 0;line-height:1;", g = o.map(({
81
- seriesName: r,
82
- marker: s,
83
- value: c
84
- }) => `<div style="${p}"><div style="margin: 0px 0 0;line-height:1;">${s}${r ? `<span style="font-size:11px;color:#FFFFFF;font-weight:400;margin-left:2px;margin-right:10px">${r}</span>` : ""}<span style="float:right;margin-left:10px;font-size:11px;color:#FFFFFF;font-weight:900">${c}</span></div></div>`);
85
- return i(a, g.join(""));
86
- };
87
- }
88
- const w = {
89
- graph: {
90
- /**
91
- * Common container style for chart widget skeletons
92
- */
93
- container: {
94
- display: "flex",
95
- alignItems: "center",
96
- justifyContent: "space-between",
97
- flexDirection: "column",
98
- gap: ({
99
- spacing: t
100
- }) => t(1),
101
- height: ({
102
- spacing: t
103
- }) => t(38)
104
- }
105
- }
106
- };
107
- export {
108
- b as a,
109
- F as b,
110
- w as c,
111
- x as d,
112
- d as e,
113
- m as f,
114
- v as g,
115
- y as h,
116
- u as n
117
- };
118
- //# sourceMappingURL=styles-Y8q7Jff3.js.map