@antv/infographic 0.2.2 → 0.2.3

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 (60) hide show
  1. package/dist/infographic.min.js +62 -62
  2. package/dist/infographic.min.js.map +1 -1
  3. package/esm/designs/layouts/Align.js +6 -6
  4. package/esm/designs/layouts/Flex.js +8 -6
  5. package/esm/designs/structures/index.d.ts +1 -0
  6. package/esm/designs/structures/index.js +1 -0
  7. package/esm/designs/structures/list-zigzag.d.ts +11 -0
  8. package/esm/designs/structures/list-zigzag.js +240 -0
  9. package/esm/index.d.ts +1 -1
  10. package/esm/index.js +1 -1
  11. package/esm/renderer/composites/icon.d.ts +2 -5
  12. package/esm/renderer/composites/icon.js +5 -10
  13. package/esm/renderer/composites/illus.d.ts +3 -2
  14. package/esm/renderer/composites/illus.js +6 -2
  15. package/esm/renderer/composites/index.d.ts +2 -2
  16. package/esm/renderer/composites/index.js +2 -2
  17. package/esm/renderer/palettes/registry.d.ts +1 -1
  18. package/esm/renderer/palettes/registry.js +1 -1
  19. package/esm/renderer/renderer.js +6 -3
  20. package/esm/resource/loader.d.ts +2 -1
  21. package/esm/resource/loader.js +55 -23
  22. package/esm/templates/built-in.js +2 -0
  23. package/esm/templates/list-zigzag.d.ts +2 -0
  24. package/esm/templates/list-zigzag.js +68 -0
  25. package/lib/designs/layouts/Align.js +6 -6
  26. package/lib/designs/layouts/Flex.js +8 -6
  27. package/lib/designs/structures/index.d.ts +1 -0
  28. package/lib/designs/structures/index.js +1 -0
  29. package/lib/designs/structures/list-zigzag.d.ts +11 -0
  30. package/lib/designs/structures/list-zigzag.js +246 -0
  31. package/lib/index.d.ts +1 -1
  32. package/lib/index.js +3 -2
  33. package/lib/renderer/composites/icon.d.ts +2 -5
  34. package/lib/renderer/composites/icon.js +5 -11
  35. package/lib/renderer/composites/illus.d.ts +3 -2
  36. package/lib/renderer/composites/illus.js +7 -2
  37. package/lib/renderer/composites/index.d.ts +2 -2
  38. package/lib/renderer/composites/index.js +2 -2
  39. package/lib/renderer/palettes/registry.d.ts +1 -1
  40. package/lib/renderer/palettes/registry.js +1 -1
  41. package/lib/renderer/renderer.js +5 -2
  42. package/lib/resource/loader.d.ts +2 -1
  43. package/lib/resource/loader.js +55 -23
  44. package/lib/templates/built-in.js +2 -0
  45. package/lib/templates/list-zigzag.d.ts +2 -0
  46. package/lib/templates/list-zigzag.js +71 -0
  47. package/package.json +1 -1
  48. package/src/designs/layouts/Align.tsx +6 -6
  49. package/src/designs/layouts/Flex.tsx +8 -6
  50. package/src/designs/structures/index.ts +1 -0
  51. package/src/designs/structures/list-zigzag.tsx +492 -0
  52. package/src/index.ts +2 -0
  53. package/src/renderer/composites/icon.ts +6 -16
  54. package/src/renderer/composites/illus.ts +12 -2
  55. package/src/renderer/composites/index.ts +2 -2
  56. package/src/renderer/palettes/registry.ts +2 -2
  57. package/src/renderer/renderer.ts +5 -11
  58. package/src/resource/loader.ts +54 -20
  59. package/src/templates/built-in.ts +2 -0
  60. 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 = 0; // 相对容器
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 = 0;
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);
@@ -14,6 +14,7 @@ export * from './list-pyramid';
14
14
  export * from './list-row';
15
15
  export * from './list-sector';
16
16
  export * from './list-waterfall';
17
+ export * from './list-zigzag';
17
18
  export * from './quadrant';
18
19
  export * from './registry';
19
20
  export { getStructure, getStructures, registerStructure } from './registry';
@@ -14,6 +14,7 @@ export * from './list-pyramid';
14
14
  export * from './list-row';
15
15
  export * from './list-sector';
16
16
  export * from './list-waterfall';
17
+ export * from './list-zigzag';
17
18
  export * from './quadrant';
18
19
  export * from './registry';
19
20
  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>;
