lowcoder-comps 0.0.7 → 0.0.8

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.
Files changed (79) hide show
  1. package/icons/icon-chart.svg +15 -0
  2. package/icons/icon-comp-calendar.svg +22 -0
  3. package/index.html +26 -0
  4. package/index.tsx +19 -0
  5. package/jest.config.js +5 -0
  6. package/package/012a06bb.js +34 -0
  7. package/package/06481cb7.js +1060 -0
  8. package/package/0c8b29d5.js +6 -0
  9. package/package/114884df.js +805 -0
  10. package/package/1264ddb2.js +194 -0
  11. package/package/1cee31ec.js +1095 -0
  12. package/package/269c3ba3.js +46662 -0
  13. package/package/2a2c2e55.js +799 -0
  14. package/package/2b3ab1e4.js +98763 -0
  15. package/package/37590a81.js +967 -0
  16. package/package/3cd7980e.js +184 -0
  17. package/package/40112498.js +424 -0
  18. package/package/4b6e1d6f.js +24 -0
  19. package/package/4bc1082b.js +86 -0
  20. package/package/53e49f9b.js +1600 -0
  21. package/package/55bd5c26.js +266 -0
  22. package/package/591684c8.js +2071 -0
  23. package/package/6c000872.js +16 -0
  24. package/package/756addec.js +775 -0
  25. package/package/7668124e.js +8 -0
  26. package/package/79e8eeeb.js +949 -0
  27. package/package/926fbfec.js +91 -0
  28. package/package/945eefb3.js +2665 -0
  29. package/package/a35f148e.js +1228 -0
  30. package/package/a4d12a43.js +175 -0
  31. package/package/a60de5d1.js +804 -0
  32. package/package/a8dde1ea.js +589 -0
  33. package/package/b4148642.js +7 -0
  34. package/package/b7dd22a2.js +847 -0
  35. package/package/d4f3a2c4.js +18046 -0
  36. package/package/e0f479f3.js +91 -0
  37. package/package/eaa160c9.js +341 -0
  38. package/package/f1bfd8b5.js +311 -0
  39. package/package/f1f9ba79.js +900 -0
  40. package/package/fba61f63.js +2868 -0
  41. package/package/icons/icon-chart.svg +15 -0
  42. package/package/icons/icon-comp-calendar.svg +22 -0
  43. package/package/index.js +5 -0
  44. package/package/package.json +73 -0
  45. package/package.json +1 -4
  46. package/src/__test__/allComp.test.tsx +61 -0
  47. package/src/app-env.d.ts +3 -0
  48. package/src/comps/calendarComp/calendarComp.tsx +442 -0
  49. package/src/comps/calendarComp/calendarConstants.tsx +897 -0
  50. package/src/comps/chartComp/chartComp.tsx +249 -0
  51. package/src/comps/chartComp/chartConfigs/barChartConfig.tsx +51 -0
  52. package/src/comps/chartComp/chartConfigs/cartesianAxisConfig.tsx +307 -0
  53. package/src/comps/chartComp/chartConfigs/chartUrls.tsx +6 -0
  54. package/src/comps/chartComp/chartConfigs/legendConfig.tsx +55 -0
  55. package/src/comps/chartComp/chartConfigs/lineChartConfig.tsx +96 -0
  56. package/src/comps/chartComp/chartConfigs/pieChartConfig.tsx +83 -0
  57. package/src/comps/chartComp/chartConfigs/scatterChartConfig.tsx +62 -0
  58. package/src/comps/chartComp/chartConstants.tsx +243 -0
  59. package/src/comps/chartComp/chartPropertyView.tsx +161 -0
  60. package/src/comps/chartComp/chartUtils.ts +240 -0
  61. package/src/comps/chartComp/reactEcharts/core.tsx +187 -0
  62. package/src/comps/chartComp/reactEcharts/index.ts +20 -0
  63. package/src/comps/chartComp/reactEcharts/types.ts +70 -0
  64. package/src/comps/chartComp/seriesComp.tsx +119 -0
  65. package/src/comps/imageEditorComp/imageEditorClass.tsx +52 -0
  66. package/src/comps/imageEditorComp/imageEditorConstants.tsx +109 -0
  67. package/src/comps/imageEditorComp/index.tsx +184 -0
  68. package/src/comps/mermaidComp/index.tsx +44 -0
  69. package/src/comps/mermaidComp/mermaid.tsx +29 -0
  70. package/src/global.ts +1 -0
  71. package/src/i18n/comps/index.tsx +29 -0
  72. package/src/i18n/comps/locales/en.ts +142 -0
  73. package/src/i18n/comps/locales/enObj.tsx +120 -0
  74. package/src/i18n/comps/locales/index.ts +7 -0
  75. package/src/i18n/comps/locales/types.tsx +9 -0
  76. package/src/i18n/comps/locales/zh.ts +4 -0
  77. package/src/i18n/comps/locales/zhObj.tsx +4 -0
  78. package/src/index.ts +11 -0
  79. package/vite.config.js +10 -0
