@carto/ps-react-ui 4.4.2 → 4.5.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.
- package/dist/download-config-DemuQ3Jm.js +56 -0
- package/dist/download-config-DemuQ3Jm.js.map +1 -0
- package/dist/error-Cj8eUMrl.js +40 -0
- package/dist/error-Cj8eUMrl.js.map +1 -0
- package/dist/formatter-B9Bxn1k7.js +6 -0
- package/dist/formatter-B9Bxn1k7.js.map +1 -0
- package/dist/no-data-DkIt7Qt1.js +61 -0
- package/dist/no-data-DkIt7Qt1.js.map +1 -0
- package/dist/row-D4VOhcNI.js +34 -0
- package/dist/row-D4VOhcNI.js.map +1 -0
- package/dist/series-Bola3CmD.js +90 -0
- package/dist/series-Bola3CmD.js.map +1 -0
- package/dist/styles-Y8q7Jff3.js +118 -0
- package/dist/styles-Y8q7Jff3.js.map +1 -0
- package/dist/types/widgets/actions/brush-toggle/types.d.ts +8 -2
- package/dist/types/widgets/category/components/category-row-multi.d.ts +2 -1
- package/dist/types/widgets/category/components/category-row-single.d.ts +2 -1
- package/dist/types/widgets/category/types.d.ts +1 -0
- package/dist/types/widgets/echart/shared-resize-observer.d.ts +12 -0
- package/dist/types/widgets/echart/types.d.ts +2 -0
- package/dist/types/widgets/histogram/config.d.ts +15 -3
- package/dist/types/widgets/histogram/index.d.ts +2 -1
- package/dist/types/widgets/histogram/types.d.ts +6 -3
- package/dist/types/widgets/stores/index.d.ts +2 -1
- package/dist/types/widgets/stores/types.d.ts +2 -0
- package/dist/types/widgets/stores/use-widget-selector.d.ts +35 -0
- package/dist/types/widgets/stores/widget-store-performance.test.d.ts +1 -0
- package/dist/types/widgets/stores/widget-store.d.ts +49 -27
- package/dist/types/widgets/table/types.d.ts +1 -1
- package/dist/types/widgets/utils/chart-config/index.d.ts +1 -1
- package/dist/types/widgets/utils/chart-config/option-builders.d.ts +13 -8
- package/dist/types/widgets/utils/formatter.d.ts +1 -0
- package/dist/types/widgets/utils/index.d.ts +1 -1
- package/dist/use-widget-ref-BFazQvJK.js +22 -0
- package/dist/use-widget-ref-BFazQvJK.js.map +1 -0
- package/dist/use-widget-selector-DqRmWQ1K.js +12 -0
- package/dist/use-widget-selector-DqRmWQ1K.js.map +1 -0
- package/dist/widget-store-CIrb9RKP.js +263 -0
- package/dist/widget-store-CIrb9RKP.js.map +1 -0
- package/dist/widgets/actions.js +799 -817
- package/dist/widgets/actions.js.map +1 -1
- package/dist/widgets/bar.js +53 -47
- package/dist/widgets/bar.js.map +1 -1
- package/dist/widgets/category.js +261 -255
- package/dist/widgets/category.js.map +1 -1
- package/dist/widgets/echart.js +109 -99
- package/dist/widgets/echart.js.map +1 -1
- package/dist/widgets/error.js +1 -1
- package/dist/widgets/formula.js +71 -63
- package/dist/widgets/formula.js.map +1 -1
- package/dist/widgets/histogram.js +119 -80
- package/dist/widgets/histogram.js.map +1 -1
- package/dist/widgets/loader.js +53 -60
- package/dist/widgets/loader.js.map +1 -1
- package/dist/widgets/markdown.js +51 -50
- package/dist/widgets/markdown.js.map +1 -1
- package/dist/widgets/no-data.js +1 -1
- package/dist/widgets/pie.js +111 -99
- package/dist/widgets/pie.js.map +1 -1
- package/dist/widgets/range.js +146 -144
- package/dist/widgets/range.js.map +1 -1
- package/dist/widgets/scatterplot.js +50 -44
- package/dist/widgets/scatterplot.js.map +1 -1
- package/dist/widgets/skeleton-loader.js +18 -17
- package/dist/widgets/skeleton-loader.js.map +1 -1
- package/dist/widgets/spread.js +110 -94
- package/dist/widgets/spread.js.map +1 -1
- package/dist/widgets/stores.js +5 -2
- package/dist/widgets/stores.js.map +1 -1
- package/dist/widgets/table.js +422 -436
- package/dist/widgets/table.js.map +1 -1
- package/dist/widgets/timeseries.js +52 -46
- package/dist/widgets/timeseries.js.map +1 -1
- package/dist/widgets/toolbar-actions.js +101 -6693
- package/dist/widgets/toolbar-actions.js.map +1 -1
- package/dist/widgets/utils.js +16 -14
- package/dist/widgets/utils.js.map +1 -1
- package/dist/widgets/wrapper.js +156 -158
- package/dist/widgets/wrapper.js.map +1 -1
- package/dist/widgets.js +4 -4
- package/package.json +5 -4
- package/src/hooks/use-widget-ref.ts +3 -4
- package/src/widgets/README.md +3 -3
- package/src/widgets/actions/brush-toggle/brush-toggle.tsx +60 -79
- package/src/widgets/actions/brush-toggle/types.ts +8 -2
- package/src/widgets/actions/change-column/change-column.tsx +15 -15
- package/src/widgets/actions/change-column/sortable-column-item.tsx +3 -1
- package/src/widgets/actions/download/download.tsx +4 -3
- package/src/widgets/actions/fullscreen/fullscreen.tsx +7 -11
- package/src/widgets/actions/lock-selection/lock-selection.tsx +12 -15
- package/src/widgets/actions/relative-data/relative-data.tsx +22 -26
- package/src/widgets/actions/searcher/searcher-toggle.tsx +11 -12
- package/src/widgets/actions/searcher/searcher.tsx +20 -21
- package/src/widgets/actions/stack-toggle/stack-toggle.tsx +15 -21
- package/src/widgets/actions/zoom-toggle/zoom-toggle.tsx +27 -43
- package/src/widgets/bar/config.ts +22 -14
- package/src/widgets/category/category-ui.tsx +31 -27
- package/src/widgets/category/components/category-row-multi.tsx +6 -2
- package/src/widgets/category/components/category-row-single.tsx +5 -1
- package/src/widgets/category/types.ts +1 -0
- package/src/widgets/echart/echart-ui.test.tsx +20 -16
- package/src/widgets/echart/echart-ui.tsx +6 -12
- package/src/widgets/echart/echart.tsx +13 -27
- package/src/widgets/echart/shared-resize-observer.ts +45 -0
- package/src/widgets/echart/types.ts +2 -0
- package/src/widgets/error/error.tsx +7 -9
- package/src/widgets/formula/components/prefix.tsx +4 -6
- package/src/widgets/formula/components/row.tsx +4 -4
- package/src/widgets/formula/components/series.tsx +4 -6
- package/src/widgets/formula/components/suffix.tsx +4 -6
- package/src/widgets/formula/components/value.tsx +9 -16
- package/src/widgets/histogram/config.ts +101 -20
- package/src/widgets/histogram/index.ts +6 -1
- package/src/widgets/histogram/types.ts +9 -3
- package/src/widgets/loader/loader.tsx +31 -44
- package/src/widgets/markdown/markdown.tsx +4 -7
- package/src/widgets/no-data/no-data.tsx +7 -10
- package/src/widgets/pie/config.ts +17 -5
- package/src/widgets/range/components/range-item.tsx +20 -18
- package/src/widgets/scatterplot/config.ts +8 -3
- package/src/widgets/skeleton-loader/skeleton-loader.tsx +2 -5
- package/src/widgets/spread/components/max-value.tsx +14 -16
- package/src/widgets/spread/components/min-value.tsx +14 -16
- package/src/widgets/stores/index.ts +2 -1
- package/src/widgets/stores/types.ts +2 -0
- package/src/widgets/stores/use-widget-selector.ts +47 -0
- package/src/widgets/stores/widget-store-performance.test.ts +750 -0
- package/src/widgets/stores/widget-store.test.ts +81 -0
- package/src/widgets/stores/widget-store.ts +225 -44
- package/src/widgets/table/config.ts +0 -1
- package/src/widgets/table/hooks/use-pagination.ts +28 -52
- package/src/widgets/table/hooks/use-selection.ts +20 -24
- package/src/widgets/table/hooks/use-sort.ts +22 -39
- package/src/widgets/table/types.ts +1 -1
- package/src/widgets/timeseries/config.ts +21 -13
- package/src/widgets/utils/chart-config/index.ts +1 -1
- package/src/widgets/utils/chart-config/option-builders.ts +22 -12
- package/src/widgets/utils/formatter.ts +2 -1
- package/src/widgets/utils/index.ts +1 -1
- package/src/widgets/wrapper/wrapper-ui.tsx +12 -13
- package/src/widgets/wrapper/wrapper.tsx +4 -6
- package/dist/error-CEkRPccv.js +0 -39
- package/dist/error-CEkRPccv.js.map +0 -1
- package/dist/formatter-B1Xh8XDH.js +0 -5
- package/dist/formatter-B1Xh8XDH.js.map +0 -1
- package/dist/no-data-hR3KcJ-_.js +0 -60
- package/dist/no-data-hR3KcJ-_.js.map +0 -1
- package/dist/row-DTCV0Ocm.js +0 -35
- package/dist/row-DTCV0Ocm.js.map +0 -1
- package/dist/series-CYNOu2Ju.js +0 -91
- package/dist/series-CYNOu2Ju.js.map +0 -1
- package/dist/styles-C_8vOEep.js +0 -167
- package/dist/styles-C_8vOEep.js.map +0 -1
- package/dist/use-widget-ref-wtFLDFCD.js +0 -25
- package/dist/use-widget-ref-wtFLDFCD.js.map +0 -1
- package/dist/widget-store-CzDt8oSK.js +0 -163
- package/dist/widget-store-CzDt8oSK.js.map +0 -1
|
@@ -29,6 +29,7 @@ export function pieConfig(props: PieConfig): PieWidgetConfig {
|
|
|
29
29
|
type: 'pie',
|
|
30
30
|
option: mergeEchartWidgetConfig(getCommonOptions(props), getOption(props)),
|
|
31
31
|
formatter: props.formatter,
|
|
32
|
+
labelFormatter: props.labelFormatter,
|
|
32
33
|
}
|
|
33
34
|
}
|
|
34
35
|
|
|
@@ -36,6 +37,7 @@ function getOption({
|
|
|
36
37
|
data = [],
|
|
37
38
|
theme,
|
|
38
39
|
formatter,
|
|
40
|
+
labelFormatter,
|
|
39
41
|
}: PieConfig): EchartOptionsProps {
|
|
40
42
|
const multiSeries = (data?.length ?? 0) > 1
|
|
41
43
|
|
|
@@ -44,7 +46,7 @@ function getOption({
|
|
|
44
46
|
let niceMax = 1
|
|
45
47
|
|
|
46
48
|
return {
|
|
47
|
-
legend: buildLegendConfig(true),
|
|
49
|
+
legend: buildLegendConfig({ hasLegend: true, labelFormatter }),
|
|
48
50
|
grid: {
|
|
49
51
|
...buildGridConfig(true, theme),
|
|
50
52
|
right: parseInt(theme.spacing(4)),
|
|
@@ -97,6 +99,10 @@ function getOption({
|
|
|
97
99
|
},
|
|
98
100
|
axisLabel: {
|
|
99
101
|
padding: [parseInt(theme.spacing(0.5)), 0, 0, 0],
|
|
102
|
+
...(labelFormatter && {
|
|
103
|
+
formatter: (value: string | number) =>
|
|
104
|
+
String(labelFormatter(value)),
|
|
105
|
+
}),
|
|
100
106
|
},
|
|
101
107
|
},
|
|
102
108
|
tooltip: {
|
|
@@ -113,7 +119,9 @@ function getOption({
|
|
|
113
119
|
|
|
114
120
|
const marker = typeof item.marker === 'string' ? item.marker : ''
|
|
115
121
|
const seriesName = item.seriesName ? `${item.seriesName}: ` : ''
|
|
116
|
-
const name =
|
|
122
|
+
const name = labelFormatter
|
|
123
|
+
? String(labelFormatter(item.name ?? ''))
|
|
124
|
+
: (item.name ?? '')
|
|
117
125
|
|
|
118
126
|
return { name, seriesName, marker, value: formattedValue }
|
|
119
127
|
}),
|
|
@@ -132,7 +140,7 @@ function getOption({
|
|
|
132
140
|
const hasLegend = true
|
|
133
141
|
|
|
134
142
|
return {
|
|
135
|
-
legend: buildLegendConfig(hasLegend),
|
|
143
|
+
legend: buildLegendConfig({ hasLegend, labelFormatter }),
|
|
136
144
|
grid: {
|
|
137
145
|
...buildGridConfig(hasLegend, theme),
|
|
138
146
|
left: 0,
|
|
@@ -164,7 +172,9 @@ function getOption({
|
|
|
164
172
|
|
|
165
173
|
const marker = typeof item.marker === 'string' ? item.marker : ''
|
|
166
174
|
const seriesName = item.seriesName ? `${item.seriesName}: ` : ''
|
|
167
|
-
const name =
|
|
175
|
+
const name = labelFormatter
|
|
176
|
+
? String(labelFormatter(item.name ?? ''))
|
|
177
|
+
: (item.name ?? '')
|
|
168
178
|
|
|
169
179
|
return {
|
|
170
180
|
name: seriesName,
|
|
@@ -203,7 +213,9 @@ function getOption({
|
|
|
203
213
|
? formatter(value)
|
|
204
214
|
: (value ?? '')
|
|
205
215
|
|
|
206
|
-
const nameFormatted =
|
|
216
|
+
const nameFormatted = labelFormatter
|
|
217
|
+
? String(labelFormatter(name ?? ''))
|
|
218
|
+
: (name ?? '')
|
|
207
219
|
|
|
208
220
|
return `{c|${formattedValue}}\n\n{b|${nameFormatted}}`
|
|
209
221
|
},
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { Box, Slider, TextField } from '@mui/material'
|
|
2
2
|
import { useState, useMemo, type FocusEvent, type KeyboardEvent } from 'react'
|
|
3
|
-
import {
|
|
3
|
+
import { widgetStoreActions } from '../../stores/widget-store'
|
|
4
|
+
import { useWidgetSelector } from '../../stores/use-widget-selector'
|
|
4
5
|
import type { RangeItemProps, RangeWidgetState } from '../types'
|
|
5
6
|
import { styles } from '../style'
|
|
6
|
-
import { useShallow } from 'zustand/shallow'
|
|
7
7
|
|
|
8
8
|
import { defaultFormatter } from '../../utils/formatter'
|
|
9
9
|
|
|
@@ -13,18 +13,19 @@ type EditingState = '' | 'min' | 'max'
|
|
|
13
13
|
* Renders a single range slider with editable min/max text inputs, reading its configuration from the widget store.
|
|
14
14
|
*/
|
|
15
15
|
export function RangeItem({ id, index }: RangeItemProps) {
|
|
16
|
-
const
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
16
|
+
const {
|
|
17
|
+
item,
|
|
18
|
+
onChange,
|
|
19
|
+
formatter: _formatter,
|
|
20
|
+
} = useWidgetSelector(id, (w) => {
|
|
21
|
+
const rw = w as RangeWidgetState | undefined
|
|
22
|
+
return {
|
|
23
|
+
item: rw?.data[index],
|
|
24
|
+
onChange: rw?.onChange,
|
|
25
|
+
formatter: rw?.formatter,
|
|
26
|
+
}
|
|
27
|
+
})
|
|
28
|
+
const formatter = _formatter ?? defaultFormatter
|
|
28
29
|
|
|
29
30
|
const currentValue = useMemo(
|
|
30
31
|
() => (item ? (item.value ?? [item.min, item.max]) : [0, 0]),
|
|
@@ -39,14 +40,15 @@ export function RangeItem({ id, index }: RangeItemProps) {
|
|
|
39
40
|
const handleSliderChange = (_: Event, newValue: number | number[]) => {
|
|
40
41
|
if (Array.isArray(newValue)) {
|
|
41
42
|
const [min, max] = newValue
|
|
42
|
-
const data =
|
|
43
|
+
const data =
|
|
44
|
+
widgetStoreActions.getWidget<RangeWidgetState>(id)?.data ?? []
|
|
43
45
|
|
|
44
46
|
data[index] = {
|
|
45
47
|
...item,
|
|
46
48
|
value: newValue,
|
|
47
49
|
}
|
|
48
50
|
|
|
49
|
-
setWidget(id, {
|
|
51
|
+
widgetStoreActions.setWidget(id, {
|
|
50
52
|
data,
|
|
51
53
|
})
|
|
52
54
|
|
|
@@ -80,9 +82,9 @@ export function RangeItem({ id, index }: RangeItemProps) {
|
|
|
80
82
|
]
|
|
81
83
|
}
|
|
82
84
|
|
|
83
|
-
const data = getWidget<RangeWidgetState>(id)?.data ?? []
|
|
85
|
+
const data = widgetStoreActions.getWidget<RangeWidgetState>(id)?.data ?? []
|
|
84
86
|
|
|
85
|
-
setWidget(id, {
|
|
87
|
+
widgetStoreActions.setWidget(id, {
|
|
86
88
|
data: data.map((d: RangeWidgetState['data'][number], i: number) =>
|
|
87
89
|
i === index
|
|
88
90
|
? {
|
|
@@ -14,6 +14,7 @@ import {
|
|
|
14
14
|
createTooltipFormatter,
|
|
15
15
|
createChartDownloadConfig,
|
|
16
16
|
applyYAxisFormatter,
|
|
17
|
+
applyXAxisFormatter,
|
|
17
18
|
} from '../utils/chart-config'
|
|
18
19
|
|
|
19
20
|
export const scatterplotDownloadConfig =
|
|
@@ -32,6 +33,7 @@ export function scatterplotConfig(
|
|
|
32
33
|
type: 'scatterplot',
|
|
33
34
|
option: mergeEchartWidgetConfig(getCommonOptions(props), getOption(props)),
|
|
34
35
|
formatter: props.formatter,
|
|
36
|
+
labelFormatter: props.labelFormatter,
|
|
35
37
|
}
|
|
36
38
|
}
|
|
37
39
|
|
|
@@ -39,6 +41,7 @@ function getOption({
|
|
|
39
41
|
data = [],
|
|
40
42
|
theme,
|
|
41
43
|
formatter,
|
|
44
|
+
labelFormatter,
|
|
42
45
|
}: ScatterplotConfig): EchartOptionsProps {
|
|
43
46
|
const hasLegend = data.length > 1
|
|
44
47
|
|
|
@@ -94,12 +97,12 @@ function getOption({
|
|
|
94
97
|
}
|
|
95
98
|
|
|
96
99
|
return {
|
|
97
|
-
legend: buildLegendConfig(hasLegend),
|
|
100
|
+
legend: buildLegendConfig({ hasLegend, labelFormatter }),
|
|
98
101
|
grid: {
|
|
99
102
|
...(!hasLegend && { bottom: parseInt(theme.spacing(1)) }),
|
|
100
103
|
...(hasLegend && { bottom: parseInt(theme.spacing(10)) }),
|
|
101
104
|
},
|
|
102
|
-
xAxis,
|
|
105
|
+
xAxis: applyXAxisFormatter(xAxis, labelFormatter),
|
|
103
106
|
yAxis: applyYAxisFormatter(yAxis, formatter),
|
|
104
107
|
tooltip: {
|
|
105
108
|
trigger: 'item',
|
|
@@ -114,7 +117,9 @@ function getOption({
|
|
|
114
117
|
? formatter(_value)
|
|
115
118
|
: (_value ?? '')
|
|
116
119
|
const marker = typeof item.marker === 'string' ? item.marker : ''
|
|
117
|
-
const name =
|
|
120
|
+
const name = labelFormatter
|
|
121
|
+
? String(labelFormatter(item.seriesName ?? ''))
|
|
122
|
+
: (item.seriesName ?? '')
|
|
118
123
|
|
|
119
124
|
return { name, seriesName: '', marker, value: formattedValue }
|
|
120
125
|
}),
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import type { SkeletonLoaderProps } from './types'
|
|
2
|
-
import {
|
|
2
|
+
import { useWidgetSelector } from '../stores/use-widget-selector'
|
|
3
3
|
import { Suspense } from 'react'
|
|
4
|
-
import { useShallow } from 'zustand/shallow'
|
|
5
4
|
|
|
6
5
|
/**
|
|
7
6
|
* Displays a skeleton loading placeholder while widget data is loading. Subscribes to widget loading state in the store and renders the provided Skeleton component or children accordingly.
|
|
@@ -18,9 +17,7 @@ export function SkeletonLoader({
|
|
|
18
17
|
children,
|
|
19
18
|
Skeleton,
|
|
20
19
|
}: SkeletonLoaderProps) {
|
|
21
|
-
const isLoading =
|
|
22
|
-
useShallow((state) => state.widgets[id]?.isLoading),
|
|
23
|
-
)
|
|
20
|
+
const isLoading = useWidgetSelector(id, (w) => w?.isLoading)
|
|
24
21
|
|
|
25
22
|
if (isLoading) {
|
|
26
23
|
if (!Skeleton) {
|
|
@@ -1,27 +1,25 @@
|
|
|
1
1
|
import { type SpreadWidgetState, type ValueProps } from '../types'
|
|
2
|
-
import {
|
|
2
|
+
import { useWidgetSelector } from '../../stores/use-widget-selector'
|
|
3
3
|
import { Item } from '../../formula/components/item'
|
|
4
|
-
import { useShallow } from 'zustand/shallow'
|
|
5
4
|
import { defaultFormatter } from '../../utils/formatter'
|
|
6
5
|
|
|
7
6
|
/**
|
|
8
7
|
* Displays the formatted maximum value for a spread widget data item.
|
|
9
8
|
*/
|
|
10
9
|
export function MaxValue({ id, index = 0, ...props }: ValueProps) {
|
|
11
|
-
const
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
)
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
) ?? defaultFormatter
|
|
10
|
+
const {
|
|
11
|
+
max,
|
|
12
|
+
color,
|
|
13
|
+
formatter: _formatter,
|
|
14
|
+
} = useWidgetSelector(id, (w) => {
|
|
15
|
+
const sw = w as SpreadWidgetState | undefined
|
|
16
|
+
return {
|
|
17
|
+
max: sw?.data[index]?.max,
|
|
18
|
+
color: sw?.data[index]?.color,
|
|
19
|
+
formatter: sw?.formatter,
|
|
20
|
+
}
|
|
21
|
+
})
|
|
22
|
+
const formatter = _formatter ?? defaultFormatter
|
|
25
23
|
|
|
26
24
|
return (
|
|
27
25
|
<Item TypographyProps={{ color }} {...props}>
|
|
@@ -1,27 +1,25 @@
|
|
|
1
1
|
import { type SpreadWidgetState, type ValueProps } from '../types'
|
|
2
|
-
import {
|
|
2
|
+
import { useWidgetSelector } from '../../stores/use-widget-selector'
|
|
3
3
|
import { Item } from '../../formula/components/item'
|
|
4
|
-
import { useShallow } from 'zustand/shallow'
|
|
5
4
|
import { defaultFormatter } from '../../utils/formatter'
|
|
6
5
|
|
|
7
6
|
/**
|
|
8
7
|
* Displays the formatted minimum value for a spread widget data item.
|
|
9
8
|
*/
|
|
10
9
|
export function MinValue({ id, index = 0, ...props }: ValueProps) {
|
|
11
|
-
const
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
)
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
) ?? defaultFormatter
|
|
10
|
+
const {
|
|
11
|
+
min,
|
|
12
|
+
color,
|
|
13
|
+
formatter: _formatter,
|
|
14
|
+
} = useWidgetSelector(id, (w) => {
|
|
15
|
+
const sw = w as SpreadWidgetState | undefined
|
|
16
|
+
return {
|
|
17
|
+
min: sw?.data[index]?.min,
|
|
18
|
+
color: sw?.data[index]?.color,
|
|
19
|
+
formatter: sw?.formatter,
|
|
20
|
+
}
|
|
21
|
+
})
|
|
22
|
+
const formatter = _formatter ?? defaultFormatter
|
|
25
23
|
|
|
26
24
|
return (
|
|
27
25
|
<Item TypographyProps={{ color }} {...props}>
|
|
@@ -31,6 +31,8 @@ export interface WidgetsStoreProps {
|
|
|
31
31
|
registeredTools?: ToolRegistration[]
|
|
32
32
|
/** Formatter function for widget values */
|
|
33
33
|
formatter?: (value: number) => string
|
|
34
|
+
/** Formatter function for widget label/category values */
|
|
35
|
+
labelFormatter?: (value: string | number) => string | number
|
|
34
36
|
/** Locale for number formatting (e.g., 'en-US', 'es-ES', 'fr-FR') */
|
|
35
37
|
locale?: string
|
|
36
38
|
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { useWidgetStore } from './widget-store'
|
|
2
|
+
import type { WidgetState } from './types'
|
|
3
|
+
import { useShallow } from 'zustand/shallow'
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Scoped selector hook for reading a single widget's state from the store.
|
|
7
|
+
*
|
|
8
|
+
* Consolidates multiple `useWidgetStore(useShallow(...))` calls into a single
|
|
9
|
+
* subscription per component. The selector receives only this widget's state
|
|
10
|
+
* (or undefined if not yet registered), and uses shallow comparison to avoid
|
|
11
|
+
* re-renders when unrelated properties change.
|
|
12
|
+
*
|
|
13
|
+
* @param widgetId - The widget ID to subscribe to.
|
|
14
|
+
* @param selector - A function that extracts the needed properties from the widget state.
|
|
15
|
+
* Must be a stable reference (inline arrow is fine due to useCallback wrapping).
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* ```tsx
|
|
19
|
+
* // Before: 4 separate subscriptions
|
|
20
|
+
* const title = useWidgetStore(useShallow((s) => s.getWidget(id)?.title))
|
|
21
|
+
* const collapsed = useWidgetStore(useShallow((s) => s.getWidget(id)?.collapsed))
|
|
22
|
+
* const disabled = useWidgetStore(useShallow((s) => s.getWidget(id)?.disabled))
|
|
23
|
+
* const isFetching = useWidgetStore(useShallow((s) => s.getWidget(id)?.isFetching))
|
|
24
|
+
*
|
|
25
|
+
* // After: 1 subscription
|
|
26
|
+
* const { title, collapsed, disabled, isFetching } = useWidgetSelector(id, (w) => ({
|
|
27
|
+
* title: w?.title, collapsed: w?.collapsed, disabled: w?.disabled, isFetching: w?.isFetching,
|
|
28
|
+
* }))
|
|
29
|
+
*
|
|
30
|
+
* // With extra dependencies (e.g., index prop):
|
|
31
|
+
* const value = useWidgetSelector(
|
|
32
|
+
* id,
|
|
33
|
+
* (w) => (w as MyState | undefined)?.data?.[index]?.value,
|
|
34
|
+
* [index],
|
|
35
|
+
* )
|
|
36
|
+
* ```
|
|
37
|
+
*/
|
|
38
|
+
export function useWidgetSelector<T>(
|
|
39
|
+
widgetId: string,
|
|
40
|
+
selector: (widget: WidgetState | undefined) => T,
|
|
41
|
+
): T {
|
|
42
|
+
return useWidgetStore(
|
|
43
|
+
useShallow((state: { widgets: Record<string, WidgetState> }) =>
|
|
44
|
+
selector(state.widgets[widgetId]),
|
|
45
|
+
),
|
|
46
|
+
)
|
|
47
|
+
}
|