@@ -0,0 +1,240 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "@antv/infographic/jsx-runtime";
2
+ import tinycolor from 'tinycolor2';
3
+ import { getElementBounds, Group } from '../../jsx';
4
+ import { BtnAdd, BtnRemove, BtnsGroup, ItemsGroup } from '../components';
5
+ import { FlexLayout } from '../layouts';
6
+ import { getColorPrimary, getThemeColors } from '../utils';
7
+ import { registerStructure } from './registry';
8
+ const MAX_ITEMS = 6;
9
+ const ARROW_WIDTH = 700;
10
+ const ARROW_HEIGHT_DOWN = 330;
11
+ const ARROW_HEIGHT_UP = 333;
12
+ const PRESET_RATIOS_DOWN = {
13
+ 1: [{ x: 0.5, y: 0.6, anchor: 'top-right' }],
14
+ 2: [
15
+ { x: 0.42, y: 0.5, anchor: 'top-right' },
16
+ { x: 0.72, y: 0.4, anchor: 'bottom' },
17
+ ],
18
+ 3: [
19
+ { x: 0.3, y: 0.5, anchor: 'top-right' },
20
+ { x: 0.48, y: 0.3, anchor: 'bottom-left' },
21
+ { x: 0.8, y: 0.75, anchor: 'top-right' },
22
+ ],
23
+ 4: [
24
+ { x: 0.3, y: 0.5, anchor: 'top-right' },
25
+ { x: 0.35, y: 0.2, anchor: 'bottom-left' },
26
+ { x: 0.65, y: 0.73, anchor: 'top-right' },
27
+ { x: 0.8, y: 0.52, anchor: 'bottom-left' },
28
+ ],
29
+ 5: [
30
+ { x: 0.19, y: 0.4, anchor: 'top-right' },
31
+ { x: 0.38, y: 0.2, anchor: 'bottom' },
32
+ { x: 0.52, y: 0.62, anchor: 'top-right' },
33
+ { x: 0.7, y: 0.43, anchor: 'bottom' },
34
+ { x: 0.82, y: 0.8, anchor: 'top-right' },
35
+ ],
36
+ 6: [
37
+ { x: 0.16, y: 0.35, anchor: 'top-right' },
38
+ { x: 0.38, y: 0.2, anchor: 'bottom' },
39
+ { x: 0.48, y: 0.54, anchor: 'top-right' },
40
+ { x: 0.55, y: 0.43, anchor: 'bottom-left' },
41
+ { x: 0.8, y: 0.75, anchor: 'top-right' },
42
+ { x: 0.86, y: 0.65, anchor: 'bottom-left' },
43
+ ],
44
+ };
45
+ const PRESET_RATIOS_UP = {
46
+ 1: [{ x: 0.5, y: 0.4, anchor: 'bottom-right' }],
47
+ 2: [
48
+ { x: 0.42, y: 0.5, anchor: 'bottom-right' },
49
+ { x: 0.72, y: 0.6, anchor: 'top' },
50
+ ],
51
+ 3: [
52
+ { x: 0.3, y: 0.5, anchor: 'bottom-right' },
53
+ { x: 0.48, y: 0.7, anchor: 'top-left' },
54
+ { x: 0.8, y: 0.25, anchor: 'bottom-right' },
55
+ ],
56
+ 4: [
57
+ { x: 0.3, y: 0.5, anchor: 'bottom-right' },
58
+ { x: 0.35, y: 0.8, anchor: 'top-left' },
59
+ { x: 0.65, y: 0.27, anchor: 'bottom-right' },
60
+ { x: 0.8, y: 0.48, anchor: 'top-left' },
61
+ ],
62
+ 5: [
63
+ { x: 0.19, y: 0.6, anchor: 'bottom-right' },
64
+ { x: 0.38, y: 0.8, anchor: 'top' },
65
+ { x: 0.52, y: 0.38, anchor: 'bottom-right' },
66
+ { x: 0.7, y: 0.57, anchor: 'top' },
67
+ { x: 0.82, y: 0.2, anchor: 'bottom-right' },
68
+ ],
69
+ 6: [
70
+ { x: 0.16, y: 0.65, anchor: 'bottom-right' },
71
+ { x: 0.38, y: 0.8, anchor: 'top' },
72
+ { x: 0.48, y: 0.46, anchor: 'bottom-right' },
73
+ { x: 0.55, y: 0.57, anchor: 'top-left' },
74
+ { x: 0.8, y: 0.25, anchor: 'bottom-right' },
75
+ { x: 0.86, y: 0.35, anchor: 'top-left' },
76
+ ],
77
+ };
78
+ const getPresetPoints = (count, presetRatios, arrowHeight) => {
79
+ const ratios = presetRatios[count];
80
+ if (!ratios)
81
+ return null;
82
+ return ratios.map((point) => ({
83
+ x: point.x * ARROW_WIDTH,
84
+ y: point.y * arrowHeight,
85
+ anchor: point.anchor,
86
+ }));
87
+ };
88
+ const getAnchoredPosition = (point, size) => {
89
+ const anchor = point.anchor || 'center';
90
+ let x = point.x - size.width / 2;
91
+ let y = point.y - size.height / 2;
92
+ let centerY = point.y;
93
+ switch (anchor) {
94
+ case 'top':
95
+ x = point.x - size.width / 2;
96
+ y = point.y;
97
+ centerY = point.y + size.height / 2;
98
+ break;
99
+ case 'bottom':
100
+ x = point.x - size.width / 2;
101
+ y = point.y - size.height;
102
+ centerY = point.y - size.height / 2;
103
+ break;
104
+ case 'top-left':
105
+ x = point.x;
106
+ y = point.y;
107
+ centerY = point.y + size.height / 2;
108
+ break;
109
+ case 'top-right':
110
+ x = point.x - size.width;
111
+ y = point.y;
112
+ centerY = point.y + size.height / 2;
113
+ break;
114
+ case 'bottom-left':
115
+ x = point.x;
116
+ y = point.y - size.height;
117
+ centerY = point.y - size.height / 2;
118
+ break;
119
+ case 'bottom-right':
120
+ x = point.x - size.width;
121
+ y = point.y - size.height;
122
+ centerY = point.y - size.height / 2;
123
+ break;
124
+ default:
125
+ break;
126
+ }
127
+ return { x, y, centerY };
128
+ };
129
+ const getUnitVector = (from, to) => {
130
+ const dx = to.x - from.x;
131
+ const dy = to.y - from.y;
132
+ const length = Math.hypot(dx, dy) || 1;
133
+ return { x: dx / length, y: dy / length };
134
+ };
135
+ const createListZigzag = (config) => {
136
+ const { presetRatios, arrowHeight, Arrow } = config;
137
+ const ListZigzag = (props) => {
138
+ const { Title, Item, data, options, itemGap = 24 } = props;
139
+ const { title, desc, items = [] } = data;
140
+ const layoutCount = Math.min(items.length, MAX_ITEMS);
141
+ const displayItems = items.slice(0, layoutCount);
142
+ const titleContent = Title ? _jsx(Title, { title: title, desc: desc }) : null;
143
+ const colorPrimary = getColorPrimary(options);
144
+ const themeColors = getThemeColors({ colorPrimary }, options);
145
+ const colorShadow = themeColors.colorTextSecondary || '#737373';
146
+ const btnBounds = getElementBounds(_jsx(BtnAdd, { indexes: [0] }));
147
+ if (items.length === 0) {
148
+ const anchor = getPresetPoints(1, presetRatios, arrowHeight)?.[0];
149
+ if (!anchor) {
150
+ return (_jsxs(FlexLayout, { id: "infographic-container", flexDirection: "column", justifyContent: "center", alignItems: "center", children: [titleContent, _jsx(Group, { children: _jsx(Arrow, { colorPrimary: colorPrimary, colorShadow: colorShadow }) })] }));
151
+ }
152
+ const btnX = anchor.x - btnBounds.width / 2;
153
+ const btnY = anchor.y - btnBounds.height / 2;
154
+ return (_jsxs(FlexLayout, { id: "infographic-container", flexDirection: "column", justifyContent: "center", alignItems: "center", children: [titleContent, _jsxs(Group, { children: [_jsx(Arrow, { colorPrimary: colorPrimary, colorShadow: colorShadow }), _jsx(ItemsGroup, {}), _jsx(BtnsGroup, { children: _jsx(BtnAdd, { indexes: [0], x: btnX, y: btnY }) })] })] }));
155
+ }
156
+ const itemBounds = getElementBounds(_jsx(Item, { indexes: [0], data: data, datum: items[0], positionH: "center" }));
157
+ const btnElements = [];
158
+ const itemElements = [];
159
+ const presetPoints = getPresetPoints(layoutCount, presetRatios, arrowHeight);
160
+ if (!presetPoints) {
161
+ return (_jsxs(FlexLayout, { id: "infographic-container", flexDirection: "column", justifyContent: "center", alignItems: "center", children: [titleContent, _jsxs(Group, { children: [_jsx(Arrow, { colorPrimary: colorPrimary, colorShadow: colorShadow }), _jsx(ItemsGroup, {})] })] }));
162
+ }
163
+ const anchorPoints = presetPoints;
164
+ const baseDirection = anchorPoints.length > 1
165
+ ? getUnitVector(anchorPoints[0], anchorPoints[anchorPoints.length - 1])
166
+ : { x: 1, y: 0 };
167
+ const startDirection = anchorPoints.length > 1
168
+ ? getUnitVector(anchorPoints[0], anchorPoints[1])
169
+ : baseDirection;
170
+ const endDirection = anchorPoints.length > 1
171
+ ? getUnitVector(anchorPoints[anchorPoints.length - 2], anchorPoints[anchorPoints.length - 1])
172
+ : baseDirection;
173
+ const addOffset = Math.max(itemBounds.width, itemBounds.height) * 0.45 + itemGap;
174
+ const toItemPosition = (point) => {
175
+ const { x, y, centerY } = getAnchoredPosition(point, itemBounds);
176
+ return { x, y, centerY };
177
+ };
178
+ anchorPoints.forEach((anchor, index) => {
179
+ const itemPosition = toItemPosition(anchor);
180
+ const isTop = itemPosition.centerY < arrowHeight / 2;
181
+ const indexes = [index];
182
+ const item = displayItems[index];
183
+ if (!item)
184
+ return;
185
+ itemElements.push(_jsx(Item, { indexes: indexes, datum: item, data: data, x: itemPosition.x, y: itemPosition.y, positionH: "center" }));
186
+ const btnRemoveX = itemPosition.x + itemBounds.width - btnBounds.width / 2;
187
+ const btnRemoveY = isTop
188
+ ? itemPosition.y - btnBounds.height / 2
189
+ : itemPosition.y + itemBounds.height - btnBounds.height / 2;
190
+ btnElements.push(_jsx(BtnRemove, { indexes: indexes, x: btnRemoveX, y: btnRemoveY }));
191
+ });
192
+ if (anchorPoints.length > 0) {
193
+ const firstAnchor = anchorPoints[0];
194
+ const firstAddX = firstAnchor.x - startDirection.x * addOffset - btnBounds.width / 2;
195
+ const firstAddY = firstAnchor.y - startDirection.y * addOffset - btnBounds.height / 2;
196
+ btnElements.push(_jsx(BtnAdd, { indexes: [0], x: firstAddX, y: firstAddY }));
197
+ for (let index = 0; index < anchorPoints.length - 1; index++) {
198
+ const current = anchorPoints[index];
199
+ const next = anchorPoints[index + 1];
200
+ const midX = (current.x + next.x) / 2;
201
+ const midY = (current.y + next.y) / 2;
202
+ const midAddX = midX - btnBounds.width / 2;
203
+ const midAddY = midY - btnBounds.height / 2;
204
+ btnElements.push(_jsx(BtnAdd, { indexes: [index + 1], x: midAddX, y: midAddY }));
205
+ }
206
+ const lastAnchor = anchorPoints[anchorPoints.length - 1];
207
+ const lastAddX = lastAnchor.x + endDirection.x * addOffset - btnBounds.width / 2;
208
+ const lastAddY = lastAnchor.y + endDirection.y * addOffset - btnBounds.height / 2;
209
+ btnElements.push(_jsx(BtnAdd, { indexes: [layoutCount], x: lastAddX, y: lastAddY }));
210
+ }
211
+ return (_jsxs(FlexLayout, { id: "infographic-container", flexDirection: "column", justifyContent: "center", alignItems: "center", children: [titleContent, _jsxs(Group, { children: [_jsx(Arrow, { colorPrimary: colorPrimary, colorShadow: colorShadow }), _jsx(ItemsGroup, { children: itemElements }), _jsx(BtnsGroup, { children: btnElements })] })] }));
212
+ };
213
+ return ListZigzag;
214
+ };
215
+ const ArrowDown = ({ colorPrimary = '#17CA2C', colorShadow = '#737373', }) => {
216
+ const colorPrimaryDark = tinycolor(colorPrimary).darken(20).toHexString();
217
+ return (_jsxs(Group, { width: ARROW_WIDTH, height: ARROW_HEIGHT_DOWN, children: [_jsx("path", { d: "M228.864 159.446C230.266 159.446 231.623 158.768 232.689 157.535L274.263 110.162L265.717 102.923L227.311 148.082C225.977 149.623 224.281 150.47 222.529 150.47H175.404L182.03 158.367C182.795 159.445 182.795 159.446 183.734 159.446H228.864Z", fill: colorShadow }), _jsx("path", { d: "M462.869 234.92C464.271 234.92 465.628 234.242 466.695 233.01L508.268 185.636L499.722 178.397L461.316 223.557C459.983 225.098 458.287 225.945 456.534 225.945H409.409L416.035 233.841C416.8 234.92 416.8 234.92 417.74 234.92H462.869Z", fill: colorShadow }), _jsx("path", { d: "M697.005 330C698.783 330 700 328.82 700 327.001V256.638C700 254.857 697.848 253.965 696.591 255.225L693.409 258.411V320.402C693.409 322.058 692.069 323.401 690.414 323.401H630.718L627.536 326.587C626.278 327.847 627.169 330 628.947 330H697.005Z", fill: colorShadow }), _jsx("path", { d: "M689.642 321.89C690.744 321.89 691.638 320.995 691.638 319.891V250.743C691.638 248.962 689.488 248.07 688.23 249.329L662.647 274.947L520.987 153.863C519.541 152.627 517.703 151.948 515.802 151.948H469.518C470.236 151.949 470.956 152.206 471.53 152.729L498.163 176.978L498.13 177.018L639.84 297.784L619.174 318.477C617.916 319.737 618.807 321.89 620.586 321.89H689.642Z", fill: colorPrimary }), _jsx("path", { d: "M429.279 198.995L467.208 153.03C468.3 151.716 470.268 151.579 471.531 152.729L498.163 176.978L460.69 221.107C459.173 222.894 456.946 223.924 454.6 223.924H408.473C409.366 223.924 410.252 223.527 410.845 222.764L429.279 198.995Z", fill: colorPrimaryDark }), _jsx("path", { d: "M408.473 223.924H408.314L408.318 223.92C408.369 223.922 408.421 223.924 408.473 223.924Z", fill: colorPrimaryDark }), _jsx("path", { d: "M406.524 223.203C407.826 224.318 409.796 224.116 410.845 222.761L429.279 198.932L287.411 77.8866C285.964 76.6523 284.125 75.9742 282.223 75.9742H234.606L234.625 75.9907C235.429 75.9118 236.263 76.1557 236.915 76.7378L263.662 100.621L263.546 100.758L406.524 223.203Z", fill: colorPrimary }), _jsx("path", { d: "M236.914 76.7386C235.651 75.6097 233.707 75.7513 232.621 77.0513L194.557 123.104L175.644 146.821C175.076 147.535 174.25 147.917 173.409 147.947L173.407 147.95H219.923C222.271 147.95 224.499 146.915 226.017 145.122L263.645 100.649L236.914 76.7386Z", fill: colorPrimaryDark }), _jsx("path", { d: "M175.648 146.816C174.589 148.145 172.637 148.329 171.348 147.221L4.09334 3.51697C2.68586 2.30767 3.54106 0 5.39671 0H47.5805C49.4864 0 51.3297 0.680433 52.7785 1.91877L194.557 123.104L175.648 146.816Z", fill: colorPrimary })] }));
218
+ };
219
+ const ArrowUp = ({ colorPrimary = '#17CA2C', colorShadow = '#737373', }) => {
220
+ const colorPrimaryDark = tinycolor(colorPrimary).darken(20).toHexString();
221
+ return (_jsxs(Group, { width: ARROW_WIDTH, height: ARROW_HEIGHT_UP, children: [_jsx("path", { d: "M19.0526 324L12.6762 329.482C11.2703 330.691 12.1234 333 13.976 333H56.1578C58.058 333 59.896 332.321 61.3413 331.085L201.854 210.901L194.249 201.693L54.0527 321.606C52.246 323.151 49.9486 324 47.5732 324H19.0526Z", fill: colorShadow }), _jsx("path", { d: "M234.587 248L241.131 255.922C241.656 256.552 242.382 256.909 243.134 256.983L243.115 257H290.716C292.618 257 294.457 256.322 295.903 255.087L437.091 134.536L429.305 125.5L288.613 245.609C286.805 247.153 284.507 248 282.132 248H234.587Z", fill: colorShadow }), _jsx("path", { d: "M461.123 162.429L475.642 179.918C476.237 180.635 477.092 181.001 477.951 181H524.22C526.121 181 527.959 180.321 529.404 179.085L670.786 58.1578L662.326 49.6809L522.115 169.606C520.309 171.151 518.011 172 515.636 172H469.369L461.123 162.429Z", fill: colorShadow }), _jsx("path", { d: "M687.912 74.8875C690.374 75.9052 693.412 74.1668 693.412 71.1716V11H698.004C699.106 11 700 11.8954 700 13V82.1716C700 83.9534 697.85 84.8457 696.593 83.5858L687.912 74.8875Z", fill: colorShadow }), _jsx("path", { d: "M689.419 0C690.522 0 691.415 0.895432 691.415 2V71.1716C691.415 72.9534 689.265 73.8457 688.008 72.5858L662.433 46.9598L520.819 168.085C519.374 169.321 517.536 170 515.636 170H469.367C470.084 169.999 470.804 169.742 471.379 169.219L498.003 144.961L497.969 144.922L639.634 24.115L618.975 3.41421C617.717 2.15428 618.608 0 620.386 0H689.419Z", fill: colorPrimary }), _jsx("path", { d: "M429.141 122.937L467.058 168.918C468.149 170.232 470.116 170.369 471.378 169.219L498.003 144.961L460.542 100.818C459.025 99.0305 456.798 98 454.453 98H408.341C409.234 98.0001 410.12 98.3968 410.712 99.1606L429.141 122.937Z", fill: colorPrimaryDark }), _jsx("path", { d: "M408.341 98H408.183L408.186 98.004C408.237 98.0013 408.289 98 408.341 98Z", fill: colorPrimaryDark }), _jsx("path", { d: "M406.393 98.721C407.695 97.606 409.664 97.8077 410.712 99.1633L429.141 123L287.318 244.087C285.872 245.322 284.033 246 282.132 246H234.53L234.55 245.983C235.353 246.062 236.187 245.818 236.839 245.236L263.577 221.345L263.461 221.208L406.393 98.721Z", fill: colorPrimary }), _jsx("path", { d: "M236.837 245.235C235.575 246.365 233.631 246.223 232.546 244.922L194.494 198.854L175.588 175.129C175.019 174.415 174.194 174.032 173.353 174.002L173.351 174H219.852C222.199 174 224.427 175.035 225.944 176.829L263.56 221.317L236.837 245.235Z", fill: colorPrimaryDark }), _jsx("path", { d: "M175.593 175.135C174.533 173.805 172.581 173.622 171.291 174.73L4.09013 318.484C2.68329 319.693 3.53868 322 5.394 322H47.5627C49.4695 322 51.3136 321.319 52.7627 320.08L194.494 198.854L175.593 175.135Z", fill: colorPrimary })] }));
222
+ };
223
+ export const ListZigzagDown = createListZigzag({
224
+ arrowHeight: ARROW_HEIGHT_DOWN,
225
+ presetRatios: PRESET_RATIOS_DOWN,
226
+ Arrow: ArrowDown,
227
+ });
228
+ export const ListZigzagUp = createListZigzag({
229
+ arrowHeight: ARROW_HEIGHT_UP,
230
+ presetRatios: PRESET_RATIOS_UP,
231
+ Arrow: ArrowUp,
232
+ });
233
+ registerStructure('list-zigzag-down', {
234
+ component: ListZigzagDown,
235
+ composites: ['title', 'item'],
236
+ });
237
+ registerStructure('list-zigzag-up', {
238
+ component: ListZigzagUp,
239
+ composites: ['title', 'item'],
240
+ });
package/esm/index.d.ts CHANGED
@@ -4,7 +4,7 @@ export { getItemProps, getThemeColors } from './designs/utils';
4
4
  export { BrushSelect, ClickSelect, DblClickEditText, DragElement, HotkeyHistory, Interaction, SelectHighlight, ZoomWheel, } from './editor/interactions';
