@carto/ps-react-ui 4.3.8 → 4.3.10
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/components.js +692 -700
- package/dist/components.js.map +1 -1
- package/dist/{lasso-tool-jl4YK02H.js → lasso-tool-BYbxrJ-7.js} +184 -190
- package/dist/lasso-tool-BYbxrJ-7.js.map +1 -0
- package/dist/{row-BKmVAUN5.js → row-DTCV0Ocm.js} +2 -2
- package/dist/row-DTCV0Ocm.js.map +1 -0
- package/dist/{series-D1pynfeh.js → series-CYNOu2Ju.js} +2 -2
- package/dist/{series-D1pynfeh.js.map → series-CYNOu2Ju.js.map} +1 -1
- package/dist/smart-tooltip-D4vwQpFf.js +37 -0
- package/dist/smart-tooltip-D4vwQpFf.js.map +1 -0
- package/dist/{styles-DrPyd0y5.js → styles-CAroD5Rc.js} +12 -12
- package/dist/styles-CAroD5Rc.js.map +1 -0
- package/dist/types/widgets/_shared/chart-config/option-builders.d.ts +1 -1
- package/dist/types/widgets/category/config.d.ts +3 -10
- package/dist/types/widgets/range/config.d.ts +0 -4
- package/dist/types/widgets/spread/config.d.ts +0 -5
- package/dist/types/widgets/table/components/cell.d.ts +4 -2
- package/dist/types/widgets/table/config.d.ts +1 -2
- package/dist/types/widgets/table/table-ui.d.ts +1 -1
- package/dist/types/widgets/table/types.d.ts +1 -1
- package/dist/types/widgets/wrapper/components/options.d.ts +1 -1
- package/dist/widgets/actions.js +607 -621
- package/dist/widgets/actions.js.map +1 -1
- package/dist/widgets/bar.js +48 -49
- package/dist/widgets/bar.js.map +1 -1
- package/dist/widgets/category.js +28 -28
- package/dist/widgets/category.js.map +1 -1
- package/dist/widgets/formula.js +3 -3
- package/dist/widgets/histogram.js +50 -50
- package/dist/widgets/histogram.js.map +1 -1
- package/dist/widgets/markdown.js +1 -1
- package/dist/widgets/pie.js +9 -9
- package/dist/widgets/pie.js.map +1 -1
- package/dist/widgets/range.js +1 -1
- package/dist/widgets/range.js.map +1 -1
- package/dist/widgets/scatterplot.js +13 -13
- package/dist/widgets/scatterplot.js.map +1 -1
- package/dist/widgets/spread.js +3 -3
- package/dist/widgets/spread.js.map +1 -1
- package/dist/widgets/table.js +242 -241
- package/dist/widgets/table.js.map +1 -1
- package/dist/widgets/timeseries.js +3 -3
- package/dist/widgets/timeseries.js.map +1 -1
- package/dist/widgets/wrapper.js +152 -162
- package/dist/widgets/wrapper.js.map +1 -1
- package/package.json +1 -1
- package/src/components/basemaps/basemaps.tsx +3 -1
- package/src/components/geolocation-controls/geolocation-controls.tsx +10 -6
- package/src/components/lasso-tool/lasso-tool-inline.tsx +6 -2
- package/src/components/lasso-tool/lasso-tool.tsx +9 -3
- package/src/components/list-data/list-data-skeleton.tsx +1 -1
- package/src/components/list-data/list-data.tsx +5 -3
- package/src/components/measurement-tools/measurement-tools.tsx +5 -1
- package/src/components/smart-tooltip/smart-tooltip.tsx +3 -1
- package/src/widgets/_shared/chart-config/option-builders.test.ts +2 -2
- package/src/widgets/_shared/chart-config/option-builders.ts +6 -4
- package/src/widgets/actions/download/download.test.tsx +6 -2
- package/src/widgets/actions/download/download.tsx +3 -1
- package/src/widgets/actions/fullscreen/fullscreen.tsx +8 -1
- package/src/widgets/actions/relative-data/relative-data.tsx +2 -6
- package/src/widgets/actions/searcher/searcher.tsx +0 -6
- package/src/widgets/bar/config.ts +8 -4
- package/src/widgets/bar/skeleton.tsx +1 -1
- package/src/widgets/category/components/category-row-multi.tsx +1 -1
- package/src/widgets/category/config.ts +1 -11
- package/src/widgets/formula/components/row.tsx +1 -1
- package/src/widgets/histogram/config.ts +7 -2
- package/src/widgets/histogram/skeleton.tsx +2 -2
- package/src/widgets/pie/skeleton.tsx +1 -1
- package/src/widgets/range/config.ts +0 -5
- package/src/widgets/scatterplot/skeleton.tsx +2 -2
- package/src/widgets/spread/config.ts +0 -6
- package/src/widgets/table/components/cell.tsx +5 -3
- package/src/widgets/table/components/row.tsx +6 -1
- package/src/widgets/table/config.ts +1 -1
- package/src/widgets/table/table-ui.tsx +1 -1
- package/src/widgets/table/types.ts +1 -1
- package/src/widgets/timeseries/skeleton.tsx +1 -1
- package/src/widgets/wrapper/components/actions.test.tsx +6 -2
- package/src/widgets/wrapper/components/actions.tsx +3 -1
- package/src/widgets/wrapper/components/options.test.tsx +12 -4
- package/src/widgets/wrapper/components/options.tsx +8 -3
- package/src/widgets/wrapper/wrapper-ui.tsx +5 -2
- package/src/widgets/wrapper/wrapper.tsx +2 -4
- package/dist/lasso-tool-jl4YK02H.js.map +0 -1
- package/dist/row-BKmVAUN5.js.map +0 -1
- package/dist/smart-tooltip-BEtBaIdz.js +0 -39
- package/dist/smart-tooltip-BEtBaIdz.js.map +0 -1
- package/dist/styles-DrPyd0y5.js.map +0 -1
- package/dist/types/widgets/actions/relative-data/style.d.ts +0 -8
- package/dist/types/widgets/actions/zoom-toggle/index.d.ts +0 -2
- package/dist/types/widgets/table/components/index.d.ts +0 -4
- package/src/widgets/actions/relative-data/style.ts +0 -9
- package/src/widgets/actions/zoom-toggle/index.ts +0 -2
- package/src/widgets/table/components/index.ts +0 -4
|
@@ -12,8 +12,10 @@ const DEFAULT_LABELS = {
|
|
|
12
12
|
showLess: 'Show Less',
|
|
13
13
|
} as const
|
|
14
14
|
|
|
15
|
+
const EMPTY_DATA: ListDataProps['data'] = []
|
|
16
|
+
|
|
15
17
|
export function ListDataUI({
|
|
16
|
-
data =
|
|
18
|
+
data = EMPTY_DATA,
|
|
17
19
|
isLoading = false,
|
|
18
20
|
maxItems = 5,
|
|
19
21
|
labels = DEFAULT_LABELS,
|
|
@@ -47,11 +49,11 @@ export function ListDataUI({
|
|
|
47
49
|
return (
|
|
48
50
|
<>
|
|
49
51
|
<List id='expandable-list' role='list'>
|
|
50
|
-
{items.map((item
|
|
52
|
+
{items.map((item) => (
|
|
51
53
|
<SmartTooltip<HTMLLIElement>
|
|
52
54
|
// Default tooltip props
|
|
53
55
|
followCursor={false}
|
|
54
|
-
key={
|
|
56
|
+
key={item.id}
|
|
55
57
|
placement='top'
|
|
56
58
|
arrow
|
|
57
59
|
title={item.tooltipTitle}
|
|
@@ -49,6 +49,10 @@ import type {
|
|
|
49
49
|
} from '../types'
|
|
50
50
|
import { Tooltip } from '../tooltip/tooltip'
|
|
51
51
|
|
|
52
|
+
const EMPTY_PAPER_PROPS: NonNullable<
|
|
53
|
+
MeasurementToolsComponentProps['PaperProps']
|
|
54
|
+
> = {}
|
|
55
|
+
|
|
52
56
|
export function MeasurementToolsUI({
|
|
53
57
|
enabled,
|
|
54
58
|
actionProps,
|
|
@@ -57,7 +61,7 @@ export function MeasurementToolsUI({
|
|
|
57
61
|
modesMapping = DEFAULT_MEASUREMENT_TOOLS_MODES_MAPPING,
|
|
58
62
|
unitsMapping = DEFAULT_MEASUREMENT_TOOLS_UNITS_MAPPING,
|
|
59
63
|
modeSelected,
|
|
60
|
-
PaperProps: { sx, ...PaperProps } =
|
|
64
|
+
PaperProps: { sx, ...PaperProps } = EMPTY_PAPER_PROPS,
|
|
61
65
|
units,
|
|
62
66
|
unitSelected,
|
|
63
67
|
onActionToggle,
|
|
@@ -2,9 +2,11 @@ import type { TooltipProps } from '@mui/material'
|
|
|
2
2
|
import { useLayoutEffect, useRef, useState, type JSX, type Ref } from 'react'
|
|
3
3
|
import { Tooltip } from '../tooltip/tooltip'
|
|
4
4
|
|
|
5
|
+
const EMPTY_DEPENDENCIES: unknown[] = []
|
|
6
|
+
|
|
5
7
|
export function SmartTooltip<T extends HTMLElement>({
|
|
6
8
|
title,
|
|
7
|
-
dependencies =
|
|
9
|
+
dependencies = EMPTY_DEPENDENCIES,
|
|
8
10
|
timeout = 500,
|
|
9
11
|
TooltipProps,
|
|
10
12
|
children,
|
|
@@ -6,8 +6,8 @@ describe('niceNum', () => {
|
|
|
6
6
|
expect(niceNum(0)).toBe(0)
|
|
7
7
|
})
|
|
8
8
|
|
|
9
|
-
it('should return
|
|
10
|
-
expect(niceNum(-5)).toBe(
|
|
9
|
+
it('should return the same negative value for negative numbers', () => {
|
|
10
|
+
expect(niceNum(-5)).toBe(-5)
|
|
11
11
|
})
|
|
12
12
|
|
|
13
13
|
it('should round 547 to 600', () => {
|
|
@@ -13,12 +13,14 @@ import type {
|
|
|
13
13
|
* Rounds a value up to the nearest "nice" number.
|
|
14
14
|
* A nice number is a multiple of 10^floor(log10(value)).
|
|
15
15
|
*
|
|
16
|
-
* Examples: 547 → 600, 200 → 200, 1200 → 2000, 18 → 20, 5 → 5
|
|
16
|
+
* Examples: 547 → 600, 200 → 200, 1200 → 2000, 18 → 20, 5 → 5, -547 → -500
|
|
17
17
|
*/
|
|
18
18
|
export function niceNum(value: number): number {
|
|
19
|
-
if (value
|
|
20
|
-
const
|
|
21
|
-
|
|
19
|
+
if (value === 0) return 0
|
|
20
|
+
const absValue = Math.abs(value)
|
|
21
|
+
const base = Math.pow(10, Math.floor(Math.log10(absValue)))
|
|
22
|
+
const rounded = Math.ceil(absValue / base) * base
|
|
23
|
+
return value < 0 ? -rounded : rounded
|
|
22
24
|
}
|
|
23
25
|
|
|
24
26
|
/**
|
|
@@ -271,8 +271,12 @@ describe('Download', () => {
|
|
|
271
271
|
const parentClickHandler = vi.fn()
|
|
272
272
|
|
|
273
273
|
render(
|
|
274
|
-
|
|
275
|
-
|
|
274
|
+
<div
|
|
275
|
+
role='button'
|
|
276
|
+
tabIndex={0}
|
|
277
|
+
onClick={parentClickHandler}
|
|
278
|
+
onKeyDown={parentClickHandler}
|
|
279
|
+
>
|
|
276
280
|
<Download id={widgetId} items={mockDownload} />
|
|
277
281
|
</div>,
|
|
278
282
|
)
|
|
@@ -12,10 +12,12 @@ import { useState, type MouseEvent } from 'react'
|
|
|
12
12
|
import { useWidgetStore } from '../../../widgets'
|
|
13
13
|
import { useShallow } from 'zustand/shallow'
|
|
14
14
|
|
|
15
|
+
const EMPTY_LABELS: NonNullable<DownloadProps['labels']> = {}
|
|
16
|
+
|
|
15
17
|
export function Download({
|
|
16
18
|
id,
|
|
17
19
|
items,
|
|
18
|
-
labels =
|
|
20
|
+
labels = EMPTY_LABELS,
|
|
19
21
|
Icon,
|
|
20
22
|
IconButtonProps,
|
|
21
23
|
}: DownloadProps) {
|
|
@@ -15,13 +15,20 @@ import type {
|
|
|
15
15
|
import { styles } from './styles'
|
|
16
16
|
import { useShallow } from 'zustand/shallow'
|
|
17
17
|
|
|
18
|
+
const EMPTY_DIALOG_CONTENT_PROPS: NonNullable<
|
|
19
|
+
FullScreenProps['DialogContentProps']
|
|
20
|
+
> = {}
|
|
21
|
+
|
|
18
22
|
export function FullScreen({
|
|
19
23
|
id,
|
|
20
24
|
labels,
|
|
21
25
|
children,
|
|
22
26
|
Icon,
|
|
23
27
|
IconButtonProps,
|
|
24
|
-
DialogContentProps: {
|
|
28
|
+
DialogContentProps: {
|
|
29
|
+
sx,
|
|
30
|
+
...DialogContentProps
|
|
31
|
+
} = EMPTY_DIALOG_CONTENT_PROPS,
|
|
25
32
|
DialogProps,
|
|
26
33
|
}: FullScreenProps) {
|
|
27
34
|
const isFullScreen = useWidgetStore(
|
|
@@ -73,13 +73,9 @@ export function RelativeData({
|
|
|
73
73
|
return () => unregisterTool(id, RELATIVE_DATA_TOOL_ID)
|
|
74
74
|
}, [id, order, registerTool, unregisterTool, isRelative])
|
|
75
75
|
|
|
76
|
-
// Update enabled flag when toggle changes
|
|
77
|
-
useEffect(() => {
|
|
78
|
-
setToolEnabled(id, RELATIVE_DATA_TOOL_ID, isRelative)
|
|
79
|
-
}, [id, isRelative, setToolEnabled])
|
|
80
|
-
|
|
81
76
|
const handleToggle = useCallback(() => {
|
|
82
77
|
const newIsRelative = !isRelative
|
|
78
|
+
setToolEnabled(id, RELATIVE_DATA_TOOL_ID, newIsRelative)
|
|
83
79
|
let max = previousMaxValue.current
|
|
84
80
|
|
|
85
81
|
if (newIsRelative) {
|
|
@@ -110,7 +106,7 @@ export function RelativeData({
|
|
|
110
106
|
}
|
|
111
107
|
: originalFormatter.current,
|
|
112
108
|
})
|
|
113
|
-
}, [isRelative, setWidget, id, getWidget])
|
|
109
|
+
}, [isRelative, setWidget, id, getWidget, setToolEnabled])
|
|
114
110
|
|
|
115
111
|
const tooltipLabel = isRelative
|
|
116
112
|
? (labels?.absolute ?? 'Show absolute values')
|
|
@@ -53,7 +53,6 @@ export function Searcher({
|
|
|
53
53
|
const setWidget = useWidgetStore((state) => state.setWidget)
|
|
54
54
|
const registerTool = useWidgetStore((state) => state.registerTool)
|
|
55
55
|
const unregisterTool = useWidgetStore((state) => state.unregisterTool)
|
|
56
|
-
const setToolEnabled = useWidgetStore((state) => state.setToolEnabled)
|
|
57
56
|
const updateToolConfig = useWidgetStore((state) => state.updateToolConfig)
|
|
58
57
|
|
|
59
58
|
const setSearchText = useCallback(
|
|
@@ -85,11 +84,6 @@ export function Searcher({
|
|
|
85
84
|
return () => unregisterTool(id, SEARCHER_TOOL_ID)
|
|
86
85
|
}, [id, order, filter, registerTool, unregisterTool, enabled, searchText])
|
|
87
86
|
|
|
88
|
-
// Update enabled flag when it changes
|
|
89
|
-
useEffect(() => {
|
|
90
|
-
setToolEnabled(id, SEARCHER_TOOL_ID, enabled)
|
|
91
|
-
}, [id, enabled, setToolEnabled])
|
|
92
|
-
|
|
93
87
|
// Update config when search text changes (debounced)
|
|
94
88
|
const debouncedUpdateConfig = useCallback(
|
|
95
89
|
(text: string) => {
|
|
@@ -47,6 +47,7 @@ function getOption({
|
|
|
47
47
|
}: BarConfig): EchartOptionsProps {
|
|
48
48
|
const hasLegend = (data?.length ?? 0) > 1
|
|
49
49
|
|
|
50
|
+
let niceMin = 0
|
|
50
51
|
let niceMax = 1
|
|
51
52
|
|
|
52
53
|
return {
|
|
@@ -67,23 +68,26 @@ function getOption({
|
|
|
67
68
|
},
|
|
68
69
|
yAxis: {
|
|
69
70
|
type: 'value' as const,
|
|
70
|
-
min:
|
|
71
|
+
min: (extent: { min: number }) => {
|
|
72
|
+
niceMin = extent.min < 0 ? niceNum(extent.min) : 0
|
|
73
|
+
return niceMin
|
|
74
|
+
},
|
|
71
75
|
max: (extent: { min: number; max: number }) => {
|
|
72
76
|
niceMax = extent.max <= 0 ? 1 : niceNum(extent.max)
|
|
73
77
|
return niceMax
|
|
74
78
|
},
|
|
75
|
-
splitNumber: 1,
|
|
76
79
|
axisLabel: {
|
|
77
80
|
fontSize: theme.typography.overlineDelicate.fontSize,
|
|
78
81
|
fontFamily: theme.typography.overlineDelicate.fontFamily,
|
|
79
82
|
margin: parseInt(theme.spacing(1)),
|
|
80
83
|
show: true,
|
|
81
84
|
showMaxLabel: true,
|
|
82
|
-
showMinLabel:
|
|
85
|
+
showMinLabel: true,
|
|
83
86
|
verticalAlign: 'bottom' as const,
|
|
84
87
|
inside: true,
|
|
85
88
|
formatter: (value: number) => {
|
|
86
|
-
if (value !== niceMax) return ''
|
|
89
|
+
if (value !== niceMax && value !== niceMin) return ''
|
|
90
|
+
if (value === 0) return ''
|
|
87
91
|
return formatter ? formatter(value) : String(value)
|
|
88
92
|
},
|
|
89
93
|
},
|
|
@@ -30,7 +30,7 @@ export function CategoryRowMulti({
|
|
|
30
30
|
<Typography sx={styles.rowLabel}>{name}</Typography>
|
|
31
31
|
<Box sx={styles.barContainer}>
|
|
32
32
|
{values.map((value, index) => (
|
|
33
|
-
<Box key={`${name}-${value}
|
|
33
|
+
<Box key={`${name}-${value}`} sx={styles.multiBarRow}>
|
|
34
34
|
<Box sx={styles.multiBarContainer}>
|
|
35
35
|
<CategoryBar
|
|
36
36
|
value={value}
|
|
@@ -4,22 +4,12 @@ import type {
|
|
|
4
4
|
CategoryWidgetConfig,
|
|
5
5
|
CategoryWidgetData,
|
|
6
6
|
CategorySeriesConfig,
|
|
7
|
-
CategoryLabels,
|
|
8
7
|
} from './types'
|
|
9
8
|
|
|
10
|
-
|
|
9
|
+
interface CategoryDownloadConfigProps extends ConfigProps {
|
|
11
10
|
series?: CategorySeriesConfig[]
|
|
12
11
|
}
|
|
13
12
|
|
|
14
|
-
export interface CategoryConfigProps {
|
|
15
|
-
data?: CategoryWidgetData
|
|
16
|
-
series?: CategorySeriesConfig[]
|
|
17
|
-
formatter?: (value: number) => string
|
|
18
|
-
maxItems?: number
|
|
19
|
-
labels?: CategoryLabels
|
|
20
|
-
max?: number
|
|
21
|
-
}
|
|
22
|
-
|
|
23
13
|
export function categoryDownloadConfig({
|
|
24
14
|
refUI,
|
|
25
15
|
series,
|
|
@@ -11,7 +11,7 @@ export function Row(props: RowProps) {
|
|
|
11
11
|
|
|
12
12
|
return data?.map((_, index) => {
|
|
13
13
|
return (
|
|
14
|
-
<Box sx={styles.row} key={index}>
|
|
14
|
+
<Box sx={styles.row} key={`row-${index}`}>
|
|
15
15
|
{typeof props.children === 'function'
|
|
16
16
|
? props.children({ index })
|
|
17
17
|
: props.children}
|
|
@@ -49,6 +49,7 @@ function getOption({
|
|
|
49
49
|
}: HistogramConfig): EchartOptionsProps {
|
|
50
50
|
const hasLegend = (data?.length ?? 0) > 1
|
|
51
51
|
|
|
52
|
+
let niceMin = 0
|
|
52
53
|
let niceMax = 1
|
|
53
54
|
|
|
54
55
|
return {
|
|
@@ -86,7 +87,10 @@ function getOption({
|
|
|
86
87
|
},
|
|
87
88
|
yAxis: {
|
|
88
89
|
type: 'value' as const,
|
|
89
|
-
min:
|
|
90
|
+
min: (extent: { min: number }) => {
|
|
91
|
+
niceMin = extent.min < 0 ? niceNum(extent.min) : 0
|
|
92
|
+
return niceMin
|
|
93
|
+
},
|
|
90
94
|
max: (extent: { min: number; max: number }) => {
|
|
91
95
|
niceMax = extent.max <= 0 ? 1 : niceNum(extent.max)
|
|
92
96
|
return niceMax
|
|
@@ -101,7 +105,8 @@ function getOption({
|
|
|
101
105
|
showMinLabel: true,
|
|
102
106
|
verticalAlign: 'bottom' as const,
|
|
103
107
|
formatter: (value: number) => {
|
|
104
|
-
if (value !== niceMax) return ''
|
|
108
|
+
if (value !== niceMax && value !== niceMin) return ''
|
|
109
|
+
if (value === 0) return ''
|
|
105
110
|
return formatter ? formatter(value) : String(value)
|
|
106
111
|
},
|
|
107
112
|
},
|
|
@@ -22,7 +22,7 @@ export function HistogramSkeleton() {
|
|
|
22
22
|
const height = `${heights[i]}%`
|
|
23
23
|
return (
|
|
24
24
|
<Skeleton
|
|
25
|
-
key={i}
|
|
25
|
+
key={`skeleton-bar-${i}`}
|
|
26
26
|
variant='rectangular'
|
|
27
27
|
sx={{
|
|
28
28
|
flex: 1,
|
|
@@ -44,7 +44,7 @@ export function HistogramSkeleton() {
|
|
|
44
44
|
{Array(4)
|
|
45
45
|
.fill(0)
|
|
46
46
|
.map((_, i) => (
|
|
47
|
-
<Skeleton key={i} width={32} height={8} />
|
|
47
|
+
<Skeleton key={`skeleton-label-${i}`} width={32} height={8} />
|
|
48
48
|
))}
|
|
49
49
|
</Box>
|
|
50
50
|
</Box>
|
|
@@ -24,7 +24,7 @@ export function ScatterplotSkeleton() {
|
|
|
24
24
|
<Box sx={styles.skeleton.graph.container}>
|
|
25
25
|
{SCATTER_POINTS.map((point, index) => (
|
|
26
26
|
<Skeleton
|
|
27
|
-
key={index}
|
|
27
|
+
key={`skeleton-point-${index}`}
|
|
28
28
|
variant='circular'
|
|
29
29
|
width={12}
|
|
30
30
|
height={12}
|
|
@@ -42,7 +42,7 @@ export function ScatterplotSkeleton() {
|
|
|
42
42
|
.fill(0)
|
|
43
43
|
.map((_, i) => (
|
|
44
44
|
<Box
|
|
45
|
-
key={i}
|
|
45
|
+
key={`skeleton-${i}`}
|
|
46
46
|
sx={{
|
|
47
47
|
display: 'flex',
|
|
48
48
|
alignItems: 'center',
|
|
@@ -1,12 +1,6 @@
|
|
|
1
1
|
import { downloadToCSV, downloadToPNG, type DownloadItem } from '../actions'
|
|
2
2
|
import type { ConfigProps } from '../loader/types'
|
|
3
3
|
import type { SpreadWidgetConfig, SpreadWidgetData } from './types'
|
|
4
|
-
import type { SeriesConfig } from '../formula/types'
|
|
5
|
-
|
|
6
|
-
export interface SpreadConfigProps {
|
|
7
|
-
formatter?: (value: number) => string
|
|
8
|
-
series?: SeriesConfig[]
|
|
9
|
-
}
|
|
10
4
|
|
|
11
5
|
export function spreadDownloadConfig({
|
|
12
6
|
refUI,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { TableCell as MuiTableCell, Link, Typography } from '@mui/material'
|
|
2
2
|
import ReactMarkdown, { type Components } from 'react-markdown'
|
|
3
|
-
import type { TableColumn } from '../types'
|
|
3
|
+
import type { TableColumn, TableRow } from '../types'
|
|
4
4
|
import { getCellValue } from '../helpers'
|
|
5
5
|
import type { ReactNode } from 'react'
|
|
6
6
|
|
|
@@ -10,6 +10,8 @@ import type { ReactNode } from 'react'
|
|
|
10
10
|
export interface CellProps {
|
|
11
11
|
/** Column definition */
|
|
12
12
|
column: TableColumn
|
|
13
|
+
/** Full table row for context */
|
|
14
|
+
row: TableRow
|
|
13
15
|
/** Cell value */
|
|
14
16
|
value: unknown
|
|
15
17
|
}
|
|
@@ -54,12 +56,12 @@ const CELL_MARKDOWN_COMPONENTS: Components = {
|
|
|
54
56
|
* Markdown is rendered when the raw value is a string and no formatter is defined.
|
|
55
57
|
* If a formatter is used, its output is rendered directly without markdown parsing.
|
|
56
58
|
*/
|
|
57
|
-
export function Cell({ column, value }: CellProps) {
|
|
59
|
+
export function Cell({ column, row, value }: CellProps) {
|
|
58
60
|
// If formatter is defined, use it directly without markdown
|
|
59
61
|
if (column.formatter) {
|
|
60
62
|
return (
|
|
61
63
|
<MuiTableCell align={column.align}>
|
|
62
|
-
{column.formatter(value)}
|
|
64
|
+
{column.formatter(value, row)}
|
|
63
65
|
</MuiTableCell>
|
|
64
66
|
)
|
|
65
67
|
}
|
|
@@ -53,7 +53,12 @@ export function Row({
|
|
|
53
53
|
</TableCell>
|
|
54
54
|
)}
|
|
55
55
|
{columns.map((column) => (
|
|
56
|
-
<Cell
|
|
56
|
+
<Cell
|
|
57
|
+
key={column.id}
|
|
58
|
+
row={row}
|
|
59
|
+
column={column}
|
|
60
|
+
value={row[column.id]}
|
|
61
|
+
/>
|
|
57
62
|
))}
|
|
58
63
|
</MuiTableRow>
|
|
59
64
|
)
|
|
@@ -8,7 +8,7 @@ import type {
|
|
|
8
8
|
SortDirection,
|
|
9
9
|
} from './types'
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
const DEFAULT_MODE: Mode = 'local'
|
|
12
12
|
export const DEFAULT_PAGE = 0
|
|
13
13
|
export const DEFAULT_ROWS_PER_PAGE = 10
|
|
14
14
|
export const DEFAULT_ROWS_PER_PAGE_OPTIONS = [5, 10, 25, 50]
|
|
@@ -18,7 +18,7 @@ import type { TableUIProps } from './types'
|
|
|
18
18
|
/**
|
|
19
19
|
* Props for the base Table component
|
|
20
20
|
*/
|
|
21
|
-
|
|
21
|
+
interface TableComponentProps extends MuiTableProps {
|
|
22
22
|
/** Table element ref */
|
|
23
23
|
ref?: Ref<HTMLTableElement>
|
|
24
24
|
}
|
|
@@ -42,8 +42,12 @@ describe('Actions', () => {
|
|
|
42
42
|
]
|
|
43
43
|
|
|
44
44
|
render(
|
|
45
|
-
|
|
46
|
-
|
|
45
|
+
<div
|
|
46
|
+
role='button'
|
|
47
|
+
tabIndex={0}
|
|
48
|
+
onClick={parentOnClick}
|
|
49
|
+
onKeyDown={parentOnClick}
|
|
50
|
+
>
|
|
47
51
|
<Actions actions={actions} />
|
|
48
52
|
</div>,
|
|
49
53
|
)
|
|
@@ -2,7 +2,9 @@ import { Box } from '@mui/material'
|
|
|
2
2
|
import type { WrapperActionsProps } from '../types'
|
|
3
3
|
import { styles } from '../styles'
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
const EMPTY_ACTIONS: NonNullable<WrapperActionsProps['actions']> = []
|
|
6
|
+
|
|
7
|
+
export function Actions({ actions = EMPTY_ACTIONS }: WrapperActionsProps) {
|
|
6
8
|
return (
|
|
7
9
|
<Box sx={styles.actions} className='widget-wrapper-actions'>
|
|
8
10
|
{actions.map((action, index) => {
|
|
@@ -88,8 +88,12 @@ describe('Options', () => {
|
|
|
88
88
|
]
|
|
89
89
|
|
|
90
90
|
render(
|
|
91
|
-
|
|
92
|
-
|
|
91
|
+
<div
|
|
92
|
+
role='button'
|
|
93
|
+
tabIndex={0}
|
|
94
|
+
onClick={parentOnClick}
|
|
95
|
+
onKeyDown={parentOnClick}
|
|
96
|
+
>
|
|
93
97
|
<Options options={options} />
|
|
94
98
|
</div>,
|
|
95
99
|
)
|
|
@@ -112,8 +116,12 @@ describe('Options', () => {
|
|
|
112
116
|
]
|
|
113
117
|
|
|
114
118
|
render(
|
|
115
|
-
|
|
116
|
-
|
|
119
|
+
<div
|
|
120
|
+
role='button'
|
|
121
|
+
tabIndex={0}
|
|
122
|
+
onClick={parentOnClick}
|
|
123
|
+
onKeyDown={parentOnClick}
|
|
124
|
+
>
|
|
117
125
|
<Options options={options} />
|
|
118
126
|
</div>,
|
|
119
127
|
)
|
|
@@ -10,7 +10,12 @@ import type { WrapperOptionsProps } from '../types'
|
|
|
10
10
|
import { useState } from 'react'
|
|
11
11
|
import { styles } from '../styles'
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
const EMPTY_OPTIONS: NonNullable<WrapperOptionsProps['options']> = []
|
|
14
|
+
|
|
15
|
+
export function Options({
|
|
16
|
+
labels,
|
|
17
|
+
options = EMPTY_OPTIONS,
|
|
18
|
+
}: WrapperOptionsProps) {
|
|
14
19
|
const [anchorEl, setAnchorEl] = useState<null | HTMLElement>(null)
|
|
15
20
|
|
|
16
21
|
const handleOptionAction = (
|
|
@@ -57,9 +62,9 @@ export function Options({ labels, options = [] }: WrapperOptionsProps) {
|
|
|
57
62
|
},
|
|
58
63
|
}}
|
|
59
64
|
>
|
|
60
|
-
{options.map((option
|
|
65
|
+
{options.map((option) => (
|
|
61
66
|
<MenuItem
|
|
62
|
-
key={
|
|
67
|
+
key={option.label}
|
|
63
68
|
disabled={option.disabled}
|
|
64
69
|
onClick={(e) => handleOptionAction(e, option)}
|
|
65
70
|
>
|
|
@@ -12,13 +12,16 @@ import { Actions } from './components/actions'
|
|
|
12
12
|
import { useWidgetStore } from '../stores/widget-store'
|
|
13
13
|
import { useShallow } from 'zustand/shallow'
|
|
14
14
|
|
|
15
|
+
const EMPTY_ACTIONS: NonNullable<WrapperUIProps['actions']> = []
|
|
16
|
+
const EMPTY_OPTIONS: NonNullable<WrapperUIProps['options']> = []
|
|
17
|
+
|
|
15
18
|
export function WrapperUI({
|
|
16
19
|
children,
|
|
17
20
|
id,
|
|
18
|
-
actions =
|
|
21
|
+
actions = EMPTY_ACTIONS,
|
|
19
22
|
sx,
|
|
20
23
|
labels,
|
|
21
|
-
options =
|
|
24
|
+
options = EMPTY_OPTIONS,
|
|
22
25
|
onChangeCollapsed,
|
|
23
26
|
}: WrapperUIProps) {
|
|
24
27
|
const title = useWidgetStore(
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { WrapperProps, WrapperState } from './types'
|
|
2
2
|
import { WrapperUI } from './wrapper-ui'
|
|
3
3
|
import { useWidgetStore } from '../stores/widget-store'
|
|
4
|
-
import {
|
|
4
|
+
import { useLayoutEffect } from 'react'
|
|
5
5
|
|
|
6
6
|
export function WidgetWrapper({
|
|
7
7
|
id,
|
|
@@ -17,9 +17,7 @@ export function WidgetWrapper({
|
|
|
17
17
|
}: WrapperProps) {
|
|
18
18
|
const setWidget = useWidgetStore((state) => state.setWidget)
|
|
19
19
|
|
|
20
|
-
|
|
21
|
-
// This prevents 3 separate re-render cycles on mount and prop changes
|
|
22
|
-
useEffect(() => {
|
|
20
|
+
useLayoutEffect(() => {
|
|
23
21
|
setWidget<WrapperState>(id, {
|
|
24
22
|
collapsed: defaultCollapsed,
|
|
25
23
|
disabled,
|