@antv/infographic 0.2.2 → 0.2.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +43 -7
- package/README.zh-CN.md +43 -7
- package/dist/infographic.min.js +111 -111
- package/dist/infographic.min.js.map +1 -1
- package/esm/designs/layouts/Align.js +6 -6
- package/esm/designs/layouts/Flex.js +8 -6
- package/esm/designs/structures/chart-wordcloud.js +1 -1
- package/esm/designs/structures/hierarchy-structure.d.ts +45 -0
- package/esm/designs/structures/hierarchy-structure.js +266 -0
- package/esm/designs/structures/index.d.ts +2 -0
- package/esm/designs/structures/index.js +2 -0
- package/esm/designs/structures/list-zigzag.d.ts +11 -0
- package/esm/designs/structures/list-zigzag.js +240 -0
- package/esm/index.d.ts +1 -1
- package/esm/index.js +1 -1
- package/esm/renderer/composites/icon.d.ts +2 -5
- package/esm/renderer/composites/icon.js +5 -10
- package/esm/renderer/composites/illus.d.ts +3 -2
- package/esm/renderer/composites/illus.js +6 -2
- package/esm/renderer/composites/index.d.ts +2 -2
- package/esm/renderer/composites/index.js +2 -2
- package/esm/renderer/palettes/registry.d.ts +1 -1
- package/esm/renderer/palettes/registry.js +1 -1
- package/esm/renderer/renderer.js +6 -3
- package/esm/resource/loader.d.ts +2 -1
- package/esm/resource/loader.js +55 -23
- package/esm/templates/built-in.js +4 -0
- package/esm/templates/hierarchy-structure.d.ts +2 -0
- package/esm/templates/hierarchy-structure.js +21 -0
- package/esm/templates/list-zigzag.d.ts +2 -0
- package/esm/templates/list-zigzag.js +68 -0
- package/lib/designs/layouts/Align.js +6 -6
- package/lib/designs/layouts/Flex.js +8 -6
- package/lib/designs/structures/chart-wordcloud.js +1 -1
- package/lib/designs/structures/hierarchy-structure.d.ts +45 -0
- package/lib/designs/structures/hierarchy-structure.js +270 -0
- package/lib/designs/structures/index.d.ts +2 -0
- package/lib/designs/structures/index.js +2 -0
- package/lib/designs/structures/list-zigzag.d.ts +11 -0
- package/lib/designs/structures/list-zigzag.js +246 -0
- package/lib/index.d.ts +1 -1
- package/lib/index.js +3 -2
- package/lib/renderer/composites/icon.d.ts +2 -5
- package/lib/renderer/composites/icon.js +5 -11
- package/lib/renderer/composites/illus.d.ts +3 -2
- package/lib/renderer/composites/illus.js +7 -2
- package/lib/renderer/composites/index.d.ts +2 -2
- package/lib/renderer/composites/index.js +2 -2
- package/lib/renderer/palettes/registry.d.ts +1 -1
- package/lib/renderer/palettes/registry.js +1 -1
- package/lib/renderer/renderer.js +5 -2
- package/lib/resource/loader.d.ts +2 -1
- package/lib/resource/loader.js +55 -23
- package/lib/templates/built-in.js +4 -0
- package/lib/templates/hierarchy-structure.d.ts +2 -0
- package/lib/templates/hierarchy-structure.js +24 -0
- package/lib/templates/list-zigzag.d.ts +2 -0
- package/lib/templates/list-zigzag.js +71 -0
- package/package.json +1 -1
- package/src/designs/layouts/Align.tsx +6 -6
- package/src/designs/layouts/Flex.tsx +8 -6
- package/src/designs/structures/chart-wordcloud.tsx +1 -1
- package/src/designs/structures/hierarchy-structure.tsx +658 -0
- package/src/designs/structures/index.ts +2 -0
- package/src/designs/structures/list-zigzag.tsx +492 -0
- package/src/index.ts +2 -0
- package/src/renderer/composites/icon.ts +6 -16
- package/src/renderer/composites/illus.ts +12 -2
- package/src/renderer/composites/index.ts +2 -2
- package/src/renderer/palettes/registry.ts +2 -2
- package/src/renderer/renderer.ts +5 -11
- package/src/resource/loader.ts +54 -20
- package/src/templates/built-in.ts +4 -0
- package/src/templates/hierarchy-structure.ts +23 -0
- package/src/templates/list-zigzag.ts +70 -0
|
@@ -19,13 +19,13 @@ export const AlignLayout = createLayout((children, { horizontal, vertical, ...pr
|
|
|
19
19
|
if (horizontal !== undefined) {
|
|
20
20
|
switch (horizontal) {
|
|
21
21
|
case 'left':
|
|
22
|
-
childProps.x =
|
|
22
|
+
childProps.x = -bounds.x; // 相对容器边界
|
|
23
23
|
break;
|
|
24
24
|
case 'center':
|
|
25
|
-
childProps.x = (containerWidth - bounds.width) / 2;
|
|
25
|
+
childProps.x = (containerWidth - bounds.width) / 2 - bounds.x;
|
|
26
26
|
break;
|
|
27
27
|
case 'right':
|
|
28
|
-
childProps.x = containerWidth - bounds.width;
|
|
28
|
+
childProps.x = containerWidth - bounds.width - bounds.x;
|
|
29
29
|
break;
|
|
30
30
|
}
|
|
31
31
|
}
|
|
@@ -37,13 +37,13 @@ export const AlignLayout = createLayout((children, { horizontal, vertical, ...pr
|
|
|
37
37
|
if (vertical !== undefined) {
|
|
38
38
|
switch (vertical) {
|
|
39
39
|
case 'top':
|
|
40
|
-
childProps.y =
|
|
40
|
+
childProps.y = -bounds.y;
|
|
41
41
|
break;
|
|
42
42
|
case 'middle':
|
|
43
|
-
childProps.y = (containerHeight - bounds.height) / 2;
|
|
43
|
+
childProps.y = (containerHeight - bounds.height) / 2 - bounds.y;
|
|
44
44
|
break;
|
|
45
45
|
case 'bottom':
|
|
46
|
-
childProps.y = containerHeight - bounds.height;
|
|
46
|
+
childProps.y = containerHeight - bounds.height - bounds.y;
|
|
47
47
|
break;
|
|
48
48
|
}
|
|
49
49
|
}
|
|
@@ -81,6 +81,8 @@ export const FlexLayout = createLayout((children, { flexDirection = 'row', justi
|
|
|
81
81
|
const bounds = lineBounds[childIndex];
|
|
82
82
|
const childMainSize = isRow ? bounds.width : bounds.height;
|
|
83
83
|
const childCrossSize = isRow ? bounds.height : bounds.width;
|
|
84
|
+
const mainOffset = isRow ? bounds.x : bounds.y;
|
|
85
|
+
const crossOffset = isRow ? bounds.y : bounds.x;
|
|
84
86
|
let crossPos = currentCrossPos;
|
|
85
87
|
if (hasContainerSize) {
|
|
86
88
|
switch (alignItems) {
|
|
@@ -98,15 +100,15 @@ export const FlexLayout = createLayout((children, { flexDirection = 'row', justi
|
|
|
98
100
|
let x, y;
|
|
99
101
|
if (isRow) {
|
|
100
102
|
x = isReverse
|
|
101
|
-
? containerWidth - currentMainPos - childMainSize
|
|
102
|
-
: currentMainPos;
|
|
103
|
-
y = crossPos;
|
|
103
|
+
? containerWidth - currentMainPos - childMainSize - mainOffset
|
|
104
|
+
: currentMainPos - mainOffset;
|
|
105
|
+
y = crossPos - crossOffset;
|
|
104
106
|
}
|
|
105
107
|
else {
|
|
106
|
-
x = crossPos;
|
|
108
|
+
x = crossPos - crossOffset;
|
|
107
109
|
y = isReverse
|
|
108
|
-
? containerHeight - currentMainPos - childMainSize
|
|
109
|
-
: currentMainPos;
|
|
110
|
+
? containerHeight - currentMainPos - childMainSize - mainOffset
|
|
111
|
+
: currentMainPos - mainOffset;
|
|
110
112
|
}
|
|
111
113
|
const clonedChild = cloneElement(child, { x, y });
|
|
112
114
|
layoutChildren.push(clonedChild);
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import type { ComponentType } from '../../jsx';
|
|
2
|
+
import type { BaseStructureProps } from './types';
|
|
3
|
+
export interface HierarchyStructureProps extends BaseStructureProps {
|
|
4
|
+
/** Vertical gap between rows. */
|
|
5
|
+
rowGap?: number;
|
|
6
|
+
/** Horizontal gap between left label and right content area. */
|
|
7
|
+
labelGap?: number;
|
|
8
|
+
/** Horizontal gap between groups inside a grouped row. */
|
|
9
|
+
groupGap?: number;
|
|
10
|
+
/** Horizontal/vertical gap between pills. */
|
|
11
|
+
pillGap?: number;
|
|
12
|
+
/** Columns per group (when grouped). */
|
|
13
|
+
pillColumns?: number;
|
|
14
|
+
/** Columns for flat rows (no groups). */
|
|
15
|
+
ungroupedColumns?: number;
|
|
16
|
+
/** Position of the layer label block. */
|
|
17
|
+
layerLabelPosition?: 'left' | 'right';
|
|
18
|
+
/** Padding inside right content container. */
|
|
19
|
+
rowPadding?: number;
|
|
20
|
+
/** Padding inside each group container. */
|
|
21
|
+
groupPadding?: number;
|
|
22
|
+
/** Left/right padding inside left label block. */
|
|
23
|
+
labelPaddingX?: number;
|
|
24
|
+
/** Top/bottom padding inside left label block. */
|
|
25
|
+
labelPaddingY?: number;
|
|
26
|
+
/** Left/right padding inside a pill. */
|
|
27
|
+
pillPaddingX?: number;
|
|
28
|
+
/** Top/bottom padding inside a pill. */
|
|
29
|
+
pillPaddingY?: number;
|
|
30
|
+
/** Font size for left layer labels. */
|
|
31
|
+
labelFontSize?: number;
|
|
32
|
+
/** Font size for group titles. */
|
|
33
|
+
groupTitleFontSize?: number;
|
|
34
|
+
/** Font size for pill text. */
|
|
35
|
+
pillFontSize?: number;
|
|
36
|
+
/** Gap between group title and its pill grid. */
|
|
37
|
+
groupTitleGap?: number;
|
|
38
|
+
/** Corner radius for row containers. */
|
|
39
|
+
rowRadius?: number;
|
|
40
|
+
/** Corner radius for group containers. */
|
|
41
|
+
groupRadius?: number;
|
|
42
|
+
/** Corner radius for pills. */
|
|
43
|
+
pillRadius?: number;
|
|
44
|
+
}
|
|
45
|
+
export declare const HierarchyStructure: ComponentType<HierarchyStructureProps>;
|
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "@antv/infographic/jsx-runtime";
|
|
2
|
+
import { getElementBounds, Group, Rect, Text } from '../../jsx';
|
|
3
|
+
import { ItemsGroup } from '../components';
|
|
4
|
+
import { FlexLayout } from '../layouts';
|
|
5
|
+
import { getPaletteColor, getThemeColors } from '../utils';
|
|
6
|
+
import { registerStructure } from './registry';
|
|
7
|
+
const applyAlpha = (color, alpha) => {
|
|
8
|
+
if (!color || color[0] !== '#' || color.length !== 7)
|
|
9
|
+
return color;
|
|
10
|
+
const clamped = Math.max(0, Math.min(1, alpha));
|
|
11
|
+
const alphaHex = Math.round(clamped * 255)
|
|
12
|
+
.toString(16)
|
|
13
|
+
.padStart(2, '0');
|
|
14
|
+
return `${color}${alphaHex}`;
|
|
15
|
+
};
|
|
16
|
+
const normalizeLabel = (label) => label == null ? '' : String(label);
|
|
17
|
+
const measureText = (text, fontSize, fontWeight) => getElementBounds(_jsx(Text, { fontSize: fontSize, fontWeight: fontWeight, children: text }));
|
|
18
|
+
const getMaxTextBounds = (labels, fontSize, fontWeight, fallbackText = ' ') => {
|
|
19
|
+
const sampleBounds = measureText(fallbackText, fontSize, fontWeight);
|
|
20
|
+
let maxWidth = sampleBounds.width;
|
|
21
|
+
let maxHeight = sampleBounds.height;
|
|
22
|
+
labels.forEach((label) => {
|
|
23
|
+
const bounds = measureText(label || ' ', fontSize, fontWeight);
|
|
24
|
+
maxWidth = Math.max(maxWidth, bounds.width);
|
|
25
|
+
maxHeight = Math.max(maxHeight, bounds.height);
|
|
26
|
+
});
|
|
27
|
+
return { width: maxWidth, height: maxHeight };
|
|
28
|
+
};
|
|
29
|
+
const getPillDimensions = (labels, fontSize, paddingX, paddingY) => {
|
|
30
|
+
const bounds = getMaxTextBounds(labels, fontSize, 'normal', 'Item');
|
|
31
|
+
return {
|
|
32
|
+
pillWidth: bounds.width + paddingX * 2,
|
|
33
|
+
pillHeight: bounds.height + paddingY * 2,
|
|
34
|
+
};
|
|
35
|
+
};
|
|
36
|
+
export const HierarchyStructure = (props) => {
|
|
37
|
+
const { Title, data, options, rowGap = 20, labelGap = 20, groupGap = 20, pillGap = 14, pillColumns = 2, ungroupedColumns = 6, layerLabelPosition = 'left', rowPadding = 20, groupPadding = 16, labelPaddingX = 28, labelPaddingY = 16, pillPaddingX = 18, pillPaddingY = 10, labelFontSize = 20, groupTitleFontSize = 18, pillFontSize = 16, groupTitleGap = 10, rowRadius = 12, groupRadius = 10, pillRadius = 12, } = props;
|
|
38
|
+
const { title, desc, items = [] } = data;
|
|
39
|
+
const titleContent = Title ? _jsx(Title, { title: title, desc: desc }) : null;
|
|
40
|
+
if (items.length === 0) {
|
|
41
|
+
return (_jsxs(FlexLayout, { id: "infographic-container", flexDirection: "column", justifyContent: "center", alignItems: "center", children: [titleContent, _jsx(Group, { children: _jsx(ItemsGroup, {}) })] }));
|
|
42
|
+
}
|
|
43
|
+
const themeColors = getThemeColors(options.themeConfig);
|
|
44
|
+
const decorElements = [];
|
|
45
|
+
const itemElements = [];
|
|
46
|
+
const isLabelOnRight = layerLabelPosition === 'right';
|
|
47
|
+
const rowBackgroundAlpha = 0.12;
|
|
48
|
+
const rowBorderAlpha = 0.55;
|
|
49
|
+
const groupBackgroundAlpha = 0.08;
|
|
50
|
+
const groupBorderAlpha = 0.4;
|
|
51
|
+
const pillBackgroundAlpha = 0.06;
|
|
52
|
+
const pillBorderAlpha = 0.35;
|
|
53
|
+
const rowInfos = items.map((layer) => {
|
|
54
|
+
const layerLabel = normalizeLabel(layer.label);
|
|
55
|
+
const labelBounds = measureText(layerLabel || ' ', labelFontSize, 'bold');
|
|
56
|
+
const labelWidth = labelBounds.width + labelPaddingX * 2;
|
|
57
|
+
const labelHeight = labelBounds.height + labelPaddingY * 2;
|
|
58
|
+
const children = layer.children || [];
|
|
59
|
+
const hasGroups = children.some((child) => (child.children?.length || 0) > 0);
|
|
60
|
+
if (hasGroups) {
|
|
61
|
+
const pillLabels = [];
|
|
62
|
+
children.forEach((child) => {
|
|
63
|
+
(child.children || []).forEach((pill) => {
|
|
64
|
+
pillLabels.push(normalizeLabel(pill.label));
|
|
65
|
+
});
|
|
66
|
+
});
|
|
67
|
+
const { pillWidth, pillHeight } = getPillDimensions(pillLabels, pillFontSize, pillPaddingX, pillPaddingY);
|
|
68
|
+
const groupMetrics = children.map((group) => {
|
|
69
|
+
const groupLabel = normalizeLabel(group.label);
|
|
70
|
+
const groupTitleBounds = measureText(groupLabel || ' ', groupTitleFontSize, 'bold');
|
|
71
|
+
const groupChildren = group.children || [];
|
|
72
|
+
const groupColumns = groupChildren.length > 0
|
|
73
|
+
? Math.min(pillColumns, groupChildren.length)
|
|
74
|
+
: 0;
|
|
75
|
+
const groupRows = groupColumns > 0 ? Math.ceil(groupChildren.length / groupColumns) : 0;
|
|
76
|
+
const groupContentWidth = groupColumns > 0
|
|
77
|
+
? groupColumns * pillWidth + (groupColumns - 1) * pillGap
|
|
78
|
+
: 0;
|
|
79
|
+
const groupContentHeight = groupRows > 0
|
|
80
|
+
? groupRows * pillHeight + (groupRows - 1) * pillGap
|
|
81
|
+
: 0;
|
|
82
|
+
const innerWidth = Math.max(groupTitleBounds.width, groupContentWidth);
|
|
83
|
+
const groupWidth = innerWidth + groupPadding * 2;
|
|
84
|
+
const groupHeight = groupPadding * 2 +
|
|
85
|
+
groupTitleBounds.height +
|
|
86
|
+
(groupRows > 0 ? groupTitleGap + groupContentHeight : 0);
|
|
87
|
+
return {
|
|
88
|
+
label: groupLabel,
|
|
89
|
+
children: groupChildren,
|
|
90
|
+
width: groupWidth,
|
|
91
|
+
height: groupHeight,
|
|
92
|
+
titleHeight: groupTitleBounds.height,
|
|
93
|
+
columns: groupColumns,
|
|
94
|
+
contentWidth: groupContentWidth,
|
|
95
|
+
pillWidth,
|
|
96
|
+
pillHeight,
|
|
97
|
+
};
|
|
98
|
+
});
|
|
99
|
+
const contentInnerWidth = groupMetrics.reduce((sum, metric) => sum + metric.width, 0) +
|
|
100
|
+
(groupMetrics.length > 1 ? (groupMetrics.length - 1) * groupGap : 0);
|
|
101
|
+
const contentInnerHeight = groupMetrics.reduce((max, metric) => Math.max(max, metric.height), 0);
|
|
102
|
+
return {
|
|
103
|
+
label: layerLabel,
|
|
104
|
+
labelWidth,
|
|
105
|
+
labelHeight,
|
|
106
|
+
hasGroups: true,
|
|
107
|
+
children,
|
|
108
|
+
groupMetrics,
|
|
109
|
+
contentInnerWidth,
|
|
110
|
+
contentInnerHeight,
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
const pillLabels = children.map((child) => normalizeLabel(child.label));
|
|
114
|
+
const { pillWidth, pillHeight } = getPillDimensions(pillLabels, pillFontSize, pillPaddingX, pillPaddingY);
|
|
115
|
+
const columns = children.length > 0 ? Math.min(ungroupedColumns, children.length) : 0;
|
|
116
|
+
const rows = columns > 0 ? Math.ceil(children.length / columns) : 0;
|
|
117
|
+
const contentInnerWidth = columns > 0 ? columns * pillWidth + (columns - 1) * pillGap : 0;
|
|
118
|
+
const contentInnerHeight = rows > 0 ? rows * pillHeight + (rows - 1) * pillGap : 0;
|
|
119
|
+
return {
|
|
120
|
+
label: layerLabel,
|
|
121
|
+
labelWidth,
|
|
122
|
+
labelHeight,
|
|
123
|
+
hasGroups: false,
|
|
124
|
+
children,
|
|
125
|
+
pillWidth,
|
|
126
|
+
pillHeight,
|
|
127
|
+
columns,
|
|
128
|
+
contentInnerWidth,
|
|
129
|
+
contentInnerHeight,
|
|
130
|
+
};
|
|
131
|
+
});
|
|
132
|
+
const maxLabelWidth = rowInfos.reduce((max, row) => Math.max(max, row.labelWidth), 0);
|
|
133
|
+
const targetContentInnerWidth = rowInfos.reduce((max, row) => Math.max(max, row.contentInnerWidth), 0);
|
|
134
|
+
const getRowColors = (layerIndex) => {
|
|
135
|
+
const rowColor = getPaletteColor(options, [layerIndex]) ||
|
|
136
|
+
themeColors.colorPrimary ||
|
|
137
|
+
'#6c7dff';
|
|
138
|
+
return {
|
|
139
|
+
rowFill: applyAlpha(rowColor, rowBackgroundAlpha),
|
|
140
|
+
rowStroke: applyAlpha(rowColor, rowBorderAlpha),
|
|
141
|
+
groupFill: applyAlpha(rowColor, groupBackgroundAlpha),
|
|
142
|
+
groupStroke: applyAlpha(rowColor, groupBorderAlpha),
|
|
143
|
+
pillFill: applyAlpha(rowColor, pillBackgroundAlpha),
|
|
144
|
+
pillStroke: applyAlpha(rowColor, pillBorderAlpha),
|
|
145
|
+
};
|
|
146
|
+
};
|
|
147
|
+
const renderRowFrame = (layerLabel, layerIndexes, labelX, labelY, labelWidth, labelHeight, rowY, rowHeight, contentX, contentY, contentWidth, contentHeight, rowFill, rowStroke) => {
|
|
148
|
+
decorElements.push(_jsx(Rect, { x: labelX, y: rowY, width: labelWidth, height: rowHeight, fill: rowFill, stroke: rowStroke, rx: rowRadius, ry: rowRadius, "data-element-type": "shape" }));
|
|
149
|
+
decorElements.push(_jsx(Rect, { x: contentX, y: contentY, width: contentWidth, height: contentHeight, fill: rowFill, stroke: rowStroke, rx: rowRadius, ry: rowRadius, "data-element-type": "shape" }));
|
|
150
|
+
itemElements.push(_jsx(Text, { x: labelX, y: labelY, width: labelWidth, height: labelHeight, fontSize: labelFontSize, fontWeight: "bold", alignHorizontal: "center", alignVertical: "middle", fill: themeColors.colorText, "data-element-type": "item-label" /* ElementTypeEnum.ItemLabel */, "data-indexes": layerIndexes, children: layerLabel }));
|
|
151
|
+
};
|
|
152
|
+
const renderGroupedRow = (rowInfo, layerIndex, rowY, rowColors) => {
|
|
153
|
+
const groupMetrics = rowInfo.groupMetrics || [];
|
|
154
|
+
const layerLabel = rowInfo.label;
|
|
155
|
+
const layerIndexes = [layerIndex];
|
|
156
|
+
const labelWidth = maxLabelWidth;
|
|
157
|
+
const labelHeight = rowInfo.labelHeight;
|
|
158
|
+
const contentInnerHeight = rowInfo.contentInnerHeight;
|
|
159
|
+
const extraInnerWidth = Math.max(0, targetContentInnerWidth - rowInfo.contentInnerWidth);
|
|
160
|
+
const extraPerGroup = groupMetrics.length > 0 ? extraInnerWidth / groupMetrics.length : 0;
|
|
161
|
+
const contentInnerWidth = rowInfo.contentInnerWidth +
|
|
162
|
+
(groupMetrics.length > 0 ? extraInnerWidth : 0);
|
|
163
|
+
const contentWidth = contentInnerWidth + rowPadding * 2;
|
|
164
|
+
const contentHeight = contentInnerHeight + rowPadding * 2;
|
|
165
|
+
const rowHeight = Math.max(labelHeight, contentHeight);
|
|
166
|
+
const contentX = isLabelOnRight ? 0 : labelWidth + labelGap;
|
|
167
|
+
const labelX = isLabelOnRight ? contentX + contentWidth + labelGap : 0;
|
|
168
|
+
const labelY = rowY + (rowHeight - labelHeight) / 2;
|
|
169
|
+
const contentY = rowY + (rowHeight - contentHeight) / 2;
|
|
170
|
+
renderRowFrame(layerLabel, layerIndexes, labelX, labelY, labelWidth, labelHeight, rowY, rowHeight, contentX, contentY, contentWidth, contentHeight, rowColors.rowFill, rowColors.rowStroke);
|
|
171
|
+
let groupX = contentX + rowPadding;
|
|
172
|
+
groupMetrics.forEach((metric, groupIndex) => {
|
|
173
|
+
const groupIndexes = [...layerIndexes, groupIndex];
|
|
174
|
+
const groupWidth = metric.width + extraPerGroup;
|
|
175
|
+
const groupY = contentY + rowPadding + (contentInnerHeight - metric.height) / 2;
|
|
176
|
+
decorElements.push(_jsx(Rect, { x: groupX, y: groupY, width: groupWidth, height: metric.height, fill: rowColors.groupFill, stroke: rowColors.groupStroke, rx: groupRadius, ry: groupRadius, "data-element-type": "shape" }));
|
|
177
|
+
const hasGroupChildren = metric.children.length > 0;
|
|
178
|
+
const titleY = hasGroupChildren ? groupY + groupPadding : groupY;
|
|
179
|
+
const titleHeight = hasGroupChildren ? metric.titleHeight : metric.height;
|
|
180
|
+
const titleAlignV = hasGroupChildren ? 'top' : 'middle';
|
|
181
|
+
itemElements.push(_jsx(Text, { x: groupX + groupPadding, y: titleY, width: groupWidth - groupPadding * 2, height: titleHeight, fontSize: groupTitleFontSize, fontWeight: "bold", alignHorizontal: "center", alignVertical: titleAlignV, fill: themeColors.colorText, "data-element-type": "item-label" /* ElementTypeEnum.ItemLabel */, "data-indexes": groupIndexes, children: metric.label }));
|
|
182
|
+
if (metric.columns > 0) {
|
|
183
|
+
const innerWidth = groupWidth - groupPadding * 2;
|
|
184
|
+
const extraWidth = innerWidth - metric.contentWidth;
|
|
185
|
+
const columnExtra = extraWidth > 0 ? extraWidth / metric.columns : 0;
|
|
186
|
+
const pillWidth = metric.pillWidth + columnExtra;
|
|
187
|
+
const contentWidth = metric.columns * pillWidth + (metric.columns - 1) * pillGap;
|
|
188
|
+
const contentOffsetX = (innerWidth - contentWidth) / 2;
|
|
189
|
+
const pillStartX = groupX + groupPadding + Math.max(0, contentOffsetX);
|
|
190
|
+
const pillStartY = groupY + groupPadding + metric.titleHeight + groupTitleGap;
|
|
191
|
+
metric.children.forEach((pill, pillIndex) => {
|
|
192
|
+
const pillIndexes = [...groupIndexes, pillIndex];
|
|
193
|
+
const rowIndex = Math.floor(pillIndex / metric.columns);
|
|
194
|
+
const colIndex = pillIndex % metric.columns;
|
|
195
|
+
const pillX = pillStartX + colIndex * (pillWidth + pillGap);
|
|
196
|
+
const pillY = pillStartY + rowIndex * (metric.pillHeight + pillGap);
|
|
197
|
+
const pillRx = Math.min(pillRadius, metric.pillHeight / 2);
|
|
198
|
+
decorElements.push(_jsx(Rect, { x: pillX, y: pillY, width: pillWidth, height: metric.pillHeight, fill: rowColors.pillFill, stroke: rowColors.pillStroke, rx: pillRx, ry: pillRx, "data-element-type": "shape" }));
|
|
199
|
+
itemElements.push(_jsx(Text, { x: pillX, y: pillY, width: pillWidth, height: metric.pillHeight, fontSize: pillFontSize, fontWeight: "normal", alignHorizontal: "center", alignVertical: "middle", fill: themeColors.colorText, "data-element-type": "item-label" /* ElementTypeEnum.ItemLabel */, "data-indexes": pillIndexes, children: normalizeLabel(pill.label) }));
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
groupX += groupWidth + groupGap;
|
|
203
|
+
});
|
|
204
|
+
const rowWidth = isLabelOnRight
|
|
205
|
+
? labelX + labelWidth
|
|
206
|
+
: contentX + contentWidth;
|
|
207
|
+
return { rowWidth, rowHeight };
|
|
208
|
+
};
|
|
209
|
+
const renderUngroupedRow = (rowInfo, layerIndex, rowY, rowColors) => {
|
|
210
|
+
const layerLabel = rowInfo.label;
|
|
211
|
+
const layerIndexes = [layerIndex];
|
|
212
|
+
const labelWidth = maxLabelWidth;
|
|
213
|
+
const labelHeight = rowInfo.labelHeight;
|
|
214
|
+
const contentInnerHeight = rowInfo.contentInnerHeight;
|
|
215
|
+
const extraInnerWidth = Math.max(0, targetContentInnerWidth - rowInfo.contentInnerWidth);
|
|
216
|
+
const columns = rowInfo.columns || 0;
|
|
217
|
+
const pillWidthBase = rowInfo.pillWidth || 0;
|
|
218
|
+
const pillHeight = rowInfo.pillHeight || 0;
|
|
219
|
+
const extraPerColumn = columns > 0 ? extraInnerWidth / columns : 0;
|
|
220
|
+
const pillWidth = pillWidthBase + extraPerColumn;
|
|
221
|
+
const contentInnerWidth = columns > 0 ? columns * pillWidth + (columns - 1) * pillGap : 0;
|
|
222
|
+
const contentWidth = contentInnerWidth + rowPadding * 2;
|
|
223
|
+
const contentHeight = contentInnerHeight + rowPadding * 2;
|
|
224
|
+
const rowHeight = Math.max(labelHeight, contentHeight);
|
|
225
|
+
const contentX = isLabelOnRight ? 0 : labelWidth + labelGap;
|
|
226
|
+
const labelX = isLabelOnRight ? contentX + contentWidth + labelGap : 0;
|
|
227
|
+
const labelY = rowY + (rowHeight - labelHeight) / 2;
|
|
228
|
+
const contentY = rowY + (rowHeight - contentHeight) / 2;
|
|
229
|
+
renderRowFrame(layerLabel, layerIndexes, labelX, labelY, labelWidth, labelHeight, rowY, rowHeight, contentX, contentY, contentWidth, contentHeight, rowColors.rowFill, rowColors.rowStroke);
|
|
230
|
+
if (columns > 0) {
|
|
231
|
+
const pillStartX = contentX + rowPadding;
|
|
232
|
+
const pillStartY = contentY + rowPadding;
|
|
233
|
+
const flatChildren = rowInfo.children || [];
|
|
234
|
+
flatChildren.forEach((child, pillIndex) => {
|
|
235
|
+
const pillIndexes = [...layerIndexes, pillIndex];
|
|
236
|
+
const rowIndex = Math.floor(pillIndex / columns);
|
|
237
|
+
const colIndex = pillIndex % columns;
|
|
238
|
+
const pillX = pillStartX + colIndex * (pillWidth + pillGap);
|
|
239
|
+
const pillY = pillStartY + rowIndex * (pillHeight + pillGap);
|
|
240
|
+
const pillRx = Math.min(pillRadius, pillHeight / 2);
|
|
241
|
+
decorElements.push(_jsx(Rect, { x: pillX, y: pillY, width: pillWidth, height: pillHeight, fill: rowColors.pillFill, stroke: rowColors.pillStroke, rx: pillRx, ry: pillRx, "data-element-type": "shape" }));
|
|
242
|
+
itemElements.push(_jsx(Text, { x: pillX, y: pillY, width: pillWidth, height: pillHeight, fontSize: pillFontSize, fontWeight: "normal", alignHorizontal: "center", alignVertical: "middle", fill: themeColors.colorText, "data-element-type": "item-label" /* ElementTypeEnum.ItemLabel */, "data-indexes": pillIndexes, children: normalizeLabel(child.label) }));
|
|
243
|
+
});
|
|
244
|
+
}
|
|
245
|
+
const rowWidth = isLabelOnRight
|
|
246
|
+
? labelX + labelWidth
|
|
247
|
+
: contentX + contentWidth;
|
|
248
|
+
return { rowWidth, rowHeight };
|
|
249
|
+
};
|
|
250
|
+
let currentY = 0;
|
|
251
|
+
let maxWidth = 0;
|
|
252
|
+
rowInfos.forEach((rowInfo, layerIndex) => {
|
|
253
|
+
const rowColors = getRowColors(layerIndex);
|
|
254
|
+
const { rowWidth, rowHeight } = rowInfo.hasGroups
|
|
255
|
+
? renderGroupedRow(rowInfo, layerIndex, currentY, rowColors)
|
|
256
|
+
: renderUngroupedRow(rowInfo, layerIndex, currentY, rowColors);
|
|
257
|
+
maxWidth = Math.max(maxWidth, rowWidth);
|
|
258
|
+
currentY += rowHeight + rowGap;
|
|
259
|
+
});
|
|
260
|
+
const totalHeight = Math.max(currentY - rowGap, 0);
|
|
261
|
+
return (_jsxs(FlexLayout, { id: "infographic-container", flexDirection: "column", justifyContent: "center", alignItems: "center", children: [titleContent, _jsxs(Group, { width: maxWidth, height: totalHeight, children: [_jsx(Group, { children: decorElements }), _jsx(ItemsGroup, { children: itemElements })] })] }));
|
|
262
|
+
};
|
|
263
|
+
registerStructure('hierarchy-structure', {
|
|
264
|
+
component: HierarchyStructure,
|
|
265
|
+
composites: ['title'],
|
|
266
|
+
});
|
|
@@ -7,6 +7,7 @@ export * from './compare-binary-horizontal';
|
|
|
7
7
|
export * from './compare-hierarchy-left-right';
|
|
8
8
|
export * from './compare-hierarchy-row';
|
|
9
9
|
export * from './hierarchy-mindmap';
|
|
10
|
+
export * from './hierarchy-structure';
|
|
10
11
|
export * from './hierarchy-tree';
|
|
11
12
|
export * from './list-column';
|
|
12
13
|
export * from './list-grid';
|
|
@@ -14,6 +15,7 @@ export * from './list-pyramid';
|
|
|
14
15
|
export * from './list-row';
|
|
15
16
|
export * from './list-sector';
|
|
16
17
|
export * from './list-waterfall';
|
|
18
|
+
export * from './list-zigzag';
|
|
17
19
|
export * from './quadrant';
|
|
18
20
|
export * from './registry';
|
|
19
21
|
export { getStructure, getStructures, registerStructure } from './registry';
|
|
@@ -7,6 +7,7 @@ export * from './compare-binary-horizontal';
|
|
|
7
7
|
export * from './compare-hierarchy-left-right';
|
|
8
8
|
export * from './compare-hierarchy-row';
|
|
9
9
|
export * from './hierarchy-mindmap';
|
|
10
|
+
export * from './hierarchy-structure';
|
|
10
11
|
export * from './hierarchy-tree';
|
|
11
12
|
export * from './list-column';
|
|
12
13
|
export * from './list-grid';
|
|
@@ -14,6 +15,7 @@ export * from './list-pyramid';
|
|
|
14
15
|
export * from './list-row';
|
|
15
16
|
export * from './list-sector';
|
|
16
17
|
export * from './list-waterfall';
|
|
18
|
+
export * from './list-zigzag';
|
|
17
19
|
export * from './quadrant';
|
|
18
20
|
export * from './registry';
|
|
19
21
|
export { getStructure, getStructures, registerStructure } from './registry';
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { ComponentType } from '../../jsx';
|
|
2
|
+
import type { BaseStructureProps } from './types';
|
|
3
|
+
export interface ListZigzagProps extends BaseStructureProps {
|
|
4
|
+
itemGap?: number;
|
|
5
|
+
}
|
|
6
|
+
export interface ListZigzagDownProps extends ListZigzagProps {
|
|
7
|
+
}
|
|
8
|
+
export interface ListZigzagUpProps extends ListZigzagProps {
|
|
9
|
+
}
|
|
10
|
+
export declare const ListZigzagDown: ComponentType<ListZigzagDownProps>;
|
|
11
|
+
export declare const ListZigzagUp: ComponentType<ListZigzagUpProps>;
|