@publishfx/publish-chart 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. package/README.md +143 -0
  2. package/dist/adapters/DataAdapter.d.ts +33 -0
  3. package/dist/adapters/DataAdapter.js +75 -0
  4. package/dist/adapters/TypeAdapter.d.ts +40 -0
  5. package/dist/adapters/TypeAdapter.js +26 -0
  6. package/dist/components/base/BarChart.d.ts +7 -0
  7. package/dist/components/base/BarChart.js +362 -0
  8. package/dist/components/base/BarChart.lazy.d.ts +5 -0
  9. package/dist/components/base/BarChart.lazy.js +2 -0
  10. package/dist/components/base/LineChart.d.ts +7 -0
  11. package/dist/components/base/LineChart.js +321 -0
  12. package/dist/components/base/LineChart.lazy.d.ts +5 -0
  13. package/dist/components/base/LineChart.lazy.js +2 -0
  14. package/dist/components/composite/BarLineAdapter.d.ts +22 -0
  15. package/dist/components/composite/BarLineAdapter.js +61 -0
  16. package/dist/components/composite/BarLineAdapter.lazy.d.ts +5 -0
  17. package/dist/components/composite/BarLineAdapter.lazy.js +2 -0
  18. package/dist/components/composite/BarLineChart.d.ts +7 -0
  19. package/dist/components/composite/BarLineChart.js +255 -0
  20. package/dist/components/composite/BarLineChart.lazy.d.ts +5 -0
  21. package/dist/components/composite/BarLineChart.lazy.js +2 -0
  22. package/dist/components/composite/BarLineCompareWeekend.d.ts +10 -0
  23. package/dist/components/composite/BarLineCompareWeekend.js +502 -0
  24. package/dist/components/composite/GroupBarLine.d.ts +11 -0
  25. package/dist/components/composite/GroupBarLine.js +546 -0
  26. package/dist/components/composite/GroupBarLine.lazy.d.ts +5 -0
  27. package/dist/components/composite/GroupBarLine.lazy.js +2 -0
  28. package/dist/components/composite/GroupCompare.d.ts +10 -0
  29. package/dist/components/composite/GroupCompare.js +620 -0
  30. package/dist/components/shared/AuxiliaryLine.d.ts +8 -0
  31. package/dist/components/shared/AuxiliaryLine.js +64 -0
  32. package/dist/components/shared/NodeDetail.d.ts +9 -0
  33. package/dist/components/shared/NodeDetail.js +110 -0
  34. package/dist/components/shared/NodeGeom.d.ts +23 -0
  35. package/dist/components/shared/NodeGeom.js +35 -0
  36. package/dist/components/shared/NodePopover.d.ts +22 -0
  37. package/dist/components/shared/NodePopover.js +41 -0
  38. package/dist/components/shared/NodePopoverContent.d.ts +15 -0
  39. package/dist/components/shared/NodePopoverContent.js +85 -0
  40. package/dist/components/shared/XAxisBackground.d.ts +31 -0
  41. package/dist/components/shared/XAxisBackground.js +93 -0
  42. package/dist/core/ChartConfig.d.ts +48 -0
  43. package/dist/core/ChartConfig.js +152 -0
  44. package/dist/core/ChartContext.d.ts +49 -0
  45. package/dist/core/ChartContext.js +31 -0
  46. package/dist/core/ChartTypes.d.ts +119 -0
  47. package/dist/core/ChartTypes.js +0 -0
  48. package/dist/index.d.ts +29 -0
  49. package/dist/index.js +21 -0
  50. package/dist/services/DataTransformService.d.ts +22 -0
  51. package/dist/services/DataTransformService.js +29 -0
  52. package/dist/services/FormatterService.d.ts +24 -0
  53. package/dist/services/FormatterService.js +22 -0
  54. package/dist/utils/__tests__/formatters.test.d.ts +1 -0
  55. package/dist/utils/__tests__/formatters.test.js +333 -0
  56. package/dist/utils/chartHelpers.d.ts +52 -0
  57. package/dist/utils/chartHelpers.js +112 -0
  58. package/dist/utils/dataTransform.d.ts +12 -0
  59. package/dist/utils/dataTransform.js +64 -0
  60. package/dist/utils/formatters.d.ts +37 -0
  61. package/dist/utils/formatters.js +127 -0
  62. package/dist/utils/indicatorHelpers.d.ts +16 -0
  63. package/dist/utils/indicatorHelpers.js +15 -0
  64. package/dist/utils/lazyHelpers.d.ts +29 -0
  65. package/dist/utils/lazyHelpers.js +15 -0
  66. package/package.json +68 -0