5
5
  export { EditBar, Plugin, ResizeElement } from './editor/plugins';
6
6
  export { Defs, Ellipse, Fragment, Group, Path, Polygon, Rect, Text, cloneElement, createFragment, createLayout, getCombinedBounds, getElementBounds, getElementsBounds, jsx, jsxDEV, jsxs, renderSVG, } from './jsx';
7
- export { getFont, getFonts, getPalette, getPaletteColor, registerFont, registerPalette, registerPattern, setDefaultFont, } from './renderer';
7
+ export { getFont, getFonts, getPalette, getPalettes, getPaletteColor, registerFont, registerPalette, registerPattern, setDefaultFont, } from './renderer';
8
8
  export { loadSVGResource, registerResourceLoader } from './resource';
9
9
  export { Infographic } from './runtime';
10
10
  export { parseSyntax } from './syntax';
package/esm/index.js CHANGED
@@ -5,7 +5,7 @@ export { getItemProps, getThemeColors } from './designs/utils';
5
5
  export { BrushSelect, ClickSelect, DblClickEditText, DragElement, HotkeyHistory, Interaction, SelectHighlight, ZoomWheel, } from './editor/interactions';
6
6
  export { EditBar, Plugin, ResizeElement } from './editor/plugins';
7
7
  export { Defs, Ellipse, Fragment, Group, Path, Polygon, Rect, Text, cloneElement, createFragment, createLayout, getCombinedBounds, getElementBounds, getElementsBounds, jsx, jsxDEV, jsxs, renderSVG, } from './jsx';
