@carto/ps-react-ui 4.3.3 → 4.3.5
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 +3 -3
- package/dist/components.js.map +1 -1
- package/dist/{lasso-tool-BwRzEW7k.js → lasso-tool-wFqOD6wk.js} +13 -13
- package/dist/lasso-tool-wFqOD6wk.js.map +1 -0
- package/dist/types/components/common-types.d.ts +41 -0
- package/dist/types/components/types.d.ts +1 -1
- package/dist/types/widgets/echart/echart-ui.d.ts +1 -1
- package/dist/types/widgets/echart/types.d.ts +4 -0
- package/dist/widgets/actions.js +1 -1
- package/dist/widgets/bar.js +1 -1
- package/dist/widgets/category.js +1 -1
- package/dist/widgets/echart.js +96 -85
- package/dist/widgets/echart.js.map +1 -1
- package/dist/widgets/formula.js +1 -1
- package/dist/widgets/histogram.js +1 -1
- package/dist/widgets/markdown.js +1 -1
- package/dist/widgets/pie.js +1 -1
- package/dist/widgets/scatterplot.js +1 -1
- package/dist/widgets/spread.js +1 -1
- package/dist/widgets/table.js +1 -1
- package/dist/widgets/timeseries.js +1 -1
- package/dist/widgets/toolbar-actions.js.map +1 -1
- package/dist/widgets/wrapper.js +1 -1
- package/package.json +8 -3
- package/src/components/basemaps/basemaps.test.tsx +196 -0
- package/src/components/basemaps/basemaps.tsx +128 -0
- package/src/components/basemaps/const.ts +13 -0
- package/src/components/basemaps/group-wrapper.test.tsx +38 -0
- package/src/components/basemaps/group-wrapper.tsx +28 -0
- package/src/components/basemaps/group.test.tsx +52 -0
- package/src/components/basemaps/group.tsx +42 -0
- package/src/components/basemaps/header.test.tsx +54 -0
- package/src/components/basemaps/header.tsx +36 -0
- package/src/components/basemaps/styles.ts +76 -0
- package/src/components/basemaps/types.ts +30 -0
- package/src/components/common-types.ts +1 -0
- package/src/components/geolocation-controls/const.ts +6 -0
- package/src/components/geolocation-controls/geolocation-controls.test.tsx +133 -0
- package/src/components/geolocation-controls/geolocation-controls.tsx +95 -0
- package/src/components/geolocation-controls/types.ts +17 -0
- package/src/components/index.ts +64 -0
- package/src/components/lasso-tool/chip.tsx +37 -0
- package/src/components/lasso-tool/const.tsx +70 -0
- package/src/components/lasso-tool/icons.tsx +91 -0
- package/src/components/lasso-tool/lasso-tool-inline.test.tsx +168 -0
- package/src/components/lasso-tool/lasso-tool-inline.tsx +245 -0
- package/src/components/lasso-tool/lasso-tool.test.tsx +212 -0
- package/src/components/lasso-tool/lasso-tool.tsx +479 -0
- package/src/components/lasso-tool/styles.ts +143 -0
- package/src/components/lasso-tool/types.ts +114 -0
- package/src/components/list-data/list-data-skeleton.test.tsx +10 -0
- package/src/components/list-data/list-data-skeleton.tsx +40 -0
- package/src/components/list-data/list-data.test.tsx +94 -0
- package/src/components/list-data/list-data.tsx +106 -0
- package/src/components/list-data/styles.ts +37 -0
- package/src/components/list-data/types.ts +25 -0
- package/src/components/measurement-tools/const.tsx +108 -0
- package/src/components/measurement-tools/icons.tsx +54 -0
- package/src/components/measurement-tools/measurement-tools.test.tsx +165 -0
- package/src/components/measurement-tools/measurement-tools.tsx +443 -0
- package/src/components/measurement-tools/styles.ts +91 -0
- package/src/components/measurement-tools/types.ts +77 -0
- package/src/components/no-data-alert/no-data-alert.test.tsx +31 -0
- package/src/components/no-data-alert/no-data-alert.tsx +59 -0
- package/src/components/responsive-drawer/responsive-drawer.test.tsx +91 -0
- package/src/components/responsive-drawer/responsive-drawer.tsx +53 -0
- package/src/components/smart-tooltip/smart-tooltip.test.tsx +168 -0
- package/src/components/smart-tooltip/smart-tooltip.tsx +40 -0
- package/src/components/tooltip/tooltip.test.tsx +86 -0
- package/src/components/tooltip/tooltip.tsx +30 -0
- package/src/components/types.ts +1 -0
- package/src/components/zoom-controls/styles.ts +27 -0
- package/src/components/zoom-controls/types.ts +19 -0
- package/src/components/zoom-controls/zoom-controls.test.tsx +101 -0
- package/src/components/zoom-controls/zoom-controls.tsx +114 -0
- package/src/hooks/index.ts +2 -0
- package/src/hooks/use-debounce.ts +55 -0
- package/src/hooks/use-skeleton.test.tsx +32 -0
- package/src/hooks/use-skeleton.ts +19 -0
- package/src/hooks/use-widget-ref.ts +33 -0
- package/src/widgets/README.md +277 -0
- package/src/widgets/_shared/chart-config/config-factory.ts +67 -0
- package/src/widgets/_shared/chart-config/csv-modifiers.ts +56 -0
- package/src/widgets/_shared/chart-config/index.ts +21 -0
- package/src/widgets/_shared/chart-config/option-builders.ts +203 -0
- package/src/widgets/_shared/skeleton/index.ts +5 -0
- package/src/widgets/_shared/skeleton/styles.ts +20 -0
- package/src/widgets/actions/change-column/change-column-icon.tsx +10 -0
- package/src/widgets/actions/change-column/change-column.test.tsx +163 -0
- package/src/widgets/actions/change-column/change-column.tsx +141 -0
- package/src/widgets/actions/change-column/sortable-column-item.tsx +49 -0
- package/src/widgets/actions/change-column/types.ts +20 -0
- package/src/widgets/actions/download/download.test.tsx +322 -0
- package/src/widgets/actions/download/download.tsx +118 -0
- package/src/widgets/actions/download/exports.test.tsx +275 -0
- package/src/widgets/actions/download/exports.tsx +103 -0
- package/src/widgets/actions/download/types.ts +21 -0
- package/src/widgets/actions/fullscreen/fullscreen.test.tsx +269 -0
- package/src/widgets/actions/fullscreen/fullscreen.tsx +82 -0
- package/src/widgets/actions/fullscreen/styles.ts +17 -0
- package/src/widgets/actions/fullscreen/types.ts +27 -0
- package/src/widgets/actions/index.ts +51 -0
- package/src/widgets/actions/lock-selection/lock-selection.test.tsx +186 -0
- package/src/widgets/actions/lock-selection/lock-selection.tsx +133 -0
- package/src/widgets/actions/lock-selection/types.ts +41 -0
- package/src/widgets/actions/relative-data/relative-data.test.tsx +267 -0
- package/src/widgets/actions/relative-data/relative-data.tsx +133 -0
- package/src/widgets/actions/relative-data/style.ts +9 -0
- package/src/widgets/actions/relative-data/types.ts +31 -0
- package/src/widgets/actions/relative-data/utils.test.ts +223 -0
- package/src/widgets/actions/relative-data/utils.ts +58 -0
- package/src/widgets/actions/searcher/searcher-toggle.test.tsx +354 -0
- package/src/widgets/actions/searcher/searcher-toggle.tsx +73 -0
- package/src/widgets/actions/searcher/searcher.tsx +205 -0
- package/src/widgets/actions/searcher/types.ts +72 -0
- package/src/widgets/actions/shared/styles.ts +12 -0
- package/src/widgets/actions/stack-toggle/grouped-bar-chart-icon.tsx +14 -0
- package/src/widgets/actions/stack-toggle/stack-toggle.test.tsx +270 -0
- package/src/widgets/actions/stack-toggle/stack-toggle.tsx +146 -0
- package/src/widgets/actions/stack-toggle/types.ts +29 -0
- package/src/widgets/actions/zoom-toggle/index.ts +2 -0
- package/src/widgets/actions/zoom-toggle/style.ts +14 -0
- package/src/widgets/actions/zoom-toggle/types.ts +44 -0
- package/src/widgets/actions/zoom-toggle/zoom-toggle.tsx +186 -0
- package/src/widgets/bar/config.ts +122 -0
- package/src/widgets/bar/index.ts +9 -0
- package/src/widgets/bar/skeleton.tsx +60 -0
- package/src/widgets/bar/style.ts +33 -0
- package/src/widgets/bar/types.ts +16 -0
- package/src/widgets/category/category-ui.test.tsx +399 -0
- package/src/widgets/category/category-ui.tsx +156 -0
- package/src/widgets/category/components/category-bar.tsx +28 -0
- package/src/widgets/category/components/category-legend.tsx +30 -0
- package/src/widgets/category/components/category-row-multi.tsx +50 -0
- package/src/widgets/category/components/category-row-other.tsx +23 -0
- package/src/widgets/category/components/category-row-single.tsx +47 -0
- package/src/widgets/category/components/index.ts +14 -0
- package/src/widgets/category/config.ts +85 -0
- package/src/widgets/category/index.ts +30 -0
- package/src/widgets/category/skeleton.tsx +24 -0
- package/src/widgets/category/style.ts +133 -0
- package/src/widgets/category/types.ts +40 -0
- package/src/widgets/echart/const.ts +1 -0
- package/src/widgets/echart/echart-ui.test.tsx +537 -0
- package/src/widgets/echart/echart-ui.tsx +92 -0
- package/src/widgets/echart/echart.test.tsx +562 -0
- package/src/widgets/echart/echart.tsx +68 -0
- package/src/widgets/echart/index.ts +16 -0
- package/src/widgets/echart/options.ts +53 -0
- package/src/widgets/echart/types.ts +45 -0
- package/src/widgets/echart/utils.ts +169 -0
- package/src/widgets/error/error.test.tsx +331 -0
- package/src/widgets/error/error.tsx +40 -0
- package/src/widgets/error/index.ts +2 -0
- package/src/widgets/error/types.ts +14 -0
- package/src/widgets/formula/components/item.test.tsx +249 -0
- package/src/widgets/formula/components/item.tsx +18 -0
- package/src/widgets/formula/components/prefix.test.tsx +341 -0
- package/src/widgets/formula/components/prefix.tsx +18 -0
- package/src/widgets/formula/components/row.test.tsx +364 -0
- package/src/widgets/formula/components/row.tsx +21 -0
- package/src/widgets/formula/components/series.tsx +34 -0
- package/src/widgets/formula/components/suffix.test.tsx +383 -0
- package/src/widgets/formula/components/suffix.tsx +28 -0
- package/src/widgets/formula/components/value.test.tsx +329 -0
- package/src/widgets/formula/components/value.tsx +29 -0
- package/src/widgets/formula/config.ts +27 -0
- package/src/widgets/formula/formula-ui.test.tsx +399 -0
- package/src/widgets/formula/formula-ui.tsx +27 -0
- package/src/widgets/formula/index.ts +24 -0
- package/src/widgets/formula/serializer.test.tsx +144 -0
- package/src/widgets/formula/serializer.ts +28 -0
- package/src/widgets/formula/skeleton.tsx +10 -0
- package/src/widgets/formula/style.ts +23 -0
- package/src/widgets/formula/types.ts +50 -0
- package/src/widgets/histogram/config.ts +143 -0
- package/src/widgets/histogram/index.ts +8 -0
- package/src/widgets/histogram/skeleton.tsx +52 -0
- package/src/widgets/histogram/style.ts +8 -0
- package/src/widgets/histogram/types.ts +17 -0
- package/src/widgets/index.ts +25 -0
- package/src/widgets/loader/index.ts +4 -0
- package/src/widgets/loader/loader.tsx +70 -0
- package/src/widgets/loader/types.ts +11 -0
- package/src/widgets/loader/utils.test.ts +112 -0
- package/src/widgets/loader/utils.ts +35 -0
- package/src/widgets/markdown/config.ts +18 -0
- package/src/widgets/markdown/index.ts +14 -0
- package/src/widgets/markdown/markdown-ui.test.tsx +341 -0
- package/src/widgets/markdown/markdown-ui.tsx +52 -0
- package/src/widgets/markdown/markdown.tsx +20 -0
- package/src/widgets/markdown/skeleton.tsx +12 -0
- package/src/widgets/markdown/style.ts +28 -0
- package/src/widgets/markdown/types.ts +28 -0
- package/src/widgets/no-data/index.ts +2 -0
- package/src/widgets/no-data/no-data.test.tsx +447 -0
- package/src/widgets/no-data/no-data.tsx +116 -0
- package/src/widgets/no-data/style.ts +18 -0
- package/src/widgets/no-data/types.ts +72 -0
- package/src/widgets/note/index.ts +2 -0
- package/src/widgets/note/note.test.tsx +391 -0
- package/src/widgets/note/note.tsx +114 -0
- package/src/widgets/note/style.ts +29 -0
- package/src/widgets/note/types.ts +9 -0
- package/src/widgets/pie/config.ts +177 -0
- package/src/widgets/pie/index.ts +8 -0
- package/src/widgets/pie/skeleton.tsx +70 -0
- package/src/widgets/pie/style.ts +8 -0
- package/src/widgets/pie/types.ts +16 -0
- package/src/widgets/range/components/range-item.tsx +213 -0
- package/src/widgets/range/config.ts +10 -0
- package/src/widgets/range/index.ts +16 -0
- package/src/widgets/range/range-ui.test.tsx +203 -0
- package/src/widgets/range/range-ui.tsx +11 -0
- package/src/widgets/range/serializer.test.ts +70 -0
- package/src/widgets/range/serializer.ts +27 -0
- package/src/widgets/range/skeleton.tsx +14 -0
- package/src/widgets/range/style.ts +37 -0
- package/src/widgets/range/types.ts +39 -0
- package/src/widgets/scatterplot/config.ts +138 -0
- package/src/widgets/scatterplot/index.ts +8 -0
- package/src/widgets/scatterplot/skeleton.tsx +59 -0
- package/src/widgets/scatterplot/style.ts +21 -0
- package/src/widgets/scatterplot/types.ts +17 -0
- package/src/widgets/selection-summary/index.ts +6 -0
- package/src/widgets/selection-summary/selection-summary.tsx +46 -0
- package/src/widgets/selection-summary/style.ts +10 -0
- package/src/widgets/selection-summary/types.ts +14 -0
- package/src/widgets/skeleton-loader/index.ts +2 -0
- package/src/widgets/skeleton-loader/skeleton-loader.test.tsx +139 -0
- package/src/widgets/skeleton-loader/skeleton-loader.tsx +28 -0
- package/src/widgets/skeleton-loader/types.ts +8 -0
- package/src/widgets/spread/components/max-value.tsx +29 -0
- package/src/widgets/spread/components/min-value.tsx +29 -0
- package/src/widgets/spread/components/separator.tsx +6 -0
- package/src/widgets/spread/config.ts +34 -0
- package/src/widgets/spread/index.ts +23 -0
- package/src/widgets/spread/skeleton.tsx +10 -0
- package/src/widgets/spread/spread-ui.test.tsx +368 -0
- package/src/widgets/spread/spread-ui.tsx +29 -0
- package/src/widgets/spread/style.ts +22 -0
- package/src/widgets/spread/types.ts +47 -0
- package/src/widgets/stores/index.ts +9 -0
- package/src/widgets/stores/types.ts +192 -0
- package/src/widgets/stores/widget-store.test.ts +601 -0
- package/src/widgets/stores/widget-store.ts +239 -0
- package/src/widgets/subheader/index.ts +3 -0
- package/src/widgets/subheader/style.ts +20 -0
- package/src/widgets/subheader/subheader.test.tsx +45 -0
- package/src/widgets/subheader/subheader.tsx +16 -0
- package/src/widgets/subheader/types.ts +11 -0
- package/src/widgets/table/components/cell-header.tsx +58 -0
- package/src/widgets/table/components/cell.tsx +80 -0
- package/src/widgets/table/components/index.ts +4 -0
- package/src/widgets/table/components/pagination-actions.tsx +67 -0
- package/src/widgets/table/components/pagination.tsx +41 -0
- package/src/widgets/table/components/row.tsx +60 -0
- package/src/widgets/table/config.ts +71 -0
- package/src/widgets/table/helpers.test.ts +244 -0
- package/src/widgets/table/helpers.ts +107 -0
- package/src/widgets/table/hooks/index.ts +7 -0
- package/src/widgets/table/hooks/use-pagination.test.ts +294 -0
- package/src/widgets/table/hooks/use-pagination.ts +155 -0
- package/src/widgets/table/hooks/use-selection.test.ts +504 -0
- package/src/widgets/table/hooks/use-selection.ts +189 -0
- package/src/widgets/table/hooks/use-sort.test.ts +296 -0
- package/src/widgets/table/hooks/use-sort.ts +138 -0
- package/src/widgets/table/index.ts +53 -0
- package/src/widgets/table/serializer.ts +54 -0
- package/src/widgets/table/skeleton.tsx +48 -0
- package/src/widgets/table/style.ts +34 -0
- package/src/widgets/table/table-ui.tsx +64 -0
- package/src/widgets/table/types.ts +223 -0
- package/src/widgets/timeseries/config.ts +135 -0
- package/src/widgets/timeseries/index.ts +8 -0
- package/src/widgets/timeseries/skeleton.tsx +55 -0
- package/src/widgets/timeseries/style.ts +36 -0
- package/src/widgets/timeseries/types.ts +17 -0
- package/src/widgets/toolbar-actions/index.ts +6 -0
- package/src/widgets/toolbar-actions/styles.ts +38 -0
- package/src/widgets/toolbar-actions/toolbar-actions.test.tsx +691 -0
- package/src/widgets/toolbar-actions/toolbar-actions.tsx +145 -0
- package/src/widgets/toolbar-actions/types.ts +60 -0
- package/src/widgets/wrapper/components/actions.test.tsx +101 -0
- package/src/widgets/wrapper/components/actions.tsx +30 -0
- package/src/widgets/wrapper/components/options.test.tsx +323 -0
- package/src/widgets/wrapper/components/options.tsx +73 -0
- package/src/widgets/wrapper/components/title.test.tsx +126 -0
- package/src/widgets/wrapper/components/title.tsx +32 -0
- package/src/widgets/wrapper/index.ts +16 -0
- package/src/widgets/wrapper/styles.ts +98 -0
- package/src/widgets/wrapper/types.ts +55 -0
- package/src/widgets/wrapper/wrapper-ui.test.tsx +232 -0
- package/src/widgets/wrapper/wrapper-ui.tsx +57 -0
- package/src/widgets/wrapper/wrapper.test.tsx +365 -0
- package/src/widgets/wrapper/wrapper.tsx +50 -0
- package/dist/lasso-tool-BwRzEW7k.js.map +0 -1
- package/dist/types/common/common.d.ts +0 -3
- package/dist/types/common/index.d.ts +0 -26
- package/dist/types/common/lasso-tools.d.ts +0 -36
- package/dist/types/common/measurement-tools.d.ts +0 -65
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import type { TypographyProps } from '@mui/material'
|
|
2
|
+
import type { ReactNode } from 'react'
|
|
3
|
+
import type { BaseWidgetState, WidgetsStoreProps } from '../stores/types'
|
|
4
|
+
import type { WrapperState } from '../wrapper/types'
|
|
5
|
+
import type { DownloadItem } from '../actions/download/types'
|
|
6
|
+
|
|
7
|
+
export interface FormulaUIProps {
|
|
8
|
+
id: WidgetsStoreProps['id']
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export interface DataItem {
|
|
12
|
+
value: number
|
|
13
|
+
prefix?: string | ReactNode
|
|
14
|
+
suffix?: string | ReactNode
|
|
15
|
+
color?: string
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export interface RowProps {
|
|
19
|
+
id: WidgetsStoreProps['id']
|
|
20
|
+
children: ReactNode | ((props: { index: number }) => ReactNode)
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export interface ValueProps extends Omit<ItemProps, 'children'> {
|
|
24
|
+
id: WidgetsStoreProps['id']
|
|
25
|
+
index?: number
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export interface ItemProps {
|
|
29
|
+
children: ReactNode
|
|
30
|
+
disabled?: boolean
|
|
31
|
+
TypographyProps?: TypographyProps
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export type FormulaWidgetData = DataItem[]
|
|
35
|
+
|
|
36
|
+
export interface SeriesConfig {
|
|
37
|
+
name: string
|
|
38
|
+
color?: string
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export type FormulaWidgetState = BaseWidgetState<
|
|
42
|
+
WrapperState<FormulaWidgetConfig> & { data: FormulaWidgetData }
|
|
43
|
+
>
|
|
44
|
+
|
|
45
|
+
export interface FormulaWidgetConfig {
|
|
46
|
+
formatter?: (value: number) => string
|
|
47
|
+
series?: SeriesConfig[]
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export type FormulaDownloadConfig = DownloadItem<FormulaWidgetData>[]
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import {
|
|
2
|
+
getCommonOptions,
|
|
3
|
+
mergeEchartWidgetConfig,
|
|
4
|
+
type EchartOptionsProps,
|
|
5
|
+
} from '../echart'
|
|
6
|
+
import type {
|
|
7
|
+
HistogramConfig,
|
|
8
|
+
HistogramWidgetConfig,
|
|
9
|
+
HistogramWidgetData,
|
|
10
|
+
} from './types'
|
|
11
|
+
import {
|
|
12
|
+
flattenObjectArrayToCSV,
|
|
13
|
+
buildLegendConfig,
|
|
14
|
+
buildGridConfig,
|
|
15
|
+
createTooltipPositioner,
|
|
16
|
+
createTooltipFormatter,
|
|
17
|
+
applyYAxisFormatter,
|
|
18
|
+
} from '../_shared/chart-config'
|
|
19
|
+
import { downloadToCSV, downloadToPNG, type DownloadItem } from '../actions'
|
|
20
|
+
import type { ConfigProps } from '../loader/types'
|
|
21
|
+
|
|
22
|
+
export function histogramDownloadConfig({
|
|
23
|
+
refUI,
|
|
24
|
+
}: ConfigProps): DownloadItem<HistogramWidgetData>[] {
|
|
25
|
+
return [
|
|
26
|
+
{
|
|
27
|
+
...downloadToPNG,
|
|
28
|
+
modifier: () => downloadToPNG.modifier(refUI),
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
...downloadToCSV,
|
|
32
|
+
modifier: async (data) => {
|
|
33
|
+
const rows = flattenObjectArrayToCSV(data)
|
|
34
|
+
return downloadToCSV.modifier(rows)
|
|
35
|
+
},
|
|
36
|
+
},
|
|
37
|
+
]
|
|
38
|
+
}
|
|
39
|
+
export function histogramConfig(props: HistogramConfig): HistogramWidgetConfig {
|
|
40
|
+
return {
|
|
41
|
+
type: 'histogram',
|
|
42
|
+
option: mergeEchartWidgetConfig(getCommonOptions(props), getOption(props)),
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
function getOption({
|
|
46
|
+
data = [],
|
|
47
|
+
theme,
|
|
48
|
+
formatter,
|
|
49
|
+
}: HistogramConfig): EchartOptionsProps {
|
|
50
|
+
const hasLegend = (data?.length ?? 0) > 1
|
|
51
|
+
|
|
52
|
+
const yAxis = {
|
|
53
|
+
type: 'value' as const,
|
|
54
|
+
showMaxLabel: true,
|
|
55
|
+
showMinLabel: true,
|
|
56
|
+
splitNumber: 1,
|
|
57
|
+
axisLabel: {
|
|
58
|
+
fontSize: theme.typography.overlineDelicate.fontSize,
|
|
59
|
+
fontFamily: theme.typography.overlineDelicate.fontFamily,
|
|
60
|
+
margin: parseInt(theme.spacing(1)),
|
|
61
|
+
show: true,
|
|
62
|
+
showMaxLabel: true,
|
|
63
|
+
showMinLabel: true,
|
|
64
|
+
verticalAlign: 'bottom' as const,
|
|
65
|
+
},
|
|
66
|
+
axisLine: {
|
|
67
|
+
show: false,
|
|
68
|
+
},
|
|
69
|
+
axisTick: {
|
|
70
|
+
show: false,
|
|
71
|
+
},
|
|
72
|
+
splitLine: {
|
|
73
|
+
show: true,
|
|
74
|
+
lineStyle: {
|
|
75
|
+
color: theme.palette.black[4],
|
|
76
|
+
},
|
|
77
|
+
},
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
return {
|
|
81
|
+
legend: buildLegendConfig(hasLegend),
|
|
82
|
+
grid: buildGridConfig(hasLegend, theme),
|
|
83
|
+
xAxis: {
|
|
84
|
+
type: 'category',
|
|
85
|
+
axisLine: {
|
|
86
|
+
show: false,
|
|
87
|
+
},
|
|
88
|
+
axisLabel: {
|
|
89
|
+
fontSize: theme.typography.overlineDelicate.fontSize,
|
|
90
|
+
fontFamily: theme.typography.overlineDelicate.fontFamily,
|
|
91
|
+
showMinLabel: true,
|
|
92
|
+
showMaxLabel: true,
|
|
93
|
+
hideOverlap: true,
|
|
94
|
+
margin: 0,
|
|
95
|
+
padding: [
|
|
96
|
+
parseInt(theme.spacing(0.5)),
|
|
97
|
+
parseInt(theme.spacing(0.5)),
|
|
98
|
+
0,
|
|
99
|
+
parseInt(theme.spacing(0.5)),
|
|
100
|
+
],
|
|
101
|
+
color: theme.palette.black[60],
|
|
102
|
+
},
|
|
103
|
+
axisTick: {
|
|
104
|
+
show: false,
|
|
105
|
+
},
|
|
106
|
+
splitLine: {
|
|
107
|
+
show: true,
|
|
108
|
+
lineStyle: {
|
|
109
|
+
color: theme.palette.black[4],
|
|
110
|
+
},
|
|
111
|
+
},
|
|
112
|
+
},
|
|
113
|
+
yAxis: applyYAxisFormatter(yAxis, formatter),
|
|
114
|
+
tooltip: {
|
|
115
|
+
position: createTooltipPositioner(theme),
|
|
116
|
+
formatter: createTooltipFormatter((item) => {
|
|
117
|
+
const value = item.value as Record<string, string | number>
|
|
118
|
+
const index = item.dimensionNames?.[item.encode?.y?.at(0) ?? 1]
|
|
119
|
+
const _value = value[index ?? '']
|
|
120
|
+
|
|
121
|
+
const formattedValue =
|
|
122
|
+
typeof _value === 'number' && formatter
|
|
123
|
+
? formatter(_value)
|
|
124
|
+
: (_value ?? '')
|
|
125
|
+
|
|
126
|
+
const marker = typeof item.marker === 'string' ? item.marker : ''
|
|
127
|
+
const seriesName = item.seriesName ? `${item.seriesName}: ` : ''
|
|
128
|
+
const name = item.name ?? ''
|
|
129
|
+
|
|
130
|
+
return { name, seriesName, marker, value: formattedValue }
|
|
131
|
+
}),
|
|
132
|
+
},
|
|
133
|
+
series: data.map((_: unknown, index: number) => ({
|
|
134
|
+
datasetIndex: index,
|
|
135
|
+
type: 'bar',
|
|
136
|
+
barGap: '1%', // No gap between bars in histogram
|
|
137
|
+
barCategoryGap: '1%', // No gap between categories in histogram
|
|
138
|
+
emphasis: {
|
|
139
|
+
focus: 'series',
|
|
140
|
+
},
|
|
141
|
+
})),
|
|
142
|
+
} as EchartOptionsProps
|
|
143
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { Box, Skeleton } from '@mui/material'
|
|
2
|
+
import { styles } from './style'
|
|
3
|
+
|
|
4
|
+
export function HistogramSkeleton() {
|
|
5
|
+
return (
|
|
6
|
+
<Box sx={styles.skeleton.graph.container}>
|
|
7
|
+
<Box
|
|
8
|
+
sx={{
|
|
9
|
+
display: 'flex',
|
|
10
|
+
alignItems: 'flex-end',
|
|
11
|
+
justifyContent: 'space-between',
|
|
12
|
+
gap: ({ spacing }) => spacing(0.5),
|
|
13
|
+
height: ({ spacing }) => spacing(30),
|
|
14
|
+
width: '100%',
|
|
15
|
+
}}
|
|
16
|
+
>
|
|
17
|
+
{Array(8)
|
|
18
|
+
.fill(0)
|
|
19
|
+
.map((_, i) => {
|
|
20
|
+
// Create varying heights for histogram bars
|
|
21
|
+
const heights = [60, 80, 95, 85, 70, 55, 40, 30]
|
|
22
|
+
const height = `${heights[i]}%`
|
|
23
|
+
return (
|
|
24
|
+
<Skeleton
|
|
25
|
+
key={i}
|
|
26
|
+
variant='rectangular'
|
|
27
|
+
sx={{
|
|
28
|
+
flex: 1,
|
|
29
|
+
height,
|
|
30
|
+
}}
|
|
31
|
+
/>
|
|
32
|
+
)
|
|
33
|
+
})}
|
|
34
|
+
</Box>
|
|
35
|
+
<Box
|
|
36
|
+
sx={{
|
|
37
|
+
display: 'flex',
|
|
38
|
+
alignItems: 'center',
|
|
39
|
+
justifyContent: 'space-between',
|
|
40
|
+
width: '100%',
|
|
41
|
+
mt: ({ spacing }) => spacing(1),
|
|
42
|
+
}}
|
|
43
|
+
>
|
|
44
|
+
{Array(4)
|
|
45
|
+
.fill(0)
|
|
46
|
+
.map((_, i) => (
|
|
47
|
+
<Skeleton key={i} width={32} height={8} />
|
|
48
|
+
))}
|
|
49
|
+
</Box>
|
|
50
|
+
</Box>
|
|
51
|
+
)
|
|
52
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { EchartWidgetData, EchartWidgetState } from '../echart'
|
|
2
|
+
import type {
|
|
3
|
+
EchartWidgetOptionProps,
|
|
4
|
+
EchartWidgetProps,
|
|
5
|
+
} from '../echart/types'
|
|
6
|
+
import type { ConfigProps } from '../loader'
|
|
7
|
+
|
|
8
|
+
export type HistogramWidgetData = EchartWidgetData
|
|
9
|
+
|
|
10
|
+
export type HistogramWidgetState = EchartWidgetState
|
|
11
|
+
|
|
12
|
+
export type HistogramWidgetConfig = EchartWidgetProps & {
|
|
13
|
+
type: 'histogram'
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export type HistogramConfig = ConfigProps &
|
|
17
|
+
EchartWidgetOptionProps<HistogramWidgetData>
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
// Widget store
|
|
2
|
+
export { useWidgetStore } from './stores/widget-store'
|
|
3
|
+
export type {
|
|
4
|
+
BaseWidgetState,
|
|
5
|
+
WidgetsStoreProps,
|
|
6
|
+
WidgetState,
|
|
7
|
+
WidgetStore,
|
|
8
|
+
WidgetStoreActions,
|
|
9
|
+
WidgetStoreState,
|
|
10
|
+
} from './stores/types'
|
|
11
|
+
|
|
12
|
+
// Hooks
|
|
13
|
+
export { useWidgetRef } from '../hooks/use-widget-ref'
|
|
14
|
+
|
|
15
|
+
// NoData
|
|
16
|
+
export { WidgetNoData } from './no-data'
|
|
17
|
+
export type { WidgetNoDataProps } from './no-data'
|
|
18
|
+
|
|
19
|
+
// Error
|
|
20
|
+
export { WidgetError } from './error'
|
|
21
|
+
export type { WidgetErrorProps } from './error'
|
|
22
|
+
|
|
23
|
+
// Note
|
|
24
|
+
export { WidgetNote } from './note'
|
|
25
|
+
export type { WidgetNoteProps } from './note'
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { useEffect } from 'react'
|
|
2
|
+
import type { WidgetLoaderProps } from './types'
|
|
3
|
+
import { useWidgetStore } from '../stores/widget-store'
|
|
4
|
+
import type { WrapperState } from '../wrapper'
|
|
5
|
+
|
|
6
|
+
export function WidgetLoader<T>(props: WidgetLoaderProps<T>) {
|
|
7
|
+
const setWidget = useWidgetStore((state) => state.setWidget)
|
|
8
|
+
const executeToolPipeline = useWidgetStore(
|
|
9
|
+
(state) => state.executeToolPipeline,
|
|
10
|
+
)
|
|
11
|
+
|
|
12
|
+
// Split into 3 effects for metadata and 1 for data pipeline:
|
|
13
|
+
// Each property that can be modified independently gets its own effect to avoid
|
|
14
|
+
// accidentally resetting other properties.
|
|
15
|
+
//
|
|
16
|
+
// - Effect 1: Type (can be modified by tools that change visualization type)
|
|
17
|
+
// - Effect 2: Loading/Error states (change during fetch lifecycle)
|
|
18
|
+
// - Effect 3: Config (can be modified by tools that change widget configuration)
|
|
19
|
+
// - Effect 4: Data pipeline execution (transforms data through registered tools)
|
|
20
|
+
// - Effect 5: Re-execute pipeline when tool state changes
|
|
21
|
+
|
|
22
|
+
// Effect 1: Type updates
|
|
23
|
+
useEffect(() => {
|
|
24
|
+
setWidget<WrapperState>(props.id, {
|
|
25
|
+
type: props.type,
|
|
26
|
+
})
|
|
27
|
+
}, [props.id, props.type, setWidget])
|
|
28
|
+
|
|
29
|
+
// Effect 2: Loading and error states
|
|
30
|
+
useEffect(() => {
|
|
31
|
+
setWidget<WrapperState>(props.id, {
|
|
32
|
+
isLoading: props.isLoading ?? false,
|
|
33
|
+
isFetching: props.isFetching ?? false,
|
|
34
|
+
error: props.error,
|
|
35
|
+
})
|
|
36
|
+
}, [props.id, props.isLoading, props.isFetching, props.error, setWidget])
|
|
37
|
+
|
|
38
|
+
// Effect 3: Config updates
|
|
39
|
+
useEffect(() => {
|
|
40
|
+
if (props.config) {
|
|
41
|
+
setWidget<WrapperState>(props.id, {
|
|
42
|
+
...props.config,
|
|
43
|
+
})
|
|
44
|
+
}
|
|
45
|
+
}, [props.id, props.config, setWidget])
|
|
46
|
+
|
|
47
|
+
// Effect 4: Execute tool pipeline when props.data changes
|
|
48
|
+
useEffect(() => {
|
|
49
|
+
void executeToolPipeline(props.id, props.data)
|
|
50
|
+
}, [props.id, props.data, executeToolPipeline])
|
|
51
|
+
|
|
52
|
+
// Effect 5: Re-execute pipeline when tool state changes (enabled/config)
|
|
53
|
+
useEffect(() => {
|
|
54
|
+
let prevTools = useWidgetStore.getState().widgets[props.id]?.registeredTools
|
|
55
|
+
|
|
56
|
+
const unsubscribe = useWidgetStore.subscribe((state) => {
|
|
57
|
+
const currentTools = state.widgets[props.id]?.registeredTools
|
|
58
|
+
|
|
59
|
+
// Only re-execute if tools array changed
|
|
60
|
+
if (currentTools !== prevTools) {
|
|
61
|
+
prevTools = currentTools
|
|
62
|
+
void executeToolPipeline(props.id, props.data)
|
|
63
|
+
}
|
|
64
|
+
})
|
|
65
|
+
|
|
66
|
+
return unsubscribe
|
|
67
|
+
}, [props.id, props.data, executeToolPipeline])
|
|
68
|
+
|
|
69
|
+
return props.children
|
|
70
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { ReactNode } from 'react'
|
|
2
|
+
import type { WidgetsStoreProps, WidgetState } from '../stores/types'
|
|
3
|
+
|
|
4
|
+
export interface WidgetLoaderProps<T> extends WidgetsStoreProps {
|
|
5
|
+
children: ReactNode
|
|
6
|
+
config?: T
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export interface ConfigProps {
|
|
10
|
+
refUI?: WidgetState['refUI']
|
|
11
|
+
}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest'
|
|
2
|
+
import { resolveConfig, mergeWidgetConfig } from './utils'
|
|
3
|
+
|
|
4
|
+
describe('resolveConfig', () => {
|
|
5
|
+
interface TestConfig {
|
|
6
|
+
max: number
|
|
7
|
+
items: number
|
|
8
|
+
label?: string
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
type TestData = { value: number }[]
|
|
12
|
+
|
|
13
|
+
const baseConfig: TestConfig = {
|
|
14
|
+
max: 100,
|
|
15
|
+
items: 10,
|
|
16
|
+
label: 'default',
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const testData: TestData = [{ value: 50 }, { value: 75 }]
|
|
20
|
+
|
|
21
|
+
it('should return undefined when config is undefined', () => {
|
|
22
|
+
const result = resolveConfig(undefined, baseConfig, testData)
|
|
23
|
+
expect(result).toBeUndefined()
|
|
24
|
+
})
|
|
25
|
+
|
|
26
|
+
it('should return the object config unchanged when config is an object', () => {
|
|
27
|
+
const objectConfig = { max: 200, items: 20 }
|
|
28
|
+
const result = resolveConfig(objectConfig, baseConfig, testData)
|
|
29
|
+
expect(result).toEqual(objectConfig)
|
|
30
|
+
})
|
|
31
|
+
|
|
32
|
+
it('should call function config with baseConfig and data when config is a function', () => {
|
|
33
|
+
const fnConfig = (base: TestConfig, data: TestData) => ({
|
|
34
|
+
max: base.max * 2,
|
|
35
|
+
items: data.length,
|
|
36
|
+
})
|
|
37
|
+
|
|
38
|
+
const result = resolveConfig(fnConfig, baseConfig, testData)
|
|
39
|
+
expect(result).toEqual({ max: 200, items: 2 })
|
|
40
|
+
})
|
|
41
|
+
|
|
42
|
+
it('should allow function config to access baseConfig properties', () => {
|
|
43
|
+
const fnConfig = (base: TestConfig) => ({
|
|
44
|
+
label: `Modified: ${base.label}`,
|
|
45
|
+
})
|
|
46
|
+
|
|
47
|
+
const result = resolveConfig(fnConfig, baseConfig, testData)
|
|
48
|
+
expect(result).toEqual({ label: 'Modified: default' })
|
|
49
|
+
})
|
|
50
|
+
|
|
51
|
+
it('should allow function config to compute values from data', () => {
|
|
52
|
+
const fnConfig = (_base: TestConfig, data: TestData) => ({
|
|
53
|
+
max: Math.max(...data.map((d) => d.value)),
|
|
54
|
+
})
|
|
55
|
+
|
|
56
|
+
const result = resolveConfig(fnConfig, baseConfig, testData)
|
|
57
|
+
expect(result).toEqual({ max: 75 })
|
|
58
|
+
})
|
|
59
|
+
|
|
60
|
+
it('should return partial config from function', () => {
|
|
61
|
+
const fnConfig = () => ({ items: 5 })
|
|
62
|
+
|
|
63
|
+
const result = resolveConfig(fnConfig, baseConfig, testData)
|
|
64
|
+
expect(result).toEqual({ items: 5 })
|
|
65
|
+
// Ensure it's partial - doesn't include all base properties
|
|
66
|
+
expect(result).not.toHaveProperty('max')
|
|
67
|
+
expect(result).not.toHaveProperty('label')
|
|
68
|
+
})
|
|
69
|
+
})
|
|
70
|
+
|
|
71
|
+
describe('mergeWidgetConfig', () => {
|
|
72
|
+
interface TestConfig {
|
|
73
|
+
max: number
|
|
74
|
+
items: number
|
|
75
|
+
label?: string
|
|
76
|
+
series?: { name: string }[]
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
it('should merge two partial configs', () => {
|
|
80
|
+
const base: Partial<TestConfig> = { max: 100, items: 10 }
|
|
81
|
+
const override: Partial<TestConfig> = { max: 200 }
|
|
82
|
+
|
|
83
|
+
const result = mergeWidgetConfig<TestConfig>(base, override)
|
|
84
|
+
expect(result).toEqual({ max: 200, items: 10 })
|
|
85
|
+
})
|
|
86
|
+
|
|
87
|
+
it('should handle undefined base config', () => {
|
|
88
|
+
const override: Partial<TestConfig> = { max: 200 }
|
|
89
|
+
|
|
90
|
+
const result = mergeWidgetConfig<TestConfig>(undefined, override)
|
|
91
|
+
expect(result).toEqual({ max: 200 })
|
|
92
|
+
})
|
|
93
|
+
|
|
94
|
+
it('should handle undefined override config', () => {
|
|
95
|
+
const base: Partial<TestConfig> = { max: 100 }
|
|
96
|
+
|
|
97
|
+
const result = mergeWidgetConfig<TestConfig>(base, undefined)
|
|
98
|
+
expect(result).toEqual({ max: 100 })
|
|
99
|
+
})
|
|
100
|
+
|
|
101
|
+
it('should replace arrays instead of merging them', () => {
|
|
102
|
+
const base: Partial<TestConfig> = {
|
|
103
|
+
series: [{ name: 'Series 1' }, { name: 'Series 2' }],
|
|
104
|
+
}
|
|
105
|
+
const override: Partial<TestConfig> = {
|
|
106
|
+
series: [{ name: 'New Series' }],
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
const result = mergeWidgetConfig<TestConfig>(base, override)
|
|
110
|
+
expect(result.series).toEqual([{ name: 'New Series' }])
|
|
111
|
+
})
|
|
112
|
+
})
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import deepmerge from 'deepmerge'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Config can be either an object or a function that receives baseConfig and data
|
|
5
|
+
* and returns a partial config to be merged with the base.
|
|
6
|
+
*/
|
|
7
|
+
export type ConfigOrFn<TConfig, TData = unknown> =
|
|
8
|
+
| Partial<TConfig>
|
|
9
|
+
| ((baseConfig: TConfig, data: TData) => Partial<TConfig>)
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Resolves a config that may be either an object or a function.
|
|
13
|
+
* If it's a function, calls it with baseConfig and data.
|
|
14
|
+
* If it's an object (or undefined), returns it as-is.
|
|
15
|
+
*/
|
|
16
|
+
export function resolveConfig<TConfig, TData>(
|
|
17
|
+
config: ConfigOrFn<TConfig, TData> | undefined,
|
|
18
|
+
baseConfig: TConfig,
|
|
19
|
+
data: TData,
|
|
20
|
+
): Partial<TConfig> | undefined {
|
|
21
|
+
if (typeof config === 'function') {
|
|
22
|
+
return config(baseConfig, data)
|
|
23
|
+
}
|
|
24
|
+
return config
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export function mergeWidgetConfig<T>(
|
|
28
|
+
...options: [Partial<T> | undefined, Partial<T> | undefined]
|
|
29
|
+
): T {
|
|
30
|
+
return deepmerge(options[0] ?? {}, options[1] ?? {}, {
|
|
31
|
+
arrayMerge(_, source) {
|
|
32
|
+
return source as T[keyof T][]
|
|
33
|
+
},
|
|
34
|
+
})
|
|
35
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { downloadToCSV, type DownloadItem } from '../actions'
|
|
2
|
+
import type { MarkdownWidgetConfig, MarkdownWidgetData } from './types'
|
|
3
|
+
|
|
4
|
+
export function markdownDownloadConfig(): DownloadItem<MarkdownWidgetData>[] {
|
|
5
|
+
return [
|
|
6
|
+
{
|
|
7
|
+
...downloadToCSV,
|
|
8
|
+
modifier: async (data) => {
|
|
9
|
+
const content = data?.content ?? ''
|
|
10
|
+
return downloadToCSV.modifier([['Content'], [content]])
|
|
11
|
+
},
|
|
12
|
+
},
|
|
13
|
+
]
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export function markdownConfig(): MarkdownWidgetConfig {
|
|
17
|
+
return {}
|
|
18
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export { Markdown } from './markdown'
|
|
2
|
+
export { MarkdownUI } from './markdown-ui'
|
|
3
|
+
export { MarkdownSkeleton } from './skeleton'
|
|
4
|
+
export { markdownConfig, markdownDownloadConfig } from './config'
|
|
5
|
+
|
|
6
|
+
export type {
|
|
7
|
+
MarkdownComponentProps,
|
|
8
|
+
MarkdownUIProps,
|
|
9
|
+
MarkdownWidgetData,
|
|
10
|
+
MarkdownWidgetState,
|
|
11
|
+
MarkdownWidgetConfig,
|
|
12
|
+
MarkdownDownloadConfig,
|
|
13
|
+
MarkdownDataItem,
|
|
14
|
+
} from './types'
|