@carto/ps-react-ui 4.5.0 → 4.6.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 → download-config-C3I0jWIL.js} +2 -2
- package/dist/{download-config-DemuQ3Jm.js.map → download-config-C3I0jWIL.js.map} +1 -1
- package/dist/{row-D4VOhcNI.js → row-DZSP99LW.js} +2 -2
- package/dist/{row-D4VOhcNI.js.map → row-DZSP99LW.js.map} +1 -1
- package/dist/{series-Bola3CmD.js → series-DLNHDWs0.js} +3 -3
- package/dist/{series-Bola3CmD.js.map → series-DLNHDWs0.js.map} +1 -1
- package/dist/types/hooks/index.d.ts +0 -1
- package/dist/types/widgets/actions/brush-toggle/brush-toggle.d.ts +3 -0
- package/dist/types/widgets/actions/index.d.ts +4 -4
- package/dist/types/widgets/actions/lock-selection/types.d.ts +2 -0
- package/dist/types/widgets/actions/relative-data/relative-data.d.ts +7 -2
- package/dist/types/widgets/actions/relative-data/types.d.ts +2 -0
- package/dist/types/widgets/actions/zoom-toggle/zoom-toggle.d.ts +4 -0
- package/dist/types/widgets/category/index.d.ts +10 -2
- package/dist/types/widgets/category/style.d.ts +1 -0
- package/dist/types/widgets/no-data/no-data.d.ts +3 -2
- package/dist/types/widgets/no-data/types.d.ts +5 -1
- package/dist/types/widgets/stores/index.d.ts +1 -1
- package/dist/types/widgets/stores/types.d.ts +10 -10
- package/dist/types/widgets/stores/widget-store.d.ts +2 -3
- package/dist/types/widgets/table/index.d.ts +6 -2
- package/dist/{use-widget-ref-BFazQvJK.js → use-widget-ref-Ddr_SlJJ.js} +2 -2
- package/dist/{use-widget-ref-BFazQvJK.js.map → use-widget-ref-Ddr_SlJJ.js.map} +1 -1
- package/dist/{use-widget-selector-DqRmWQ1K.js → use-widget-selector-DFl2hW0R.js} +2 -2
- package/dist/{use-widget-selector-DqRmWQ1K.js.map → use-widget-selector-DFl2hW0R.js.map} +1 -1
- package/dist/{widget-store-CIrb9RKP.js → widget-store-Bw5zRUGg.js} +93 -95
- package/dist/widget-store-Bw5zRUGg.js.map +1 -0
- package/dist/widgets/actions.js +770 -755
- package/dist/widgets/actions.js.map +1 -1
- package/dist/widgets/bar.js +2 -2
- package/dist/widgets/category.js +187 -183
- package/dist/widgets/category.js.map +1 -1
- package/dist/widgets/echart.js +2 -2
- package/dist/widgets/error.js +37 -2
- package/dist/widgets/error.js.map +1 -1
- package/dist/widgets/formula.js +5 -5
- package/dist/widgets/histogram.js +1 -1
- package/dist/widgets/loader.js +1 -1
- package/dist/widgets/markdown.js +2 -2
- package/dist/widgets/no-data.js +58 -2
- package/dist/widgets/no-data.js.map +1 -1
- package/dist/widgets/note.js +121 -2
- package/dist/widgets/note.js.map +1 -1
- package/dist/widgets/pie.js +2 -2
- package/dist/widgets/range.js +3 -3
- package/dist/widgets/scatterplot.js +2 -2
- package/dist/widgets/skeleton-loader.js +1 -1
- package/dist/widgets/spread.js +5 -5
- package/dist/widgets/stores.js +2 -2
- package/dist/widgets/subheader.js +29 -29
- package/dist/widgets/subheader.js.map +1 -1
- package/dist/widgets/table.js +3 -3
- package/dist/widgets/timeseries.js +2 -2
- package/dist/widgets/utils.js +1 -1
- package/dist/widgets/wrapper.js +2 -2
- package/package.json +1 -5
- package/src/hooks/index.ts +0 -1
- package/src/widgets/actions/brush-toggle/brush-toggle.tsx +18 -22
- package/src/widgets/actions/change-column/change-column.test.tsx +1 -1
- package/src/widgets/actions/download/download.test.tsx +1 -1
- package/src/widgets/actions/index.ts +11 -2
- package/src/widgets/actions/lock-selection/lock-selection.test.tsx +14 -0
- package/src/widgets/actions/lock-selection/lock-selection.tsx +18 -11
- package/src/widgets/actions/lock-selection/types.ts +2 -0
- package/src/widgets/actions/relative-data/relative-data.test.tsx +211 -20
- package/src/widgets/actions/relative-data/relative-data.tsx +65 -34
- package/src/widgets/actions/relative-data/types.ts +2 -0
- package/src/widgets/actions/searcher/searcher.tsx +28 -30
- package/src/widgets/actions/stack-toggle/stack-toggle.tsx +11 -2
- package/src/widgets/actions/zoom-toggle/zoom-toggle.tsx +53 -45
- package/src/widgets/category/category-ui.tsx +7 -6
- package/src/widgets/category/index.ts +13 -14
- package/src/widgets/category/style.ts +1 -0
- package/src/widgets/no-data/no-data.test.tsx +90 -40
- package/src/widgets/no-data/no-data.tsx +7 -5
- package/src/widgets/no-data/types.ts +5 -1
- package/src/widgets/stores/index.ts +2 -0
- package/src/widgets/stores/types.ts +10 -18
- package/src/widgets/stores/widget-store.test.ts +132 -13
- package/src/widgets/stores/widget-store.ts +29 -35
- package/src/widgets/subheader/subheader.tsx +11 -3
- package/src/widgets/table/index.ts +6 -4
- package/dist/error-Cj8eUMrl.js +0 -40
- package/dist/error-Cj8eUMrl.js.map +0 -1
- package/dist/no-data-DkIt7Qt1.js +0 -61
- package/dist/no-data-DkIt7Qt1.js.map +0 -1
- package/dist/note-t51drNe0.js +0 -124
- package/dist/note-t51drNe0.js.map +0 -1
- package/dist/types/hooks/use-debounce.d.ts +0 -19
- package/dist/types/widgets/category/components/index.d.ts +0 -10
- package/dist/types/widgets/index.d.ts +0 -9
- package/dist/types/widgets/table/hooks/index.d.ts +0 -6
- package/dist/widget-store-CIrb9RKP.js.map +0 -1
- package/dist/widgets.js +0 -13
- package/dist/widgets.js.map +0 -1
- package/src/hooks/use-debounce.ts +0 -55
- package/src/widgets/category/components/index.ts +0 -14
- package/src/widgets/index.ts +0 -25
- package/src/widgets/table/hooks/index.ts +0 -7
package/dist/widgets/stores.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { u as o, w as r } from "../widget-store-
|
|
2
|
-
import { u as i } from "../use-widget-selector-
|
|
1
|
+
import { u as o, w as r } from "../widget-store-Bw5zRUGg.js";
|
|
2
|
+
import { u as i } from "../use-widget-selector-DFl2hW0R.js";
|
|
3
3
|
export {
|
|
4
4
|
i as useWidgetSelector,
|
|
5
5
|
o as useWidgetStore,
|
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
import { jsx as
|
|
2
|
-
import { c as
|
|
3
|
-
import { Box as
|
|
4
|
-
const
|
|
1
|
+
import { jsx as c, jsxs as g } from "react/jsx-runtime";
|
|
2
|
+
import { c as x } from "react/compiler-runtime";
|
|
3
|
+
import { Box as a } from "@mui/material";
|
|
4
|
+
const d = {
|
|
5
5
|
root: {
|
|
6
6
|
display: "flex",
|
|
7
7
|
alignItems: "center",
|
|
8
8
|
gap: ({
|
|
9
|
-
spacing:
|
|
10
|
-
}) =>
|
|
9
|
+
spacing: t
|
|
10
|
+
}) => t(1),
|
|
11
11
|
minHeight: ({
|
|
12
|
-
spacing:
|
|
13
|
-
}) =>
|
|
12
|
+
spacing: t
|
|
13
|
+
}) => t(3)
|
|
14
14
|
},
|
|
15
15
|
slotLeft: {
|
|
16
16
|
flexShrink: 0
|
|
@@ -21,30 +21,30 @@ const c = {
|
|
|
21
21
|
justifyContent: "flex-end",
|
|
22
22
|
alignItems: "center",
|
|
23
23
|
gap: ({
|
|
24
|
-
spacing:
|
|
25
|
-
}) =>
|
|
24
|
+
spacing: t
|
|
25
|
+
}) => t(1)
|
|
26
26
|
}
|
|
27
27
|
};
|
|
28
|
-
function u(
|
|
29
|
-
const
|
|
30
|
-
slotLeft:
|
|
31
|
-
slotRight:
|
|
32
|
-
sx:
|
|
33
|
-
} =
|
|
34
|
-
let l;
|
|
35
|
-
t[0] !== f ? (l = {
|
|
36
|
-
...c.root,
|
|
37
|
-
...f
|
|
38
|
-
}, t[0] = f, t[1] = l) : l = t[1];
|
|
28
|
+
function u(t) {
|
|
29
|
+
const e = x(10), {
|
|
30
|
+
slotLeft: o,
|
|
31
|
+
slotRight: r,
|
|
32
|
+
sx: n
|
|
33
|
+
} = t;
|
|
39
34
|
let s;
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
]
|
|
35
|
+
e[0] !== n ? (s = {
|
|
36
|
+
...d.root,
|
|
37
|
+
...n
|
|
38
|
+
}, e[0] = n, e[1] = s) : s = e[1];
|
|
39
|
+
let l;
|
|
40
|
+
e[2] !== o ? (l = o && /* @__PURE__ */ c(a, { sx: d.slotLeft, className: "widget-subheader-slot-left", children: o }), e[2] = o, e[3] = l) : l = e[3];
|
|
41
|
+
let i;
|
|
42
|
+
e[4] !== r ? (i = r && /* @__PURE__ */ c(a, { sx: d.slotRight, className: "widget-subheader-slot-right", children: r }), e[4] = r, e[5] = i) : i = e[5];
|
|
43
|
+
let f;
|
|
44
|
+
return e[6] !== s || e[7] !== l || e[8] !== i ? (f = /* @__PURE__ */ g(a, { sx: s, className: "widget-subheader", children: [
|
|
45
|
+
l,
|
|
46
|
+
i
|
|
47
|
+
] }), e[6] = s, e[7] = l, e[8] = i, e[9] = f) : f = e[9], f;
|
|
48
48
|
}
|
|
49
49
|
export {
|
|
50
50
|
u as WidgetSubHeader
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"subheader.js","sources":["../../src/widgets/subheader/style.ts","../../src/widgets/subheader/subheader.tsx"],"sourcesContent":["import type { SxProps, Theme } from '@mui/material'\n\nexport const styles = {\n root: {\n display: 'flex',\n alignItems: 'center',\n gap: ({ spacing }) => spacing(1),\n minHeight: ({ spacing }) => spacing(3),\n },\n slotLeft: {\n flexShrink: 0,\n },\n slotRight: {\n flexGrow: 1,\n display: 'flex',\n justifyContent: 'flex-end',\n alignItems: 'center',\n gap: ({ spacing }) => spacing(1),\n },\n} satisfies Record<string, SxProps<Theme>>\n","import { Box } from '@mui/material'\nimport { styles } from './style'\nimport type { WidgetSubHeaderProps } from './types'\n\n/**\n * Flexible two-slot layout for displaying supplementary widget information such as totals, timestamps, or controls. Uses flexbox with space-between justification.\n *\n * @example\n * ```tsx\n * <WidgetSubHeader\n * slotLeft={<Typography variant=\"caption\">Total: 1,234</Typography>}\n * slotRight={<Typography variant=\"caption\">Updated: 2m ago</Typography>}\n * />\n * ```\n */\nexport function WidgetSubHeader({\n slotLeft,\n slotRight,\n sx,\n}: WidgetSubHeaderProps) {\n return (\n <Box sx={{ ...styles.root, ...sx }}>\n {slotLeft && <Box sx={styles.slotLeft}
|
|
1
|
+
{"version":3,"file":"subheader.js","sources":["../../src/widgets/subheader/style.ts","../../src/widgets/subheader/subheader.tsx"],"sourcesContent":["import type { SxProps, Theme } from '@mui/material'\n\nexport const styles = {\n root: {\n display: 'flex',\n alignItems: 'center',\n gap: ({ spacing }) => spacing(1),\n minHeight: ({ spacing }) => spacing(3),\n },\n slotLeft: {\n flexShrink: 0,\n },\n slotRight: {\n flexGrow: 1,\n display: 'flex',\n justifyContent: 'flex-end',\n alignItems: 'center',\n gap: ({ spacing }) => spacing(1),\n },\n} satisfies Record<string, SxProps<Theme>>\n","import { Box } from '@mui/material'\nimport { styles } from './style'\nimport type { WidgetSubHeaderProps } from './types'\n\n/**\n * Flexible two-slot layout for displaying supplementary widget information such as totals, timestamps, or controls. Uses flexbox with space-between justification.\n *\n * @example\n * ```tsx\n * <WidgetSubHeader\n * slotLeft={<Typography variant=\"caption\">Total: 1,234</Typography>}\n * slotRight={<Typography variant=\"caption\">Updated: 2m ago</Typography>}\n * />\n * ```\n */\nexport function WidgetSubHeader({\n slotLeft,\n slotRight,\n sx,\n}: WidgetSubHeaderProps) {\n return (\n <Box sx={{ ...styles.root, ...sx }} className='widget-subheader'>\n {slotLeft && (\n <Box sx={styles.slotLeft} className='widget-subheader-slot-left'>\n {slotLeft}\n </Box>\n )}\n {slotRight && (\n <Box sx={styles.slotRight} className='widget-subheader-slot-right'>\n {slotRight}\n </Box>\n )}\n </Box>\n )\n}\n"],"names":["styles","root","display","alignItems","gap","spacing","minHeight","slotLeft","flexShrink","slotRight","flexGrow","justifyContent","WidgetSubHeader","t0","$","_c","sx","t1","t2","Box","t3","t4","jsxs"],"mappings":";;;AAEO,MAAMA,IAAS;AAAA,EACpBC,MAAM;AAAA,IACJC,SAAS;AAAA,IACTC,YAAY;AAAA,IACZC,KAAKA,CAAC;AAAA,MAAEC,SAAAA;AAAAA,IAAAA,MAAcA,EAAQ,CAAC;AAAA,IAC/BC,WAAWA,CAAC;AAAA,MAAED,SAAAA;AAAAA,IAAAA,MAAcA,EAAQ,CAAC;AAAA,EAAA;AAAA,EAEvCE,UAAU;AAAA,IACRC,YAAY;AAAA,EAAA;AAAA,EAEdC,WAAW;AAAA,IACTC,UAAU;AAAA,IACVR,SAAS;AAAA,IACTS,gBAAgB;AAAA,IAChBR,YAAY;AAAA,IACZC,KAAKA,CAAC;AAAA,MAAEC,SAAAA;AAAAA,IAAAA,MAAcA,EAAQ,CAAC;AAAA,EAAA;AAEnC;ACJO,SAAAO,EAAAC,GAAA;AAAA,QAAAC,IAAAC,EAAA,EAAA,GAAyB;AAAA,IAAAR,UAAAA;AAAAA,IAAAE,WAAAA;AAAAA,IAAAO,IAAAA;AAAAA,EAAAA,IAAAH;AAIT,MAAAI;AAAA,EAAAH,SAAAE,KAEVC,IAAA;AAAA,IAAA,GAAKjB,EAAMC;AAAAA,IAAK,GAAKe;AAAAA,EAAAA,GAAIF,OAAAE,GAAAF,OAAAG,KAAAA,IAAAH,EAAA,CAAA;AAAA,MAAAI;AAAA,EAAAJ,SAAAP,KAC/BW,IAAAX,uBACEY,GAAA,EAAQ,IAAAnB,EAAMO,UAAqB,WAAA,8BACjCA,UAAAA,EAAAA,CACH,GACDO,OAAAP,GAAAO,OAAAI,KAAAA,IAAAJ,EAAA,CAAA;AAAA,MAAAM;AAAA,EAAAN,SAAAL,KACAW,IAAAX,uBACEU,GAAA,EAAQ,IAAAnB,EAAMS,WAAsB,WAAA,+BAClCA,UAAAA,EAAAA,CACH,GACDK,OAAAL,GAAAK,OAAAM,KAAAA,IAAAN,EAAA,CAAA;AAAA,MAAAO;AAAA,SAAAP,EAAA,CAAA,MAAAG,KAAAH,SAAAI,KAAAJ,EAAA,CAAA,MAAAM,KAVHC,IAAA,gBAAAC,EAACH,GAAA,EAAQ,IAAAF,GAAqC,WAAA,oBAC3CC,UAAAA;AAAAA,IAAAA;AAAAA,IAKAE;AAAAA,EAAAA,GAKH,GAAMN,OAAAG,GAAAH,OAAAI,GAAAJ,OAAAM,GAAAN,OAAAO,KAAAA,IAAAP,EAAA,CAAA,GAXNO;AAWM;"}
|
package/dist/widgets/table.js
CHANGED
|
@@ -6,10 +6,10 @@ import se from "@mui/icons-material/FirstPage";
|
|
|
6
6
|
import ce from "@mui/icons-material/KeyboardArrowLeft";
|
|
7
7
|
import ae from "@mui/icons-material/KeyboardArrowRight";
|
|
8
8
|
import fe from "@mui/icons-material/LastPage";
|
|
9
|
+
import { u as de } from "../use-widget-ref-Ddr_SlJJ.js";
|
|
9
10
|
import "react";
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import { u as B } from "../use-widget-selector-DqRmWQ1K.js";
|
|
11
|
+
import { w as x } from "../widget-store-Bw5zRUGg.js";
|
|
12
|
+
import { u as B } from "../use-widget-selector-DFl2hW0R.js";
|
|
13
13
|
import "zustand/shallow";
|
|
14
14
|
import "@mui/icons-material";
|
|
15
15
|
import { d as J, a as F } from "../exports-Cr43OCul.js";
|
|
@@ -2,11 +2,11 @@ import { jsxs as m, jsx as r } from "react/jsx-runtime";
|
|
|
2
2
|
import { c as y } from "react/compiler-runtime";
|
|
3
3
|
import "react";
|
|
4
4
|
import "echarts";
|
|
5
|
-
import "../widget-store-
|
|
5
|
+
import "../widget-store-Bw5zRUGg.js";
|
|
6
6
|
import "zustand/shallow";
|
|
7
7
|
import { g as b } from "../options-D9wflre6.js";
|
|
8
8
|
import { m as k } from "../utils-BOhInag6.js";
|
|
9
|
-
import { c as v, f as w } from "../download-config-
|
|
9
|
+
import { c as v, f as w } from "../download-config-C3I0jWIL.js";
|
|
10
10
|
import { g as L, b as C, a as I, d as S, e as _, c as A } from "../styles-Y8q7Jff3.js";
|
|
11
11
|
import { Box as l, Skeleton as s } from "@mui/material";
|
|
12
12
|
const Y = v(w);
|
package/dist/widgets/utils.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { d as i, a as n } from "../formatter-B9Bxn1k7.js";
|
|
2
|
-
import { c as f, f as p, s as c } from "../download-config-
|
|
2
|
+
import { c as f, f as p, s as c } from "../download-config-C3I0jWIL.js";
|
|
3
3
|
import { a as m, b as u, c as C, d as b, e as x, f as g, g as F, h as y, n as A } from "../styles-Y8q7Jff3.js";
|
|
4
4
|
function r({
|
|
5
5
|
type: a,
|
package/dist/widgets/wrapper.js
CHANGED
|
@@ -6,8 +6,8 @@ import { useState as H, useLayoutEffect as G } from "react";
|
|
|
6
6
|
import "../lasso-tool-BYbxrJ-7.js";
|
|
7
7
|
import "../cjs-D4KH3azB.js";
|
|
8
8
|
import { S as U } from "../smart-tooltip-D4vwQpFf.js";
|
|
9
|
-
import { u as V } from "../use-widget-selector-
|
|
10
|
-
import { w as M } from "../widget-store-
|
|
9
|
+
import { u as V } from "../use-widget-selector-DFl2hW0R.js";
|
|
10
|
+
import { w as M } from "../widget-store-Bw5zRUGg.js";
|
|
11
11
|
const k = {
|
|
12
12
|
root: {
|
|
13
13
|
".Mui-disabled .MuiAccordionSummary-expandIconWrapper": {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@carto/ps-react-ui",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.6.0",
|
|
4
4
|
"description": "CARTO's Professional Service React Material library",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"devDependencies": {
|
|
@@ -38,10 +38,6 @@
|
|
|
38
38
|
"import": "./dist/components.js",
|
|
39
39
|
"types": "./dist/types/components/index.d.ts"
|
|
40
40
|
},
|
|
41
|
-
"./widgets": {
|
|
42
|
-
"import": "./dist/widgets.js",
|
|
43
|
-
"types": "./dist/types/widgets/index.d.ts"
|
|
44
|
-
},
|
|
45
41
|
"./widgets/actions": {
|
|
46
42
|
"import": "./dist/widgets/actions.js",
|
|
47
43
|
"types": "./dist/types/widgets/actions/index.d.ts"
|
package/src/hooks/index.ts
CHANGED
|
@@ -2,7 +2,7 @@ import { Box, IconButton } from '@mui/material'
|
|
|
2
2
|
import { HighlightAltOutlined } from '@mui/icons-material'
|
|
3
3
|
import { useEffect, useCallback, useRef } from 'react'
|
|
4
4
|
import { widgetStoreActions } from '../../stores/widget-store'
|
|
5
|
-
import type { BrushSelectedItems, BrushToggleProps } from './types'
|
|
5
|
+
import type { BrushSelectedItems, BrushToggleProps, BrushState } from './types'
|
|
6
6
|
import { styles } from './style'
|
|
7
7
|
import { Tooltip } from '../../../components'
|
|
8
8
|
import { getEChartBrushConfig } from '../../echart/utils'
|
|
@@ -17,6 +17,9 @@ export const BRUSH_TOGGLE_TOOL_ID = 'brush-toggle'
|
|
|
17
17
|
* Registers as a config pipeline tool so that brush configuration is automatically
|
|
18
18
|
* re-applied when the base config is updated (e.g., by WidgetLoader).
|
|
19
19
|
*
|
|
20
|
+
* Brush state is stored in the widget store root, and the tool derives its
|
|
21
|
+
* `enabled` flag from the store. This keeps state accessible across component instances.
|
|
22
|
+
*
|
|
20
23
|
* When brush is active, users can drag across bars to select a range.
|
|
21
24
|
* Selection clearing is handled via the chart's brush interactions/toolbox configuration.
|
|
22
25
|
* Only intended for use in fullscreen ToolbarActions for bar and histogram widgets.
|
|
@@ -38,26 +41,19 @@ export function BrushToggle({
|
|
|
38
41
|
}: BrushToggleProps) {
|
|
39
42
|
const selected = useRef<BrushSelectedItems>({ dataIndex: [], seriesIndex: 0 })
|
|
40
43
|
|
|
44
|
+
// Read brush state from widget store root — single source of truth
|
|
41
45
|
const { brush } = useWidgetSelector(id, (w) => ({
|
|
42
|
-
brush: w
|
|
43
|
-
?.enabled,
|
|
46
|
+
brush: (w as BrushState | undefined)?.brush ?? false,
|
|
44
47
|
}))
|
|
45
48
|
|
|
46
|
-
const toggleTool = useCallback(
|
|
47
|
-
(value: boolean) => {
|
|
48
|
-
widgetStoreActions.setToolEnabled(id, BRUSH_TOGGLE_TOOL_ID, value)
|
|
49
|
-
},
|
|
50
|
-
[id],
|
|
51
|
-
)
|
|
52
|
-
|
|
53
49
|
const handleToggle = useCallback(() => {
|
|
54
50
|
const newBrush = !brush
|
|
55
|
-
|
|
51
|
+
widgetStoreActions.setWidget(id, { brush: newBrush })
|
|
56
52
|
|
|
57
53
|
if (newBrush) {
|
|
58
54
|
onBrushSelected?.({ dataIndex: [], seriesIndex: 0 }) // Clear selection when enabling brush
|
|
59
55
|
}
|
|
60
|
-
}, [brush,
|
|
56
|
+
}, [brush, id, onBrushSelected])
|
|
61
57
|
|
|
62
58
|
// Re-dispatch brush action after every ECharts render while brush is active
|
|
63
59
|
useEffect(() => {
|
|
@@ -135,22 +131,17 @@ export function BrushToggle({
|
|
|
135
131
|
|
|
136
132
|
const handleBrushEnd = useCallback(() => {
|
|
137
133
|
onBrushSelected?.(selected.current)
|
|
138
|
-
|
|
139
|
-
}, [onBrushSelected,
|
|
134
|
+
widgetStoreActions.setWidget(id, { brush: false }) // Disable brush after selection is made
|
|
135
|
+
}, [onBrushSelected, id])
|
|
140
136
|
|
|
141
|
-
// Register config tool
|
|
137
|
+
// Register config tool once — fn closure depends on event handlers.
|
|
138
|
+
// Enabled is synced separately to avoid full re-registration on toggle.
|
|
142
139
|
useEffect(() => {
|
|
143
|
-
const existingTool = widgetStoreActions
|
|
144
|
-
.getWidget(id)
|
|
145
|
-
?.registeredTools?.find((tool) => tool.id === BRUSH_TOGGLE_TOOL_ID)
|
|
146
|
-
|
|
147
|
-
const initialEnabled = existingTool?.enabled ?? false
|
|
148
|
-
|
|
149
140
|
widgetStoreActions.registerTool(id, {
|
|
150
141
|
id: BRUSH_TOGGLE_TOOL_ID,
|
|
151
142
|
type: 'config',
|
|
152
143
|
order: 25,
|
|
153
|
-
enabled:
|
|
144
|
+
enabled: false,
|
|
154
145
|
fn: (currentConfig) => {
|
|
155
146
|
const config = currentConfig as Record<string, unknown>
|
|
156
147
|
const option = config.option as EchartOptionsProps | undefined
|
|
@@ -178,6 +169,11 @@ export function BrushToggle({
|
|
|
178
169
|
return () => widgetStoreActions.unregisterTool(id, BRUSH_TOGGLE_TOOL_ID)
|
|
179
170
|
}, [id, handleBrushSelected, handleBrushEnd])
|
|
180
171
|
|
|
172
|
+
// Sync enabled from store — lightweight, no re-registration
|
|
173
|
+
useEffect(() => {
|
|
174
|
+
widgetStoreActions.setToolEnabled(id, BRUSH_TOGGLE_TOOL_ID, brush)
|
|
175
|
+
}, [id, brush])
|
|
176
|
+
|
|
181
177
|
const enableLabel = labels?.enable ?? 'Enable brush selection'
|
|
182
178
|
const disableLabel = labels?.disable ?? 'Disable brush selection'
|
|
183
179
|
const tooltipLabel = brush ? disableLabel : enableLabel
|
|
@@ -217,7 +217,7 @@ describe('ChangeColumn', () => {
|
|
|
217
217
|
|
|
218
218
|
// When config columns match widget columns, fn returns the same reference
|
|
219
219
|
const input = { columns: mockColumns }
|
|
220
|
-
const result = tool?.fn(input
|
|
220
|
+
const result = tool?.fn(input)
|
|
221
221
|
expect(result).toBe(input)
|
|
222
222
|
})
|
|
223
223
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { describe, test, expect, beforeEach, vi } from 'vitest'
|
|
2
2
|
import { render, screen, fireEvent, waitFor } from '@testing-library/react'
|
|
3
3
|
import { Download } from './download'
|
|
4
|
-
import { useWidgetStore } from '../../../widgets'
|
|
4
|
+
import { useWidgetStore } from '../../../widgets/stores'
|
|
5
5
|
import type { DownloadItem } from './types'
|
|
6
6
|
|
|
7
7
|
describe('Download', () => {
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
/* Fullscreen Widget */
|
|
2
2
|
export { FullScreen } from './fullscreen/fullscreen'
|
|
3
|
-
export type {
|
|
3
|
+
export type {
|
|
4
|
+
FullScreenState,
|
|
5
|
+
FullScreenConfig,
|
|
6
|
+
FullScreenProps,
|
|
7
|
+
} from './fullscreen/types'
|
|
4
8
|
|
|
5
9
|
/* Download Widget */
|
|
6
10
|
export { Download } from './download/download'
|
|
@@ -13,7 +17,10 @@ export {
|
|
|
13
17
|
RELATIVE_DATA_TOOL_ID,
|
|
14
18
|
RELATIVE_DATA_CONFIG_TOOL_ID,
|
|
15
19
|
} from './relative-data/relative-data'
|
|
16
|
-
export type {
|
|
20
|
+
export type {
|
|
21
|
+
RelativeDataProps,
|
|
22
|
+
RelativeDataState,
|
|
23
|
+
} from './relative-data/types'
|
|
17
24
|
|
|
18
25
|
/* Zoom Toggle Widget */
|
|
19
26
|
export { ZoomToggle, ZOOM_TOGGLE_TOOL_ID } from './zoom-toggle/zoom-toggle'
|
|
@@ -35,6 +42,7 @@ export type {
|
|
|
35
42
|
SearcherProps,
|
|
36
43
|
SearcherFilterFn,
|
|
37
44
|
SearcherState,
|
|
45
|
+
SearcherStateProps,
|
|
38
46
|
} from './searcher/types'
|
|
39
47
|
|
|
40
48
|
/* Change Column Widget */
|
|
@@ -52,6 +60,7 @@ export {
|
|
|
52
60
|
export type {
|
|
53
61
|
LockSelectionProps,
|
|
54
62
|
LockSelectionState,
|
|
63
|
+
LockSelectionStateProps,
|
|
55
64
|
} from './lock-selection/types'
|
|
56
65
|
|
|
57
66
|
/* Brush Toggle Widget */
|
|
@@ -3,6 +3,7 @@ import { render, screen, fireEvent } from '@testing-library/react'
|
|
|
3
3
|
import { LockSelection, LOCK_SELECTION_TOOL_ID } from './lock-selection'
|
|
4
4
|
import { useWidgetStore } from '../../stores/widget-store'
|
|
5
5
|
import type { EchartWidgetData } from '../../echart/types'
|
|
6
|
+
import type { LockSelectionState } from './types'
|
|
6
7
|
import { WidgetLoader } from '../../loader/loader'
|
|
7
8
|
|
|
8
9
|
// Test data
|
|
@@ -110,6 +111,19 @@ describe('LockSelection', () => {
|
|
|
110
111
|
expect(tool?.enabled).toBe(false)
|
|
111
112
|
})
|
|
112
113
|
|
|
114
|
+
test('clears lock state when selectedItems becomes empty while locked', () => {
|
|
115
|
+
// Simulate remount: isLocked persists in store but selectedItems is now empty
|
|
116
|
+
useWidgetStore
|
|
117
|
+
.getState()
|
|
118
|
+
.setWidget(widgetId, { isLocked: true, lockedItems: ['Electronics'] })
|
|
119
|
+
|
|
120
|
+
render(<LockSelection id={widgetId} selectedItems={[]} />)
|
|
121
|
+
|
|
122
|
+
const widget = useWidgetStore.getState().getWidget(widgetId)
|
|
123
|
+
expect((widget as LockSelectionState | undefined)?.isLocked).toBe(false)
|
|
124
|
+
expect((widget as LockSelectionState | undefined)?.lockedItems).toEqual([])
|
|
125
|
+
})
|
|
126
|
+
|
|
113
127
|
test('has active state when locked', () => {
|
|
114
128
|
render(<LockSelection id={widgetId} selectedItems={['Electronics']} />)
|
|
115
129
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { IconButton } from '@mui/material'
|
|
2
2
|
import { CheckBoxOutlined } from '@mui/icons-material'
|
|
3
|
-
import { useCallback, useEffect
|
|
3
|
+
import { useCallback, useEffect } from 'react'
|
|
4
4
|
import type { LockSelectionProps, LockSelectionState } from './types'
|
|
5
5
|
import { actionButtonStyles } from '../shared/styles'
|
|
6
6
|
import { Tooltip } from '../../../components'
|
|
@@ -39,28 +39,35 @@ export function LockSelection({
|
|
|
39
39
|
}))
|
|
40
40
|
|
|
41
41
|
const isLocked = storeIsLocked ?? false
|
|
42
|
-
const lockedItems = useMemo(
|
|
43
|
-
() => (isLocked ? selectedItems : []),
|
|
44
|
-
[isLocked, selectedItems],
|
|
45
|
-
)
|
|
46
42
|
|
|
47
|
-
// Register tool
|
|
43
|
+
// Register tool once — fn reads lockedItems from the store at execution time
|
|
48
44
|
useEffect(() => {
|
|
49
45
|
widgetStoreActions.registerTool(id, {
|
|
50
46
|
id: LOCK_SELECTION_TOOL_ID,
|
|
51
47
|
order,
|
|
52
|
-
enabled:
|
|
53
|
-
fn: (data
|
|
54
|
-
const
|
|
48
|
+
enabled: false,
|
|
49
|
+
fn: (data) => {
|
|
50
|
+
const widget = widgetStoreActions.getWidget<LockSelectionState>(id)
|
|
51
|
+
const items = widget?.lockedItems ?? []
|
|
55
52
|
if (items.length === 0) return data
|
|
56
53
|
|
|
57
54
|
return filterDataByLockedItems(data as EchartWidgetData, items)
|
|
58
55
|
},
|
|
59
|
-
config: { lockedItems },
|
|
60
56
|
})
|
|
61
57
|
|
|
62
58
|
return () => widgetStoreActions.unregisterTool(id, LOCK_SELECTION_TOOL_ID)
|
|
63
|
-
}, [id, order
|
|
59
|
+
}, [id, order])
|
|
60
|
+
|
|
61
|
+
// Sync enabled from store — lightweight, no re-registration.
|
|
62
|
+
// When selectedItems is empty (e.g., remount with no active selection),
|
|
63
|
+
// disable the tool and clear stale lock state.
|
|
64
|
+
useEffect(() => {
|
|
65
|
+
if (isLocked && selectedItems.length === 0) {
|
|
66
|
+
widgetStoreActions.setWidget(id, { isLocked: false, lockedItems: [] })
|
|
67
|
+
return
|
|
68
|
+
}
|
|
69
|
+
widgetStoreActions.setToolEnabled(id, LOCK_SELECTION_TOOL_ID, isLocked)
|
|
70
|
+
}, [id, isLocked, selectedItems.length])
|
|
64
71
|
|
|
65
72
|
const handleToggle = useCallback(() => {
|
|
66
73
|
if (isLocked) {
|