@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
|
@@ -1,17 +1,13 @@
|
|
|
1
1
|
import { Box, IconButton } from '@mui/material'
|
|
2
2
|
import { HighlightAltOutlined } from '@mui/icons-material'
|
|
3
3
|
import { useEffect, useCallback, useRef } from 'react'
|
|
4
|
-
import {
|
|
5
|
-
import type { BrushToggleProps } from './types'
|
|
4
|
+
import { widgetStoreActions } from '../../stores/widget-store'
|
|
5
|
+
import type { BrushSelectedItems, BrushToggleProps } from './types'
|
|
6
6
|
import { styles } from './style'
|
|
7
7
|
import { Tooltip } from '../../../components'
|
|
8
8
|
import { getEChartBrushConfig } from '../../echart/utils'
|
|
9
|
-
import type {
|
|
10
|
-
|
|
11
|
-
EchartWidgetData,
|
|
12
|
-
EchartWidgetState,
|
|
13
|
-
} from '../../echart/types'
|
|
14
|
-
import { useShallow } from 'zustand/shallow'
|
|
9
|
+
import type { EchartOptionsProps, EchartWidgetState } from '../../echart/types'
|
|
10
|
+
import { useWidgetSelector } from '../../stores/use-widget-selector'
|
|
15
11
|
|
|
16
12
|
export const BRUSH_TOGGLE_TOOL_ID = 'brush-toggle'
|
|
17
13
|
|
|
@@ -40,26 +36,18 @@ export function BrushToggle({
|
|
|
40
36
|
Icon,
|
|
41
37
|
IconButtonProps,
|
|
42
38
|
}: BrushToggleProps) {
|
|
43
|
-
const
|
|
44
|
-
const registerTool = useWidgetStore((state) => state.registerTool)
|
|
45
|
-
const unregisterTool = useWidgetStore((state) => state.unregisterTool)
|
|
46
|
-
const setToolEnabled = useWidgetStore((state) => state.setToolEnabled)
|
|
47
|
-
const selected = useRef<(string | number)[]>([])
|
|
48
|
-
|
|
49
|
-
const brushTool = useWidgetStore(
|
|
50
|
-
useShallow((state) => {
|
|
51
|
-
const tools = state.getWidget(id)?.registeredTools ?? []
|
|
52
|
-
return tools.find((tool) => tool.id === BRUSH_TOGGLE_TOOL_ID)
|
|
53
|
-
}),
|
|
54
|
-
)
|
|
39
|
+
const selected = useRef<BrushSelectedItems>({ dataIndex: [], seriesIndex: 0 })
|
|
55
40
|
|
|
56
|
-
const brush =
|
|
41
|
+
const { brush } = useWidgetSelector(id, (w) => ({
|
|
42
|
+
brush: w?.registeredTools?.find((tool) => tool.id === BRUSH_TOGGLE_TOOL_ID)
|
|
43
|
+
?.enabled,
|
|
44
|
+
}))
|
|
57
45
|
|
|
58
46
|
const toggleTool = useCallback(
|
|
59
47
|
(value: boolean) => {
|
|
60
|
-
setToolEnabled(id, BRUSH_TOGGLE_TOOL_ID, value)
|
|
48
|
+
widgetStoreActions.setToolEnabled(id, BRUSH_TOGGLE_TOOL_ID, value)
|
|
61
49
|
},
|
|
62
|
-
[id
|
|
50
|
+
[id],
|
|
63
51
|
)
|
|
64
52
|
|
|
65
53
|
const handleToggle = useCallback(() => {
|
|
@@ -67,7 +55,7 @@ export function BrushToggle({
|
|
|
67
55
|
toggleTool(newBrush)
|
|
68
56
|
|
|
69
57
|
if (newBrush) {
|
|
70
|
-
onBrushSelected?.([])
|
|
58
|
+
onBrushSelected?.({ dataIndex: [], seriesIndex: 0 }) // Clear selection when enabling brush
|
|
71
59
|
}
|
|
72
60
|
}, [brush, onBrushSelected, toggleTool])
|
|
73
61
|
|
|
@@ -75,7 +63,8 @@ export function BrushToggle({
|
|
|
75
63
|
useEffect(() => {
|
|
76
64
|
if (!brush) return
|
|
77
65
|
|
|
78
|
-
const instance =
|
|
66
|
+
const instance =
|
|
67
|
+
widgetStoreActions.getWidget<EchartWidgetState>(id)?.instance?.current
|
|
79
68
|
if (!instance) return
|
|
80
69
|
|
|
81
70
|
const handleRendered = () => {
|
|
@@ -99,64 +88,65 @@ export function BrushToggle({
|
|
|
99
88
|
return () => {
|
|
100
89
|
instance.off('rendered', handleRendered)
|
|
101
90
|
}
|
|
102
|
-
}, [brush,
|
|
91
|
+
}, [brush, id])
|
|
103
92
|
|
|
104
93
|
// Handle brushSelected event to capture selected bar indices
|
|
105
|
-
const handleBrushSelected = useCallback(
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
seriesIndex?: number
|
|
112
|
-
}[]
|
|
94
|
+
const handleBrushSelected = useCallback((event: unknown) => {
|
|
95
|
+
const brushEvent = event as {
|
|
96
|
+
batch?: {
|
|
97
|
+
selected?: {
|
|
98
|
+
dataIndex?: number[]
|
|
99
|
+
seriesIndex?: number
|
|
113
100
|
}[]
|
|
101
|
+
}[]
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
const allSelected =
|
|
105
|
+
brushEvent.batch?.flatMap((batchItem) => batchItem.selected ?? []) ?? []
|
|
106
|
+
|
|
107
|
+
if (!allSelected.length) {
|
|
108
|
+
selected.current = {
|
|
109
|
+
dataIndex: [],
|
|
110
|
+
seriesIndex: 0,
|
|
114
111
|
}
|
|
112
|
+
return
|
|
113
|
+
}
|
|
115
114
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
(
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
) ?? [],
|
|
137
|
-
),
|
|
138
|
-
),
|
|
139
|
-
]
|
|
140
|
-
|
|
141
|
-
selected.current = items ?? []
|
|
142
|
-
},
|
|
143
|
-
[getWidget, id],
|
|
144
|
-
)
|
|
115
|
+
// Use the first seriesIndex as the primary one (matches previous behavior)
|
|
116
|
+
const primarySeriesIndex = allSelected[0]?.seriesIndex ?? 0
|
|
117
|
+
|
|
118
|
+
const mergedDataIndex = Array.from(
|
|
119
|
+
new Set(
|
|
120
|
+
allSelected
|
|
121
|
+
.filter(
|
|
122
|
+
(item) =>
|
|
123
|
+
item.seriesIndex === undefined ||
|
|
124
|
+
item.seriesIndex === primarySeriesIndex,
|
|
125
|
+
)
|
|
126
|
+
.flatMap((item) => item.dataIndex ?? []),
|
|
127
|
+
),
|
|
128
|
+
)
|
|
129
|
+
|
|
130
|
+
selected.current = {
|
|
131
|
+
dataIndex: mergedDataIndex,
|
|
132
|
+
seriesIndex: primarySeriesIndex,
|
|
133
|
+
}
|
|
134
|
+
}, [])
|
|
145
135
|
|
|
146
136
|
const handleBrushEnd = useCallback(() => {
|
|
147
137
|
onBrushSelected?.(selected.current)
|
|
148
138
|
toggleTool(false) // Disable brush after selection is made
|
|
149
139
|
}, [onBrushSelected, toggleTool])
|
|
150
140
|
|
|
151
|
-
// Register config tool
|
|
141
|
+
// Register config tool with all reactive deps — store's no-op detection handles performance
|
|
152
142
|
useEffect(() => {
|
|
153
|
-
const existingTool =
|
|
154
|
-
(
|
|
155
|
-
|
|
143
|
+
const existingTool = widgetStoreActions
|
|
144
|
+
.getWidget(id)
|
|
145
|
+
?.registeredTools?.find((tool) => tool.id === BRUSH_TOGGLE_TOOL_ID)
|
|
156
146
|
|
|
157
147
|
const initialEnabled = existingTool?.enabled ?? false
|
|
158
148
|
|
|
159
|
-
registerTool(id, {
|
|
149
|
+
widgetStoreActions.registerTool(id, {
|
|
160
150
|
id: BRUSH_TOGGLE_TOOL_ID,
|
|
161
151
|
type: 'config',
|
|
162
152
|
order: 25,
|
|
@@ -169,8 +159,6 @@ export function BrushToggle({
|
|
|
169
159
|
|
|
170
160
|
const brushConfig = getEChartBrushConfig()
|
|
171
161
|
|
|
172
|
-
const onEventsWithoutBrush = { ...currentOnEvents }
|
|
173
|
-
delete onEventsWithoutBrush.brushSelected
|
|
174
162
|
const onEvents = {
|
|
175
163
|
...currentOnEvents,
|
|
176
164
|
brushSelected: handleBrushSelected,
|
|
@@ -187,15 +175,8 @@ export function BrushToggle({
|
|
|
187
175
|
}
|
|
188
176
|
},
|
|
189
177
|
})
|
|
190
|
-
return () => unregisterTool(id, BRUSH_TOGGLE_TOOL_ID)
|
|
191
|
-
}, [
|
|
192
|
-
getWidget,
|
|
193
|
-
handleBrushEnd,
|
|
194
|
-
handleBrushSelected,
|
|
195
|
-
id,
|
|
196
|
-
registerTool,
|
|
197
|
-
unregisterTool,
|
|
198
|
-
])
|
|
178
|
+
return () => widgetStoreActions.unregisterTool(id, BRUSH_TOGGLE_TOOL_ID)
|
|
179
|
+
}, [id, handleBrushSelected, handleBrushEnd])
|
|
199
180
|
|
|
200
181
|
const enableLabel = labels?.enable ?? 'Enable brush selection'
|
|
201
182
|
const disableLabel = labels?.disable ?? 'Disable brush selection'
|
|
@@ -3,9 +3,15 @@ import type { ReactNode } from 'react'
|
|
|
3
3
|
import type { BaseWidgetState } from '../../stores/types'
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
|
-
*
|
|
6
|
+
* Brush selection result emitted by BrushToggle.
|
|
7
|
+
* Contains raw indices so consumers can resolve data according to their widget type.
|
|
7
8
|
*/
|
|
8
|
-
export
|
|
9
|
+
export interface BrushSelectedItems {
|
|
10
|
+
/** Data indices of the selected items in the dataset */
|
|
11
|
+
dataIndex: number[]
|
|
12
|
+
/** Series index from the brush event (defaults to 0) */
|
|
13
|
+
seriesIndex: number
|
|
14
|
+
}
|
|
9
15
|
|
|
10
16
|
/**
|
|
11
17
|
* State stored in widget store for brush functionality
|
|
@@ -21,14 +21,14 @@ import {
|
|
|
21
21
|
useState,
|
|
22
22
|
type MouseEvent,
|
|
23
23
|
} from 'react'
|
|
24
|
-
import {
|
|
24
|
+
import { widgetStoreActions } from '../../stores/widget-store'
|
|
25
25
|
import type { ChangeColumnProps } from './types'
|
|
26
26
|
import { actionButtonStyles } from '../shared/styles'
|
|
27
27
|
import { Tooltip } from '../../../components'
|
|
28
28
|
import type { TableColumn, TableWidgetState } from '../../table/types'
|
|
29
29
|
import { ChangeColumnIcon } from './change-column-icon'
|
|
30
30
|
import { SortableColumnItem } from './sortable-column-item'
|
|
31
|
-
import {
|
|
31
|
+
import { useWidgetSelector } from '../../stores/use-widget-selector'
|
|
32
32
|
|
|
33
33
|
export const CHANGE_COLUMN_TOOL_ID = 'change-column'
|
|
34
34
|
|
|
@@ -57,12 +57,9 @@ export function ChangeColumn({
|
|
|
57
57
|
MenuProps,
|
|
58
58
|
}: ChangeColumnProps) {
|
|
59
59
|
const [anchorEl, setAnchorEl] = useState<HTMLElement | null>(null)
|
|
60
|
-
const
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
const columns = useWidgetStore(
|
|
64
|
-
useShallow((state) => state.getWidget<TableWidgetState>(id)?.columns),
|
|
65
|
-
)
|
|
60
|
+
const { columns } = useWidgetSelector(id, (w) => ({
|
|
61
|
+
columns: (w as TableWidgetState | undefined)?.columns,
|
|
62
|
+
}))
|
|
66
63
|
|
|
67
64
|
/**
|
|
68
65
|
* Config tool function that reorders columns to match the current widget state.
|
|
@@ -72,9 +69,7 @@ export function ChangeColumn({
|
|
|
72
69
|
*/
|
|
73
70
|
const reorderFn = useCallback(
|
|
74
71
|
(currentConfig: unknown): unknown => {
|
|
75
|
-
const widgetState =
|
|
76
|
-
.getState()
|
|
77
|
-
.getWidget<TableWidgetState>(id)
|
|
72
|
+
const widgetState = widgetStoreActions.getWidget<TableWidgetState>(id)
|
|
78
73
|
const currentColumns = widgetState?.columns
|
|
79
74
|
if (!currentColumns || currentColumns.length === 0) return currentConfig
|
|
80
75
|
|
|
@@ -130,15 +125,15 @@ export function ChangeColumn({
|
|
|
130
125
|
|
|
131
126
|
// Register config tool on mount
|
|
132
127
|
useEffect(() => {
|
|
133
|
-
registerTool(id, {
|
|
128
|
+
widgetStoreActions.registerTool(id, {
|
|
134
129
|
id: CHANGE_COLUMN_TOOL_ID,
|
|
135
130
|
type: 'config',
|
|
136
131
|
order: 100,
|
|
137
132
|
enabled: true,
|
|
138
133
|
fn: reorderFn,
|
|
139
134
|
})
|
|
140
|
-
return () => unregisterTool(id, CHANGE_COLUMN_TOOL_ID)
|
|
141
|
-
}, [id,
|
|
135
|
+
return () => widgetStoreActions.unregisterTool(id, CHANGE_COLUMN_TOOL_ID)
|
|
136
|
+
}, [id, reorderFn])
|
|
142
137
|
|
|
143
138
|
const handleToggle = useCallback((event: MouseEvent<HTMLElement>) => {
|
|
144
139
|
event.stopPropagation()
|
|
@@ -156,7 +151,7 @@ export function ChangeColumn({
|
|
|
156
151
|
const newIndex = columns.findIndex((col) => col.id === over.id)
|
|
157
152
|
if (oldIndex !== -1 && newIndex !== -1) {
|
|
158
153
|
const newColumns = arrayMove(columns, oldIndex, newIndex)
|
|
159
|
-
setWidget(id, { columns: newColumns })
|
|
154
|
+
widgetStoreActions.setWidget(id, { columns: newColumns })
|
|
160
155
|
}
|
|
161
156
|
}
|
|
162
157
|
|
|
@@ -201,6 +196,11 @@ export function ChangeColumn({
|
|
|
201
196
|
onClose={handleClose}
|
|
202
197
|
anchorOrigin={{ vertical: 'bottom', horizontal: 'right' }}
|
|
203
198
|
transformOrigin={{ vertical: 'top', horizontal: 'right' }}
|
|
199
|
+
slotProps={{
|
|
200
|
+
paper: {
|
|
201
|
+
sx: { overflow: 'hidden' },
|
|
202
|
+
},
|
|
203
|
+
}}
|
|
204
204
|
{...MenuProps}
|
|
205
205
|
>
|
|
206
206
|
<SortableContext
|
|
@@ -22,7 +22,9 @@ export function SortableColumnItem({ column }: SortableColumnItemProps) {
|
|
|
22
22
|
} = useSortable({ id: column.id })
|
|
23
23
|
|
|
24
24
|
const style = {
|
|
25
|
-
transform: CSS.Transform.toString(
|
|
25
|
+
transform: CSS.Transform.toString(
|
|
26
|
+
transform ? { ...transform, x: 0 } : null,
|
|
27
|
+
),
|
|
26
28
|
transition,
|
|
27
29
|
opacity: isDragging ? 0.5 : 1,
|
|
28
30
|
cursor: isDragging ? 'grabbing' : 'grab',
|
|
@@ -9,8 +9,7 @@ import {
|
|
|
9
9
|
import type { DownloadItem, DownloadProps } from './types'
|
|
10
10
|
import { FileDownloadOutlined } from '@mui/icons-material'
|
|
11
11
|
import { useState, type MouseEvent } from 'react'
|
|
12
|
-
import {
|
|
13
|
-
import { useShallow } from 'zustand/shallow'
|
|
12
|
+
import { useWidgetSelector } from '../../stores/use-widget-selector'
|
|
14
13
|
|
|
15
14
|
const EMPTY_LABELS: NonNullable<DownloadProps['labels']> = {}
|
|
16
15
|
|
|
@@ -32,7 +31,9 @@ export function Download({
|
|
|
32
31
|
Icon,
|
|
33
32
|
IconButtonProps,
|
|
34
33
|
}: DownloadProps) {
|
|
35
|
-
const data =
|
|
34
|
+
const { data } = useWidgetSelector(id, (w) => ({
|
|
35
|
+
data: w?.data,
|
|
36
|
+
}))
|
|
36
37
|
|
|
37
38
|
const [isDownloading, setIsDownloading] = useState(false)
|
|
38
39
|
const [anchorEl, setAnchorEl] = useState<null | HTMLElement>(null)
|
|
@@ -5,7 +5,8 @@ import {
|
|
|
5
5
|
IconButton,
|
|
6
6
|
Typography,
|
|
7
7
|
} from '@mui/material'
|
|
8
|
-
import {
|
|
8
|
+
import { widgetStoreActions } from '../../stores/widget-store'
|
|
9
|
+
import { useWidgetSelector } from '../../stores/use-widget-selector'
|
|
9
10
|
import { Close, FullscreenOutlined } from '@mui/icons-material'
|
|
10
11
|
import type {
|
|
11
12
|
FullScreenConfig,
|
|
@@ -13,7 +14,6 @@ import type {
|
|
|
13
14
|
FullScreenState,
|
|
14
15
|
} from './types'
|
|
15
16
|
import { styles } from './styles'
|
|
16
|
-
import { useShallow } from 'zustand/shallow'
|
|
17
17
|
|
|
18
18
|
const EMPTY_DIALOG_CONTENT_PROPS: NonNullable<
|
|
19
19
|
FullScreenProps['DialogContentProps']
|
|
@@ -44,16 +44,12 @@ export function FullScreen({
|
|
|
44
44
|
} = EMPTY_DIALOG_CONTENT_PROPS,
|
|
45
45
|
DialogProps,
|
|
46
46
|
}: FullScreenProps) {
|
|
47
|
-
const isFullScreen =
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
useShallow((state) => state.getWidget<FullScreenState>(id)?.title),
|
|
52
|
-
)
|
|
53
|
-
const setWidget = useWidgetStore((state) => state.setWidget)
|
|
54
|
-
|
|
47
|
+
const { isFullScreen, title } = useWidgetSelector(id, (w) => ({
|
|
48
|
+
isFullScreen: (w as FullScreenState | undefined)?.isFullScreen,
|
|
49
|
+
title: (w as FullScreenState | undefined)?.title,
|
|
50
|
+
}))
|
|
55
51
|
const updateFullScreenConfig = (updates: Partial<FullScreenConfig>) => {
|
|
56
|
-
setWidget<FullScreenState>(id, {
|
|
52
|
+
widgetStoreActions.setWidget<FullScreenState>(id, {
|
|
57
53
|
isFullScreen: updates.isFullScreen,
|
|
58
54
|
})
|
|
59
55
|
}
|
|
@@ -4,8 +4,8 @@ import { useCallback, useEffect, useMemo } from 'react'
|
|
|
4
4
|
import type { LockSelectionProps, LockSelectionState } from './types'
|
|
5
5
|
import { actionButtonStyles } from '../shared/styles'
|
|
6
6
|
import { Tooltip } from '../../../components'
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
7
|
+
import { widgetStoreActions } from '../../stores/widget-store'
|
|
8
|
+
import { useWidgetSelector } from '../../stores/use-widget-selector'
|
|
9
9
|
import type { EchartWidgetData } from '../../echart/types'
|
|
10
10
|
|
|
11
11
|
export const LOCK_SELECTION_TOOL_ID = 'lock-selection'
|
|
@@ -34,12 +34,9 @@ export function LockSelection({
|
|
|
34
34
|
Icon,
|
|
35
35
|
IconButtonProps,
|
|
36
36
|
}: LockSelectionProps) {
|
|
37
|
-
const
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
const storeIsLocked = useWidgetStore(
|
|
41
|
-
useShallow((state) => state.getWidget<LockSelectionState>(id)?.isLocked),
|
|
42
|
-
)
|
|
37
|
+
const { storeIsLocked } = useWidgetSelector(id, (w) => ({
|
|
38
|
+
storeIsLocked: (w as LockSelectionState | undefined)?.isLocked,
|
|
39
|
+
}))
|
|
43
40
|
|
|
44
41
|
const isLocked = storeIsLocked ?? false
|
|
45
42
|
const lockedItems = useMemo(
|
|
@@ -47,9 +44,9 @@ export function LockSelection({
|
|
|
47
44
|
[isLocked, selectedItems],
|
|
48
45
|
)
|
|
49
46
|
|
|
50
|
-
// Register tool
|
|
47
|
+
// Register tool with all reactive deps — store's no-op detection handles performance
|
|
51
48
|
useEffect(() => {
|
|
52
|
-
registerTool(id, {
|
|
49
|
+
widgetStoreActions.registerTool(id, {
|
|
53
50
|
id: LOCK_SELECTION_TOOL_ID,
|
|
54
51
|
order,
|
|
55
52
|
enabled: isLocked,
|
|
@@ -62,24 +59,24 @@ export function LockSelection({
|
|
|
62
59
|
config: { lockedItems },
|
|
63
60
|
})
|
|
64
61
|
|
|
65
|
-
return () => unregisterTool(id, LOCK_SELECTION_TOOL_ID)
|
|
66
|
-
}, [id, order,
|
|
62
|
+
return () => widgetStoreActions.unregisterTool(id, LOCK_SELECTION_TOOL_ID)
|
|
63
|
+
}, [id, order, isLocked, lockedItems])
|
|
67
64
|
|
|
68
65
|
const handleToggle = useCallback(() => {
|
|
69
66
|
if (isLocked) {
|
|
70
67
|
// Unlock: clear locked items and disable tool
|
|
71
|
-
setWidget(id, {
|
|
68
|
+
widgetStoreActions.setWidget(id, {
|
|
72
69
|
isLocked: false,
|
|
73
70
|
lockedItems: [],
|
|
74
71
|
})
|
|
75
72
|
} else {
|
|
76
73
|
// Lock: save selected items and enable tool
|
|
77
|
-
setWidget(id, {
|
|
74
|
+
widgetStoreActions.setWidget(id, {
|
|
78
75
|
isLocked: true,
|
|
79
76
|
lockedItems: selectedItems,
|
|
80
77
|
})
|
|
81
78
|
}
|
|
82
|
-
}, [id, isLocked, selectedItems
|
|
79
|
+
}, [id, isLocked, selectedItems])
|
|
83
80
|
|
|
84
81
|
// Don't render if no selections
|
|
85
82
|
if (selectedItems.length === 0) {
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { IconButton } from '@mui/material'
|
|
2
2
|
import { PercentOutlined } from '@mui/icons-material'
|
|
3
3
|
import { useCallback, useEffect, useRef } from 'react'
|
|
4
|
-
import {
|
|
4
|
+
import { widgetStoreActions } from '../../stores/widget-store'
|
|
5
|
+
import { useWidgetSelector } from '../../stores/use-widget-selector'
|
|
5
6
|
import type { RelativeDataProps } from './types'
|
|
6
7
|
import { actionButtonStyles } from '../shared/styles'
|
|
7
8
|
import { Tooltip } from '../../../components'
|
|
@@ -37,24 +38,18 @@ export function RelativeData({
|
|
|
37
38
|
const percentFormatterRef = useRef<((value: number) => string) | undefined>(
|
|
38
39
|
undefined,
|
|
39
40
|
)
|
|
40
|
-
const getWidget = useWidgetStore((state) => state.getWidget)
|
|
41
|
-
const registerTool = useWidgetStore((state) => state.registerTool)
|
|
42
|
-
const unregisterTool = useWidgetStore((state) => state.unregisterTool)
|
|
43
|
-
const setToolEnabled = useWidgetStore((state) => state.setToolEnabled)
|
|
44
|
-
const updateToolConfig = useWidgetStore((state) => state.updateToolConfig)
|
|
45
41
|
|
|
46
|
-
const storeIsRelative =
|
|
47
|
-
(
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
)
|
|
42
|
+
const { storeIsRelative } = useWidgetSelector(id, (w) => ({
|
|
43
|
+
storeIsRelative: w?.registeredTools?.find(
|
|
44
|
+
(t) => t.id === RELATIVE_DATA_CONFIG_TOOL_ID,
|
|
45
|
+
)?.config?.isRelative as boolean | undefined,
|
|
46
|
+
}))
|
|
52
47
|
|
|
53
48
|
const isRelative = storeIsRelative ?? defaultIsRelative
|
|
54
49
|
|
|
55
|
-
// Register tool
|
|
50
|
+
// Register data tool with all reactive deps — store's no-op detection handles performance
|
|
56
51
|
useEffect(() => {
|
|
57
|
-
registerTool(id, {
|
|
52
|
+
widgetStoreActions.registerTool(id, {
|
|
58
53
|
id: RELATIVE_DATA_TOOL_ID,
|
|
59
54
|
order,
|
|
60
55
|
enabled: defaultIsRelative,
|
|
@@ -65,17 +60,17 @@ export function RelativeData({
|
|
|
65
60
|
},
|
|
66
61
|
})
|
|
67
62
|
|
|
68
|
-
return () => unregisterTool(id, RELATIVE_DATA_TOOL_ID)
|
|
69
|
-
}, [id, order,
|
|
63
|
+
return () => widgetStoreActions.unregisterTool(id, RELATIVE_DATA_TOOL_ID)
|
|
64
|
+
}, [id, order, defaultIsRelative])
|
|
70
65
|
|
|
71
|
-
// Register config tool
|
|
66
|
+
// Register config tool with all reactive deps — store's no-op detection handles performance
|
|
72
67
|
useEffect(() => {
|
|
73
|
-
registerTool(id, {
|
|
68
|
+
widgetStoreActions.registerTool(id, {
|
|
74
69
|
id: RELATIVE_DATA_CONFIG_TOOL_ID,
|
|
75
70
|
type: 'config',
|
|
76
71
|
order,
|
|
77
72
|
enabled: true,
|
|
78
|
-
fn: (currentConfig, toolConfig) => {
|
|
73
|
+
fn: (currentConfig: unknown, toolConfig?: Record<string, unknown>) => {
|
|
79
74
|
const config = currentConfig as Record<string, unknown>
|
|
80
75
|
if (toolConfig?.isRelative) {
|
|
81
76
|
if (!percentFormatterRef.current) {
|
|
@@ -104,20 +99,21 @@ export function RelativeData({
|
|
|
104
99
|
isRelative: defaultIsRelative,
|
|
105
100
|
},
|
|
106
101
|
})
|
|
107
|
-
return () =>
|
|
108
|
-
|
|
102
|
+
return () =>
|
|
103
|
+
widgetStoreActions.unregisterTool(id, RELATIVE_DATA_CONFIG_TOOL_ID)
|
|
104
|
+
}, [id, order, defaultIsRelative])
|
|
109
105
|
|
|
110
106
|
const handleToggle = useCallback(() => {
|
|
111
107
|
const newIsRelative = !isRelative
|
|
112
|
-
setToolEnabled(id, RELATIVE_DATA_TOOL_ID, newIsRelative)
|
|
108
|
+
widgetStoreActions.setToolEnabled(id, RELATIVE_DATA_TOOL_ID, newIsRelative)
|
|
113
109
|
|
|
114
110
|
if (newIsRelative) {
|
|
115
|
-
const widget = getWidget(id) as {
|
|
111
|
+
const widget = widgetStoreActions.getWidget(id) as {
|
|
116
112
|
formatter?: (value: number) => string
|
|
117
113
|
locale?: string
|
|
118
114
|
max?: number
|
|
119
115
|
}
|
|
120
|
-
updateToolConfig(id, RELATIVE_DATA_CONFIG_TOOL_ID, {
|
|
116
|
+
widgetStoreActions.updateToolConfig(id, RELATIVE_DATA_CONFIG_TOOL_ID, {
|
|
121
117
|
isRelative: true,
|
|
122
118
|
originalFormatter: widget?.formatter,
|
|
123
119
|
originalMax: widget?.max,
|
|
@@ -125,11 +121,11 @@ export function RelativeData({
|
|
|
125
121
|
})
|
|
126
122
|
} else {
|
|
127
123
|
percentFormatterRef.current = undefined
|
|
128
|
-
updateToolConfig(id, RELATIVE_DATA_CONFIG_TOOL_ID, {
|
|
124
|
+
widgetStoreActions.updateToolConfig(id, RELATIVE_DATA_CONFIG_TOOL_ID, {
|
|
129
125
|
isRelative: false,
|
|
130
126
|
})
|
|
131
127
|
}
|
|
132
|
-
}, [isRelative, id
|
|
128
|
+
}, [isRelative, id])
|
|
133
129
|
|
|
134
130
|
const tooltipLabel = isRelative
|
|
135
131
|
? (labels?.absolute ?? 'Show absolute values')
|
|
@@ -4,8 +4,8 @@ import { useCallback, useEffect } from 'react'
|
|
|
4
4
|
import type { SearcherToggleProps, SearcherState } from './types'
|
|
5
5
|
import { actionButtonStyles } from '../shared/styles'
|
|
6
6
|
import { Tooltip } from '../../../components'
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
7
|
+
import { widgetStoreActions } from '../../stores/widget-store'
|
|
8
|
+
import { useWidgetSelector } from '../../stores/use-widget-selector'
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
11
|
* Widget action button to toggle search functionality.
|
|
@@ -30,25 +30,24 @@ export function SearcherToggle({
|
|
|
30
30
|
Icon,
|
|
31
31
|
IconButtonProps,
|
|
32
32
|
}: SearcherToggleProps) {
|
|
33
|
-
const
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
useShallow((state) => state.getWidget<SearcherState>(id)?.isSearchEnabled),
|
|
37
|
-
)
|
|
33
|
+
const { storeIsEnabled } = useWidgetSelector(id, (w) => ({
|
|
34
|
+
storeIsEnabled: (w as SearcherState | undefined)?.isSearchEnabled,
|
|
35
|
+
}))
|
|
38
36
|
|
|
39
37
|
const isEnabled = storeIsEnabled ?? defaultEnabled
|
|
40
38
|
|
|
41
39
|
// Initialize store with default value on mount
|
|
42
40
|
useEffect(() => {
|
|
43
|
-
const currentValue =
|
|
41
|
+
const currentValue =
|
|
42
|
+
widgetStoreActions.getWidget<SearcherState>(id)?.isSearchEnabled
|
|
44
43
|
if (currentValue === undefined) {
|
|
45
|
-
setWidget(id, { isSearchEnabled: defaultEnabled })
|
|
44
|
+
widgetStoreActions.setWidget(id, { isSearchEnabled: defaultEnabled })
|
|
46
45
|
}
|
|
47
|
-
}, [defaultEnabled,
|
|
46
|
+
}, [defaultEnabled, id])
|
|
48
47
|
|
|
49
48
|
const handleToggle = useCallback(() => {
|
|
50
|
-
setWidget(id, { isSearchEnabled: !isEnabled })
|
|
51
|
-
}, [id, isEnabled
|
|
49
|
+
widgetStoreActions.setWidget(id, { isSearchEnabled: !isEnabled })
|
|
50
|
+
}, [id, isEnabled])
|
|
52
51
|
|
|
53
52
|
const tooltipLabel = isEnabled
|
|
54
53
|
? (labels?.disable ?? 'Disable search')
|