8
- export { getFont, getFonts, getPalette, getPaletteColor, registerFont, registerPalette, registerPattern, setDefaultFont, } from './renderer';
8
+ export { getFont, getFonts, getPalette, getPalettes, getPaletteColor, registerFont, registerPalette, registerPattern, setDefaultFont, } from './renderer';
9
9
  export { loadSVGResource, registerResourceLoader } from './resource';
10
10
  export { Infographic } from './runtime';
11
11
  export { parseSyntax } from './syntax';
@@ -1,6 +1,3 @@
1
1
  import { ParsedInfographicOptions } from '../../options';
2
- import { ResourceConfig } from '../../resource';
3
- import type { DynamicAttributes } from '../../themes';
4
- import type { IconAttributes, IconElement } from '../../types';
5
- export declare function renderIcon(svg: SVGSVGElement, node: SVGElement, value: string | ResourceConfig | undefined, attrs?: DynamicAttributes<IconAttributes>): IconElement | null;
6
- export declare function renderItemIcon(svg: SVGSVGElement, node: SVGElement, value: string | ResourceConfig | undefined, options: ParsedInfographicOptions): SVGGElement | null;
2
+ import type { ItemDatum } from '../../types';
3
+ export declare function renderItemIcon(svg: SVGSVGElement, node: SVGElement, datum: ItemDatum, options: ParsedInfographicOptions): SVGGElement | null;
@@ -1,13 +1,8 @@
1
1
  import { loadResource } from '../../resource';