@@ -0,0 +1,502 @@
1
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
2
+ import { memo, useEffect, useMemo, useRef, useState } from "react";
3
+ import { Axis, Chart, Interval, Legend, Line, Tooltip, View } from "bizcharts";
4
+ import { useChartContext } from "../../core/ChartContext.js";
5
+ import { mergeChartConfig } from "../../core/ChartConfig.js";
6
+ import { calculateBarWidth, createStripePatternCanvas, getAxisFormat, getAxisHorPaddingByText, markerStyle } from "../../utils/chartHelpers.js";
7
+ import { groupArray, transformIndicatorList } from "../../utils/dataTransform.js";
8
+ import { getIndicatorCompareName } from "../../utils/indicatorHelpers.js";
9
+ import XAxisBackground from "../shared/XAxisBackground.js";
10
+ import { NodeDetail } from "../shared/NodeDetail.js";
11
+ import { NodeGeom } from "../shared/NodeGeom.js";
12
+ import { CompareChange } from "@moonton/publish-components";
13
+ const STRIPE_PATTERN_THRESHOLD = 10;
14
+ const BarLineCompareWeekend = ({ height = 310, data, x = '', y = '', z = '', indicatorMap, onChartClick, indicators = [], timeRange: _timeRange, nodeSetting = {
15
+ showType: 0,
16
+ type: []
17
+ }, highlightDate = [] })=>{
18
+ const { formatter, dataTransform, config: contextConfig } = useChartContext();
19
+ const mergedConfig = useMemo(()=>mergeChartConfig(contextConfig, {}), [
20
+ contextConfig
21
+ ]);
22
+ const safeIndicatorMap = indicatorMap || contextConfig.indicatorMap || {};
23
+ const themeColors = mergedConfig.theme.colors;
24
+ const combineColors = mergedConfig.theme.combineColors || [
25
+ '#FF8C00',
26
+ '#FFD700'
27
+ ];
28
+ const [pointP, setPointP] = useState({
29
+ x: 0,
30
+ y: 0
31
+ });
32
+ const [pointData, setPointData] = useState({
33
+ info: [],
34
+ infosCompare: []
35
+ });
36
+ const [chartWidth, setChatWidth] = useState(0);
37
+ const [chartOffset, setChartOffset] = useState(0);
38
+ const [padding, setPadding] = useState([
39
+ 10,
40
+ 0
41
+ ]);
42
+ const [mainBarSize, setMainBarSize] = useState(void 0);
43
+ const indicatorSeries = useMemo(()=>transformIndicatorList(indicators || [], data), [
44
+ indicators,
45
+ data
46
+ ]);
47
+ const transformData = useMemo(()=>{
48
+ const result = indicatorSeries[y] || [];
49
+ result.forEach((item)=>{
50
+ const processedItem = dataTransform.processNodeInfo(item, contextConfig.nodeMap);
51
+ item.nodeLen = processedItem.nodeLen || 0;
52
+ item.node = processedItem.node || 0;
53
+ item.color = processedItem.color;
54
+ });
55
+ return result;
56
+ }, [
57
+ indicatorSeries,
58
+ y,
59
+ dataTransform,
60
+ contextConfig.nodeMap
61
+ ]);
62
+ const lineIndicators = useMemo(()=>[
63
+ ...indicators
64
+ ].slice(1) || [], [
65
+ indicators
66
+ ]);
67
+ const lineData = useMemo(()=>{
68
+ const result = [];
69
+ lineIndicators.forEach((key)=>{
70
+ const series = indicatorSeries[key] || [];
71
+ series.forEach((item)=>{
72
+ result.push(item);
73
+ });
74
+ });
75
+ return result;
76
+ }, [
77
+ indicatorSeries,
78
+ lineIndicators
79
+ ]);
80
+ const backgroundFilterFn = useMemo(()=>(item)=>{
81
+ const groupName = item.groupName;
82
+ return highlightDate.includes(groupName);
83
+ }, [
84
+ highlightDate
85
+ ]);
86
+ const chartInsRef = useRef(null);
87
+ const stripePatternRef = useRef(null);
88
+ useEffect(()=>{
89
+ const offscreen = document.createElement('canvas');
90
+ const ctx = offscreen.getContext('2d');
91
+ if (!ctx) return;
92
+ const dataCount = transformData.length;
93
+ const spaceUnit = dataCount > STRIPE_PATTERN_THRESHOLD ? 12 : 24;
94
+ const sourceCanvas = createStripePatternCanvas(themeColors[0], spaceUnit);
95
+ const pattern = ctx.createPattern(sourceCanvas, 'repeat');
96
+ if (pattern) stripePatternRef.current = pattern;
97
+ }, [
98
+ transformData.length,
99
+ themeColors
100
+ ]);
101
+ useEffect(()=>{
102
+ setPointP({
103
+ x: 0,
104
+ y: 0
105
+ });
106
+ setPointData({
107
+ info: [],
108
+ infosCompare: []
109
+ });
110
+ const rightValueArr = lineData.filter((v)=>'-' !== v.indicatorValue).map((v)=>v.indicatorValue);
111
+ const maxRight = Math.max(...rightValueArr?.length ? rightValueArr : [
112
+ 0
113
+ ]);
114
+ const offsetRight = getAxisHorPaddingByText(maxRight, safeIndicatorMap || {}, z);
115
+ if (nodeSetting?.showType) if (nodeSetting?.showType === 2 && chartWidth / (transformData.length / 2) > 30) if (transformData.some((item)=>item?.nodeLen > 2)) setPadding([
116
+ 10,
117
+ offsetRight,
118
+ 40,
119
+ 20
120
+ ]);
121
+ else transformData.some((item)=>item?.nodeLen == 2) ? setPadding([
122
+ 10,
123
+ offsetRight,
124
+ 24,
125
+ 20
126
+ ]) : setPadding([
127
+ 10,
128
+ offsetRight,
129
+ 10,
130
+ 20
131
+ ]);
132
+ else setPadding([
133
+ 10,
134
+ offsetRight,
135
+ 10,
136
+ 20
137
+ ]);
138
+ else setPadding([
139
+ 10,
140
+ offsetRight,
141
+ 10,
142
+ 20
143
+ ]);
144
+ }, [
145
+ chartWidth,
146
+ transformData,
147
+ lineData,
148
+ safeIndicatorMap,
149
+ z
150
+ ]);
151
+ const scale = {
152
+ indicatorValue: {
153
+ type: 'linear-strict'
154
+ }
155
+ };
156
+ const legendMapRef = useRef({});
157
+ const getChartKey = ()=>nodeSetting?.showType + y + z + x;
158
+ return /*#__PURE__*/ jsxs(Chart, {
159
+ height: height,
160
+ data: transformData,
161
+ ...mergedConfig.baseChartConfig,
162
+ onPlotClick: (e, chart)=>{
163
+ const value = chart.getTooltipItems({
164
+ x: e.x,
165
+ y: e.y
166
+ });
167
+ onChartClick && onChartClick(value[0]);
168
+ },
169
+ appendPadding: padding,
170
+ scale: scale,
171
+ onGetG2Instance: (c)=>{
172
+ chartInsRef.current = c;
173
+ },
174
+ onPointMouseover: (e, _chart)=>{
175
+ if (1 == nodeSetting.showType) {
176
+ setPointP({
177
+ x: e.data.x,
178
+ y: e.data.y
179
+ });
180
+ setPointData(e.data.data.nodeInfos || {
181
+ info: [],
182
+ infosCompare: []
183
+ });
184
+ }
185
+ },
186
+ onAfterrender: (_e, chart)=>{
187
+ if (2 == nodeSetting.showType) {
188
+ setChatWidth(chart.coordinateBBox.width);
189
+ setChartOffset(chart.coordinateBBox.x);
190
+ }
191
+ const estimatedBarWidth = calculateBarWidth(chart, transformData, x, 0.45);
192
+ if (void 0 !== estimatedBarWidth) setMainBarSize(estimatedBarWidth);
193
+ },
194
+ children: [
195
+ /*#__PURE__*/ jsx(XAxisBackground, {
196
+ x: x,
197
+ isHighlight: true,
198
+ data: transformData,
199
+ filterFn: backgroundFilterFn,
200
+ mainBarSize: mainBarSize,
201
+ dataLength: transformData.length
202
+ }),
203
+ /*#__PURE__*/ jsx(Interval, {
204
+ position: `${x}*indicatorValue`,
205
+ style: [
206
+ 'indicatorType',
207
+ (indicatorType)=>{
208
+ const isCompareY = indicatorType === `${y}_compare`;
209
+ if (isCompareY && stripePatternRef.current) return {
210
+ cursor: 'pointer',
211
+ fill: stripePatternRef.current
212
+ };
213
+ return {
214
+ cursor: 'pointer'
215
+ };
216
+ }
217
+ ],
218
+ color: [
219
+ 'indicatorType',
220
+ (indicatorType)=>{
221
+ if (!indicatorType || 'string' != typeof indicatorType) return themeColors[0];
222
+ const baseKey = indicatorType.replace(/_compare.*/, '');
223
+ if (baseKey === y) return themeColors[0];
224
+ const idx = (indicators || []).indexOf(baseKey);
225
+ return themeColors[idx >= 0 ? idx : 1];
226
+ }
227
+ ],
228
+ adjust: [
229
+ {
230
+ type: 'dodge',
231
+ marginRatio: 0
232
+ }
233
+ ]
234
+ }),
235
+ /*#__PURE__*/ jsx(Axis, {
236
+ name: "indicatorValue",
237
+ position: "left",
238
+ label: {
239
+ formatter (val) {
240
+ return getAxisFormat(val, safeIndicatorMap || {}, y);
241
+ }
242
+ }
243
+ }),
244
+ /*#__PURE__*/ jsx(Tooltip, {
245
+ shared: true,
246
+ children: (title, items)=>{
247
+ const groupCompare = items?.length ? groupArray(items) : [];
248
+ return /*#__PURE__*/ jsxs("div", {
249
+ style: {
250
+ padding: '10px 0'
251
+ },
252
+ children: [
253
+ title,
254
+ groupCompare && /*#__PURE__*/ jsx(Fragment, {
255
+ children: /*#__PURE__*/ jsx("div", {
256
+ style: {
257
+ margin: '10px 0'
258
+ },
259
+ children: groupCompare.map((v, index)=>/*#__PURE__*/ jsxs("div", {
260
+ children: [
261
+ v.map((it, k)=>/*#__PURE__*/ jsxs("div", {
262
+ style: {
263
+ display: 'flex',
264
+ justifyContent: 'space-between',
265
+ marginBottom: '10px'
266
+ },
267
+ children: [
268
+ /*#__PURE__*/ jsxs("span", {
269
+ children: [
270
+ /*#__PURE__*/ jsx("span", {
271
+ style: markerStyle(it.color, it.name.includes('_compare'))
272
+ }),
273
+ it.name.includes('_') ? `${getIndicatorCompareName(safeIndicatorMap || {}, it.name)}(${it.data.compareTime})` : getIndicatorCompareName(safeIndicatorMap || {}, it.name)
274
+ ]
275
+ }),
276
+ /*#__PURE__*/ jsx("span", {
277
+ style: {
278
+ fontWeight: 'bold',
279
+ paddingLeft: '10px'
280
+ },
281
+ children: formatter.formatIndicator(it.data.indicatorValue, safeIndicatorMap?.[it.name.split('_')[0]])
282
+ })
283
+ ]
284
+ }, `${index}_${k}`)),
285
+ /*#__PURE__*/ jsxs("div", {
286
+ style: {
287
+ margin: '0 0 10px 16px',
288
+ display: 'flex',
289
+ justifyContent: 'space-between'
290
+ },
291
+ children: [
292
+ "相比变化 ",
293
+ /*#__PURE__*/ jsx("span", {
294
+ style: {
295
+ fontWeight: 'bold'
296
+ },
297
+ children: /*#__PURE__*/ jsx(CompareChange, {
298
+ value: v[0].data.change,
299
+ fontSize: 12
300
+ })
301
+ })
302
+ ]
303
+ })
304
+ ]
305
+ }, index))
306
+ })
307
+ })
308
+ ]
309
+ });
310
+ }
311
+ }),
312
+ /*#__PURE__*/ jsxs(View, {
313
+ data: lineData,
314
+ scale: scale,
315
+ padding: 0,
316
+ children: [
317
+ /*#__PURE__*/ jsx(Axis, {
318
+ name: "indicatorValue",
319
+ position: "right",
320
+ label: {
321
+ formatter (val) {
322
+ return getAxisFormat(val, safeIndicatorMap || {}, z);
323
+ }
324
+ }
325
+ }),
326
+ /*#__PURE__*/ jsx(Axis, {
327
+ name: x,
328
+ visible: false
329
+ }),
330
+ /*#__PURE__*/ jsx(Line, {
331
+ position: `${x}*indicatorValue`,
332
+ style: [
333
+ "indicatorType",
334
+ (groupType)=>{
335
+ if (groupType.includes("_compare")) return {
336
+ lineDash: [
337
+ 4,
338
+ 4
339
+ ]
340
+ };
341
+ }
342
+ ],
343
+ state: {
344
+ active: {
345
+ style: (element)=>{
346
+ if ("dash" === element.getModel().shape) return {
347
+ lineDash: [
348
+ 4,
349
+ 4
350
+ ],
351
+ lineWidth: 3
352
+ };
353
+ return {
354
+ lineWidth: 3
355
+ };
356
+ }
357
+ }
358
+ },
359
+ color: [
360
+ 'indicatorType',
361
+ (indicatorType)=>{
362
+ if (!indicatorType || 'string' != typeof indicatorType) return combineColors[0];
363
+ const baseKey = indicatorType.replace(/_compare.*/, '');
364
+ const idx = lineIndicators.indexOf(baseKey);
365
+ if (0 === idx) return combineColors[0];
366
+ const colorIdx = 2 + idx;
367
+ return themeColors[colorIdx % themeColors.length];
368
+ }
369
+ ],
370
+ shape: [
371
+ 'indicatorType',
372
+ (indicatorType)=>{
373
+ if (indicatorType.includes('_compare')) return 'dash';
374
+ return 'line';
375
+ }
376
+ ]
377
+ })
378
+ ]
379
+ }),
380
+ /*#__PURE__*/ jsx(Axis, {
381
+ grid: null,
382
+ name: x,
383
+ label: {
384
+ autoEllipsis: true,
385
+ autoHide: true
386
+ }
387
+ }),
388
+ /*#__PURE__*/ jsx(Legend, {
389
+ position: 2 === nodeSetting.showType ? 'top' : 'bottom',
390
+ custom: true,
391
+ allowAllCanceled: true,
392
+ maxItemWidth: 1,
393
+ flipPage: false,
394
+ items: [
395
+ {
396
+ value: y,
397
+ name: getIndicatorCompareName(safeIndicatorMap || {}, y),
398
+ unchecked: legendMapRef.current?.[y] === false,
399
+ marker: {
400
+ symbol: 'circle',
401
+ style: {
402
+ fill: themeColors[0],
403
+ r: 5
404
+ }
405
+ }
406
+ },
407
+ ...lineIndicators.map((key, idx)=>{
408
+ const isPrimary = key === z;
409
+ const baseColor = isPrimary ? combineColors[0] : themeColors[(2 + idx) % themeColors.length];
410
+ return {
411
+ value: key,
412
+ name: getIndicatorCompareName(safeIndicatorMap || {}, key),
413
+ unchecked: legendMapRef.current?.[key] === false,
414
+ marker: {
415
+ symbol: 'hyphen',
416
+ style: {
417
+ stroke: baseColor,
418
+ lineWidth: 2
419
+ }
420
+ }
421
+ };
422
+ })
423
+ ],
424
+ onChange: (ev)=>{
425
+ if (!ev || !ev.item) return;
426
+ const { item } = ev;
427
+ const value = item.value;
428
+ if (null == value) return;
429
+ const checked = !item.unchecked;
430
+ if (!legendMapRef.current) legendMapRef.current = {};
431
+ legendMapRef.current[value] = checked;
432
+ const chart = chartInsRef.current;
433
+ if (!chart) return;
434
+ const getLegendKey = (indicatorType)=>{
435
+ if (!indicatorType || 'string' != typeof indicatorType) return indicatorType || '';
436
+ if (indicatorType === y || indicatorType === `${y}_compare`) return y;
437
+ const baseKey = indicatorType.replace(/_compare.*/, '');
438
+ if (lineIndicators.includes(baseKey)) return baseKey;
439
+ return indicatorType;
440
+ };
441
+ const applyFilter = (target)=>{
442
+ if (!target || 'object' != typeof target) return;
443
+ if (!legendMapRef.current) legendMapRef.current = {};
444
+ try {
445
+ if (target && 'function' == typeof target.filter) target.filter('indicatorType', (val)=>{
446
+ if (!val || 'string' != typeof val) return true;
447
+ const key = getLegendKey(val);
448
+ const mapValue = legendMapRef.current[key];
449
+ return false !== mapValue;
450
+ });
451
+ } catch (error) {
452
+ console.warn('Failed to apply filter:', error);
453
+ }
454
+ };
455
+ if (chart && chart.geometries) {
456
+ const mainChartGeometries = chart.geometries || [];
457
+ const hasIntervalGeom = mainChartGeometries.some((geom)=>geom && 'interval' === geom.type);
458
+ if (hasIntervalGeom) applyFilter(chart);
459
+ }
460
+ if (chart && chart.views && Array.isArray(chart.views) && chart.views.length > 0) {
461
+ const validViews = chart.views.filter((view)=>null != view && 'object' == typeof view);
462
+ validViews.forEach((view)=>{
463
+ if (!view || 'object' != typeof view) return;
464
+ try {
465
+ const geometries = (view.geometries || []).filter((geom)=>null != geom);
466
+ const hasLineGeom = geometries.some((geom)=>geom && 'line' === geom.type);
467
+ if (!hasLineGeom) {
468
+ try {
469
+ if (view && 'function' == typeof view.render) view.render(true);
470
+ } catch (error) {}
471
+ return;
472
+ }
473
+ if (hasLineGeom) {
474
+ applyFilter(view);
475
+ try {
476
+ if (view && 'function' == typeof view.render) view.render(true);
477
+ } catch (error) {}
478
+ }
479
+ } catch (error) {}
480
+ });
481
+ }
482
+ try {
483
+ if (chart && 'function' == typeof chart.render) chart.render(true);
484
+ } catch (error) {}
485
+ }
486
+ }),
487
+ data.some((item)=>item?.nodeInfos?.info?.length > 0 || item?.nodeInfos?.infosCompare?.length > 0) ? /*#__PURE__*/ jsx(Fragment, {
488
+ children: 1 == nodeSetting.showType && NodeGeom ? /*#__PURE__*/ jsx(NodeGeom, {
489
+ pointData: pointData,
490
+ pointP: pointP
491
+ }) : 2 == nodeSetting.showType && NodeDetail ? 0 == chartOffset || chartOffset ? /*#__PURE__*/ jsx(NodeDetail, {
492
+ chartWidth: chartWidth,
493
+ chartOffset: chartOffset,
494
+ dvRows: transformData,
495
+ ratio: 2
496
+ }) : null : null
497
+ }) : null
498
+ ]
499
+ }, getChartKey());
500
+ };
501
+ const composite_BarLineCompareWeekend = /*#__PURE__*/ memo(BarLineCompareWeekend);
502
+ export { composite_BarLineCompareWeekend as default };
@@ -0,0 +1,11 @@
1
+ /**
2
+ * 分组柱状折线组合图组件
3
+ */
4
+ import React from "react";
5
+ import type { BaseChartProps } from "../../core/ChartTypes";
6
+ export declare const newThemeColors: string[];
7
+ interface GroupBarLineProps extends BaseChartProps {
8
+ legend?: string;
9
+ }
10
+ declare const _default: React.NamedExoticComponent<GroupBarLineProps>;
11
+ export default _default;