@carto/ps-react-ui 4.4.1 → 4.4.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.
Files changed (210) hide show
  1. package/dist/components.js.map +1 -1
  2. package/dist/error-CEkRPccv.js.map +1 -1
  3. package/dist/exports-Cr43OCul.js.map +1 -1
  4. package/dist/formatter-B1Xh8XDH.js +5 -0
  5. package/dist/formatter-B1Xh8XDH.js.map +1 -0
  6. package/dist/lasso-tool-BYbxrJ-7.js.map +1 -1
  7. package/dist/note-t51drNe0.js.map +1 -1
  8. package/dist/options-D9wflre6.js.map +1 -1
  9. package/dist/row-DTCV0Ocm.js.map +1 -1
  10. package/dist/series-CYNOu2Ju.js.map +1 -1
  11. package/dist/smart-tooltip-D4vwQpFf.js.map +1 -1
  12. package/dist/styles-C_8vOEep.js +167 -0
  13. package/dist/styles-C_8vOEep.js.map +1 -0
  14. package/dist/tooltip-BDnrRKrp.js.map +1 -1
  15. package/dist/types/components/basemaps/basemaps.d.ts +20 -0
  16. package/dist/types/components/geolocation-controls/geolocation-controls.d.ts +11 -0
  17. package/dist/types/components/lasso-tool/lasso-tool-inline.d.ts +17 -0
  18. package/dist/types/components/lasso-tool/lasso-tool.d.ts +21 -0
  19. package/dist/types/components/list-data/list-data.d.ts +16 -0
  20. package/dist/types/components/measurement-tools/measurement-tools.d.ts +20 -0
  21. package/dist/types/components/smart-tooltip/smart-tooltip.d.ts +17 -0
  22. package/dist/types/components/tooltip/tooltip.d.ts +13 -0
  23. package/dist/types/components/zoom-controls/zoom-controls.d.ts +16 -0
  24. package/dist/types/hooks/use-widget-ref.d.ts +4 -4
  25. package/dist/types/widgets/actions/download/download.d.ts +11 -0
  26. package/dist/types/widgets/actions/download/exports.d.ts +15 -0
  27. package/dist/types/widgets/actions/fullscreen/fullscreen.d.ts +13 -0
  28. package/dist/types/widgets/actions/index.d.ts +1 -1
  29. package/dist/types/widgets/actions/relative-data/relative-data.d.ts +1 -0
  30. package/dist/types/widgets/bar/config.d.ts +8 -4
  31. package/dist/types/widgets/category/category-ui.d.ts +3 -0
  32. package/dist/types/widgets/category/components/category-bar.d.ts +3 -0
  33. package/dist/types/widgets/category/components/category-legend.d.ts +3 -0
  34. package/dist/types/widgets/category/components/category-row-multi.d.ts +3 -0
  35. package/dist/types/widgets/category/components/category-row-other.d.ts +3 -0
  36. package/dist/types/widgets/category/components/category-row-single.d.ts +3 -0
  37. package/dist/types/widgets/category/config.d.ts +11 -0
  38. package/dist/types/widgets/echart/echart-ui.d.ts +7 -0
  39. package/dist/types/widgets/echart/echart.d.ts +6 -0
  40. package/dist/types/widgets/echart/options.d.ts +7 -0
  41. package/dist/types/widgets/echart/types.d.ts +1 -0
  42. package/dist/types/widgets/echart/utils.d.ts +41 -0
  43. package/dist/types/widgets/error/error.d.ts +10 -0
  44. package/dist/types/widgets/formula/components/item.d.ts +3 -0
  45. package/dist/types/widgets/formula/components/prefix.d.ts +3 -0
  46. package/dist/types/widgets/formula/components/row.d.ts +3 -0
  47. package/dist/types/widgets/formula/components/series.d.ts +3 -0
  48. package/dist/types/widgets/formula/components/suffix.d.ts +3 -0
  49. package/dist/types/widgets/formula/components/value.d.ts +3 -0
  50. package/dist/types/widgets/formula/config.d.ts +11 -0
  51. package/dist/types/widgets/formula/formula-ui.d.ts +3 -0
  52. package/dist/types/widgets/histogram/config.d.ts +8 -4
  53. package/dist/types/widgets/loader/loader.d.ts +22 -0
  54. package/dist/types/widgets/loader/utils.d.ts +26 -3
  55. package/dist/types/widgets/markdown/config.d.ts +10 -0
  56. package/dist/types/widgets/markdown/markdown-ui.d.ts +7 -0
  57. package/dist/types/widgets/markdown/markdown.d.ts +3 -0
  58. package/dist/types/widgets/note/note.d.ts +10 -0
  59. package/dist/types/widgets/pie/config.d.ts +8 -4
  60. package/dist/types/widgets/range/components/range-item.d.ts +3 -0
  61. package/dist/types/widgets/range/config.d.ts +5 -0
  62. package/dist/types/widgets/range/range-ui.d.ts +3 -0
  63. package/dist/types/widgets/scatterplot/config.d.ts +7 -3
  64. package/dist/types/widgets/selection-summary/selection-summary.d.ts +11 -0
  65. package/dist/types/widgets/skeleton-loader/skeleton-loader.d.ts +10 -0
  66. package/dist/types/widgets/spread/components/max-value.d.ts +3 -0
  67. package/dist/types/widgets/spread/components/min-value.d.ts +3 -0
  68. package/dist/types/widgets/spread/components/separator.d.ts +3 -0
  69. package/dist/types/widgets/spread/config.d.ts +11 -0
  70. package/dist/types/widgets/spread/spread-ui.d.ts +3 -0
  71. package/dist/types/widgets/subheader/subheader.d.ts +11 -0
  72. package/dist/types/widgets/table/config.d.ts +8 -3
  73. package/dist/types/widgets/table/hooks/use-pagination.d.ts +11 -3
  74. package/dist/types/widgets/table/hooks/use-selection.d.ts +11 -2
  75. package/dist/types/widgets/table/hooks/use-sort.d.ts +11 -3
  76. package/dist/types/widgets/timeseries/config.d.ts +8 -4
  77. package/dist/types/widgets/utils/chart-config/download-config.d.ts +3 -0
  78. package/dist/types/widgets/{_shared → utils}/chart-config/index.d.ts +2 -0
  79. package/dist/types/widgets/{_shared → utils}/chart-config/option-builders.d.ts +1 -1
  80. package/dist/types/widgets/utils/formatter.d.ts +1 -0
  81. package/dist/types/widgets/utils/index.d.ts +7 -0
  82. package/dist/types/widgets/wrapper/components/actions.d.ts +3 -0
  83. package/dist/types/widgets/wrapper/components/options.d.ts +3 -0
  84. package/dist/types/widgets/wrapper/components/title.d.ts +3 -0
  85. package/dist/types/widgets/wrapper/wrapper-ui.d.ts +14 -0
  86. package/dist/types/widgets/wrapper/wrapper.d.ts +14 -0
  87. package/dist/use-widget-ref-wtFLDFCD.js.map +1 -1
  88. package/dist/utils-BOhInag6.js.map +1 -1
  89. package/dist/widgets/actions.js +651 -628
  90. package/dist/widgets/actions.js.map +1 -1
  91. package/dist/widgets/bar.js +66 -86
  92. package/dist/widgets/bar.js.map +1 -1
  93. package/dist/widgets/category.js +21 -21
  94. package/dist/widgets/category.js.map +1 -1
  95. package/dist/widgets/echart.js.map +1 -1
  96. package/dist/widgets/formula.js +54 -54
  97. package/dist/widgets/formula.js.map +1 -1
  98. package/dist/widgets/histogram.js +45 -65
  99. package/dist/widgets/histogram.js.map +1 -1
  100. package/dist/widgets/loader.js.map +1 -1
  101. package/dist/widgets/markdown.js.map +1 -1
  102. package/dist/widgets/pie.js +122 -99
  103. package/dist/widgets/pie.js.map +1 -1
  104. package/dist/widgets/range.js +23 -22
  105. package/dist/widgets/range.js.map +1 -1
  106. package/dist/widgets/scatterplot.js +39 -59
  107. package/dist/widgets/scatterplot.js.map +1 -1
  108. package/dist/widgets/selection-summary.js.map +1 -1
  109. package/dist/widgets/skeleton-loader.js.map +1 -1
  110. package/dist/widgets/spread.js +40 -41
  111. package/dist/widgets/spread.js.map +1 -1
  112. package/dist/widgets/subheader.js.map +1 -1
  113. package/dist/widgets/table.js.map +1 -1
  114. package/dist/widgets/timeseries.js +39 -59
  115. package/dist/widgets/timeseries.js.map +1 -1
  116. package/dist/widgets/utils.js +31 -0
  117. package/dist/widgets/utils.js.map +1 -0
  118. package/dist/widgets/wrapper.js.map +1 -1
  119. package/package.json +5 -1
  120. package/src/components/basemaps/basemaps.tsx +20 -0
  121. package/src/components/geolocation-controls/geolocation-controls.tsx +11 -0
  122. package/src/components/lasso-tool/lasso-tool-inline.tsx +17 -0
  123. package/src/components/lasso-tool/lasso-tool.tsx +21 -0
  124. package/src/components/list-data/list-data.tsx +16 -0
  125. package/src/components/measurement-tools/measurement-tools.tsx +20 -0
  126. package/src/components/smart-tooltip/smart-tooltip.tsx +17 -0
  127. package/src/components/tooltip/tooltip.tsx +13 -0
  128. package/src/components/zoom-controls/zoom-controls.tsx +16 -0
  129. package/src/hooks/use-widget-ref.ts +4 -4
  130. package/src/widgets/README.md +10 -10
  131. package/src/widgets/actions/download/download.tsx +11 -0
  132. package/src/widgets/actions/download/exports.tsx +15 -0
  133. package/src/widgets/actions/fullscreen/fullscreen.tsx +13 -0
  134. package/src/widgets/actions/index.ts +1 -0
  135. package/src/widgets/actions/relative-data/relative-data.test.tsx +62 -1
  136. package/src/widgets/actions/relative-data/relative-data.tsx +62 -39
  137. package/src/widgets/bar/config.ts +12 -20
  138. package/src/widgets/bar/style.ts +1 -1
  139. package/src/widgets/category/category-ui.tsx +4 -2
  140. package/src/widgets/category/components/category-bar.tsx +3 -0
  141. package/src/widgets/category/components/category-legend.tsx +3 -0
  142. package/src/widgets/category/components/category-row-multi.tsx +3 -0
  143. package/src/widgets/category/components/category-row-other.tsx +3 -0
  144. package/src/widgets/category/components/category-row-single.tsx +3 -0
  145. package/src/widgets/category/config.ts +11 -0
  146. package/src/widgets/echart/echart-ui.tsx +7 -0
  147. package/src/widgets/echart/echart.tsx +6 -0
  148. package/src/widgets/echart/options.ts +7 -0
  149. package/src/widgets/echart/types.ts +1 -0
  150. package/src/widgets/echart/utils.ts +41 -0
  151. package/src/widgets/error/error.tsx +10 -0
  152. package/src/widgets/formula/components/item.tsx +3 -0
  153. package/src/widgets/formula/components/prefix.tsx +3 -0
  154. package/src/widgets/formula/components/row.tsx +3 -0
  155. package/src/widgets/formula/components/series.tsx +3 -0
  156. package/src/widgets/formula/components/suffix.tsx +3 -0
  157. package/src/widgets/formula/components/value.tsx +4 -2
  158. package/src/widgets/formula/config.ts +11 -0
  159. package/src/widgets/formula/formula-ui.tsx +3 -0
  160. package/src/widgets/histogram/config.ts +11 -20
  161. package/src/widgets/histogram/style.ts +1 -1
  162. package/src/widgets/loader/loader.tsx +22 -0
  163. package/src/widgets/loader/utils.ts +26 -3
  164. package/src/widgets/markdown/config.ts +10 -0
  165. package/src/widgets/markdown/markdown-ui.tsx +7 -0
  166. package/src/widgets/markdown/markdown.tsx +3 -0
  167. package/src/widgets/note/note.tsx +10 -0
  168. package/src/widgets/pie/config.ts +85 -30
  169. package/src/widgets/pie/style.ts +1 -1
  170. package/src/widgets/range/components/range-item.tsx +5 -2
  171. package/src/widgets/range/config.ts +5 -0
  172. package/src/widgets/range/range-ui.tsx +3 -0
  173. package/src/widgets/scatterplot/config.ts +11 -20
  174. package/src/widgets/scatterplot/style.ts +1 -1
  175. package/src/widgets/selection-summary/selection-summary.tsx +11 -0
  176. package/src/widgets/skeleton-loader/skeleton-loader.tsx +10 -0
  177. package/src/widgets/spread/components/max-value.tsx +4 -2
  178. package/src/widgets/spread/components/min-value.tsx +4 -2
  179. package/src/widgets/spread/components/separator.tsx +3 -0
  180. package/src/widgets/spread/config.ts +11 -0
  181. package/src/widgets/spread/spread-ui.tsx +3 -0
  182. package/src/widgets/subheader/subheader.tsx +11 -0
  183. package/src/widgets/table/config.ts +8 -3
  184. package/src/widgets/table/hooks/use-pagination.ts +11 -3
  185. package/src/widgets/table/hooks/use-selection.ts +11 -2
  186. package/src/widgets/table/hooks/use-sort.ts +11 -3
  187. package/src/widgets/timeseries/config.ts +11 -20
  188. package/src/widgets/timeseries/style.ts +1 -1
  189. package/src/widgets/utils/chart-config/download-config.ts +22 -0
  190. package/src/widgets/{_shared → utils}/chart-config/index.ts +4 -0
  191. package/src/widgets/{_shared → utils}/chart-config/option-builders.ts +1 -1
  192. package/src/widgets/utils/formatter.ts +1 -0
  193. package/src/widgets/utils/index.ts +26 -0
  194. package/src/widgets/wrapper/components/actions.tsx +3 -0
  195. package/src/widgets/wrapper/components/options.tsx +3 -0
  196. package/src/widgets/wrapper/components/title.tsx +3 -0
  197. package/src/widgets/wrapper/wrapper-ui.tsx +14 -0
  198. package/src/widgets/wrapper/wrapper.tsx +14 -0
  199. package/dist/styles-CAroD5Rc.js +0 -123
  200. package/dist/styles-CAroD5Rc.js.map +0 -1
  201. /package/dist/types/widgets/{_shared → utils}/chart-config/config-factory.d.ts +0 -0
  202. /package/dist/types/widgets/{_shared → utils}/chart-config/csv-modifiers.d.ts +0 -0
  203. /package/dist/types/widgets/{_shared → utils}/chart-config/option-builders.test.d.ts +0 -0
  204. /package/dist/types/widgets/{_shared → utils}/skeleton/index.d.ts +0 -0
  205. /package/dist/types/widgets/{_shared → utils}/skeleton/styles.d.ts +0 -0
  206. /package/src/widgets/{_shared → utils}/chart-config/config-factory.ts +0 -0
  207. /package/src/widgets/{_shared → utils}/chart-config/csv-modifiers.ts +0 -0
  208. /package/src/widgets/{_shared → utils}/chart-config/option-builders.test.ts +0 -0
  209. /package/src/widgets/{_shared → utils}/skeleton/index.ts +0 -0
  210. /package/src/widgets/{_shared → utils}/skeleton/styles.ts +0 -0