2
2
  import { createIconElement, getAttributes } from '../../utils';
3
3
  import { parseDynamicAttributes } from '../utils';
4
- export function renderIcon(svg, node, value, attrs = {}) {
5
- if (!value)
6
- return null;
7
- const parsedAttrs = parseDynamicAttributes(node, attrs);
8
- return createIcon(svg, node, value, parsedAttrs);
9
- }
10
- export function renderItemIcon(svg, node, value, options) {
4
+ export function renderItemIcon(svg, node, datum, options) {
5
+ const value = datum.icon;
11
6
  if (!value)
12
7
  return null;
13
8
  const { themeConfig } = options;
@@ -15,11 +10,11 @@ export function renderItemIcon(svg, node, value, options) {
15
10
  ...themeConfig.item?.icon,
16
11
  };
17
12
  const parsedAttrs = parseDynamicAttributes(node, attrs);
18
- return createIcon(svg, node, value, parsedAttrs);
13
+ return createIcon(svg, node, value, parsedAttrs, datum);
19
14
  }
20
- function createIcon(svg, node, value, attrs) {
15
+ function createIcon(svg, node, value, attrs, datum) {
21
16
  // load async
22
- loadResource(svg, 'icon', value);
17
+ loadResource(svg, 'icon', value, datum);
23
18
  return createIconElement(value, {
24
19
  ...getAttributes(node, [
25
20
  'id',
@@ -1,3 +1,4 @@
1
1
  import { type ResourceConfig } from '../../resource';
2
- import type { IllusElement } from '../../types';
3
- export declare function renderIllus(svg: SVGSVGElement, node: SVGElement, value: string | ResourceConfig | undefined): IllusElement | null;
2
+ import type { IllusElement, ItemDatum } from '../../types';
3
+ export declare function renderIllus(svg: SVGSVGElement, node: SVGElement, value: string | ResourceConfig | undefined, datum?: ItemDatum): IllusElement | null;
4
+ export declare function renderItemIllus(svg: SVGSVGElement, node: SVGElement, datum: ItemDatum): SVGGElement | null;
@@ -1,6 +1,6 @@
1
1
  import { getResourceHref, getResourceId, loadResource, parseResourceConfig, } from '../../resource';
2
2
  import { createElement, getAttributes, getOrCreateDefs, removeAttributes, uuid, } from '../../utils';
3
- export function renderIllus(svg, node, value) {
3
+ export function renderIllus(svg, node, value, datum) {
4
4
  if (!value)
5
5
  return null;
6
6
  const config = parseResourceConfig(value);
@@ -8,7 +8,7 @@ export function renderIllus(svg, node, value) {
8
8
  return null;
9
9
  const id = getResourceId(config);
10
10
  const clipPathId = createClipPath(svg, node, id);
11
- loadResource(svg, 'illus', config);
11
+ loadResource(svg, 'illus', config, datum);
12
12
  const { data, color } = config;
13
13
  return createIllusElement(id, {
14
14
  ...parseIllusBounds(node),
@@ -16,6 +16,10 @@ export function renderIllus(svg, node, value) {
16
16
  ...(color ? { color } : {}),
17
17
  }, data);
18
18
  }
19
+ export function renderItemIllus(svg, node, datum) {
20
+ const value = datum.illus;
21
+ return renderIllus(svg, node, value, datum);
22
+ }
19
23
  function createClipPath(svg, node, id) {
20
24
  const clipPathId = `clip-${id}-${uuid()}`;
21
25
  if (svg.querySelector(`#${clipPathId}`)) {
@@ -1,8 +1,8 @@
1
1
  export { renderBackground } from './background';
2
2
  export { renderBaseElement } from './base';
3
3
  export { renderButtonsGroup } from './button';
4
- export { renderIcon, renderItemIcon } from './icon';
5
- export { renderIllus } from './illus';
4
+ export { renderItemIcon } from './icon';
5
+ export { renderIllus, renderItemIllus } from './illus';
6
6
  export { renderShape, renderStaticShape } from './shape';
7
7
  export { renderSVG } from './svg';
8
8
  export { renderItemText, renderStaticText, renderText } from './text';
@@ -1,8 +1,8 @@
1
1
  export { renderBackground } from './background';
2
2
  export { renderBaseElement } from './base';
3
3
  export { renderButtonsGroup } from './button';
4
- export { renderIcon, renderItemIcon } from './icon';
5
- export { renderIllus } from './illus';
4
+ export { renderItemIcon } from './icon';
5
+ export { renderIllus, renderItemIllus } from './illus';
6
6
  export { renderShape, renderStaticShape } from './shape';
7
7
  export { renderSVG } from './svg';
8
8
  export { renderItemText, renderStaticText, renderText } from './text';
@@ -1,4 +1,4 @@
1
1
  import type { Palette } from './types';
2
2
  export declare function registerPalette(name: string, palette: Palette): void;
3
3
  export declare function getPalette(type: string): Palette | undefined;
4
- export declare function getPalettes(): Palette[];
4
+ export declare function getPalettes(): Record<string, Palette>;
@@ -6,5 +6,5 @@ export function getPalette(type) {
6
6
  return PALETTE_REGISTRY.get(type);
7
7
  }
8
8
  export function getPalettes() {
9
- return Array.from(PALETTE_REGISTRY.values());
9
+ return Object.fromEntries(PALETTE_REGISTRY);
10
10
  }
@@ -1,5 +1,5 @@
1
1
  import { getDatumByIndexes, getItemIndexes, isBtnsGroup, isDesc, isGroup, isIllus, isItemDesc, isItemIcon, isItemIllus, isItemLabel, isItemValue, isShape, isShapesGroup, isText, isTitle, parsePadding, setAttributes, setSVGPadding, } from '../utils';
2
- import { renderBackground, renderBaseElement, renderButtonsGroup, renderIllus, renderItemIcon, renderItemText, renderShape, renderStaticShape, renderStaticText, renderSVG, renderText, } from './composites';
2
+ import { renderBackground, renderBaseElement, renderButtonsGroup, renderIllus, renderItemIcon, renderItemIllus, renderItemText, renderShape, renderStaticShape, renderStaticText, renderSVG, renderText, } from './composites';
3
3
  import { loadFonts } from './fonts';
4
4
  const upsert = (original, modified) => {
5
5
  if (original === modified)
@@ -88,16 +88,19 @@ function fill(svg, options) {
88
88
  if (element.dataset.elementType?.startsWith('item-')) {
89
89
  const indexes = getItemIndexes(element.dataset.indexes || '0');
90
90
  const itemType = element.dataset.elementType.replace('item-', '');
91
+ const datum = getDatumByIndexes(data, indexes);
91
92
  if (isItemLabel(element) || isItemDesc(element) || isItemValue(element)) {
92
93
  const modified = renderItemText(itemType, element, options);
93
94
  return upsert(element, modified);
94
95
  }
96
+ if (!datum)
97
+ return;
95
98
  if (isItemIllus(element)) {
96
- const modified = renderIllus(svg, element, getDatumByIndexes(data, indexes)?.illus);
99
+ const modified = renderItemIllus(svg, element, datum);
97
100
  return upsert(element, modified);
98
101
  }
99
102
  if (isItemIcon(element)) {
100
- const modified = renderItemIcon(svg, element, getDatumByIndexes(data, indexes)?.icon, options);
103
+ const modified = renderItemIcon(svg, element, datum, options);
101
104
  return upsert(element, modified);
102
105
  }
103
106
  }
@@ -1,6 +1,7 @@
1
+ import type { ItemDatum } from '../types';
1
2
  import type { ResourceConfig, ResourceScene } from './types';
2
3
  /**
3
4
  * load resource into svg defs
4
5
  * @returns resource ref id
5
6
  */
6
- export declare function loadResource(svg: SVGSVGElement | null, scene: ResourceScene, config: string | ResourceConfig): Promise<string | null>;
7
+ export declare function loadResource(svg: SVGSVGElement | null, scene: ResourceScene, config: string | ResourceConfig, datum?: ItemDatum): Promise<string | null>;
@@ -2,37 +2,47 @@ import { getOrCreateDefs } from '../utils';
2
2
  import { loadImageBase64Resource, loadRemoteResource, loadSearchResource, loadSVGResource, } from './loaders';
3
3
  import { getCustomResourceLoader } from './registry';
4
4
  import { getResourceId, parseResourceConfig } from './utils';
5
- async function getResource(scene, config) {
5
+ async function getResource(scene, config, datum) {
6
6
  const cfg = parseResourceConfig(config);
7
7
  if (!cfg)
8
8
  return null;
9
9
  cfg.scene || (cfg.scene = scene);
10
10
  const { source, data, format, encoding } = cfg;
11
- if (source === 'inline') {
12
- const isDataURI = data.startsWith('data:');
13
- if (format === 'svg' && encoding === 'raw') {
14
- return loadSVGResource(data);
11
+ let resource = null;
12
+ try {
13
+ if (source === 'inline') {
14
+ const isDataURI = data.startsWith('data:');
15
+ if (format === 'svg' && encoding === 'raw') {
16
+ resource = loadSVGResource(data);
17
+ }
18
+ else if (format === 'svg' && isDataURI) {
19
+ resource = await loadImageBase64Resource(data);
20
+ }
21
+ else if (isDataURI || format === 'image') {
22
+ resource = await loadImageBase64Resource(data);
23
+ }
24
+ else {
25
+ resource = loadSVGResource(data);
26
+ }
15
27
  }
16
- if (format === 'svg' && isDataURI) {
17
- return await loadImageBase64Resource(data);
28
+ else if (source === 'remote') {
29
+ resource = await loadRemoteResource(data, format);
18
30
  }
19
- if (isDataURI || format === 'image') {
20
- return await loadImageBase64Resource(data);
31
+ else if (source === 'search') {
32
+ resource = await loadSearchResource(data, format);
33
+ }
34
+ else {
35
+ const customLoader = getCustomResourceLoader();
36
+ if (customLoader)
37
+ resource = await customLoader(cfg);
21
38
  }
22
- return loadSVGResource(data);
23
- }
24
- else if (source === 'remote') {
25
- return await loadRemoteResource(data, format);
26
- }
27
- else if (source === 'search') {
28
- return await loadSearchResource(data, format);
29
39
  }
30
- else {
31
- const customLoader = getCustomResourceLoader();
32
- if (customLoader)
33
- return await customLoader(cfg);
40
+ catch {
41
+ resource = null;
34
42
  }
35
- return null;
43
+ if (resource)
44
+ return resource;
45
+ return await loadSearchResource(getFallbackQuery(cfg, scene, datum), format);
36
46
  }
37
47
  const RESOURCE_MAP = new Map();
38
48
  const RESOURCE_LOAD_MAP = new WeakMap();
@@ -40,7 +50,7 @@ const RESOURCE_LOAD_MAP = new WeakMap();
40
50
  * load resource into svg defs
41
51
  * @returns resource ref id
42
52
  */
43
- export async function loadResource(svg, scene, config) {
53
+ export async function loadResource(svg, scene, config, datum) {
44
54
  if (!svg)
45
55
  return null;
46
56
  const cfg = parseResourceConfig(config);
@@ -49,7 +59,7 @@ export async function loadResource(svg, scene, config) {
49
59
  const id = getResourceId(cfg);
50
60
  const resource = RESOURCE_MAP.has(id)
51
61
  ? RESOURCE_MAP.get(id) || null
52
- : await getResource(scene, cfg);
62
+ : await getResource(scene, cfg, datum);
53
63
  if (!resource)
54
64
  return null;
55
65
  if (!RESOURCE_LOAD_MAP.has(svg))
@@ -63,3 +73,25 @@ export async function loadResource(svg, scene, config) {
63
73
  map.set(id, resource);
64
74
  return id;
65
75
  }
76
+ function getFallbackQuery(cfg, scene, datum) {
77
+ const defaultQuery = scene === 'illus' ? 'illustration' : 'icon';
78
+ const datumQuery = normalizeQuery(datum?.label) || normalizeQuery(datum?.desc);
79
+ if (datumQuery)
80
+ return datumQuery;
81
+ const data = normalizeQuery(cfg.data);
82
+ if (!data)
83
+ return defaultQuery;
84
+ if (cfg.source === 'inline')
85
+ return defaultQuery;
86
+ if (data.startsWith('data:'))
87
+ return defaultQuery;
88
+ if (data.startsWith('<svg') || data.startsWith('<symbol'))
89
+ return defaultQuery;
90
+ return data;
91
+ }
92
+ function normalizeQuery(value) {
93
+ if (typeof value !== 'string')
94
+ return null;
95
+ const trimmed = value.trim();
96
+ return trimmed ? trimmed : null;
97
+ }