diff --git a/client/packages/lowcoder-comps/src/comps/candleStickChartComp/candleStickChartComp.tsx b/client/packages/lowcoder-comps/src/comps/candleStickChartComp/candleStickChartComp.tsx index 3f22b5c45..ff33cc260 100644 --- a/client/packages/lowcoder-comps/src/comps/candleStickChartComp/candleStickChartComp.tsx +++ b/client/packages/lowcoder-comps/src/comps/candleStickChartComp/candleStickChartComp.tsx @@ -168,15 +168,15 @@ CandleStickChartTmpComp = withViewFn(CandleStickChartTmpComp, (comp) => { }} > (echartsCompRef.current = e)} - style={{ height: "100%" }} - notMerge - lazyUpdate - opts={{ locale: getEchartsLocale() }} - option={option} - theme={mode !== 'map' ? themeConfig : undefined} - mode={mode} - /> + ref={(e) => (echartsCompRef.current = e)} + style={{ height: "100%" }} + notMerge + lazyUpdate + opts={{ locale: getEchartsLocale() }} + option={option} + theme={mode !== 'map' ? themeConfig : undefined} + mode={mode} + /> ); }); diff --git a/client/packages/lowcoder-comps/src/comps/candleStickChartComp/candleStickChartPropertyView.tsx b/client/packages/lowcoder-comps/src/comps/candleStickChartComp/candleStickChartPropertyView.tsx index f0eea1e15..b3c545d4a 100644 --- a/client/packages/lowcoder-comps/src/comps/candleStickChartComp/candleStickChartPropertyView.tsx +++ b/client/packages/lowcoder-comps/src/comps/candleStickChartComp/candleStickChartPropertyView.tsx @@ -38,12 +38,12 @@ export function candleStickChartPropertyView( {children.onEvent.propertyView()}
- {children.style?.getPropertyView()} + {children.style?.getPropertyView()}
{hiddenPropertyView(children)}
); - + const getChatConfigByMode = (mode: string) => { switch(mode) { case "json": diff --git a/client/packages/lowcoder-comps/src/comps/candleStickChartComp/candleStickChartUtils.ts b/client/packages/lowcoder-comps/src/comps/candleStickChartComp/candleStickChartUtils.ts index 8d94c105f..b4b5d6f71 100644 --- a/client/packages/lowcoder-comps/src/comps/candleStickChartComp/candleStickChartUtils.ts +++ b/client/packages/lowcoder-comps/src/comps/candleStickChartComp/candleStickChartUtils.ts @@ -13,6 +13,7 @@ import { calcXYConfig } from "comps/chartComp/chartConfigs/cartesianAxisConfig"; import Big from "big.js"; import { googleMapsApiUrl } from "../chartComp/chartConfigs/chartUrls"; import { useContext } from "react"; +import parseBackground from "../../util/gradientBackgroundColor"; export function transformData( originData: JSONObject[], @@ -136,62 +137,62 @@ export function getEchartsConfig( ): EChartsOptionWithMap { if (props.mode === "json") { let opt={ - "title": { - "text": props.echartsTitle, - 'top': props.echartsLegendConfig.top === 'bottom' ?'top':'bottom', - "left":"center" - }, - "backgroundColor": props?.style?.background || theme?.style?.background, - "color": props.echartsOption.data?.map(data => data.color), - "tooltip": props.tooltip&&{ - "trigger": "axis", - "axisPointer": { - "type": "cross" - } - }, - "grid": { - "left": "10%", - "right": "10%", - "bottom": "10%", - }, - "xAxis": { - "type": "category", - "data": props.echartsOption.xAxis.data - }, - "yAxis": { - "type": "value", - "scale": true - }, - "series": [ - { - "name": props.echartsConfig.type, - "type": props.echartsConfig.type, - "left": "10%", - "top": 60, - "bottom": 60, - "width": "80%", - "min": 0, - "max": 100, - "gap": 2, - "label": { - "show": true, - "position": props.echartsLabelConfig.top + "title": { + "text": props.echartsTitle, + 'top': props.echartsLegendConfig.top === 'bottom' ?'top':'bottom', + "left":"center" + }, + "backgroundColor": parseBackground( props?.style?.background || theme?.style?.background || "#FFFFFF"), + "color": props.echartsOption.data?.map(data => data.color), + "tooltip": props.tooltip&&{ + "trigger": "axis", + "axisPointer": { + "type": "cross" + } + }, + "grid": { + "left": "10%", + "right": "10%", + "bottom": "10%", + }, + "xAxis": { + "type": "category", + "data": props.echartsOption.xAxis.data + }, + "yAxis": { + "type": "value", + "scale": true }, - "data": props.echartsOption.data, + "series": [ + { + "name": props.echartsConfig.type, + "type": props.echartsConfig.type, + "left": "10%", + "top": 60, + "bottom": 60, + "width": "80%", + "min": 0, + "max": 100, + "gap": 2, + "label": { + "show": true, + "position": props.echartsLabelConfig.top + }, + "data": props.echartsOption.data, + } + ] } - ] -} return props.echartsOption ? opt : {}; - + } - + if(props.mode === "map") { const { mapZoomLevel, mapCenterLat, mapCenterLng, - mapOptions, - showCharts, + mapOptions, + showCharts, } = props; const echartsOption = mapOptions && showCharts ? mapOptions : {}; diff --git a/client/packages/lowcoder-comps/src/comps/chartComp/chartConfigs/echartsFunnelAlignConfig.tsx b/client/packages/lowcoder-comps/src/comps/chartComp/chartConfigs/echartsFunnelAlignConfig.tsx new file mode 100644 index 000000000..812666b17 --- /dev/null +++ b/client/packages/lowcoder-comps/src/comps/chartComp/chartConfigs/echartsFunnelAlignConfig.tsx @@ -0,0 +1,49 @@ +import { + AlignClose, + AlignRight, + AlignLeft, + dropdownControl, + MultiCompBuilder, +} from "lowcoder-sdk"; +import {FunnelSeriesOption, LegendComponentOption} from "echarts"; +import { trans } from "i18n/comps"; + +const FunnelAlignOptions = [ + { + label: , + value: "left", + }, + { + label: , + value: "center", + }, + { + label: , + value: "right", + } +] as const; + +export const EchartsFunnelAlignConfig = (function () { + return new MultiCompBuilder( + { + funnelAlign: dropdownControl(FunnelAlignOptions, "center"), + }, + (props): FunnelSeriesOption => { + const config: FunnelSeriesOption = { + funnelAlign: "center", + }; + config.funnelAlign = props.funnelAlign + return config; + } + ) + .setPropertyViewFn((children) => ( + <> + {children.funnelAlign.propertyView({ + label: trans("echarts.funnelAlign"), + radioButton: true, + tooltip: trans("echarts.changingAlignTooltip") + })} + + )) + .build(); +})(); diff --git a/client/packages/lowcoder-comps/src/comps/chartComp/chartConfigs/echartsLabelConfig.tsx b/client/packages/lowcoder-comps/src/comps/chartComp/chartConfigs/echartsLabelConfig.tsx index 64b808e01..d522dcec2 100644 --- a/client/packages/lowcoder-comps/src/comps/chartComp/chartConfigs/echartsLabelConfig.tsx +++ b/client/packages/lowcoder-comps/src/comps/chartComp/chartConfigs/echartsLabelConfig.tsx @@ -9,6 +9,10 @@ import { LegendComponentOption } from "echarts"; import { trans } from "i18n/comps"; const LabelPositionOptions = [ + { + label: , + value: "left", + }, { label: , value: "inside", @@ -16,11 +20,7 @@ const LabelPositionOptions = [ { label: , value: "right", - }, - { - label: , - value: "left", - }, + } ] as const; export const EchartsLabelConfig = (function () { @@ -42,6 +42,7 @@ export const EchartsLabelConfig = (function () { {children.position.propertyView({ label: trans("echarts.labelPosition"), radioButton: true, + tooltip: trans("echarts.changingLabelTooltip") })} )) diff --git a/client/packages/lowcoder-comps/src/comps/chartComp/chartConfigs/echartsLegendAlignConfig.tsx b/client/packages/lowcoder-comps/src/comps/chartComp/chartConfigs/echartsLegendAlignConfig.tsx new file mode 100644 index 000000000..e29611463 --- /dev/null +++ b/client/packages/lowcoder-comps/src/comps/chartComp/chartConfigs/echartsLegendAlignConfig.tsx @@ -0,0 +1,50 @@ +import { + AlignClose, + AlignRight, + AlignLeft, + dropdownControl, + MultiCompBuilder, +} from "lowcoder-sdk"; +import { LegendComponentOption } from "echarts"; +import { trans } from "i18n/comps"; + +const FunnelLegnedAlignOptions = [ + { + label: , + value: "left", + }, + { + label: , + value: "center", + }, + { + label: , + value: "right", + } +] as const; + +export const EchartsLegendAlignConfig = (function () { + return new MultiCompBuilder( + { + left: dropdownControl(FunnelLegnedAlignOptions, "center"), + }, + (props): LegendComponentOption => { + const config: LegendComponentOption = { + left: "center", + type: "scroll", + }; + config.left = props.left + return config; + } + ) + .setPropertyViewFn((children) => ( + <> + {children.left.propertyView({ + label: trans("echarts.legendAlign"), + radioButton: true, + tooltip: trans("echarts.changingLegend_y_Tooltip") + })} + + )) + .build(); +})(); diff --git a/client/packages/lowcoder-comps/src/comps/chartComp/chartConfigs/echartsLegendConfig.tsx b/client/packages/lowcoder-comps/src/comps/chartComp/chartConfigs/echartsLegendConfig.tsx index 41fb166fb..21dea46f3 100644 --- a/client/packages/lowcoder-comps/src/comps/chartComp/chartConfigs/echartsLegendConfig.tsx +++ b/client/packages/lowcoder-comps/src/comps/chartComp/chartConfigs/echartsLegendConfig.tsx @@ -37,6 +37,7 @@ export const EchartsLegendConfig = (function () { {children.position.propertyView({ label: trans("echarts.legendPosition"), radioButton: true, + tooltip: trans("echarts.changingLegend_x_Tooltip") })} )) diff --git a/client/packages/lowcoder-comps/src/comps/chartComp/chartConfigs/echartsLegendOrientConfig.tsx b/client/packages/lowcoder-comps/src/comps/chartComp/chartConfigs/echartsLegendOrientConfig.tsx new file mode 100644 index 000000000..82ebb79ec --- /dev/null +++ b/client/packages/lowcoder-comps/src/comps/chartComp/chartConfigs/echartsLegendOrientConfig.tsx @@ -0,0 +1,45 @@ +import { + HorizontalIcon, + VerticalIcon, + dropdownControl, + MultiCompBuilder, +} from "lowcoder-sdk"; +import { LegendComponentOption } from "echarts"; +import { trans } from "i18n/comps"; + +const LegendOrientOptions = [ + { + label: , + value: "horizontal", + }, + { + label: , + value: "vertical", + }, +] as const; + +export const EchartsLegendOrientConfig = (function () { + return new MultiCompBuilder( + { + orient: dropdownControl(LegendOrientOptions, "horizontal"), + }, + (props): LegendComponentOption => { + const config: LegendComponentOption = { + orient: "horizontal", + type: "scroll" + }; + config.orient = props.orient + return config; + } + ) + .setPropertyViewFn((children) => ( + <> + {children.orient.propertyView({ + label: trans("echarts.legendOrient"), + radioButton: true, + tooltip: trans("echarts.changingLegend_orient_Tooltip") + })} + + )) + .build(); +})(); diff --git a/client/packages/lowcoder-comps/src/comps/chartComp/chartConfigs/echartsSortingConfig.tsx b/client/packages/lowcoder-comps/src/comps/chartComp/chartConfigs/echartsSortingConfig.tsx new file mode 100644 index 000000000..0d0e28482 --- /dev/null +++ b/client/packages/lowcoder-comps/src/comps/chartComp/chartConfigs/echartsSortingConfig.tsx @@ -0,0 +1,44 @@ +import { + AlignBottom, + AlignTop, + dropdownControl, + MultiCompBuilder, +} from "lowcoder-sdk"; +import {FunnelSeriesOption, LegendComponentOption} from "echarts"; +import { trans } from "i18n/comps"; + +const SortingOptions = [ + { + label: , + value: "descending", + }, + { + label: , + value: "ascending", + }, +] as const; + +export const EchartsSortingConfig = (function () { + return new MultiCompBuilder( + { + sort: dropdownControl(SortingOptions, "descending"), + }, + (props): FunnelSeriesOption => { + const config: FunnelSeriesOption = { + sort: "descending" + }; + config.sort = props.sort + return config; + } + ) + .setPropertyViewFn((children) => ( + <> + {children.sort.propertyView({ + label: trans("echarts.sort"), + radioButton: true, + tooltip: trans("echarts.changingSortTooltip") + })} + + )) + .build(); +})(); diff --git a/client/packages/lowcoder-comps/src/comps/chartComp/chartConfigs/echartsTitleConfig.tsx b/client/packages/lowcoder-comps/src/comps/chartComp/chartConfigs/echartsTitleConfig.tsx index a9305de25..05b1871fe 100644 --- a/client/packages/lowcoder-comps/src/comps/chartComp/chartConfigs/echartsTitleConfig.tsx +++ b/client/packages/lowcoder-comps/src/comps/chartComp/chartConfigs/echartsTitleConfig.tsx @@ -9,6 +9,10 @@ import { LegendComponentOption } from "echarts"; import { trans } from "i18n/comps"; const TitlePositionOptions = [ + { + label: , + value: "left", + }, { label: , value: "center", @@ -16,11 +20,7 @@ const TitlePositionOptions = [ { label: , value: "right", - }, - { - label: , - value: "left", - }, + } ] as const; export const EchartsTitleConfig = (function () { @@ -42,6 +42,7 @@ export const EchartsTitleConfig = (function () { {children.position.propertyView({ label: trans("echarts.titlePosition"), radioButton: true, + tooltip: trans("echarts.changingTitle_x_Tooltip") })} )) diff --git a/client/packages/lowcoder-comps/src/comps/funnelChartComp/funnelChartComp.tsx b/client/packages/lowcoder-comps/src/comps/funnelChartComp/funnelChartComp.tsx index 0c95ed8ff..339f4e717 100644 --- a/client/packages/lowcoder-comps/src/comps/funnelChartComp/funnelChartComp.tsx +++ b/client/packages/lowcoder-comps/src/comps/funnelChartComp/funnelChartComp.tsx @@ -140,14 +140,14 @@ FunnelChartTmpComp = withViewFn(FunnelChartTmpComp, (comp) => { }; }, [onUIEvent]); - const echartsConfigChildren = _.omit(comp.children, echartsConfigOmitChildren); + let echartsConfigChildren = _.omit(comp.children, echartsConfigOmitChildren); const option = useMemo(() => { return getEchartsConfig( childrenToProps(echartsConfigChildren) as ToViewReturn, chartSize, - theme?.theme?.components?.candleStickChart || {}, + themeConfig, ); - }, [chartSize, ...Object.values(echartsConfigChildren)]); + }, [chartSize, ...Object.values(echartsConfigChildren), theme]); useEffect(() => { comp.children.mapInstance.dispatch(changeValueAction(null, false)) @@ -175,7 +175,6 @@ FunnelChartTmpComp = withViewFn(FunnelChartTmpComp, (comp) => { lazyUpdate opts={{ locale: getEchartsLocale() }} option={option} - theme={mode !== 'map' ? themeConfig : undefined} mode={mode} /> diff --git a/client/packages/lowcoder-comps/src/comps/funnelChartComp/funnelChartConstants.tsx b/client/packages/lowcoder-comps/src/comps/funnelChartComp/funnelChartConstants.tsx index 0475493b0..d6a140865 100644 --- a/client/packages/lowcoder-comps/src/comps/funnelChartComp/funnelChartConstants.tsx +++ b/client/packages/lowcoder-comps/src/comps/funnelChartComp/funnelChartConstants.tsx @@ -16,7 +16,9 @@ import { uiChildren, clickEvent, styleControl, - EchartsStyle + EchartsStyle, + EchartDefaultChartStyle, + EchartDefaultTextStyle } from "lowcoder-sdk"; import { RecordConstructorToComp, RecordConstructorToView } from "lowcoder-core"; import { BarChartConfig } from "../chartComp/chartConfigs/barChartConfig"; @@ -24,14 +26,18 @@ import { XAxisConfig, YAxisConfig } from "../chartComp/chartConfigs/cartesianAxi import { LegendConfig } from "../chartComp/chartConfigs/legendConfig"; import { EchartsLegendConfig } from "../chartComp/chartConfigs/echartsLegendConfig"; import { EchartsLabelConfig } from "../chartComp/chartConfigs/echartsLabelConfig"; +import { EchartsFunnelAlignConfig } from "../chartComp/chartConfigs/echartsFunnelAlignConfig"; import { LineChartConfig } from "../chartComp/chartConfigs/lineChartConfig"; import { PieChartConfig } from "../chartComp/chartConfigs/pieChartConfig"; import { ScatterChartConfig } from "../chartComp/chartConfigs/scatterChartConfig"; import { SeriesListComp } from "../chartComp/seriesComp"; import { EChartsOption } from "echarts"; import { i18nObjs, trans } from "i18n/comps"; -import { FunnelChartConfig } from "../chartComp/chartConfigs/funnelChartConfig"; +import { FunnelChartConfig} from "../chartComp/chartConfigs/funnelChartConfig"; import { EchartsTitleConfig } from "comps/chartComp/chartConfigs/echartsTitleConfig"; +import { EchartsSortingConfig } from "../chartComp/chartConfigs/echartsSortingConfig"; +import { EchartsLegendAlignConfig } from "../chartComp/chartConfigs/echartsLegendAlignConfig"; +import { EchartsLegendOrientConfig } from "../chartComp/chartConfigs/echartsLegendOrientConfig"; export const ChartTypeOptions = [ { @@ -252,7 +258,11 @@ let chartJsonModeChildren: any = { echartsOption: jsonControl(toObject, i18nObjs.defaultFunnelChartOption), echartsTitle: withDefault(StringControl, trans("funnelChart.defaultTitle")), echartsLegendConfig: EchartsLegendConfig, + echartsSortingConfig: EchartsSortingConfig, echartsLabelConfig: EchartsLabelConfig, + echartsFunnelAlignConfig: EchartsFunnelAlignConfig, + echartsLegendOrientConfig: EchartsLegendOrientConfig, + echartsLegendAlignConfig: EchartsLegendAlignConfig, echartsConfig: EchartsOptionComp, echartsTitleConfig:EchartsTitleConfig, // style: styleControl(EchartsStyle, 'style'), @@ -265,12 +275,17 @@ let chartJsonModeChildren: any = { width:withDefault(NumberControl,trans('funnelChart.defaultWidth')), min:withDefault(NumberControl,trans('funnelChart.defaultMin')), max:withDefault(NumberControl,trans('funnelChart.defaultMax')), - gap:withDefault(NumberControl,trans('funnelChart.defaultGap')) + gap:withDefault(NumberControl,trans('funnelChart.defaultGap')), + opacity:withDefault(NumberControl,trans('funnelChart.defaultOpacity')) } + if (EchartsStyle) { chartJsonModeChildren = { ...chartJsonModeChildren, - style: styleControl(EchartsStyle, 'style'), + chartStyle: styleControl(EchartDefaultChartStyle, 'chartStyle'), + titleStyle: styleControl(EchartDefaultTextStyle, 'titleStyle'), + labelStyle: styleControl(EchartDefaultTextStyle, 'labelStyle'), + legendStyle: styleControl(EchartDefaultTextStyle, 'legendStyle'), } } diff --git a/client/packages/lowcoder-comps/src/comps/funnelChartComp/funnelChartPropertyView.tsx b/client/packages/lowcoder-comps/src/comps/funnelChartComp/funnelChartPropertyView.tsx index 38171e34e..346a48260 100644 --- a/client/packages/lowcoder-comps/src/comps/funnelChartComp/funnelChartPropertyView.tsx +++ b/client/packages/lowcoder-comps/src/comps/funnelChartComp/funnelChartPropertyView.tsx @@ -31,27 +31,47 @@ export function funnelChartPropertyView( ), })} - {children.legendVisibility.getView()&& children.echartsLegendConfig.getPropertyView()} - {children.label.getView()&& children.echartsLabelConfig.getPropertyView()} {children.echartsTitleConfig.getPropertyView()} - {children.left.propertyView({ label: trans("funnelChart.left") })} - {children.top.propertyView({ label: trans("funnelChart.top") })} - {children.bottom.propertyView({ label: trans("funnelChart.bottom") })} - {children.width.propertyView({ label: trans("funnelChart.width") })} - {children.min.propertyView({ label: trans("funnelChart.min") })} - {children.max.propertyView({ label: trans("funnelChart.max") })} - {children.gap.propertyView({ label: trans("funnelChart.gap") })} - {children.echartsTitle.propertyView({ label: trans("funnelChart.title") })} - {children.tooltip.propertyView({label: trans("funnelChart.tooltip")})} - {children.label.propertyView({label: trans("funnelChart.label")})} - {children.legendVisibility.propertyView({label: trans("funnelChart.legendVisibility")})} + {children.legendVisibility.getView() && children.echartsLegendConfig.getPropertyView()} + {children.legendVisibility.getView() && children.echartsLegendAlignConfig.getPropertyView()} + {children.legendVisibility.getView() && children.echartsLegendOrientConfig.getPropertyView()} + {children.echartsSortingConfig.getPropertyView()} + {children.label.getView()&& children.echartsLabelConfig.getPropertyView()} + {children.echartsFunnelAlignConfig.getPropertyView()} + {children.echartsTitle.propertyView({ label: trans("funnelChart.title"), tooltip: trans("echarts.titleTooltip") })} + {children.left.propertyView({ label: trans("funnelChart.left"), tooltip: trans("echarts.positionChart_x_Tooltip") })} + {children.top.propertyView({ label: trans("funnelChart.top"), tooltip: trans("echarts.topTooltip") })} + {children.bottom.propertyView({ label: trans("funnelChart.bottom"), tooltip: trans("echarts.bottomTooltip") })} + {children.width.propertyView({ label: trans("funnelChart.width"), tooltip: trans("echarts.widthTooltip") })} + {children.min.propertyView({ label: trans("funnelChart.min"), tooltip: trans("echarts.minTooltip") })} + {children.max.propertyView({ label: trans("funnelChart.max"), tooltip: trans("echarts.maxTooltip") })} + {children.gap.propertyView({ label: trans("funnelChart.gap"), tooltip: trans("echarts.gapTooltip") })} + {children.opacity.propertyView({ label: trans("funnelChart.opacity"), tooltip: trans("echarts.opacityTooltip") })} + {children.tooltip.propertyView({label: trans("funnelChart.tooltip"), tooltip: trans("echarts.tooltipVisibilityTooltip")})} + {children.label.propertyView({label: trans("funnelChart.label"), tooltip: trans("echarts.labelVisibilityTooltip")})} + {children.legendVisibility.propertyView({label: trans("funnelChart.legendVisibility"), tooltip: trans("echarts.legendVisibilityTooltip")})}
{children.onEvent.propertyView()}
-
- {children.style?.getPropertyView()} +
+ {children.chartStyle?.getPropertyView()} +
+
+ {children.titleStyle?.getPropertyView()}
+ { + children.label.getView() ? +
+ {children.labelStyle?.getPropertyView()} +
: <> + } + { + children.legendVisibility.getView() ? +
+ {children.legendStyle?.getPropertyView()} +
: <> + }
{hiddenPropertyView(children)}
); diff --git a/client/packages/lowcoder-comps/src/comps/funnelChartComp/funnelChartUtils.ts b/client/packages/lowcoder-comps/src/comps/funnelChartComp/funnelChartUtils.ts index 2f2b814cc..1442ea995 100644 --- a/client/packages/lowcoder-comps/src/comps/funnelChartComp/funnelChartUtils.ts +++ b/client/packages/lowcoder-comps/src/comps/funnelChartComp/funnelChartUtils.ts @@ -12,6 +12,8 @@ import { chartColorPalette, isNumeric, JSONObject, loadScript } from "lowcoder-s import { calcXYConfig } from "comps/chartComp/chartConfigs/cartesianAxisConfig"; import Big from "big.js"; import { googleMapsApiUrl } from "../chartComp/chartConfigs/chartUrls"; +import opacityToHex from "../../util/opacityToHex"; +import parseBackground from "../../util/gradientBackgroundColor"; export function transformData( originData: JSONObject[], @@ -133,42 +135,89 @@ export function getEchartsConfig( chartSize?: ChartSize, theme?: any, ): EChartsOptionWithMap { + if (props.mode === "json") { let opt={ - "title": { - "text": props.echartsTitle, - 'top': props.echartsLegendConfig.top === 'bottom' ?'top':'bottom', - "left":props.echartsTitleConfig.top - }, - "backgroundColor": props?.style?.background || theme?.style?.background, - "color": props.echartsOption.data?.map(data => data.color), - "tooltip": props.tooltip&&{ - "trigger": "item", - "formatter": "{a}
{b} : {c}%" - }, - "legend":props.legendVisibility&& { - "data": props.echartsOption.data?.map(data=>data.name), - "top": props.echartsLegendConfig.top, - }, - "series": [ - { - "name": props.echartsConfig.type, - "type": props.echartsConfig.type, - "left": `${props.left}%`, - "top": props.top, - "bottom": props.bottom, - "width": `${props.left}%`, - "min": props.min, - "max": props.max, - "gap": props.gap, - "label": { - "show": props.label, - "position": props.echartsLabelConfig.top + "title": { + "text": props.echartsTitle, + 'top': "top", + "left":props.echartsTitleConfig.top, + "textStyle": { + "fontFamily": props?.titleStyle?.chartFontFamily || theme?.titleStyle?.fontFamily, + "fontSize": props?.titleStyle?.chartTextSize || theme?.titleStyle?.fontSize || '18', + "fontWeight": props?.titleStyle?.chartTextWeight || theme?.titleStyle?.fontWeight, + "color": props?.titleStyle?.chartTextColor || theme?.titleStyle?.fontColor || "#000000", + "fontStyle": props?.titleStyle?.chartFontStyle || theme?.titleStyle?.fontStyle, + "textShadowColor": props?.titleStyle?.chartShadowColor || theme?.titleStyle?.shadowColor, + "textShadowBlur": props?.titleStyle?.chartBoxShadow?.split('px')[0] || theme?.titleStyle?.boxShadow?.split('px')[0], + "textShadowOffsetX": props?.titleStyle?.chartBoxShadow?.split('px')[1] || theme?.titleStyle?.boxShadow?.split('px')[1], + "textShadowOffsetY": props?.titleStyle?.chartBoxShadow?.split('px')[2] || theme?.titleStyle?.boxShadow?.split('px')[2] + } + }, + "backgroundColor": parseBackground( props?.chartStyle?.background || theme?.chartStyle?.backgroundColor || "#FFFFFF"), + "color": props.echartsOption.data?.map(data => data.color), + "tooltip": props.tooltip&&{ + "trigger": "item", + "formatter": "{a}
{b} : {c}%" + }, + "legend":props.legendVisibility&& { + "data": props.echartsOption.data?.map(data=>data.name), + "top": props.echartsLegendConfig.top, + "left": props.echartsLegendAlignConfig.left, + "orient": props.echartsLegendOrientConfig.orient, + "textStyle": { + "fontFamily": props?.legendStyle?.chartFontFamily || theme?.legendStyle?.fontFamily, + "fontSize": props?.legendStyle?.chartTextSize || theme?.legendStyle?.fontSize, + "fontWeight": props?.legendStyle?.chartTextWeight || theme?.legendStyle?.fontWeight, + "color": props?.legendStyle?.chartTextColor || theme?.legendStyle?.fontColor || "#000000", + "fontStyle": props?.legendStyle?.chartFontStyle || theme?.legendStyle?.fontStyle, + "textShadowColor": props?.legendStyle?.chartShadowColor || theme?.legendStyle?.shadowColor, + "textShadowBlur": props?.legendStyle?.chartBoxShadow?.split('px')[0] || theme?.legendStyle?.boxShadow?.split('px')[0], + "textShadowOffsetX": props?.legendStyle?.chartBoxShadow?.split('px')[1] || theme?.legendStyle?.boxShadow?.split('px')[1], + "textShadowOffsetY": props?.legendStyle?.chartBoxShadow?.split('px')[2] || theme?.legendStyle?.boxShadow?.split('px')[2] + } }, - "data": props.echartsOption.data + "series": [ + { + "name": props.echartsConfig.type, + "type": props.echartsConfig.type, + "left": `${props.left}%`, + "top": props.top, + "bottom": props.bottom, + "width": `${props.left}%`, + "min": props.min, + "max": props.max, + "gap": props.gap, + "funnelAlign": props.echartsFunnelAlignConfig.funnelAlign, + "sort": props.echartsSortingConfig.sort, + "itemStyle": { + "opacity": props.opacity, + "borderColor": props?.chartStyle?.chartBorderColor || theme?.chartStyle?.borderColor, + "borderWidth": props?.chartStyle?.chartBorderWidth || theme?.chartStyle?.borderWidth, + "borderType": props?.chartStyle?.chartBorderStyle || theme?.chartStyle?.borderType, + "borderRadius": props?.chartStyle?.chartBorderRadius || theme?.chartStyle?.borderRadius, + "shadowColor": props?.chartStyle?.chartShadowColor || theme?.chartStyle?.shadowColor, + "shadowBlur": props?.chartStyle?.chartBoxShadow?.split('px')[0] || theme?.chartStyle?.boxShadow?.split('px')[0], + "shadowOffsetX": props?.chartStyle?.chartBoxShadow?.split('px')[1] || theme?.chartStyle?.boxShadow?.split('px')[1], + "shadowOffsetY": props?.chartStyle?.chartBoxShadow?.split('px')[2] || theme?.chartStyle?.boxShadow?.split('px')[2] + }, + "label": { + "show": props.label, + "position": props.echartsLabelConfig.top, + "fontFamily": props?.labelStyle?.chartFontFamily || theme?.labelStyle?.fontFamily, + "fontSize": props?.labelStyle?.chartTextSize || theme?.labelStyle?.fontSize, + "fontWeight": props?.labelStyle?.chartTextWeight || theme?.labelStyle?.fontWeight, + "color": props?.labelStyle?.chartTextColor || theme?.labelStyle?.fontColor || "#000000", + "fontStyle": props?.labelStyle?.chartFontStyle || theme?.labelStyle?.fontStyle, + "textShadowColor": props?.labelStyle?.chartShadowColor || theme?.labelStyle?.shadowColor, + "textShadowBlur": props?.labelStyle?.chartBoxShadow?.split('px')[0] || theme?.labelStyle?.boxShadow?.split('px')[0], + "textShadowOffsetX": props?.labelStyle?.chartBoxShadow?.split('px')[1] || theme?.labelStyle?.boxShadow?.split('px')[1], + "textShadowOffsetY": props?.labelStyle?.chartBoxShadow?.split('px')[2] || theme?.labelStyle?.boxShadow?.split('px')[2] + }, + "data": props.echartsOption.data + } + ] } - ] -} return props.echartsOption ? opt : {}; } diff --git a/client/packages/lowcoder-comps/src/comps/gaugeChartComp/gaugeChartComp.tsx b/client/packages/lowcoder-comps/src/comps/gaugeChartComp/gaugeChartComp.tsx index 7e2574c04..b8237b584 100644 --- a/client/packages/lowcoder-comps/src/comps/gaugeChartComp/gaugeChartComp.tsx +++ b/client/packages/lowcoder-comps/src/comps/gaugeChartComp/gaugeChartComp.tsx @@ -146,9 +146,9 @@ GaugeChartTmpComp = withViewFn(GaugeChartTmpComp, (comp) => { return getEchartsConfig( childrenToProps(echartsConfigChildren) as ToViewReturn, chartSize, - theme?.theme?.components?.candleStickChart || {}, + themeConfig ); - }, [chartSize, ...Object.values(echartsConfigChildren)]); + }, [chartSize, ...Object.values(echartsConfigChildren), theme]); useEffect(() => { comp.children.mapInstance.dispatch(changeValueAction(null, false)) @@ -176,7 +176,6 @@ GaugeChartTmpComp = withViewFn(GaugeChartTmpComp, (comp) => { lazyUpdate opts={{ locale: getEchartsLocale() }} option={option} - theme={mode !== 'map' ? themeConfig : undefined} mode={mode} /> diff --git a/client/packages/lowcoder-comps/src/comps/gaugeChartComp/gaugeChartConstants.tsx b/client/packages/lowcoder-comps/src/comps/gaugeChartComp/gaugeChartConstants.tsx index 89571a5bd..f9f6210b5 100644 --- a/client/packages/lowcoder-comps/src/comps/gaugeChartComp/gaugeChartConstants.tsx +++ b/client/packages/lowcoder-comps/src/comps/gaugeChartComp/gaugeChartConstants.tsx @@ -16,7 +16,9 @@ import { uiChildren, clickEvent, styleControl, - EchartsStyle + EchartsStyle, + EchartDefaultChartStyle, + EchartDefaultTextStyle } from "lowcoder-sdk"; import { RecordConstructorToComp, RecordConstructorToView } from "lowcoder-core"; import { BarChartConfig } from "../chartComp/chartConfigs/barChartConfig"; @@ -259,18 +261,34 @@ let chartJsonModeChildren: any = { tooltip: withDefault(BoolControl, true), legendVisibility: withDefault(BoolControl, true), label: withDefault(BoolControl, true), + progressBar: withDefault(BoolControl, true), + roundCap: withDefault(BoolControl, true), left:withDefault(NumberControl,trans('gaugeChart.defaultLeft')), top:withDefault(NumberControl,trans('gaugeChart.defaultTop')), bottom:withDefault(NumberControl,trans('gaugeChart.defaultBottom')), width:withDefault(NumberControl,trans('gaugeChart.defaultWidth')), + radius:withDefault(NumberControl,trans('gaugeChart.defaultRadius')), min:withDefault(NumberControl,trans('gaugeChart.defaultMin')), max:withDefault(NumberControl,trans('gaugeChart.defaultMax')), - gap:withDefault(NumberControl,trans('gaugeChart.defaultGap')) + gap:withDefault(NumberControl,trans('gaugeChart.defaultGap')), + position_x:withDefault(NumberControl,trans('gaugeChart.defaultPosition_X')), + position_y:withDefault(NumberControl,trans('gaugeChart.defaultPosition_Y')), + startAngle:withDefault(NumberControl,trans('gaugeChart.defaultStartAngle')), + endAngle:withDefault(NumberControl,trans('gaugeChart.defaultEndAngle')), + splitNumber:withDefault(NumberControl,trans('gaugeChart.defaultSplitNumber')), + pointerLength:withDefault(NumberControl,trans('gaugeChart.defaultPointerLength')), + pointerWidth:withDefault(NumberControl,trans('gaugeChart.defaultPointerWidth')), + progressBarWidth:withDefault(NumberControl,trans('gaugeChart.defaultProgressBarWidth')), + } if (EchartsStyle) { chartJsonModeChildren = { ...chartJsonModeChildren, - style: styleControl(EchartsStyle, 'style'), + chartStyle: styleControl(EchartDefaultChartStyle, 'chartStyle'), + titleStyle: styleControl(EchartDefaultTextStyle, 'titleStyle'), + labelStyle: styleControl(EchartDefaultTextStyle, 'labelStyle'), + legendStyle: styleControl(EchartDefaultTextStyle, 'legendStyle'), + axisLabelStyle: styleControl(EchartDefaultTextStyle, 'axisLabelStyle'), } } const chartMapModeChildren = { diff --git a/client/packages/lowcoder-comps/src/comps/gaugeChartComp/gaugeChartPropertyView.tsx b/client/packages/lowcoder-comps/src/comps/gaugeChartComp/gaugeChartPropertyView.tsx index 026006072..cb25183bd 100644 --- a/client/packages/lowcoder-comps/src/comps/gaugeChartComp/gaugeChartPropertyView.tsx +++ b/client/packages/lowcoder-comps/src/comps/gaugeChartComp/gaugeChartPropertyView.tsx @@ -32,21 +32,44 @@ export function gaugeChartPropertyView( ), })} {children.echartsTitleConfig.getPropertyView()} - {children.echartsTitle.propertyView({ label: trans("gaugeChart.title") })} + {children.echartsTitle.propertyView({ label: trans("gaugeChart.title"), tooltip: trans("echarts.titleTooltip") })} {/* {children.left.propertyView({ label: trans("gaugeChart.left") })} {children.top.propertyView({ label: trans("gaugeChart.top") })} {children.bottom.propertyView({ label: trans("gaugeChart.bottom") })} {children.width.propertyView({ label: trans("gaugeChart.width") })} */} - {children.min.propertyView({ label: trans("gaugeChart.min") })} - {children.max.propertyView({ label: trans("gaugeChart.max") })} + {children.radius.propertyView({ label: trans("gaugeChart.radius"), tooltip: trans("echarts.radiusTooltip") })} + {children.min.propertyView({ label: trans("gaugeChart.min"), tooltip: trans("echarts.minTooltip") })} + {children.max.propertyView({ label: trans("gaugeChart.max"), tooltip: trans("echarts.maxTooltip") })} + {children.position_x.propertyView({ label: trans("gaugeChart.position_x"), tooltip: trans("echarts.positionChart_x_Tooltip") })} + {children.position_y.propertyView({ label: trans("gaugeChart.position_y"), tooltip: trans("echarts.positionChart_x_Tooltip") })} + {children.startAngle.propertyView({ label: trans("gaugeChart.startAngle"), tooltip: trans("echarts.startAngleTooltip") })} + {children.endAngle.propertyView({ label: trans("gaugeChart.endAngle"), tooltip: trans("echarts.endAngleTooltip") })} + {children.splitNumber.propertyView({ label: trans("gaugeChart.splitNumber"), tooltip: trans("echarts.splitNumberTooltip") })} + {children.pointerLength.propertyView({ label: trans("gaugeChart.pointerLength"), tooltip: trans("echarts.pointerLengthTooltip") })} + {children.pointerWidth.propertyView({ label: trans("gaugeChart.pointerWidth"), tooltip: trans("echarts.pointerWidthTooltip") })} + {children.progressBar.getView() && children.progressBarWidth.propertyView({ label: trans("gaugeChart.progressBarWidth"), tooltip: trans("echarts.pointerWidthTooltip") })} {/* {children.gap.propertyView({ label: trans("gaugeChart.gap") })} */} - {children.tooltip.propertyView({ label: trans("gaugeChart.tooltip") })} + {children.tooltip.propertyView({ label: trans("gaugeChart.tooltip"), tooltip: trans("echarts.tooltipVisibilityTooltip") })} + {children.progressBar.propertyView({ label: trans("gaugeChart.progressBar"), tooltip: trans("echarts.progressBarVisibilityTooltip") })} + {children.roundCap.propertyView({ label: trans("gaugeChart.roundCap"), tooltip: trans("echarts.roundCapVisibilityTooltip") })}
{children.onEvent.propertyView()}
-
- {children.style?.getPropertyView()} +
+ {children.chartStyle?.getPropertyView()} +
+
+ {children.titleStyle?.getPropertyView()} +
+
+ {children.labelStyle?.getPropertyView()} +
+
+ {children.legendStyle?.getPropertyView()} +
+
+ {children.axisLabelStyle?.getPropertyView()}
{hiddenPropertyView(children)}
diff --git a/client/packages/lowcoder-comps/src/comps/gaugeChartComp/gaugeChartUtils.ts b/client/packages/lowcoder-comps/src/comps/gaugeChartComp/gaugeChartUtils.ts index eb16f1a86..e2c5fa310 100644 --- a/client/packages/lowcoder-comps/src/comps/gaugeChartComp/gaugeChartUtils.ts +++ b/client/packages/lowcoder-comps/src/comps/gaugeChartComp/gaugeChartUtils.ts @@ -12,6 +12,8 @@ import { chartColorPalette, isNumeric, JSONObject, loadScript } from "lowcoder-s import { calcXYConfig } from "comps/chartComp/chartConfigs/cartesianAxisConfig"; import Big from "big.js"; import { googleMapsApiUrl } from "../chartComp/chartConfigs/chartUrls"; +import opacityToHex from "../../util/opacityToHex"; +import parseBackground from "../../util/gradientBackgroundColor"; export function transformData( originData: JSONObject[], @@ -133,55 +135,129 @@ export function getEchartsConfig( chartSize?: ChartSize, theme?: any, ): EChartsOptionWithMap { + if (props.mode === "json") { let opt={ - "title": { - "text": props.echartsTitle, - 'top': props.echartsLegendConfig.top === 'bottom' ?'top':'bottom', - "left":props.echartsTitleConfig.top - }, - "backgroundColor": props?.style?.background || theme?.style?.background, - "color": props.echartsOption.data?.map(data => data.color), - "tooltip": props.tooltip&&{ - "trigger": "item", - "formatter": "{a}
{b} : {c}%" - }, - "series": [ - { - "name": props.echartsConfig.type, - "type": props.echartsConfig.type, - "left": `${props.left}%`, - "top": props.top, - "bottom": props.bottom, - "width": `${props.left}%`, - "min": props.min, - "max": props.max, - "gap": props.gap, - 'detail': { - "backgroundColor": props?.style?.background, "formatter": "{value}%" + "title": { + "text": props.echartsTitle, + 'top': props.echartsLegendConfig.top === 'bottom' ?'top':'bottom', + "left":props.echartsTitleConfig.top, + "textStyle": { + "fontFamily": props?.titleStyle?.chartFontFamily || theme?.titleStyle?.fontFamily, + "fontSize": props?.titleStyle?.chartTextSize || theme?.titleStyle?.fontSize || 18, + "fontWeight": props?.titleStyle?.chartTextWeight || theme?.titleStyle?.fontWeight, + "color": props?.titleStyle?.chartTextColor || theme?.titleStyle?.fontColor || "#000000", + "fontStyle": props?.titleStyle?.chartFontStyle || theme?.titleStyle?.fontStyle, + "textShadowColor": props?.titleStyle?.chartShadowColor || theme?.titleStyle?.shadowColor, + "textShadowBlur": props?.titleStyle?.chartBoxShadow?.split('px')[0] || theme?.titleStyle?.boxShadow?.split('px')[0], + "textShadowOffsetX": props?.titleStyle?.chartBoxShadow?.split('px')[1] || theme?.titleStyle?.boxShadow?.split('px')[1], + "textShadowOffsetY": props?.titleStyle?.chartBoxShadow?.split('px')[2] || theme?.titleStyle?.boxShadow?.split('px')[2] + }, }, - "label": { - "show": props.label, - "position": props.echartsLabelConfig.top + "backgroundColor": parseBackground( props?.chartStyle?.background || theme?.chartStyle?.backgroundColor || "#FFFFFF"), + "tooltip": props.tooltip&&{ + "trigger": "item", + "formatter": "{a}
{b} : {c}%" + }, + "color": props?.echartsOption?.data?.map(data => data.color), + "series": [ + { + "name": props.echartsConfig.type, + "type": props.echartsConfig.type, + "radius": `${props.radius}%`, + "left": `${props.left}%`, + "top": props.top, + "bottom": props.bottom, + "width":`${props.left}%`, + "min": props.min, + "max": props.max, + "gap": props.gap, + "center": [`${props?.position_x}%`, `${props?.position_y}%`], + "startAngle": props?.startAngle, + "endAngle": props?.endAngle, + "splitNumber": props?.splitNumber, + "pointer": { + "length": `${props?.pointerLength}%`, + "width": props?.pointerWidth, + }, + "itemStyle": { + "opacity": props?.opacity, + "borderColor": props?.chartStyle?.chartBorderColor || theme?.chartStyle?.borderColor, + "borderWidth": props?.chartStyle?.chartBorderWidth || theme?.chartStyle?.borderWidth, + "borderType": props?.chartStyle?.chartBorderStyle || theme?.chartStyle?.borderType, + "borderRadius": props?.chartStyle?.chartBorderRadius || theme?.chartStyle?.borderRadius, + "shadowColor": props?.chartStyle?.chartShadowColor || theme?.chartStyle?.shadowColor, + "shadowBlur": props?.chartStyle?.chartBoxShadow?.split('px')[0] || theme?.chartStyle?.boxShadow?.split('px')[0], + "shadowOffsetX": props?.chartStyle?.chartBoxShadow?.split('px')[1] || theme?.chartStyle?.boxShadow?.split('px')[1], + "shadowOffsetY": props?.chartStyle?.chartBoxShadow?.split('px')[2] || theme?.chartStyle?.boxShadow?.split('px')[2] + }, + "progress": { + "roundCap": props.roundCap, + "show": props?.progressBar, + "width": props?.progressBarWidth + }, + "axisLine": { + "roundCap": props.roundCap, + "lineStyle": { + "width": props?.progressBarWidth + } + }, + "axisLabel": { + "distance": Number(props?.progressBarWidth) + 10, + "fontFamily": props?.axisLabelStyle?.chartFontFamily || theme?.axisLabelStyle?.fontFamily, + "fontSize": props?.axisLabelStyle?.chartTextSize || theme?.axisLabelStyle?.fontSize || 12, + "fontWeight": props?.axisLabelStyle?.chartTextWeight || theme?.axisLabelStyle?.fontWeight, + "color": props?.axisLabelStyle?.chartTextColor || theme?.axisLabelStyle?.fontColor || "#000000", + "fontStyle": props?.axisLabelStyle?.chartFontStyle || theme?.axisLabelStyle?.fontStyle, + "textShadowColor": props?.axisLabelStyle?.chartShadowColor || theme?.axisLabelStyle?.shadowColor, + "textShadowBlur": props?.axisLabelStyle?.chartBoxShadow?.split('px')[0] || theme?.axisLabelStyle?.boxShadow?.split('px')[0], + "textShadowOffsetX": props?.axisLabelStyle?.chartBoxShadow?.split('px')[1] || theme?.axisLabelStyle?.boxShadow?.split('px')[1], + "textShadowOffsetY": props?.axisLabelStyle?.chartBoxShadow?.split('px')[2] || theme?.axisLabelStyle?.boxShadow?.split('px')[2] }, - /*"detail": { - "formatter": "{value}%" - }, */ - "data": props.echartsOption.data + 'detail': { + "fontFamily": props?.legendStyle?.chartFontFamily || theme?.legendStyle?.fontFamily, + "fontSize": props?.legendStyle?.chartTextSize || theme?.legendStyle?.fontSize || 16, + "fontWeight": props?.legendStyle?.chartTextWeight || theme?.legendStyle?.fontWeight, + "color": props?.legendStyle?.chartTextColor || theme?.legendStyle?.fontColor || "#000000", + "fontStyle": props?.legendStyle?.chartFontStyle || theme?.legendStyle?.fontStyle, + "textShadowColor": props?.legendStyle?.chartShadowColor || theme?.legendStyle?.shadowColor, + "textShadowBlur": props?.legendStyle?.chartBoxShadow?.split('px')[0] || theme?.legendStyle?.boxShadow?.split('px')[0], + "textShadowOffsetX": props?.legendStyle?.chartBoxShadow?.split('px')[1] || theme?.legendStyle?.boxShadow?.split('px')[1], + "textShadowOffsetY": props?.legendStyle?.chartBoxShadow?.split('px')[2] || theme?.legendStyle?.boxShadow?.split('px')[2] + }, + "label": { + "show": props.label, + "position": props.echartsLabelConfig.top, + }, + "data": props.echartsOption.data?.map(item => ({ + "value": item.value, + "name": item.name, + title: { + "fontFamily": props?.labelStyle?.chartFontFamily || theme?.labelStyle?.fontFamily, + "fontSize": props?.labelStyle?.chartTextSize || theme?.labelStyle?.fontSize, + "fontWeight": props?.labelStyle?.chartTextWeight || theme?.labelStyle?.fontWeight, + "color": props?.labelStyle?.chartTextColor || theme?.labelStyle?.fontColor || "#000000", + "fontStyle": props?.labelStyle?.chartFontStyle || theme?.labelStyle?.fontStyle, + "textShadowColor": props?.labelStyle?.chartShadowColor || theme?.labelStyle?.shadowColor, + "textShadowBlur": props?.labelStyle?.chartBoxShadow?.split('px')[0] || theme?.labelStyle?.boxShadow?.split('px')[0], + "textShadowOffsetX": props?.labelStyle?.chartBoxShadow?.split('px')[1] || theme?.labelStyle?.boxShadow?.split('px')[1], + "textShadowOffsetY": props?.labelStyle?.chartBoxShadow?.split('px')[2] || theme?.labelStyle?.boxShadow?.split('px')[2] + } + })) + } + ] } - ] -} return props.echartsOption ? opt : {}; - + } - + if(props.mode === "map") { const { mapZoomLevel, mapCenterLat, mapCenterLng, - mapOptions, - showCharts, + mapOptions, + showCharts, } = props; const echartsOption = mapOptions && showCharts ? mapOptions : {}; diff --git a/client/packages/lowcoder-comps/src/i18n/comps/locales/en.ts b/client/packages/lowcoder-comps/src/i18n/comps/locales/en.ts index f8d5f77f7..d3520c738 100644 --- a/client/packages/lowcoder-comps/src/i18n/comps/locales/en.ts +++ b/client/packages/lowcoder-comps/src/i18n/comps/locales/en.ts @@ -52,6 +52,20 @@ export const en = { title: 'Title', defaultTitle: 'CandleStick Chart', tooltip: 'Tooltip', + legendVisibility: 'Legend Visibility', + dataZoomVisibility: 'Data Zoom Visibility', + left: 'Left', + defaultLeft:'10', + right: 'Right', + defaultRight:'10', + top: 'Top', + defaultTop:'20', + bottom: 'Bottom', + defaultBottom:'20', + defaultDataZoomBottom: '20', + dataZoomBottom: 'Data Zoom Bottom', + defaultDataZoomHeight: '15', + dataZoomHeight: 'Data Zoom Height' }, sankeyChart: { sankeyType: 'Sankey Chart Type', @@ -65,7 +79,7 @@ export const en = { funnelType:'Funnel Chart Type', tooltip: 'Tooltip', legendVisibility: 'Legend Visibility', - left: 'Left', + left: 'Position-X', defaultLeft:'35', top: 'Top', defaultTop:'60', @@ -79,7 +93,10 @@ export const en = { defaultMax:'100', gap: 'Gap', defaultGap: '2', - label:'Label', + label:'Label Visibility', + opacity: 'Opacity', + defaultOpacity: '1', + }, gaugeChart: { title: 'Title', @@ -100,13 +117,71 @@ export const en = { defaultMax:'100', gap: 'Gap', defaultGap: '2', + defaultStartAngle: '210', + startAngle: 'Start Angle', + defaultEndAngle: '-30', + endAngle: 'End Angle', + defaultSplitNumber: '10', + splitNumber: 'Split Number', + radius: 'Radius', + defaultRadius: '80', + defaultPointerLength: '50', + pointerLength: 'Pointer Length', + pointerWidth: 'Pointer Width', + defaultPointerWidth: '5', label:'Label', + position_x: 'Position-X', + defaultPosition_X: '50', + position_y: 'Position-Y', + defaultPosition_Y: '60', + progressBarWidth: 'Progress Bar Width', + defaultProgressBarWidth: '10', + progressBar: 'Progress Bar', + roundCap: "Round Cap" }, echarts: { defaultTitle: "Data Display", - legendPosition: "Legend Position", + legendPosition: "Legend-Y", + legendOrient: "Legend Orient", + legendAlign: "Legend-X", labelPosition: "Label Position", - titlePosition: "Title Position", + titlePosition: "Title-X", + titlePositionVertical: "Title-Y", + funnelAlign: "Funnel Align", + sort: "Sort", + changingTitle_x_Tooltip: "Change the Horizontal position of the Title.", + changingLegend_x_Tooltip: "Change the Vertical position of the Legend.", + changingLegend_y_Tooltip: "Change the Horizontal position of the Legend.", + changingLegend_orient_Tooltip: "Change the Orientation of the Legend.", + changingSortTooltip: "Change the Sorting direction.", + changingLabelTooltip: "Change the Position of the Label.", + changingAlignTooltip: "Change the Alignment of the Chart.", + positionChart_x_Tooltip: "Change the Horizontal position of the Chart.", + positionChart_y_Tooltip: "Change the Vertical position of the Chart.", + topTooltip: "Change the top length of the Chart.", + bottomTooltip: "Change the bottom length of the Chart.", + widthTooltip: "Change the width of the Chart.", + radiusTooltip: "Set the Radius value of the Chart.", + minTooltip: "Set the minimum value of the Chart.", + maxTooltip: "Set the maximum value of the Chart.", + gapTooltip: "Set the gap value between the Components.", + opacityTooltip: "Set the opacity of the Chart.", + titleTooltip: "Set the title of the Chart.", + roundCap: 'Round Cap', + pointerWidth: "Pointer Width", + roundCapTooltip: "Change the shape of the start, current, and end edges of the progress bar to round or straight.", + progressBarVisibilityToolip: "Show or hide the current status on the progress bar.", + endAngleTooltip: "Set the End angle value of the Chart.", + startAngleTooltip: "Set the Start angle value of the Chart.", + splitNumberTooltip: "Set the Split number of the Chart.", + pointerLengthTooltip: "Set the Pointer length of the Chart.", + pointerWidthTooltip: "Set the Pointer Width of the Chart.", + progressBarWidthToolTip: "Set the Progress Bar Width of the Chart.", + tooltipVisibilityTooltip: "Show or hide the ToolTips of the Chart.", + labelVisibilityTooltip: "Show or hide the Labels of the Chart.", + legendVisibilityTooltip: "Show or hide the Legend of the Chart.", + progressBarVisibilityTooltip: "Show or hide the Progress Bar of the Chart.", + roundCapVisibilityTooltip: "Show or hide the Round Cap of the Chart.", }, chart: { delete: "Delete", diff --git a/client/packages/lowcoder-comps/src/util/gradientBackgroundColor.tsx b/client/packages/lowcoder-comps/src/util/gradientBackgroundColor.tsx new file mode 100644 index 000000000..0ebead21a --- /dev/null +++ b/client/packages/lowcoder-comps/src/util/gradientBackgroundColor.tsx @@ -0,0 +1,100 @@ +/** + * Converts a CSS gradient string (linear-gradient or radial-gradient) or solid color + * into an ECharts-compatible background configuration. + * + * @param {string} background - A solid color or CSS gradient string + * @returns {string|object} A string or object that can be used in ECharts' `backgroundColor` + */ +export default function parseBackground(background: any) { + if (background.startsWith("linear-gradient")) { + // Parse linear-gradient + return parseLinearGradient(background); + } else if (background.startsWith("radial-gradient")) { + // Parse radial-gradient + return parseRadialGradient(background); + } else { + // Assume it's a solid color + return background; + } +} + +/** + * Parses a linear-gradient CSS string into an ECharts-compatible object. + * + * @param {string} gradient - The linear-gradient CSS string + * @returns {object} An ECharts-compatible linear gradient object + */ +function parseLinearGradient(gradient: any) { + const linearGradientRegex = /linear-gradient\((\d+deg),\s*(.+)\)/; + const match = gradient.match(linearGradientRegex); + + if (!match) { + throw new Error("Invalid linear-gradient format"); + } + + const angle = parseFloat(match[1]); // Extract the angle in degrees + const colorStops = parseColorStops(match[2]); // Extract the color stops + + // Convert angle to x2 and y2 using trigonometry + const x2 = Math.sin((angle * Math.PI) / 180); + const y = Math.cos((angle * Math.PI) / 180); + + return { + type: "linear", + x: 0, + y2: 0, + x2, + y, + colorStops, + }; +} + +/** + * Parses a radial-gradient CSS string into an ECharts-compatible object. + * + * @param {string} gradient - The radial-gradient CSS string + * @returns {object} An ECharts-compatible radial gradient object + */ +function parseRadialGradient(gradient: any) { + const radialGradientRegex = /radial-gradient\(([^,]+),\s*(.+)\)/; + const match = gradient.match(radialGradientRegex); + + if (!match) { + throw new Error("Invalid radial-gradient format"); + } + + const shape = match[1].trim(); // Extract the shape (e.g., "circle") + const colorStops = parseColorStops(match[2]); // Extract the color stops + + // ECharts radial gradient assumes a circular gradient centered at (0.5, 0.5) + return { + type: "radial", + x: 0.5, + y: 0.5, + r: 0.8, // Default radius + colorStops, + }; +} + +/** + * Parses color stops from a gradient string into an array of objects. + * + * @param {string} colorStopsString - The color stops part of the gradient string + * @returns {Array} An array of color stop objects { offset, color } + */ +function parseColorStops(colorStopsString: any) { + const colorStopRegex = + /((?:rgba?|hsla?)\([^)]+\)|#[0-9a-fA-F]{3,8}|[a-zA-Z]+)\s+([\d.]+%)/g; + const colorStops = []; + let match; + + while ( + (match = colorStopRegex.exec(colorStopsString.toLowerCase())) !== null + ) { + const color = match[1].trim().toLowerCase(); // Convert color to lowercase + const offset = parseFloat(match[2]) / 100; // Convert percentage to 0-1 + colorStops.push({ offset, color }); + } + + return colorStops; +} diff --git a/client/packages/lowcoder-comps/src/util/opacityToHex.tsx b/client/packages/lowcoder-comps/src/util/opacityToHex.tsx new file mode 100644 index 000000000..ddb71adae --- /dev/null +++ b/client/packages/lowcoder-comps/src/util/opacityToHex.tsx @@ -0,0 +1,15 @@ +export default function opacityToHex(opacity: any) { + if (opacity === undefined) + return 'FF' + try { + // Ensure opacity is clamped between 0 and 1 + opacity = Math.max(0, Math.min(1, opacity)); + const decimalValue = Math.round(opacity * 255); + const hexValue = decimalValue.toString(16).toUpperCase(); + return hexValue.padStart(2, '0'); + } catch (error) { + // Return 'FF' if an exception occurs + return 'FF'; + } +} + diff --git a/client/packages/lowcoder-design/src/components/Section.tsx b/client/packages/lowcoder-design/src/components/Section.tsx index 2f02497d0..a476395d2 100644 --- a/client/packages/lowcoder-design/src/components/Section.tsx +++ b/client/packages/lowcoder-design/src/components/Section.tsx @@ -187,4 +187,9 @@ export const sectionNames = { badgeStyle:trans("prop.badgeStyle"), columnStyle:trans("prop.columnStyle"), modalStyle:trans("prop.modalStyle"), + chartStyle:trans("prop.chartStyle"), + titleStyle:trans("prop.titleStyle"), + legendStyle:trans("prop.legendStyle"), + detailStyle:trans("prop.detailStyle"), + axisLabelStyle:trans("prop.axisLabelStyle"), }; diff --git a/client/packages/lowcoder-design/src/i18n/design/locales/en.ts b/client/packages/lowcoder-design/src/i18n/design/locales/en.ts index 6ebd73d92..c3f38d07d 100644 --- a/client/packages/lowcoder-design/src/i18n/design/locales/en.ts +++ b/client/packages/lowcoder-design/src/i18n/design/locales/en.ts @@ -40,6 +40,11 @@ export const en = { badgeStyle: 'Badge Style', columnStyle: 'Column Style', modalStyle: 'Modal Style', + chartStyle: "Chart Style", + titleStyle: "Title Style", + legendStyle: "Legend Style", + detailStyle: "Detail Style", + axisLabelStyle: "Axis Label Style" }, passwordInput: { label: "Password:", diff --git a/client/packages/lowcoder-design/src/icons/index.tsx b/client/packages/lowcoder-design/src/icons/index.tsx index a538cb9bb..d08e290d8 100644 --- a/client/packages/lowcoder-design/src/icons/index.tsx +++ b/client/packages/lowcoder-design/src/icons/index.tsx @@ -250,6 +250,8 @@ export { ReactComponent as MarketplaceIcon } from "./v1/icon-application-marketp export { ReactComponent as FavoritesIcon } from "./v1/icon-application-favorites.svg"; export { ReactComponent as HomeSettingIcon } from "./remix/settings-4-line.svg"; export { ReactComponent as EnterpriseIcon } from "./remix/earth-line.svg"; +export { ReactComponent as VerticalIcon } from "./remix/vertical.svg"; +export { ReactComponent as HorizontalIcon } from "./remix/horizontal.svg"; // components diff --git a/client/packages/lowcoder-design/src/icons/remix/horizontal.svg b/client/packages/lowcoder-design/src/icons/remix/horizontal.svg new file mode 100644 index 000000000..a534c5534 --- /dev/null +++ b/client/packages/lowcoder-design/src/icons/remix/horizontal.svg @@ -0,0 +1,14 @@ + + + + + + \ No newline at end of file diff --git a/client/packages/lowcoder-design/src/icons/remix/vertical.svg b/client/packages/lowcoder-design/src/icons/remix/vertical.svg new file mode 100644 index 000000000..555811c39 --- /dev/null +++ b/client/packages/lowcoder-design/src/icons/remix/vertical.svg @@ -0,0 +1,14 @@ + + + + + + \ No newline at end of file diff --git a/client/packages/lowcoder/src/api/commonSettingApi.ts b/client/packages/lowcoder/src/api/commonSettingApi.ts index 510e67026..22ae54229 100644 --- a/client/packages/lowcoder/src/api/commonSettingApi.ts +++ b/client/packages/lowcoder/src/api/commonSettingApi.ts @@ -52,6 +52,7 @@ export interface ThemeDetail { borderStyle?: string; chart?: string; margin?: string; + direction?: string; padding?: string; gridPaddingX?: number; gridPaddingY?: number; @@ -91,7 +92,8 @@ export function getThemeDetailName(key: keyof ThemeDetail) { case "borderWidth": return trans("themeDetail.borderWidth"); case "borderStyle": return trans("themeDetail.borderStyle"); case "fontFamily": return trans("themeDetail.fontFamily"); - case "margin": return trans("style.margin"); + case "margin": return trans("style.margin"); + case "direction": return trans("style.direction"); case "padding": return trans("style.padding"); case "gridColumns": return trans("themeDetail.gridColumns"); case "textSize": return trans("style.textSize"); @@ -114,7 +116,8 @@ export function isThemeColorKey(key: string) { case "borderWidth": case "borderStyle": case "fontFamily": - case "margin": + case "margin": + case "direction": case "padding": case "gridColumns": case "textSize": diff --git a/client/packages/lowcoder/src/components/ThemeSettingsCompStyles.tsx b/client/packages/lowcoder/src/components/ThemeSettingsCompStyles.tsx index c34f5e5c8..2b90440d5 100644 --- a/client/packages/lowcoder/src/components/ThemeSettingsCompStyles.tsx +++ b/client/packages/lowcoder/src/components/ThemeSettingsCompStyles.tsx @@ -25,7 +25,7 @@ import { TextStyleIcon, ImageCompIconSmall, RotationIcon, - LineHeightIcon + LineHeightIcon, } from "lowcoder-design/src/icons"; import { trans } from "i18n"; import { debounce } from "lodash"; @@ -101,7 +101,17 @@ const isColorStyle = (styleKey: string) => { styleKey !== 'containerHeaderPadding' && styleKey !== 'containerSiderPadding' && styleKey !== 'containerFooterPadding' && - styleKey !== 'containerBodyPadding'; + styleKey !== 'containerBodyPadding' && + styleKey !== 'direction' && + styleKey !== 'chartOpacity' && + styleKey !== 'chartBoxShadow' && + styleKey !== 'chartBorderStyle' && + styleKey !== 'chartBorderRadius' && + styleKey !== 'chartBorderWidth' && + styleKey !== 'chartTextSize' && + styleKey !== 'chartTextWeight' && + styleKey !== 'chartFontFamily' && + styleKey !== 'chartFontStyle'; } @@ -215,6 +225,26 @@ export default function ThemeSettingsCompStyles(props: CompStyleProps) { placeholder = '#FFFFFF'; break; } + case 'chartBackgroundColor': { + placeholder = '#FFFFFF'; + break; + } + case 'chartGradientColor': { + placeholder = '#FFFFFF'; + break; + } + case 'chartShadowColor': { + placeholder = '#FFFFFF'; + break; + } + case 'chartBorderColor': { + placeholder = '#FFFFFF'; + break; + } + case 'chartTextColor': { + placeholder = '#FFFFFF'; + break; + } case 'boxShadow': { placeholder = '0px 0px 0px'; break; @@ -275,6 +305,47 @@ export default function ThemeSettingsCompStyles(props: CompStyleProps) { placeholder = '0deg'; break; } + case 'direction': { + placeholder = '0 0 1 1'; + break; + } + case 'chartOpacity': { + placeholder = '1'; + break; + } + case 'chartBoxShadow': { + placeholder = '1px 1px 1px'; + break; + } + case 'chartBorderStyle': { + placeholder = 'solid'; + break; + } + case 'chartBorderRadius': { + placeholder = '1px'; + break; + } + case 'chartBorderWidth': { + placeholder = '1px'; + break; + } + case 'chartTextSize': { + placeholder = '14px'; + break; + } + case 'chartTextWeight': { + placeholder = 'normal'; + break; + } + case 'chartFontFamily': { + placeholder = 'Arial'; + break; + } + case 'chartFontStyle': { + placeholder = 'normal'; + break; + } + } return placeholder; } @@ -316,6 +387,26 @@ export default function ThemeSettingsCompStyles(props: CompStyleProps) { icon = ; break; } + case 'chartBackgroundColor': { + icon = ; + break; + } + case 'chartGradientColor': { + icon = ; + break; + } + case 'chartShadowColor': { + icon = ; + break; + } + case 'chartBorderColor': { + icon = ; + break; + } + case 'chartTextColor': { + icon = ; + break; + } case 'boxShadow': { icon = ; break; @@ -380,6 +471,47 @@ export default function ThemeSettingsCompStyles(props: CompStyleProps) { icon = ; break; } + case 'direction': { + icon = ; + break; + } + case 'chartOpacity': { + icon = ; + break; + } + case 'chartBoxShadow': { + icon = ; + break; + } + case 'chartBorderStyle': { + icon = ; + break; + } + case 'chartBorderRadius': { + icon = ; + break; + } + case 'chartBorderWidth': { + icon = ; + break; + } + case 'chartTextSize': { + icon = ; + break; + } + case 'chartTextWeight': { + icon = ; + break; + } + case 'chartFontFamily': { + icon = ; + break; + } + case 'chartFontStyle': { + icon = ; + break; + } + } return icon; } diff --git a/client/packages/lowcoder/src/comps/controls/styleControl.tsx b/client/packages/lowcoder/src/comps/controls/styleControl.tsx index a9f8372b7..c4eb8546f 100644 --- a/client/packages/lowcoder/src/comps/controls/styleControl.tsx +++ b/client/packages/lowcoder/src/comps/controls/styleControl.tsx @@ -43,6 +43,16 @@ import { SimpleColorConfig, SingleColorConfig, MarginConfig, + DirectionConfig, + ChartOpacityConfig, + ChartBoxShadowConfig, + ChartBorderStyleConfig, + ChartBorderRadiusConfig, + ChartBorderWidthConfig, + ChartTextSizeConfig, + ChartTextWeightConfig, + ChartFontFamilyConfig, + ChartFontStyleConfig, PaddingConfig, TextSizeConfig, TextWeightConfig, @@ -70,6 +80,11 @@ import { borderStyleConfig, BoxShadowConfig, BoxShadowColorConfig, + ChartBackgroundColorConfig, + ChartGradientColorConfig, + ChartShadowColorConfig, + ChartBorderColorConfig, + ChartTextColorConfig, AnimationIterationCountConfig, OpacityConfig, AnimationConfig, @@ -190,6 +205,46 @@ function isMarginConfig(config: SingleColorConfig): config is MarginConfig { return config.hasOwnProperty("margin"); } +function isDirectionConfig(config: SingleColorConfig): config is DirectionConfig { + return config.hasOwnProperty("direction"); +} + +function isChartOpacityConfig(config: SingleColorConfig): config is ChartOpacityConfig { + return config.hasOwnProperty("chartOpacity"); +} + +function isChartBoxShadowConfig(config: SingleColorConfig): config is ChartBoxShadowConfig { + return config.hasOwnProperty("chartBoxShadow"); +} + +function isChartBorderStyleConfig(config: SingleColorConfig): config is ChartBorderStyleConfig { + return config.hasOwnProperty("chartBorderStyle"); +} + +function isChartBorderRadiusConfig(config: SingleColorConfig): config is ChartBorderRadiusConfig { + return config.hasOwnProperty("chartBorderRadius"); +} + +function isChartBorderWidthConfig(config: SingleColorConfig): config is ChartBorderWidthConfig { + return config.hasOwnProperty("chartBorderWidth"); +} + +function isChartTextSizeConfig(config: SingleColorConfig): config is ChartTextSizeConfig { + return config.hasOwnProperty("chartTextSize"); +} + +function isChartTextWeightConfig(config: SingleColorConfig): config is ChartTextWeightConfig { + return config.hasOwnProperty("chartTextWeight"); +} + +function isChartFontFamilyConfig(config: SingleColorConfig): config is ChartFontFamilyConfig { + return config.hasOwnProperty("chartFontFamily"); +} + +function isChartFontStyleConfig(config: SingleColorConfig): config is ChartFontStyleConfig { + return config.hasOwnProperty("chartFontStyle"); +} + function isBoxShadowConfig( config: SingleColorConfig ): config is BoxShadowConfig { @@ -202,6 +257,32 @@ function isBoxShadowColorConfig( return config.hasOwnProperty('boxShadowColor'); } +function isChartBackgroundColorConfig( + config: SingleColorConfig +): config is ChartBackgroundColorConfig { + return config.hasOwnProperty('chartBackgroundColor'); +} +function isChartGradientColorConfig( + config: SingleColorConfig +): config is ChartGradientColorConfig { + return config.hasOwnProperty('chartGradientColor'); +} +function isChartShadowColorConfig( + config: SingleColorConfig +): config is ChartShadowColorConfig { + return config.hasOwnProperty('chartShadowColor'); +} +function isChartBorderColorConfig( + config: SingleColorConfig +): config is ChartBorderColorConfig { + return config.hasOwnProperty('chartBorderColor'); +} +function isChartTextColorConfig( + config: SingleColorConfig +): config is ChartTextColorConfig { + return config.hasOwnProperty('chartTextColor'); +} + function isAnimationIterationCountConfig( config: SingleColorConfig ): config is AnimationIterationCountConfig { @@ -326,6 +407,36 @@ function isEmptyBorderStyle(borderStyle: string) { function isEmptyMargin(margin: string) { return _.isEmpty(margin); } +function isEmptyDirection(direction: string) { + return _.isEmpty(direction); +} +function isEmptyChartOpacity(chartOpacity: string) { + return _.isEmpty(chartOpacity); +} +function isEmptyChartBoxShadow(chartBoxShadow: string) { + return _.isEmpty(chartBoxShadow); +} +function isEmptyChartBorderStyle(chartBorderStyle: string) { + return _.isEmpty(chartBorderStyle); +} +function isEmptyChartBorderRadius(chartBorderRadius: string) { + return _.isEmpty(chartBorderRadius); +} +function isEmptyChartBorderWidth(chartBorderWidth: string) { + return _.isEmpty(chartBorderWidth); +} +function isEmptyChartTextSize(chartTextSize: string) { + return _.isEmpty(chartTextSize); +} +function isEmptyChartTextWeight(chartTextWeight: string) { + return _.isEmpty(chartTextWeight); +} +function isEmptyChartFontFamily(chartFontFamily: string) { + return _.isEmpty(chartFontFamily); +} +function isEmptyChartFontStyle(chartFontStyle: string) { + return _.isEmpty(chartFontStyle); +} function isEmptyPadding(padding: string) { return _.isEmpty(padding); } @@ -345,6 +456,22 @@ function isEmptyBoxShadowColor(boxShadowColor: string) { return _.isEmpty(boxShadowColor); } +function isEmptyChartBackgroundColor(chartBackgroundColor: string) { + return _.isEmpty(chartBackgroundColor); +} +function isEmptyChartGradientColor(chartGradientColor: string) { + return _.isEmpty(chartGradientColor); +} +function isEmptyChartShadowColor(chartShadowColor: string) { + return _.isEmpty(chartShadowColor); +} +function isEmptyChartBorderColor(chartBorderColor: string) { + return _.isEmpty(chartBorderColor); +} +function isEmptyChartTextColor(chartTextColor: string) { + return _.isEmpty(chartTextColor); +} + function isEmptyAnimation(animation: string) { return _.isEmpty(animation); } @@ -493,6 +620,46 @@ function calcColors>( res[name] = props[name]; return; } + if (!isEmptyDirection(props[name]) && isDirectionConfig(config)) { + res[name] = props[name]; + return; + } + if (!isEmptyChartOpacity(props[name]) && isChartOpacityConfig(config)) { + res[name] = props[name]; + return; + } + if (!isEmptyChartBoxShadow(props[name]) && isChartBoxShadowConfig(config)) { + res[name] = props[name]; + return; + } + if (!isEmptyChartBorderStyle(props[name]) && isChartBorderStyleConfig(config)) { + res[name] = props[name]; + return; + } + if (!isEmptyChartBorderRadius(props[name]) && isChartBorderRadiusConfig(config)) { + res[name] = props[name]; + return; + } + if (!isEmptyChartBorderWidth(props[name]) && isChartBorderWidthConfig(config)) { + res[name] = props[name]; + return; + } + if (!isEmptyChartTextSize(props[name]) && isChartTextSizeConfig(config)) { + res[name] = props[name]; + return; + } + if (!isEmptyChartTextWeight(props[name]) && isChartTextWeightConfig(config)) { + res[name] = props[name]; + return; + } + if (!isEmptyChartFontFamily(props[name]) && isChartFontFamilyConfig(config)) { + res[name] = props[name]; + return; + } + if (!isEmptyChartFontStyle(props[name]) && isChartFontStyleConfig(config)) { + res[name] = props[name]; + return; + } if (!isEmptyPadding(props[name]) && isPaddingConfig(config)) { res[name] = props[name]; return; @@ -505,6 +672,26 @@ function calcColors>( res[name] = props[name]; return; } + if (!isEmptyChartBackgroundColor(props[name]) && isChartBackgroundColorConfig(config)) { + res[name] = props[name]; + return; + } + if (!isEmptyChartGradientColor(props[name]) && isChartGradientColorConfig(config)) { + res[name] = props[name]; + return; + } + if (!isEmptyChartShadowColor(props[name]) && isChartShadowColorConfig(config)) { + res[name] = props[name]; + return; + } + if (!isEmptyChartBorderColor(props[name]) && isChartBorderColorConfig(config)) { + res[name] = props[name]; + return; + } + if (!isEmptyChartTextColor(props[name]) && isChartTextColorConfig(config)) { + res[name] = props[name]; + return; + } if ( !isEmptyAnimationIterationCount(props[name]) && isAnimationIterationCountConfig(config) @@ -622,6 +809,36 @@ function calcColors>( if (isMarginConfig(config)) { res[name] = themeWithDefault[config.margin]; } + if (isDirectionConfig(config)) { + res[name] = themeWithDefault[config.direction] || '0 0 1 1'; + } + if (isChartOpacityConfig(config)) { + res[name] = themeWithDefault[config.chartOpacity] || '1'; + } + if (isChartBoxShadowConfig(config)) { + res[name] = themeWithDefault[config.chartBoxShadow] || '1px 1px 1px'; + } + if (isChartBorderStyleConfig(config)) { + res[name] = themeWithDefault[config.chartBorderStyle] || 'solid'; + } + if (isChartBorderRadiusConfig(config)) { + res[name] = themeWithDefault[config.chartBorderRadius] || '1px'; + } + if (isChartBorderWidthConfig(config)) { + res[name] = themeWithDefault[config.chartBorderWidth] || '1px'; + } + if (isChartTextSizeConfig(config)) { + res[name] = themeWithDefault[config.chartTextSize] || '14px'; + } + if (isChartTextWeightConfig(config)) { + res[name] = themeWithDefault[config.chartTextWeight] || 'normal'; + } + if (isChartFontFamilyConfig(config)) { + res[name] = themeWithDefault[config.chartFontFamily] || 'Arial'; + } + if (isChartFontStyleConfig(config)) { + res[name] = themeWithDefault[config.chartFontStyle] || 'normal'; + } if (isPaddingConfig(config)) { res[name] = themeWithDefault[config.padding]; } @@ -629,7 +846,22 @@ function calcColors>( res[name] = themeWithDefault[config.boxShadow] || '0px 0px 0px'; } if (isBoxShadowColorConfig(config)) { - res[name] = themeWithDefault[config.boxShadowColor] || '0px 0px 0px'; + res[name] = themeWithDefault[config.boxShadowColor]; + } + if (isChartBackgroundColorConfig(config)) { + res[name] = themeWithDefault[config.chartBackgroundColor]; + } + if (isChartGradientColorConfig(config)) { + res[name] = themeWithDefault[config.chartGradientColor]; + } + if (isChartShadowColorConfig(config)) { + res[name] = themeWithDefault[config.chartShadowColor]; + } + if (isChartBorderColorConfig(config)) { + res[name] = themeWithDefault[config.chartBorderColor]; + } + if (isChartTextColorConfig(config)) { + res[name] = themeWithDefault[config.chartTextColor]; } if (isAnimationIterationCountConfig(config)) { res[name] = themeWithDefault[config.animationIterationCount] || '0'; @@ -767,6 +999,7 @@ const LineHeightPropIcon = styled(LineHeightIcon)` `; const MarginIcon = styled(ExpandIcon)` margin: 0 8px 0 2px; color: #888`; +const DirectionIcon = styled(ExpandIcon)` margin: 0 13px 0 2px; color: #888`; const PaddingIcon = styled(CompressIcon)` margin: 0 8px 0 2px; color: #888`; const RadiusPropIcon = styled(BorderRadiusIcon)` width: 24px; margin: 0 11px 0 0px; color: #888`; const BorderPropIcon = styled(BorderWidthIcon)` margin: 0 8px 0 -3px; padding: 3px; color: #888`; @@ -791,6 +1024,32 @@ const BoxShadowColorPropIcon = styled(BorderWidthIcon)` color: #888; `; +const ChartBackgroundColorPropIcon = styled(BorderWidthIcon)` + margin: 0 8px 0 -3px; + padding: 13px; + color: #888; +`; +const ChartGradientColorPropIcon = styled(BorderWidthIcon)` + margin: 0 8px 0 -3px; + padding: 3px; + color: #888; +`; +const ChartShadowColorPropIcon = styled(BorderWidthIcon)` + margin: 0 8px 0 -3px; + padding: 3px; + color: #888; +`; +const ChartBorderColorPropIcon = styled(BorderWidthIcon)` + margin: 0 8px 0 -3px; + padding: 3px; + color: #888; +`; +const ChartTextColorPropIcon = styled(BorderWidthIcon)` + margin: 0 8px 0 -3px; + padding: 3px; + color: #888; +`; + const BoxShadowPropIcon = styled(ShadowIcon)` margin: 0 8px 0 -3px; padding: 3px; @@ -818,6 +1077,7 @@ const RotationPropIcon = styled(RotationIcon)` margin: 0 8px 0 -3px; padding: 3p const StyledTextSizeIcon = styled(TextSizeIcon)` margin: 0 8px 0 -3px; padding: 3px; color: #888`; const StyledTextTransformIcon = styled(TextTransformationIcon)` margin: 0 8px 0 -3px; padding: 3px; color: #888`; const StyledFontFamilyIcon = styled(FontFamilyIcon)` margin: 0 8px 0 -3px; padding: 3px; color: #888`; +const StyledFontStyleIcon = styled(TextStyleIcon)` margin: 0 8px 0 -3px; padding: 3px; color: #888`; const StyledTextWeightIcon = styled(TextWeightIcon)` margin: 0 8px 0 -3px; padding: 3px; color: #888`; const StyledTextStyleIcon = styled(TextStyleIcon)` margin: 0 8px 0 -3px; padding: 3px; color: #888`; const StyledTextDecorationPropIcon = styled(TextDecorationIcon)` margin: 0 8px 0 -3px; padding: 3px; color: #888`; @@ -913,6 +1173,16 @@ export function styleControl( name === 'footerBackgroundImagePosition' || name === 'footerBackgroundImageOrigin' || name === 'margin' || + name === 'direction' || + name === 'chartOpacity' || + name === 'chartBoxShadow' || + name === 'chartBorderStyle' || + name === 'chartBorderRadius' || + name === 'chartBorderWidth' || + name === 'chartTextSize' || + name === 'chartTextWeight' || + name === 'chartFontFamily' || + name === 'chartFontStyle' || name === 'padding' || name === 'containerHeaderPadding' || name === 'containerSiderPadding' || @@ -984,6 +1254,16 @@ export function styleControl( if ( name === 'radius' || name === 'margin' || + name === 'direction' || + name === 'chartOpacity' || + name === 'chartBoxShadow' || + name === 'chartBorderStyle' || + name === 'chartBorderRadius' || + name === 'chartBorderWidth' || + name === 'chartTextSize' || + name === 'chartTextWeight' || + name === 'chartFontFamily' || + name === 'chartFontStyle' || name === 'padding' || name === 'containerHeaderPadding' || name === 'containerSiderPadding' || @@ -993,6 +1273,11 @@ export function styleControl( name === 'animationIterationCount' || name === 'opacity' || name === 'boxShadowColor' || + name === 'chartBackgroundColor' || + name === 'chartGradientColor' || + name === 'chartShadowColor' || + name === 'chartBorderColor' || + name === 'chartTextColor' || name === 'boxShadow' || name === 'animation' || name === 'animationDelay' || @@ -1096,277 +1381,437 @@ export function styleControl( preInputNode: , placeholder: props[name], }) - : name === 'animationIterationCount' + : name === 'direction' ? ( + children[name] as InstanceType< + typeof StringControl + > + ).propertyView({ + label: config.label, + preInputNode: , + placeholder: props[name], + }) + : name === 'chartOpacity' + ? ( children[name] as InstanceType< typeof StringControl > ).propertyView({ label: config.label, - preInputNode: ( - - ), + preInputNode: , placeholder: props[name], }) - : name === 'opacity' - ? ( + : name === 'chartBoxShadow' + ? ( children[name] as InstanceType< typeof StringControl > ).propertyView({ label: config.label, - preInputNode: ( - - ), + preInputNode: , placeholder: props[name], }) - : name === 'boxShadowColor' - ? ( - children[name] as InstanceType< - typeof StringControl - > - ).propertyView({ - label: config.label, - preInputNode: ( - - ), - placeholder: props[name], - }) - : name === 'boxShadow' - ? ( + : name === 'chartBorderStyle' + ? ( children[name] as InstanceType< typeof StringControl > ).propertyView({ label: config.label, - preInputNode: ( - - ), + preInputNode: , placeholder: props[name], }) - : name === 'animation' - ? ( + : name === 'chartBorderRadius' + ? ( children[name] as InstanceType< typeof StringControl > ).propertyView({ label: config.label, - preInputNode: ( - - ), + preInputNode: , placeholder: props[name], }) - : name === 'animationDelay' - ? ( + : name === 'chartBorderWidth' + ? ( children[name] as InstanceType< typeof StringControl > ).propertyView({ label: config.label, - preInputNode: ( - - ), + preInputNode: , placeholder: props[name], }) - : name === 'animationDuration' - ? ( + : name === 'chartTextSize' + ? ( children[name] as InstanceType< typeof StringControl > ).propertyView({ label: config.label, - preInputNode: ( - - ), + preInputNode: , placeholder: props[name], }) - : name === 'padding' || - name === - 'containerHeaderPadding' || - name === - 'containerSiderPadding' || - name === - 'containerFooterPadding' || - name === 'containerBodyPadding' + : name === 'chartTextWeight' ? ( + children[name] as InstanceType< + typeof StringControl + > + ).propertyView({ + label: config.label, + preInputNode: , + placeholder: props[name], + }) + : name === 'chartFontFamily' + ? ( children[name] as InstanceType< typeof StringControl > ).propertyView({ label: config.label, - preInputNode: ( - - ), + preInputNode: , placeholder: props[name], }) - : name === 'textSize' - ? ( - children[ - name - ] as InstanceType< + : name === 'chartFontStyle' + ? ( + children[name] as InstanceType< typeof StringControl > ).propertyView({ label: config.label, - preInputNode: ( - - ), + preInputNode: , placeholder: props[name], }) - : name === 'textWeight' - ? ( - children[ - name - ] as InstanceType< - typeof StringControl - > - ).propertyView({ - label: config.label, - preInputNode: ( - - ), - placeholder: props[name], - }) - : name === 'fontFamily' + : name === 'animationIterationCount' ? ( - children[ - name - ] as InstanceType< + children[name] as InstanceType< typeof StringControl > ).propertyView({ label: config.label, preInputNode: ( - + ), placeholder: props[name], }) - : name === 'textDecoration' + : name === 'opacity' ? ( - children[ - name - ] as InstanceType< + children[name] as InstanceType< typeof StringControl > ).propertyView({ label: config.label, preInputNode: ( - + ), - placeholder: - props[name], + placeholder: props[name], }) - : name === 'textTransform' + : name === 'boxShadowColor' ? ( - children[ - name - ] as InstanceType< + children[name] as InstanceType< typeof StringControl > ).propertyView({ label: config.label, preInputNode: ( - + ), - placeholder: - props[name], + placeholder: props[name], }) - : name === 'fontStyle' + : name === 'chartBackgroundColor' ? ( - children[ - name - ] as InstanceType< + children[name] as InstanceType< + typeof StringControl + > + ).propertyView({ + label: config.label, + preInputNode: ( + + ), + placeholder: props[name], + }) + : name === 'chartGradientColor' + ? ( + children[name] as InstanceType< typeof StringControl > ).propertyView({ label: config.label, preInputNode: ( - + ), - placeholder: - props[name], + placeholder: props[name], }) - : name === - 'backgroundImage' || - name === - 'headerBackgroundImage' || - name === - 'footerBackgroundImage' - ? ( - children[ - name - ] as InstanceType< + : name === 'chartShadowColor' + ? ( + children[name] as InstanceType< typeof StringControl > ).propertyView({ - label: - config.label, + label: config.label, preInputNode: ( - + ), - placeholder: - props[name], + placeholder: props[name], }) - : name === - 'backgroundImageRepeat' || - name === - 'headerBackgroundImageRepeat' || - name === - 'footerBackgroundImageRepeat' - ? ( - children[ - name - ] as InstanceType< + : name === 'chartBorderColor' + ? ( + children[name] as InstanceType< typeof StringControl > ).propertyView({ - label: - config.label, + label: config.label, preInputNode: ( - + ), - placeholder: - props[name], + placeholder: props[name], }) - : name === - 'rotation' - ? ( - children[ - name - ] as InstanceType< + : name === 'chartTextColor' + ? ( + children[name] as InstanceType< typeof StringControl > ).propertyView({ - label: - config.label, - preInputNode: - ( - - ), - placeholder: - props[name], + label: config.label, + preInputNode: ( + + ), + placeholder: props[name], }) - : name === 'lineHeight' // Added lineHeight here - ? ( - children[name] as InstanceType - ).propertyView({ - label: config.label, - preInputNode: , - placeholder: props[name], - }) - : children[ - name - ].propertyView({ - label: - config.label, - panelDefaultColor: - props[name], - // isDep: isDepColorConfig(config), - isDep: true, - depMsg: - depMsg, - allowGradient: config.name.includes('background'), - })} + : name === 'boxShadow' + ? ( + children[name] as InstanceType< + typeof StringControl + > + ).propertyView({ + label: config.label, + preInputNode: ( + + ), + placeholder: props[name], + }) + : name === 'animation' + ? ( + children[name] as InstanceType< + typeof StringControl + > + ).propertyView({ + label: config.label, + preInputNode: ( + + ), + placeholder: props[name], + }) + : name === 'animationDelay' + ? ( + children[name] as InstanceType< + typeof StringControl + > + ).propertyView({ + label: config.label, + preInputNode: ( + + ), + placeholder: props[name], + }) + : name === 'animationDuration' + ? ( + children[name] as InstanceType< + typeof StringControl + > + ).propertyView({ + label: config.label, + preInputNode: ( + + ), + placeholder: props[name], + }) + : name === 'padding' || + name === + 'containerHeaderPadding' || + name === + 'containerSiderPadding' || + name === + 'containerFooterPadding' || + name === 'containerBodyPadding' + ? ( + children[name] as InstanceType< + typeof StringControl + > + ).propertyView({ + label: config.label, + preInputNode: ( + + ), + placeholder: props[name], + }) + : name === 'textSize' + ? ( + children[ + name + ] as InstanceType< + typeof StringControl + > + ).propertyView({ + label: config.label, + preInputNode: ( + + ), + placeholder: props[name], + }) + : name === 'textWeight' + ? ( + children[ + name + ] as InstanceType< + typeof StringControl + > + ).propertyView({ + label: config.label, + preInputNode: ( + + ), + placeholder: props[name], + }) + : name === 'fontFamily' + ? ( + children[ + name + ] as InstanceType< + typeof StringControl + > + ).propertyView({ + label: config.label, + preInputNode: ( + + ), + placeholder: props[name], + }) + : name === 'textDecoration' + ? ( + children[ + name + ] as InstanceType< + typeof StringControl + > + ).propertyView({ + label: config.label, + preInputNode: ( + + ), + placeholder: + props[name], + }) + : name === 'textTransform' + ? ( + children[ + name + ] as InstanceType< + typeof StringControl + > + ).propertyView({ + label: config.label, + preInputNode: ( + + ), + placeholder: + props[name], + }) + : name === 'fontStyle' + ? ( + children[ + name + ] as InstanceType< + typeof StringControl + > + ).propertyView({ + label: config.label, + preInputNode: ( + + ), + placeholder: + props[name], + }) + : name === + 'backgroundImage' || + name === + 'headerBackgroundImage' || + name === + 'footerBackgroundImage' + ? ( + children[ + name + ] as InstanceType< + typeof StringControl + > + ).propertyView({ + label: + config.label, + preInputNode: ( + + ), + placeholder: + props[name], + }) + : name === + 'backgroundImageRepeat' || + name === + 'headerBackgroundImageRepeat' || + name === + 'footerBackgroundImageRepeat' + ? ( + children[ + name + ] as InstanceType< + typeof StringControl + > + ).propertyView({ + label: + config.label, + preInputNode: ( + + ), + placeholder: + props[name], + }) + : name === + 'rotation' + ? ( + children[ + name + ] as InstanceType< + typeof StringControl + > + ).propertyView({ + label: + config.label, + preInputNode: + ( + + ), + placeholder: + props[name], + }) + : name === 'lineHeight' // Added lineHeight here + ? ( + children[name] as InstanceType + ).propertyView({ + label: config.label, + preInputNode: , + placeholder: props[name], + }) + : children[ + name + ].propertyView({ + label: + config.label, + panelDefaultColor: + props[name], + // isDep: isDepColorConfig(config), + isDep: true, + depMsg: + depMsg, + allowGradient: config.name.includes('background'), + })} ); })} diff --git a/client/packages/lowcoder/src/comps/controls/styleControlConstants.tsx b/client/packages/lowcoder/src/comps/controls/styleControlConstants.tsx index fca765ca3..6de547836 100644 --- a/client/packages/lowcoder/src/comps/controls/styleControlConstants.tsx +++ b/client/packages/lowcoder/src/comps/controls/styleControlConstants.tsx @@ -41,6 +41,22 @@ export type BoxShadowColorConfig = CommonColorConfig & { readonly boxShadowColor: string; }; +export type ChartBackgroundColorConfig = CommonColorConfig & { + readonly chartBackgroundColor: string; +}; +export type ChartGradientColorConfig = CommonColorConfig & { + readonly chartGradientColor: string; +}; +export type ChartShadowColorConfig = CommonColorConfig & { + readonly chartShadowColor: string; +}; +export type ChartBorderColorConfig = CommonColorConfig & { + readonly chartBorderColor: string; +}; +export type ChartTextColorConfig = CommonColorConfig & { + readonly chartTextColor: string; +}; + export type AnimationIterationCountConfig = CommonColorConfig & { readonly animationIterationCount: string; }; @@ -165,6 +181,46 @@ export type MarginConfig = CommonColorConfig & { readonly margin: string; }; +export type DirectionConfig = CommonColorConfig & { + readonly direction: string; +}; + +export type ChartOpacityConfig = CommonColorConfig & { + readonly chartOpacity: string; +}; + +export type ChartBoxShadowConfig = CommonColorConfig & { + readonly chartBoxShadow: string; +}; + +export type ChartBorderStyleConfig = CommonColorConfig & { + readonly chartBorderStyle: string; +}; + +export type ChartBorderRadiusConfig = CommonColorConfig & { + readonly chartBorderRadius: string; +}; + +export type ChartBorderWidthConfig = CommonColorConfig & { + readonly chartBorderWidth: string; +}; + +export type ChartTextSizeConfig = CommonColorConfig & { + readonly chartTextSize: string; +}; + +export type ChartTextWeightConfig = CommonColorConfig & { + readonly chartTextWeight: string; +}; + +export type ChartFontFamilyConfig = CommonColorConfig & { + readonly chartFontFamily: string; +}; + +export type ChartFontStyleConfig = CommonColorConfig & { + readonly chartFontStyle: string; +}; + export type PaddingConfig = CommonColorConfig & { readonly padding: string; }; @@ -203,6 +259,16 @@ export type SingleColorConfig = | FontFamilyConfig | FontStyleConfig | MarginConfig + | DirectionConfig + | ChartOpacityConfig + | ChartBoxShadowConfig + | ChartBorderStyleConfig + | ChartBorderRadiusConfig + | ChartBorderWidthConfig + | ChartTextSizeConfig + | ChartTextWeightConfig + | ChartFontFamilyConfig + | ChartFontStyleConfig | PaddingConfig | ContainerHeaderPaddingConfig | ContainerSiderPaddingConfig @@ -231,6 +297,11 @@ export type SingleColorConfig = | BoxShadowColorConfig | AnimationIterationCountConfig | LineHeightConfig + | ChartBackgroundColorConfig + | ChartGradientColorConfig + | ChartShadowColorConfig + | ChartBorderColorConfig + | ChartTextColorConfig @@ -457,6 +528,36 @@ const BOXSHADOWCOLOR = { boxShadowColor: "boxShadowColor", } as const; +const CHARTBACKGROUNDCOLOR = { + name: "chartBackgroundColor", + label: trans("style.chartBackgroundColor"), + chartBackgroundColor: "chartBackgroundColor", +} as const; + +const CHARTGRADIENTCOLOR = { + name: "chartGradientColor", + label: trans("style.chartGradientColor"), + chartGradientColor: "chartGradientColor", +} as const; + +const CHARTSHADOWCOLOR = { + name: "chartShadowColor", + label: trans("style.chartShadowColor"), + chartShadowColor: "chartShadowColor", +} as const; + +const CHARTBORDERCOLOR = { + name: "chartBorderColor", + label: trans("style.chartBorderColor"), + chartBorderColor: "chartBorderColor", +} as const; + +const CHARTTEXTCOLOR = { + name: "chartTextColor", + label: trans("style.chartTextColor"), + chartTextColor: "chartTextColor", +} as const; + const OPACITY = { name: "opacity", label: trans("style.opacity"), @@ -548,6 +649,66 @@ const MARGIN = { margin: "margin", } as const; +const DIRECTION = { + name: "direction", + label: trans("style.direction"), + direction: "direction", +} as const; + +const CHARTOPACITY = { + name: "chartOpacity", + label: trans("style.opacity"), + chartOpacity: "chartOpacity", +} as const; + +const CHARTBOXSHADOW = { + name: "chartBoxShadow", + label: trans("style.boxShadow"), + chartBoxShadow: "chartBoxShadow", +} as const; + +const CHARTBORDERSTYLE = { + name: "chartBorderStyle", + label: trans("style.borderStyle"), + chartBorderStyle: "chartBorderStyle", +} as const; + +const CHARTBORDERRADIUS = { + name: "chartBorderRadius", + label: trans("style.borderRadius"), + chartBorderRadius: "chartBorderRadius", +} as const; + +const CHARTBORDERWIDTH = { + name: "chartBorderWidth", + label: trans("style.borderWidth"), + chartBorderWidth: "chartBorderWidth", +} as const; + +const CHARTTEXTSIZE = { + name: "chartTextSize", + label: trans("style.textSize"), + chartTextSize: "chartTextSize", +} as const; + +const CHARTTEXTWEIGHT = { + name: "chartTextWeight", + label: trans("style.textWeight"), + chartTextWeight: "chartTextWeight", +} as const; + +const CHARTFONTFAMILY = { + name: "chartFontFamily", + label: trans("style.fontFamily"), + chartFontFamily: "chartFontFamily", +} as const; + +const CHARTFONTSTYLE = { + name: "chartFontStyle", + label: trans("style.fontStyle"), + chartFontStyle: "chartFontStyle", +} as const; + const PADDING = { name: "padding", label: trans("style.padding"), @@ -742,6 +903,16 @@ function getBackground(depTheme: keyof ThemeDetail = "primarySurface") { } as const; } +function getGradientBackground(depTheme: keyof ThemeDetail = "primarySurface") { + return { + name: "gradientBackground", + label: trans("style.gradientBackground"), + depTheme: depTheme, + depType: DEP_TYPE.SELF, + transformer: toSelf, + } as const; +} + function getStaticBackground(color: string) { return { name: "background", @@ -1793,6 +1964,30 @@ export const JsonEditorStyle = [LABEL] as const; export const EchartsStyle = [getBackground("primarySurface")] as const; +export const EchartDefaultTextStyle = [ + CHARTTEXTCOLOR, + CHARTTEXTSIZE, + CHARTTEXTWEIGHT, + CHARTFONTFAMILY, + CHARTFONTSTYLE, + CHARTSHADOWCOLOR, + CHARTBOXSHADOW, +] as const; + +export const EchartDefaultChartStyle = [ + getBackground("primarySurface"), + // CHARTBACKGROUNDCOLOR, + // CHARTGRADIENTCOLOR, + // DIRECTION, + // CHARTOPACITY, + CHARTSHADOWCOLOR, + CHARTBOXSHADOW, + CHARTBORDERCOLOR, + CHARTBORDERSTYLE, + CHARTBORDERRADIUS, + CHARTBORDERWIDTH, +] as const; + export const CalendarStyle = [ getBackground("primarySurface"), { diff --git a/client/packages/lowcoder/src/i18n/locales/en.ts b/client/packages/lowcoder/src/i18n/locales/en.ts index 59e9a4809..222157aff 100644 --- a/client/packages/lowcoder/src/i18n/locales/en.ts +++ b/client/packages/lowcoder/src/i18n/locales/en.ts @@ -568,7 +568,22 @@ export const en = { "siderBackgroundImageOrigin": "Sider Background Image Origin", "activeBackground": "Active Background Color", "labelBackground": "Label Background Color", - + "gradientBackground": "Gradient Background Color", + "direction": "Direction", + "chartOpacity": "Opacity", + "chartBoxShadow": "Box Shadow", + "chartBorderStyle": "Border Style", + "chartBorderRadius": "Border Radius", + "chartBorderWidth": "Border Width", + "chartTextSize": "Text Size", + "chartTextWeight": "Text Weight", + "chartFontFamily": "Font Family", + "chartFontStyle": "Font Style", + "chartBackgroundColor": "Background Color", + "chartGradientColor": "Gradient Color", + "chartShadowColor": "Shadow Color", + "chartBorderColor": "Border Color", + "chartTextColor": "Text Color" }, "export": { "hiddenDesc": "If true, the component is hidden",