@@ -2,13 +2,14 @@ import { IconButton } from '@mui/material'
2
2
  import { PercentOutlined } from '@mui/icons-material'
3
3
  import { useCallback, useEffect, useRef } from 'react'
4
4
  import { useWidgetStore } from '../../stores/widget-store'
5
- import type { RelativeDataProps, RelativeDataState } from './types'
5
+ import type { RelativeDataProps } from './types'
6
6
  import { actionButtonStyles } from '../shared/styles'
7
7
  import { Tooltip } from '../../../components'
8
8
  import { calculateTotal, toRelativeData } from './utils'
9
9
  import type { EchartWidgetData } from '../../../widgets/echart'
10
10
 
11
11
  export const RELATIVE_DATA_TOOL_ID = 'relative-data'
12
+ export const RELATIVE_DATA_CONFIG_TOOL_ID = 'relative-data-config'
12
13
 
13
14
  /**
14
15
  * Widget action to toggle between relative (percentage) and absolute data display.
@@ -33,36 +34,30 @@ export function RelativeData({
33
34
  Icon,
34
35
  IconButtonProps,
35
36
  }: RelativeDataProps) {
36
- const previousMaxValue = useRef<number | undefined>(undefined)
37
- const originalFormatter = useRef<((value: number) => string) | undefined>(
37
+ const percentFormatterRef = useRef<((value: number) => string) | undefined>(
38
38
  undefined,
39
39
  )
40
- const setWidget = useWidgetStore((state) => state.setWidget)
41
40
  const getWidget = useWidgetStore((state) => state.getWidget)
42
41
  const registerTool = useWidgetStore((state) => state.registerTool)
43
42
  const unregisterTool = useWidgetStore((state) => state.unregisterTool)
44
43
  const setToolEnabled = useWidgetStore((state) => state.setToolEnabled)
44
+ const updateToolConfig = useWidgetStore((state) => state.updateToolConfig)
45
45
 
46
46
  const storeIsRelative = useWidgetStore(
47
- (state) => state.getWidget<RelativeDataState>(id)?.isRelative,
47
+ (state) =>
48
+ state.widgets[id]?.registeredTools?.find(
49
+ (t) => t.id === RELATIVE_DATA_CONFIG_TOOL_ID,
50
+ )?.config?.isRelative as boolean | undefined,
48
51
  )
49
52
 
50
53
  const isRelative = storeIsRelative ?? defaultIsRelative
51
54
 
52
- // Initialize store with default value on mount
53
- useEffect(() => {
54
- const currentValue = getWidget<RelativeDataState>(id)?.isRelative
55
- if (currentValue === undefined) {
56
- setWidget(id, { isRelative: defaultIsRelative })
57
- }
58
- }, [defaultIsRelative, getWidget, id, setWidget])
59
-
60
55
  // Register tool on mount
61
56
  useEffect(() => {
62
57
  registerTool(id, {
63
58
  id: RELATIVE_DATA_TOOL_ID,
64
59
  order,
65
- enabled: isRelative,
60
+ enabled: defaultIsRelative,
66
61
  fn: (data) => {
67
62
  const echartData = data as EchartWidgetData
68
63
  const total = calculateTotal(echartData)
@@ -71,42 +66,70 @@ export function RelativeData({
71
66
  })
72
67
 
73
68
  return () => unregisterTool(id, RELATIVE_DATA_TOOL_ID)
74
- }, [id, order, registerTool, unregisterTool, isRelative])
69
+ }, [id, order, registerTool, unregisterTool, defaultIsRelative])
70
+
71
+ // Register config tool for formatter management
72
+ useEffect(() => {
73
+ registerTool(id, {
74
+ id: RELATIVE_DATA_CONFIG_TOOL_ID,
75
+ type: 'config',
76
+ order,
77
+ enabled: true,
78
+ fn: (currentConfig, toolConfig) => {
79
+ const config = currentConfig as Record<string, unknown>
80
+ if (toolConfig?.isRelative) {
81
+ if (!percentFormatterRef.current) {
82
+ const locale = toolConfig?.locale as string | undefined
83
+ percentFormatterRef.current = (value: number) =>
84
+ new Intl.NumberFormat(locale, {
85
+ style: 'percent',
86
+ minimumFractionDigits: 1,
87
+ maximumFractionDigits: 1,
88
+ }).format(value / 100)
89
+ }
90
+ return { ...config, formatter: percentFormatterRef.current, max: 100 }
91
+ }
92
+ // Switching back from relative mode
93
+ percentFormatterRef.current = undefined
94
+ if (toolConfig && 'originalFormatter' in toolConfig) {
95
+ return {
96
+ ...config,
97
+ formatter: toolConfig.originalFormatter,
98
+ max: toolConfig.originalMax,
99
+ }
100
+ }
101
+ return config
102
+ },
103
+ config: {
104
+ isRelative: defaultIsRelative,
105
+ },
106
+ })
107
+ return () => unregisterTool(id, RELATIVE_DATA_CONFIG_TOOL_ID)
108
+ }, [id, order, registerTool, unregisterTool, defaultIsRelative])
75
109
 
76
110
  const handleToggle = useCallback(() => {
77
111
  const newIsRelative = !isRelative
78
112
  setToolEnabled(id, RELATIVE_DATA_TOOL_ID, newIsRelative)
79
- let max = previousMaxValue.current
80
113
 
81
114
  if (newIsRelative) {
82
- // Backup current formatter to ref
83
115
  const widget = getWidget(id) as {
84
116
  formatter?: (value: number) => string
85
117
  locale?: string
118
+ max?: number
86
119
  }
87
- originalFormatter.current = widget?.formatter
88
-
89
- // Save current max value before setting to 100
90
- const currentMax = (getWidget(id) as { max?: number })?.max
91
- previousMaxValue.current = currentMax
92
- max = 100
120
+ updateToolConfig(id, RELATIVE_DATA_CONFIG_TOOL_ID, {
121
+ isRelative: true,
122
+ originalFormatter: widget?.formatter,
123
+ originalMax: widget?.max,
124
+ locale: widget?.locale,
125
+ })
126
+ } else {
127
+ percentFormatterRef.current = undefined
128
+ updateToolConfig(id, RELATIVE_DATA_CONFIG_TOOL_ID, {
129
+ isRelative: false,
130
+ })
93
131
  }
94
-
95
- setWidget(id, {
96
- isRelative: newIsRelative,
97
- max,
98
- formatter: newIsRelative
99
- ? (value: number) => {
100
- const widget = getWidget(id) as { locale?: string }
101
- return new Intl.NumberFormat(widget?.locale, {
102
- style: 'percent',
103
- minimumFractionDigits: 1,
104
- maximumFractionDigits: 1,
105
- }).format(value / 100)
106
- }
107
- : originalFormatter.current,
108
- })
109
- }, [isRelative, setWidget, id, getWidget, setToolEnabled])
132
+ }, [isRelative, id, getWidget, setToolEnabled, updateToolConfig])
110
133
 
111
134
  const tooltipLabel = isRelative
112
135
  ? (labels?.absolute ?? 'Show absolute values')
@@ -10,33 +10,25 @@ import {
10
10
  buildGridConfig,
11
11
  createTooltipPositioner,
12
12
  createTooltipFormatter,
13
+ createChartDownloadConfig,
13
14
  niceNum,
14
- } from '../_shared/chart-config'
15
- import { downloadToCSV, downloadToPNG, type DownloadItem } from '../actions'
16
- import type { ConfigProps } from '../loader/types'
15
+ } from '../utils/chart-config'
17
16
 
18
- export function barDownloadConfig({
19
- refUI,
20
- }: ConfigProps): DownloadItem<BarWidgetData>[] {
21
- return [
22
- {
23
- ...downloadToPNG,
24
- modifier: () => downloadToPNG.modifier(refUI),
25
- },
26
- {
27
- ...downloadToCSV,
28
- modifier: async (data) => {
29
- const rows = flattenObjectArrayToCSV(data)
30
- return downloadToCSV.modifier(rows)
31
- },
32
- },
33
- ]
34
- }
17
+ export const barDownloadConfig = createChartDownloadConfig<BarWidgetData>(
18
+ flattenObjectArrayToCSV,
19
+ )
35
20
 
21
+ /**
22
+ * Generates ECharts configuration for bar chart widgets (vertical and horizontal), including axis, tooltip, legend, and series options styled with the CARTO theme.
23
+ *
24
+ * @param props - Bar chart configuration including data and theme.
25
+ * @returns Widget config with ECharts option object.
26
+ */
36
27
  export function barConfig(props: BarConfig): BarWidgetConfig {
37
28
  return {
38
29
  type: 'bar',
39
30
  option: mergeEchartWidgetConfig(getCommonOptions(props), getOption(props)),
31
+ formatter: props.formatter,
40
32
  }
41
33
  }