@@ -0,0 +1,240 @@
1
+ import {
2
+ CharOptionCompType,
3
+ ChartCompPropsType,
4
+ ChartSize,
5
+ noDataAxisConfig,
6
+ noDataPieChartConfig,
7
+ } from "comps/chartComp/chartConstants";
8
+ import { getPieRadiusAndCenter } from "comps/chartComp/chartConfigs/pieChartConfig";
9
+ import { EChartsOption } from "echarts";
10
+ import _ from "lodash";
11
+ import { chartColorPalette, isNumeric, JSONObject } from "lowcoder-sdk";
12
+ import { calcXYConfig } from "comps/chartComp/chartConfigs/cartesianAxisConfig";
13
+ import Big from "big.js";
14
+
15
+ export function transformData(
16
+ originData: JSONObject[],
17
+ xAxis: string,
18
+ seriesColumnNames: string[]
19
+ ) {
20
+ // aggregate data by x-axis
21
+ const transformedData: JSONObject[] = [];
22
+ originData.reduce((prev, cur) => {
23
+ if (cur === null || cur === undefined) {
24
+ return prev;
25
+ }
26
+ const groupValue = cur[xAxis] as string;
27
+ if (!prev[groupValue]) {
28
+ // init as 0
29
+ const initValue: any = {};
30
+ seriesColumnNames.forEach((name) => {
31
+ initValue[name] = 0;
32
+ });
33
+ prev[groupValue] = initValue;
34
+ transformedData.push(prev[groupValue]);
35
+ }
36
+ // remain the x-axis data
37
+ prev[groupValue][xAxis] = groupValue;
38
+ seriesColumnNames.forEach((key) => {
39
+ if (key === xAxis) {
40
+ return;
41
+ } else if (isNumeric(cur[key])) {
42
+ const bigNum = Big(cur[key]);
43
+ prev[groupValue][key] = bigNum.add(prev[groupValue][key]).toNumber();
44
+ } else {
45
+ prev[groupValue][key] += 1;
46
+ }
47
+ });
48
+ return prev;
49
+ }, {} as any);
50
+ return transformedData;
51
+ }
52
+
53
+ const notAxisChartSet: Set<CharOptionCompType> = new Set(["pie"] as const);
54
+ export const echartsConfigOmitChildren = ["hidden", "selectedPoints", "onEvent"] as const;
55
+ type EchartsConfigProps = Omit<ChartCompPropsType, typeof echartsConfigOmitChildren[number]>;
56
+
57
+ export function isAxisChart(type: CharOptionCompType) {
58
+ return !notAxisChartSet.has(type);
59
+ }
60
+
61
+ export function getSeriesConfig(props: EchartsConfigProps) {
62
+ const visibleSeries = props.series.filter((s) => !s.getView().hide);
63
+ const seriesLength = visibleSeries.length;
64
+ return visibleSeries.map((s, index) => {
65
+ if (isAxisChart(props.chartConfig.type)) {
66
+ let encodeX: string, encodeY: string;
67
+ const horizontalX = props.xAxisDirection === "horizontal";
68
+ let itemStyle = props.chartConfig.itemStyle;
69
+ // FIXME: need refactor... chartConfig returns a function with paramters
70
+ if (props.chartConfig.type === "bar") {
71
+ // barChart's border radius, depend on x-axis direction and stack state
72
+ const borderRadius = horizontalX ? [2, 2, 0, 0] : [0, 2, 2, 0];
73
+ if (props.chartConfig.stack && index === visibleSeries.length - 1) {
74
+ itemStyle = { ...itemStyle, borderRadius: borderRadius };
75
+ } else if (!props.chartConfig.stack) {
76
+ itemStyle = { ...itemStyle, borderRadius: borderRadius };
77
+ }
78
+ }
79
+ if (horizontalX) {
80
+ encodeX = props.xAxisKey;
81
+ encodeY = s.getView().columnName;
82
+ } else {
83
+ encodeX = s.getView().columnName;
84
+ encodeY = props.xAxisKey;
85
+ }
86
+ return {
87
+ name: s.getView().seriesName,
88
+ selectedMode: "single",
89
+ select: {
90
+ itemStyle: {
91
+ borderColor: "#000",
92
+ },
93
+ },
94
+ encode: {
95
+ x: encodeX,
96
+ y: encodeY,
97
+ },
98
+ // each type of chart's config
99
+ ...props.chartConfig,
100
+ itemStyle: itemStyle,
101
+ label: {
102
+ ...props.chartConfig.label,
103
+ ...(!horizontalX && { position: "outside" }),
104
+ },
105
+ };
106
+ } else {
107
+ // pie
108
+ const radiusAndCenter = getPieRadiusAndCenter(seriesLength, index, props.chartConfig);
109
+ return {
110
+ ...props.chartConfig,
111
+ radius: radiusAndCenter.radius,
112
+ center: radiusAndCenter.center,
113
+ name: s.getView().seriesName,
114
+ selectedMode: "single",
115
+ encode: {
116
+ itemName: props.xAxisKey,
117
+ value: s.getView().columnName,
118
+ },
119
+ };
120
+ }
121
+ });
122
+ }
123
+
124
+ // https://echarts.apache.org/en/option.html
125
+ export function getEchartsConfig(props: EchartsConfigProps, chartSize?: ChartSize): EChartsOption {
126
+ if (props.mode === "json") {
127
+ return props.echartsOption ? props.echartsOption : {};
128
+ }
129
+ // axisChart
130
+ const axisChart = isAxisChart(props.chartConfig.type);
131
+ const gridPos = {
132
+ left: 20,
133
+ right: props.legendConfig.left === "right" ? "10%" : 20,
134
+ top: 50,
135
+ bottom: 35,
136
+ };
137
+ let config: EChartsOption = {
138
+ title: { text: props.title, left: "center" },
139
+ tooltip: {
140
+ confine: true,
141
+ trigger: axisChart ? "axis" : "item",
142
+ },
143
+ legend: props.legendConfig,
144
+ grid: {
145
+ ...gridPos,
146
+ containLabel: true,
147
+ },
148
+ };
149
+ if (props.data.length <= 0) {
150
+ // no data
151
+ return {
152
+ ...config,
153
+ ...(axisChart ? noDataAxisConfig : noDataPieChartConfig),
154
+ };
155
+ }
156
+ const yAxisConfig = props.yConfig();
157
+ const seriesColumnNames = props.series
158
+ .filter((s) => !s.getView().hide)
159
+ .map((s) => s.getView().columnName);
160
+ // y-axis is category and time, data doesn't need to aggregate
161
+ const transformedData =
162
+ yAxisConfig.type === "category" || yAxisConfig.type === "time"
163
+ ? props.data
164
+ : transformData(props.data, props.xAxisKey, seriesColumnNames);
165
+ config = {
166
+ ...config,
167
+ dataset: [
168
+ {
169
+ source: transformedData,
170
+ sourceHeader: false,
171
+ },
172
+ ],
173
+ series: getSeriesConfig(props),
174
+ };
175
+ if (axisChart) {
176
+ // pure chart's size except the margin around
177
+ let chartRealSize;
178
+ if (chartSize) {
179
+ const rightSize =
180
+ typeof gridPos.right === "number"
181
+ ? gridPos.right
182
+ : (chartSize.w * parseFloat(gridPos.right)) / 100.0;
183
+ chartRealSize = {
184
+ // actually it's self-adaptive with the x-axis label on the left, not that accurate but work
185
+ w: chartSize.w - gridPos.left - rightSize,
186
+ // also self-adaptive on the bottom
187
+ h: chartSize.h - gridPos.top - gridPos.bottom,
188
+ right: rightSize,
189
+ };
190
+ }
191
+ const finalXyConfig = calcXYConfig(
192
+ props.xConfig,
193
+ yAxisConfig,
194
+ props.xAxisDirection,
195
+ transformedData.map((d) => d[props.xAxisKey]),
196
+ chartRealSize
197
+ );
198
+ config = {
199
+ ...config,
200
+ // @ts-ignore
201
+ xAxis: finalXyConfig.xConfig,
202
+ // @ts-ignore
203
+ yAxis: finalXyConfig.yConfig,
204
+ };
205
+ }
206
+ // log.log("Echarts transformedData and config", transformedData, config);
207
+ return config;
208
+ }
209
+
210
+ export function getSelectedPoints(param: any, option: any) {
211
+ const series = option.series;
212
+ const dataSource = _.isArray(option.dataset) && option.dataset[0]?.source;
213
+ if (series && dataSource) {
214
+ return param.selected.flatMap((selectInfo: any) => {
215
+ const seriesInfo = series[selectInfo.seriesIndex];
216
+ if (!seriesInfo || !seriesInfo.encode) {
217
+ return [];
218
+ }
219
+ return selectInfo.dataIndex.map((index: any) => {
220
+ const commonResult = {
221
+ seriesName: seriesInfo.name,
222
+ };
223
+ if (seriesInfo.encode.itemName && seriesInfo.encode.value) {
224
+ return {
225
+ ...commonResult,
226
+ itemName: dataSource[index][seriesInfo.encode.itemName],
227
+ value: dataSource[index][seriesInfo.encode.value],
228
+ };
229
+ } else {
230
+ return {
231
+ ...commonResult,
232
+ x: dataSource[index][seriesInfo.encode.x],
233
+ y: dataSource[index][seriesInfo.encode.y],
234
+ };
235
+ }
236
+ });
237
+ });
238
+ }
239
+ return [];
240
+ }
@@ -0,0 +1,187 @@
1
+ import type { ECharts } from "echarts";
2
+ import { PureComponent } from "react";
3
+ import isEqual from "fast-deep-equal";
4
+ import { EChartsReactProps, EChartsInstance } from "./types";
5
+ import _ from "lodash";
6
+ import log from "loglevel";
7
+
8
+ function isString(v: any): boolean {
9
+ return typeof v === "string";
10
+ }
11
+
12
+ function isFunction(v: any): boolean {
13
+ return typeof v === "function";
14
+ }
15
+
16
+ /**
17
+ * core component for echarts binding
18
+ */
19
+ export default class EChartsReactCore extends PureComponent<EChartsReactProps> {
20
+ /**
21
+ * echarts render container
22
+ */
23
+ public ele: HTMLElement | null;
24
+
25
+ /**
26
+ * echarts library entry
27
+ */
28
+ protected echarts: any;
29
+
30
+ constructor(props: EChartsReactProps) {
31
+ super(props);
32
+
33
+ this.echarts = props.echarts;
34
+ this.ele = null;
35
+ }
36
+
37
+ componentDidMount() {
38
+ this.renderNewEcharts();
39
+ }
40
+
41
+ // update
42
+ componentDidUpdate(prevProps: EChartsReactProps) {
43
+ /**
44
+ * if shouldSetOption return false, then return, not update echarts options
45
+ * default is true
46
+ */
47
+ const { shouldSetOption } = this.props;
48
+ if (shouldSetOption && isFunction(shouldSetOption) && !shouldSetOption(prevProps, this.props)) {
49
+ return;
50
+ }
51
+
52
+ /**
53
+ * the props below need to dispose before re-render
54
+ * 1. when switching theme
55
+ * 2. when modifying opts
56
+ * 3. when modifying onEvents, thus the binded event issue #151 can be cancel
57
+ */
58
+ if (
59
+ !isEqual(prevProps.theme, this.props.theme) ||
60
+ !isEqual(prevProps.opts, this.props.opts) ||
61
+ !isEqual(prevProps.onEvents, this.props.onEvents)
62
+ ) {
63
+ this.dispose();
64
+
65
+ this.renderNewEcharts(); // re-render
66
+ return;
67
+ }
68
+
69
+ // when these props are not isEqual, update echarts
70
+ const pickKeys = ["option", "notMerge", "lazyUpdate", "showLoading", "loadingOption"];
71
+ if (!isEqual(_.pick(this.props, pickKeys), _.pick(prevProps, pickKeys))) {
72
+ this.updateEChartsOption();
73
+ }
74
+ }
75
+
76
+ componentWillUnmount() {
77
+ this.dispose();
78
+ }
79
+
80
+ /**
81
+ * return the echart object
82
+ * 1. if exist, return the existed instance
83
+ * 2. or new one instance
84
+ */
85
+ public getEchartsInstance(): ECharts {
86
+ return (
87
+ this.echarts.getInstanceByDom(this.ele) ||
88
+ this.echarts.init(this.ele, this.props.theme, this.props.opts)
89
+ );
90
+ }
91
+
92
+ /**
93
+ * dispose echarts and clear size-sensor
94
+ */
95
+ private dispose() {
96
+ if (this.ele) {
97
+ // dispose echarts instance
98
+ this.echarts.dispose(this.ele);
99
+ }
100
+ }
101
+
102
+ /**
103
+ * render a new echarts instance
104
+ */
105
+ private renderNewEcharts() {
106
+ const { onEvents, onChartReady } = this.props;
107
+
108
+ // 1. new echarts instance
109
+ const echartsInstance = this.updateEChartsOption();
110
+
111
+ // 2. bind events
112
+ this.bindEvents(echartsInstance, onEvents || {});
113
+
114
+ // 3. on chart ready
115
+ if (onChartReady && isFunction(onChartReady)) onChartReady(echartsInstance);
116
+ }
117
+
118
+ // bind the events
119
+ private bindEvents(instance: any, events: EChartsReactProps["onEvents"]) {
120
+ function _bindEvent(eventName: string, func: Function) {
121
+ // ignore the event config which not satisfy
122
+ if (isString(eventName) && isFunction(func)) {
123
+ // binding event
124
+ instance.on(eventName, (param: any) => {
125
+ func(param, instance);
126
+ });
127
+ }
128
+ }
129
+
130
+ // loop and bind
131
+ for (const eventName in events) {
132
+ if (Object.prototype.hasOwnProperty.call(events, eventName)) {
133
+ _bindEvent(eventName, events[eventName]);
134
+ }
135
+ }
136
+ }
137
+
138
+ /**
139
+ * render the echarts
140
+ */
141
+ private updateEChartsOption(): EChartsInstance {
142
+ const {
143
+ option,
144
+ notMerge = false,
145
+ lazyUpdate = false,
146
+ showLoading,
147
+ loadingOption = null,
148
+ } = this.props;
149
+ // 1. get or initial the echarts object
150
+ const echartInstance = this.getEchartsInstance();
151
+ // 2. set the echarts option
152
+ try {
153
+ // set option catch exception
154
+ echartInstance.setOption(option, {
155
+ notMerge: notMerge,
156
+ lazyUpdate: lazyUpdate,
157
+ silent: true,
158
+ });
159
+ } catch (e) {
160
+ // FIXME: if don't dispose, setOption again will call cause bugs
161
+ // https://github.com/apache/echarts/issues/16608
162
+ this.dispose();
163
+ log.warn("invalid echarts option:", e);
164
+ }
165
+ // 3. set loading mask
166
+ if (showLoading) echartInstance.showLoading(loadingOption);
167
+ else echartInstance.hideLoading();
168
+
169
+ return echartInstance;
170
+ }
171
+
172
+ render(): JSX.Element {
173
+ const { style, className = "" } = this.props;
174
+ // default height = 300
175
+ const newStyle = { height: 300, ...style };
176
+
177
+ return (
178
+ <div
179
+ ref={(e: HTMLElement | null) => {
180
+ this.ele = e;
181
+ }}
182
+ style={newStyle}
183
+ className={`echarts-for-react ${className}`}
184
+ />
185
+ );
186
+ }
187
+ }
@@ -0,0 +1,20 @@
1
+ import * as echarts from "echarts";
2
+ import { EChartsReactProps, EChartsOption, EChartsInstance } from "./types";
3
+ import EChartsReactCore from "./core";
4
+
5
+ /**
6
+ * reference: https://github.com/hustcc/echarts-for-react
7
+ * add exception-catch for setOption
8
+ * if query isn't successfully loaded, chart will fail to load and can't reload
9
+ */
10
+ export type { EChartsReactProps, EChartsOption, EChartsInstance };
11
+
12
+ // export the Component the echarts Object.
13
+ export default class EChartsReact extends EChartsReactCore {
14
+ constructor(props: EChartsReactProps) {
15
+ super(props);
16
+
17
+ // initialize as echarts package
18
+ this.echarts = echarts;
19
+ }
20
+ }
@@ -0,0 +1,70 @@
1
+ import { CSSProperties } from "react";
2
+
3
+ export type EChartsOption = any;
4
+
5
+ export type EChartsInstance = any;
6
+
7
+ export type Opts = {
8
+ readonly devicePixelRatio?: number;
9
+ readonly renderer?: "canvas" | "svg";
10
+ readonly width?: number | null | undefined | "auto";
11
+ readonly height?: number | null | undefined | "auto";
12
+ readonly locale?: string;
13
+ };
14
+
15
+ export type EChartsReactProps = {
16
+ /**
17
+ * echarts library entry, use it for import necessary.
18
+ */
19
+ readonly echarts?: any;
20
+ /**
21
+ * `className` for container
22
+ */
23
+ readonly className?: string;
24
+ /**
25
+ * `style` for container
26
+ */
27
+ readonly style?: CSSProperties;
28
+ /**
29
+ * echarts option
30
+ */
31
+ readonly option: EChartsOption;
32
+ /**
33
+ * echarts theme config, can be:
34
+ * 1. theme name string
35
+ * 2. theme object
36
+ */
37
+ readonly theme?: string | Record<string, any>;
38
+ /**
39
+ * notMerge config for echarts, default is `false`
40
+ */
41
+ readonly notMerge?: boolean;
42
+ /**
43
+ * lazyUpdate config for echarts, default is `false`
44
+ */
45
+ readonly lazyUpdate?: boolean;
46
+ /**
47
+ * showLoading config for echarts, default is `false`
48
+ */
49
+ readonly showLoading?: boolean;
50
+ /**
51
+ * loadingOption config for echarts, default is `null`
52
+ */
53
+ readonly loadingOption?: any;
54
+ /**
55
+ * echarts opts config, default is `{}`
56
+ */
57
+ readonly opts?: Opts;
58
+ /**
59
+ * when after chart reander, do the callback widht echarts instance
60
+ */
61
+ readonly onChartReady?: (instance: EChartsInstance) => void;
62
+ /**
63
+ * bind events, default is `{}`
64
+ */
65
+ readonly onEvents?: Record<string, Function>;
66
+ /**
67
+ * should update echarts options
68
+ */
69
+ readonly shouldSetOption?: (prevProps: EChartsReactProps, props: EChartsReactProps) => boolean;
70
+ };
@@ -0,0 +1,119 @@
1
+ import {
2
+ BoolControl,
3
+ StringControl,
4
+ list,
5
+ JSONObject,
6
+ isNumeric,
7
+ genRandomKey,
8
+ Dropdown,
9
+ OptionsType,
10
+ MultiCompBuilder,
11
+ valueComp,
12
+ } from "lowcoder-sdk";
13
+ import { trans } from "i18n/comps";
14
+
15
+ import { ConstructorToComp, ConstructorToDataType, ConstructorToView } from "lowcoder-core";
16
+ import { CompAction, CustomAction, customAction, isMyCustomAction } from "lowcoder-core";
17
+
18
+ export type SeriesCompType = ConstructorToComp<typeof SeriesComp>;
19
+ export type RawSeriesCompType = ConstructorToView<typeof SeriesComp>;
20
+ type SeriesDataType = ConstructorToDataType<typeof SeriesComp>;
21
+
22
+ type ActionDataType = {
23
+ type: "chartDataChanged";
24
+ chartData: Array<JSONObject>;
25
+ };
26
+
27
+ export function newSeries(name: string, columnName: string): SeriesDataType {
28
+ return {
29
+ seriesName: name,
30
+ columnName: columnName,
31
+ dataIndex: genRandomKey(),
32
+ };
33
+ }
34
+
35
+ const seriesChildrenMap = {
36
+ columnName: StringControl,
37
+ seriesName: StringControl,
38
+ hide: BoolControl,
39
+ // unique key, for sort
40
+ dataIndex: valueComp<string>(""),
41
+ };
42
+
43
+ const SeriesTmpComp = new MultiCompBuilder(seriesChildrenMap, (props) => {
44
+ return props;
45
+ })
46
+ .setPropertyViewFn(() => {
47
+ return <></>;
48
+ })
49
+ .build();
50
+
51
+ class SeriesComp extends SeriesTmpComp {
52
+ getPropertyViewWithData(columnOptions: OptionsType): React.ReactNode {
53
+ return (
54
+ <>
55
+ {this.children.seriesName.propertyView({
56
+ label: trans("chart.seriesName"),
57
+ })}
58
+ <Dropdown
59
+ value={this.children.columnName.getView()}
60
+ options={columnOptions}
61
+ label={trans("chart.dataColumns")}
62
+ onChange={(value) => {
63
+ this.children.columnName.dispatchChangeValueAction(value);
64
+ }}
65
+ />
66
+ </>
67
+ );
68
+ }
69
+ }
70
+
71
+ const SeriesListTmpComp = list(SeriesComp);
72
+
73
+ export class SeriesListComp extends SeriesListTmpComp {
74
+ override reduce(action: CompAction): this {
75
+ if (isMyCustomAction<ActionDataType>(action, "chartDataChanged")) {
76
+ // auto generate series
77
+ const actions = this.genExampleSeriesActions(action.value.chartData);
78
+ return this.reduce(this.multiAction(actions));
79
+ }
80
+ return super.reduce(action);
81
+ }
82
+
83
+ private genExampleSeriesActions(chartData: Array<JSONObject>) {
84
+ const actions: CustomAction[] = [];
85
+ if (!chartData || chartData.length <= 0 || !chartData[0]) {
86
+ return actions;
87
+ }
88
+ let delCnt = 0;
89
+ const existColumns = this.getView().map((s) => s.getView().columnName);
90
+ // delete series not in data
91
+ existColumns.forEach((columnName) => {
92
+ if (chartData[0]?.[columnName] === undefined) {
93
+ actions.push(this.deleteAction(0));
94
+ delCnt++;
95
+ }
96
+ });
97
+ if (existColumns.length > delCnt) {
98
+ // don't generate example if exists
99
+ return actions;
100
+ }
101
+ // generate example series
102
+ const exampleKeys = Object.keys(chartData[0])
103
+ .filter((key) => {
104
+ return !existColumns.includes(key) && isNumeric(chartData[0][key]);
105
+ })
106
+ .slice(0, 3);
107
+ exampleKeys.forEach((key) => actions.push(this.pushAction(newSeries(key, key))));
108
+ return actions;
109
+ }
110
+
111
+ dispatchDataChanged(chartData: Array<JSONObject>): void {
112
+ this.dispatch(
113
+ customAction<ActionDataType>({
114
+ type: "chartDataChanged",
115
+ chartData: chartData,
116
+ })
117
+ );
118
+ }
119
+ }
@@ -0,0 +1,52 @@
1
+ import React from "react";
2
+ import TuiImageEditor from "tui-image-editor";
3
+
4
+ export class ImageEditor extends React.Component<any> {
5
+ rootEl = React.createRef<any>();
6
+
7
+ imageEditorInst: TuiImageEditor | undefined;
8
+ props: any;
9
+ constructor(props: any) {
10
+ super(props);
11
+ this.props = props;
12
+ }
13
+ componentDidMount() {
14
+ if (this.rootEl.current !== null) {
15
+ this.imageEditorInst = new TuiImageEditor(this.rootEl.current, {
16
+ ...(this.props as any),
17
+ });
18
+ }
19
+ }
20
+
21
+ componentWillUnmount() {
22
+ if (this.imageEditorInst !== undefined) {
23
+ this.imageEditorInst.destroy();
24
+
25
+ this.imageEditorInst = undefined;
26
+ }
27
+ }
28
+
29
+ shouldComponentUpdate(nextProps: any) {
30
+ if (
31
+ JSON.stringify([this.props.includeUI.menu, this.props.includeUI.loadImage]) !==
32
+ JSON.stringify([nextProps.includeUI.menu, nextProps.includeUI.loadImage])
33
+ ) {
34
+ this.imageEditorInst = new TuiImageEditor(this.rootEl.current as any, {
35
+ ...nextProps,
36
+ });
37
+ }
38
+ return false;
39
+ }
40
+
41
+ getInstance() {
42
+ return this.imageEditorInst;
43
+ }
44
+
45
+ getRootElement() {
46
+ return this.rootEl.current;
47
+ }
48
+
49
+ render() {
50
+ return <div ref={this.rootEl} />;
51
+ }
52
+ }