42
34
 
@@ -1,5 +1,5 @@
1
1
  import type { SxProps, Theme } from '@mui/material'
2
- import { baseSkeletonStyles } from '../_shared/skeleton'
2
+ import { baseSkeletonStyles } from '../utils/skeleton'
3
3
 
4
4
  export const styles = {
5
5
  skeleton: {
@@ -10,9 +10,11 @@ import {
10
10
  } from './components'
11
11
  import { useShallow } from 'zustand/shallow'
12
12
  import { useState } from 'react'
13
+ import { defaultFormatter } from '../utils/formatter'
13
14
 
14
- const defaultFormatter = (value: number) => value.toString()
15
-
15
+ /**
16
+ * Renders a category widget displaying horizontal bars for categorical data with support for single and multi-series layouts, selection, and overflow grouping.
17
+ */
16
18
  export function CategoryUI({ id }: CategoryUIProps) {
17
19
  const theme = useTheme()
18
20
  const _formatter = useWidgetStore(
@@ -8,6 +8,9 @@ export interface CategoryBarProps {
8
8
  selected?: boolean
9
9
  }
10
10
 
11
+ /**
12
+ * Renders a single horizontal bar fill proportional to its value relative to the maximum.
13
+ */
11
14
  export function CategoryBar({
12
15
  value,
13
16
  maxValue,
@@ -7,6 +7,9 @@ export interface CategoryLegendProps {
7
7
  colors: string[]
8
8
  }
9
9
 
10
+ /**
11
+ * Renders a color-coded legend for multi-series category widgets.
12
+ */
10
13
  export function CategoryLegend({ series, colors }: CategoryLegendProps) {
11
14
  if (series.length === 0) {
12
15
  return null
@@ -13,6 +13,9 @@ export interface CategoryRowMultiProps {
13
13
  selected?: boolean
14
14
  }
15
15
 
16
+ /**
17
+ * Renders a multi-series category row with a label and multiple color-coded bars stacked vertically.
18
+ */
16
19
  export function CategoryRowMulti({
17
20
  name,
18
21
  values,
@@ -7,6 +7,9 @@ export interface CategoryRowOtherProps {
7
7
  otherCountLabel?: string
8
8
  }
9
9
 
10
+ /**
11
+ * Renders an "Other" summary row indicating how many additional categories are hidden beyond `maxItems`.
12
+ */
10
13
  export function CategoryRowOther({
11
14
  hiddenCount,
12
15
  otherLabel = 'Other',
@@ -13,6 +13,9 @@ export interface CategoryRowSingleProps {
13
13
  selected?: boolean
14
14
  }
15
15
 
16
+ /**
17
+ * Renders a single-series category row with a label, formatted value, and proportional bar.
18
+ */
16
19
  export function CategoryRowSingle({
17
20
  name,
18
21
  value,
@@ -10,6 +10,12 @@ interface CategoryDownloadConfigProps extends ConfigProps {
10
10
  series?: CategorySeriesConfig[]
11
11
  }
12
12
 
13
+ /**
14
+ * Creates download configuration for category widgets, supporting PNG (screenshot) and CSV (data) exports. CSV output groups values by category across multiple series.
15
+ *
16
+ * @param props - Configuration with `refUI` reference and optional `series` for CSV column headers.
17
+ * @returns Array of download items for use with the Download action.
18
+ */
13
19
  export function categoryDownloadConfig({
14
20
  refUI,
15
21
  series,
@@ -66,6 +72,11 @@ export function categoryDownloadConfig({
66
72
  ]
67
73
  }
68
74
 
75
+ /**
76
+ * Returns the default configuration for category list widgets, including empty series and a default `maxItems` of 10.
77
+ *
78
+ * @returns Default category widget config.
79
+ */
69
80
  export function categoryConfig(): CategoryWidgetConfig {
70
81
  return {
71
82
  series: [],
@@ -3,6 +3,13 @@ import * as echarts from 'echarts'
3
3
  import type { EchartUIProps } from './types'
4
4
  import { useWidgetRef } from '../../hooks'
5
5
 
6
+ /**
7
+ * Presentational component that initializes and manages an Apache ECharts instance.
8
+ *
9
+ * @remarks
10
+ * Handles chart lifecycle (init, dispose), option updates, resize observation, and event listener management.
11
+ * Uses SVG renderer with a default height of 304px.
12
+ */
6
13
  export function EchartUI(props: EchartUIProps) {
7
14
  const { id, ref, init, option, className, style, onEvents } = props
8
15
 
@@ -9,6 +9,12 @@ import { useWidgetStore } from '../stores/widget-store'
9
9
  import { useShallow } from 'zustand/shallow'
10
10
  import { useMemo } from 'react'
11
11
 
12
+ /**
13
+ * Stateful EChart widget component that reads data and options from the widget store and renders an ECharts chart.
14
+ *
15
+ * @remarks
16
+ * Transforms widget data into ECharts dataset format and delegates rendering to {@link EchartUI}.
17
+ */
12
18
  export function Echart(props: EchartProps) {
13
19
  const id = useWidgetStore(
14
20
  useShallow((state) => state.getWidget<EchartWidgetState>(props.id)?.id),
@@ -1,5 +1,12 @@
1
1
  import type { EchartOptionsProps, EchartWidgetOptionProps } from './types'
2
2
 
3
+ /**
4
+ * Returns the shared base ECharts options used across all EChart-based widgets (bar, pie, histogram, etc.).
5
+ *
6
+ * @remarks
7
+ * Configures grid spacing, tooltip styling, legend, axis pointer, and the default color palette
8
+ * derived from the MUI theme.
9
+ */
3
10
  export function getCommonOptions({
4
11
  theme,
5
12
  }: EchartWidgetOptionProps<unknown>): EchartOptionsProps {
@@ -39,4 +39,5 @@ export interface EchartWidgetProps {
39
39
  type: string
40
40
  option: EchartUIProps['option']
41
41
  onEvents?: EchartUIProps['onEvents']
42
+ formatter?: (value: number) => string
42
43
  }
@@ -3,6 +3,27 @@ import type { EchartOptionsProps } from './types'
3
3
  import type { Theme } from '@mui/material'
4
4
  import { DEFAULT_STACK_GROUP } from './const'
5
5
 
6
+ /**
7
+ * Deep-merges two ECharts option objects with smart handling for `color`, `axisLabel`, and `series` keys.
8
+ *
9
+ * @param optionA - Base ECharts options.
10
+ * @param optionB - Override ECharts options to merge on top.
11
+ * @param customMergeFn - Optional function returning a custom merge strategy per key.
12
+ * @returns The merged ECharts options object.
13
+ *
14
+ * @remarks
15
+ * - `color` arrays are replaced entirely (not concatenated).
16
+ * - `axisLabel` formatters are composed so the base formatter can suppress values by returning `''`.
17
+ * - `series` arrays are merged element-by-element rather than concatenated.
18
+ *
19
+ * @example
20
+ * ```tsx
21
+ * const option = mergeEchartWidgetConfig(props.option, {
22
+ * series: [{ barWidth: '60%', itemStyle: { borderRadius: [4, 4, 0, 0] } }],
23
+ * tooltip: { trigger: 'axis' },
24
+ * })
25
+ * ```
26
+ */
6
27
  export function mergeEchartWidgetConfig<T extends EchartOptionsProps>(
7
28
  optionA: T | undefined,
8
29
  optionB: T | undefined,
@@ -53,6 +74,14 @@ export function mergeEchartWidgetConfig<T extends EchartOptionsProps>(
53
74
  }) as T
54
75
  }
55
76
 
77
+ /**
78
+ * Generates ECharts `dataZoom` configuration for interactive zoom and pan on chart axes.
79
+ *
80
+ * @param range - Initial visible range as `{ start, end }` percentages (0-100). Defaults to full range.
81
+ * @param options - Zoom behavior options including axis sliders, inside zoom, and formatter.
82
+ * @param theme - Optional MUI theme for styled slider handles and backgrounds.
83
+ * @returns An object containing the `dataZoom` array configuration.
84
+ */
56
85
  export function getEChartZoomConfig(
57
86
  { start, end }: { start: number; end: number } = { start: 0, end: 100 },
58
87
  {
@@ -179,6 +208,12 @@ function getEChartZoomSliderStyles(theme: Theme) {
179
208
  } as const
180
209
  }
181
210
 
211
+ /**
212
+ * Generates ECharts `brush` configuration for interactive data selection on charts.
213
+ *
214
+ * @param options - Brush options including type, mode, and target axis index.
215
+ * @returns An object containing the `brush` configuration.
216
+ */
182
217
  export function getEChartBrushConfig(
183
218
  { brushType = 'lineX', brushMode = 'single', xAxisIndex = 0 } = {} as {
184
219
  brushType?: string
@@ -198,6 +233,12 @@ export function getEChartBrushConfig(
198
233
  }
199
234
  }
200
235
 
236
+ /**
237
+ * Returns an ECharts `stack` configuration to group series into a stacked layout.
238
+ *
239
+ * @param stackGroup - The stack group identifier. Defaults to the library's default group.
240
+ * @returns An object with the `stack` property set to the group name.
241
+ */
201
242
  export function getEChartStackConfig(stackGroup: string = DEFAULT_STACK_GROUP) {
202
243
  return { stack: stackGroup }
203
244
  }
@@ -3,6 +3,16 @@ import { useWidgetStore } from '../stores/widget-store'
3
3
  import { useShallow } from 'zustand/shallow'
4
4
  import type { WidgetErrorProps } from './types'
5
5
 
6
+ /**
7
+ * Displays an error alert when a widget encounters an error during data loading. Reads error state from the widget store and hides errors during loading/fetching to prevent flashing.
8
+ *
9
+ * @example
10
+ * ```tsx
11
+ * <WidgetError id="my-widget">
12
+ * <WidgetContent />
13
+ * </WidgetError>
14
+ * ```
15
+ */
6
16
  export function WidgetError({
7
17
  id,
8
18
  children,
@@ -2,6 +2,9 @@ import { Typography } from '@mui/material'
2
2
  import type { ItemProps } from '../types'
3
3
  import { styles } from '../style'
4
4
 
5
+ /**
6
+ * Base typography wrapper used by formula sub-components (Value, Prefix, Suffix) to render styled text.
7
+ */
5
8
  export function Item(props: ItemProps) {
6
9
  return (
7
10
  <Typography
@@ -3,6 +3,9 @@ import { useWidgetStore } from '../../stores/widget-store'
3
3
  import { Item } from './item'
4
4
  import { useShallow } from 'zustand/shallow'
5
5
 
6
+ /**
7
+ * Renders the prefix content (e.g., currency symbol) before a formula value, if defined in the data item.
8
+ */
6
9
  export function Prefix({ id, index = 0, ...props }: ValueProps) {
7
10
  const prefix = useWidgetStore(
8
11
  useShallow(
@@ -4,6 +4,9 @@ import type { FormulaWidgetState, RowProps } from '../types'
4
4
  import { useWidgetStore } from '../../stores/widget-store'
5
5
  import { useShallow } from 'zustand/shallow'
6
6
 
7
+ /**
8
+ * Iterates over the widget's data items and renders a row for each one using render props.
9
+ */
7
10
  export function Row(props: RowProps) {
8
11
  const data = useWidgetStore(
9
12
  useShallow((state) => state.getWidget<FormulaWidgetState>(props.id)?.data),
@@ -3,6 +3,9 @@ import type { FormulaWidgetState, ValueProps } from '../types'
3
3
  import { useWidgetStore } from '../../stores/widget-store'
4
4
  import { useShallow } from 'zustand/shallow'
5
5
 
6
+ /**
7
+ * Renders a colored avatar badge showing the first letter of the series name for multi-value formula widgets.
8
+ */
6
9
  export function Series({ id, index = 0 }: Pick<ValueProps, 'id' | 'index'>) {
7
10
  const serie = useWidgetStore(
8
11
  useShallow(
@@ -4,6 +4,9 @@ import { Item } from './item'
4
4
  import type { Theme } from '@mui/material'
5
5
  import { useShallow } from 'zustand/shallow'
6
6
 
7
+ /**
8
+ * Renders the suffix content (e.g., unit label) after a formula value, if defined in the data item.
9
+ */
7
10
  export function Suffix({ id, index = 0, ...props }: ValueProps) {
8
11
  const suffix = useWidgetStore(
9
12
  useShallow(
@@ -2,9 +2,11 @@ import { type FormulaWidgetState, type ValueProps } from '../types'
2
2
  import { useWidgetStore } from '../../stores/widget-store'
3
3
  import { Item } from './item'
4
4
  import { useShallow } from 'zustand/shallow'
5
+ import { defaultFormatter } from '../../utils/formatter'
5
6
 
6
- const defaultFormatter = (value: number) => value.toString()
7
-
7
+ /**
8
+ * Displays the formatted numeric value for a formula widget data item, applying the widget's formatter and color.
9
+ */
8
10
  export function Value({ id, index = 0, ...props }: ValueProps) {
9
11
  const value = useWidgetStore(
10
12
  useShallow(
@@ -2,6 +2,12 @@ import { downloadToCSV, downloadToPNG } from '../actions'
2
2
  import type { ConfigProps } from '../loader/types'
3
3
  import type { FormulaDownloadConfig, FormulaWidgetConfig } from './types'
4
4
 
5
+ /**
6
+ * Creates download configuration for formula widgets, supporting PNG (screenshot) and CSV (data) exports.
7
+ *
8
+ * @param props - Configuration with `refUI` reference for PNG export.
9
+ * @returns Array of download items for use with the Download action.
10
+ */
5
11
  export function formulaDownloadConfig({
6
12
  refUI,
7
13
  }: ConfigProps): FormulaDownloadConfig {
@@ -20,6 +26,11 @@ export function formulaDownloadConfig({
20
26
  ]
21
27
  }
22
28
 
29
+ /**
30
+ * Returns the default configuration for formula (single or multiple numeric value) widgets.
31
+ *
32
+ * @returns Default formula widget config with empty series.
33
+ */
23
34
  export function formulaConfig(): FormulaWidgetConfig {
24
35
  return {
25
36
  series: [],
@@ -7,6 +7,9 @@ import { Series } from './components/series'
7
7
  import { useWidgetRef } from '../../hooks'
8
8
  import { Box } from '@mui/material'
9
9
 
10
+ /**
11
+ * Renders a formula widget displaying one or more KPI values with optional prefixes, suffixes, and series indicators.
12
+ */
10
13
  export function FormulaUI(props: FormulaUIProps) {
11
14
  const { ref } = useWidgetRef(props.id)
12
15
 
@@ -14,32 +14,23 @@ import {
14
14
  buildGridConfig,
15
15
  createTooltipPositioner,
16
16
  createTooltipFormatter,
17
+ createChartDownloadConfig,
17
18
  niceNum,
18
- } from '../_shared/chart-config'
19
- import { downloadToCSV, downloadToPNG, type DownloadItem } from '../actions'
20
- import type { ConfigProps } from '../loader/types'
19
+ } from '../utils/chart-config'
21
20
 
22
- export function histogramDownloadConfig({
23
- refUI,
24
- }: ConfigProps): DownloadItem<HistogramWidgetData>[] {
25
- return [
26
- {
27
- ...downloadToPNG,
28
- modifier: () => downloadToPNG.modifier(refUI),
29
- },
30
- {
31
- ...downloadToCSV,
32
- modifier: async (data) => {
33
- const rows = flattenObjectArrayToCSV(data)
34
- return downloadToCSV.modifier(rows)
35
- },
36
- },
37
- ]
38
- }
21
+ export const histogramDownloadConfig =
22
+ createChartDownloadConfig<HistogramWidgetData>(flattenObjectArrayToCSV)
23
+ /**
24
+ * Generates ECharts configuration for distribution histogram widgets with adjacent bars (minimal gap) and axis formatting styled with the CARTO theme.
25
+ *
26
+ * @param props - Histogram configuration including bin data and theme.
27
+ * @returns Widget config with ECharts option object.
28
+ */
39
29
  export function histogramConfig(props: HistogramConfig): HistogramWidgetConfig {
40
30
  return {
41
31
  type: 'histogram',
42
32
  option: mergeEchartWidgetConfig(getCommonOptions(props), getOption(props)),
33
+ formatter: props.formatter,
43
34
  }
44
35
  }
45
36
  function getOption({
@@ -1,5 +1,5 @@
1
1
  import type { SxProps, Theme } from '@mui/material'
2
- import { baseSkeletonStyles } from '../_shared/skeleton'
2
+ import { baseSkeletonStyles } from '../utils/skeleton'
3
3
 
4
4
  export const styles = {
5
5
  skeleton: {
@@ -3,6 +3,28 @@ import type { WidgetLoaderProps } from './types'
3
3
  import { useWidgetStore } from '../stores/widget-store'
4
4
  import type { WrapperState } from '../wrapper'
5
5
 
6
+ /**
7
+ * Foundation component for all widgets that manages state initialization, synchronization with the widget store, and data transformation pipeline execution.
8
+ *
9
+ * @remarks
10
+ * The WidgetLoader is stateless -- it manages data flow but does not render any UI. Always wrap it with WidgetWrapper for consistent widget appearance.
11
+ *
12
+ * @example
13
+ * ```tsx
14
+ * <WidgetLoader
15
+ * id="sales-chart"
16
+ * type="bar"
17
+ * data={data}
18
+ * isLoading={false}
19
+ * isFetching={false}
20
+ * config={barConfig({ data })}
21
+ * >
22
+ * <WidgetWrapper id="sales-chart" title="Sales">
23
+ * <Echart id="sales-chart" />
24
+ * </WidgetWrapper>
25
+ * </WidgetLoader>
26
+ * ```
27
+ */
6
28
  export function WidgetLoader<T extends object = Record<string, unknown>>(
7
29
  props: WidgetLoaderProps<T>,
8
30
  ) {