@antv/infographic 0.2.14 → 0.2.16

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 (101) hide show
  1. package/README.md +39 -5
  2. package/README.zh-CN.md +39 -5
  3. package/dist/infographic.min.js +168 -166
  4. package/dist/infographic.min.js.map +1 -1
  5. package/esm/designs/structures/index.d.ts +1 -0
  6. package/esm/designs/structures/index.js +1 -0
  7. package/esm/designs/structures/relation-dagre-flow.js +4 -139
  8. package/esm/designs/structures/sequence-interaction.d.ts +54 -0
  9. package/esm/designs/structures/sequence-interaction.js +461 -0
  10. package/esm/designs/structures/sequence-timeline.d.ts +1 -0
  11. package/esm/designs/structures/sequence-timeline.js +4 -2
  12. package/esm/designs/utils/geometry.d.ts +44 -0
  13. package/esm/designs/utils/geometry.js +244 -0
  14. package/esm/designs/utils/index.d.ts +1 -0
  15. package/esm/designs/utils/index.js +1 -0
  16. package/esm/editor/managers/sync-registry.d.ts +2 -1
  17. package/esm/editor/types/editor.d.ts +2 -1
  18. package/esm/editor/types/sync.d.ts +2 -1
  19. package/esm/editor/utils/object.js +46 -39
  20. package/esm/exporter/png.js +2 -2
  21. package/esm/exporter/svg.js +9 -1
  22. package/esm/exporter/types.d.ts +10 -0
  23. package/esm/options/types.d.ts +6 -0
  24. package/esm/runtime/Infographic.js +20 -7
  25. package/esm/syntax/index.js +40 -20
  26. package/esm/syntax/parser.js +80 -3
  27. package/esm/syntax/relations.js +26 -2
  28. package/esm/syntax/schema.js +1 -0
  29. package/esm/templates/built-in.js +5 -4
  30. package/esm/templates/sequence-interaction.d.ts +2 -0
  31. package/esm/templates/sequence-interaction.js +76 -0
  32. package/esm/types/data.d.ts +1 -0
  33. package/esm/utils/index.d.ts +1 -0
  34. package/esm/utils/index.js +1 -0
  35. package/esm/utils/measure-text.js +31 -3
  36. package/esm/utils/types.d.ts +16 -0
  37. package/esm/utils/types.js +12 -0
  38. package/esm/version.d.ts +1 -1
  39. package/esm/version.js +1 -1
  40. package/lib/designs/structures/index.d.ts +1 -0
  41. package/lib/designs/structures/index.js +1 -0
  42. package/lib/designs/structures/relation-dagre-flow.js +5 -140
  43. package/lib/designs/structures/sequence-interaction.d.ts +54 -0
  44. package/lib/designs/structures/sequence-interaction.js +465 -0
  45. package/lib/designs/structures/sequence-timeline.d.ts +1 -0
  46. package/lib/designs/structures/sequence-timeline.js +4 -2
  47. package/lib/designs/utils/geometry.d.ts +44 -0
  48. package/lib/designs/utils/geometry.js +256 -0
  49. package/lib/designs/utils/index.d.ts +1 -0
  50. package/lib/designs/utils/index.js +1 -0
  51. package/lib/editor/managers/sync-registry.d.ts +2 -1
  52. package/lib/editor/types/editor.d.ts +2 -1
  53. package/lib/editor/types/sync.d.ts +2 -1
  54. package/lib/editor/utils/object.js +45 -38
  55. package/lib/exporter/png.js +2 -2
  56. package/lib/exporter/svg.js +9 -1
  57. package/lib/exporter/types.d.ts +10 -0
  58. package/lib/options/types.d.ts +6 -0
  59. package/lib/runtime/Infographic.js +19 -6
  60. package/lib/syntax/index.js +40 -20
  61. package/lib/syntax/parser.js +80 -3
  62. package/lib/syntax/relations.js +26 -2
  63. package/lib/syntax/schema.js +1 -0
  64. package/lib/templates/built-in.js +5 -4
  65. package/lib/templates/sequence-interaction.d.ts +2 -0
  66. package/lib/templates/sequence-interaction.js +79 -0
  67. package/lib/types/data.d.ts +1 -0
  68. package/lib/utils/index.d.ts +1 -0
  69. package/lib/utils/index.js +1 -0
  70. package/lib/utils/measure-text.js +30 -2
  71. package/lib/utils/types.d.ts +16 -0
  72. package/lib/utils/types.js +13 -0
  73. package/lib/version.d.ts +1 -1
  74. package/lib/version.js +1 -1
  75. package/package.json +1 -1
  76. package/src/designs/structures/index.ts +1 -0
  77. package/src/designs/structures/relation-dagre-flow.tsx +14 -178
  78. package/src/designs/structures/sequence-interaction.tsx +931 -0
  79. package/src/designs/structures/sequence-timeline.tsx +18 -15
  80. package/src/designs/utils/geometry.tsx +315 -0
  81. package/src/designs/utils/index.ts +1 -0
  82. package/src/editor/managers/sync-registry.ts +2 -1
  83. package/src/editor/types/editor.ts +2 -1
  84. package/src/editor/types/sync.ts +3 -1
  85. package/src/editor/utils/object.ts +50 -40
  86. package/src/exporter/png.ts +3 -2
  87. package/src/exporter/svg.ts +14 -1
  88. package/src/exporter/types.ts +10 -0
  89. package/src/options/types.ts +7 -0
  90. package/src/runtime/Infographic.tsx +27 -17
  91. package/src/syntax/index.ts +51 -18
  92. package/src/syntax/parser.ts +101 -3
  93. package/src/syntax/relations.ts +29 -2
  94. package/src/syntax/schema.ts +1 -0
  95. package/src/templates/built-in.ts +4 -2
  96. package/src/templates/sequence-interaction.ts +101 -0
  97. package/src/types/data.ts +1 -0
  98. package/src/utils/index.ts +1 -0
  99. package/src/utils/measure-text.ts +35 -3
  100. package/src/utils/types.ts +61 -0
  101. package/src/version.ts +1 -1
@@ -44,6 +44,81 @@ function parseKeyValue(raw) {
44
44
  }
45
45
  return { key: text, value: undefined };
46
46
  }
47
+ function isUnsafeObjectKey(key) {
48
+ return key === '__proto__' || key === 'constructor' || key === 'prototype';
49
+ }
50
+ function assignObjectEntry(parent, rawKey, node, line, errors) {
51
+ if (!rawKey.includes('.')) {
52
+ if (isUnsafeObjectKey(rawKey)) {
53
+ errors.push({
54
+ path: rawKey,
55
+ line,
56
+ code: 'bad_syntax',
57
+ message: `Invalid key part: ${rawKey}`,
58
+ raw: rawKey,
59
+ });
60
+ return null;
61
+ }
62
+ parent.entries[rawKey] = node;
63
+ return { parent, key: rawKey };
64
+ }
65
+ const parts = rawKey.split('.');
66
+ if (parts.some((part) => !part)) {
67
+ errors.push({
68
+ path: rawKey,
69
+ line,
70
+ code: 'bad_syntax',
71
+ message: 'Invalid dotted key path.',
72
+ raw: rawKey,
73
+ });
74
+ return null;
75
+ }
76
+ let current = parent;
77
+ for (let index = 0; index < parts.length - 1; index += 1) {
78
+ const part = parts[index];
79
+ if (isUnsafeObjectKey(part)) {
80
+ errors.push({
81
+ path: rawKey,
82
+ line,
83
+ code: 'bad_syntax',
84
+ message: `Invalid key part in dotted path: ${part}`,
85
+ raw: rawKey,
86
+ });
87
+ return null;
88
+ }
89
+ const existing = current.entries[part];
90
+ if (!existing) {
91
+ const container = createObjectNode(line);
92
+ current.entries[part] = container;
93
+ current = container;
94
+ continue;
95
+ }
96
+ if (existing.kind !== 'object') {
97
+ errors.push({
98
+ path: parts.slice(0, index + 1).join('.'),
99
+ line,
100
+ code: 'bad_syntax',
101
+ message: 'Cannot assign dotted key under a list value.',
102
+ raw: rawKey,
103
+ });
104
+ return null;
105
+ }
106
+ current = existing;
107
+ }
108
+ const finalKey = parts[parts.length - 1];
109
+ if (isUnsafeObjectKey(finalKey)) {
110
+ errors.push({
111
+ path: rawKey,
112
+ line,
113
+ code: 'bad_syntax',
114
+ message: `Invalid key part in dotted path: ${finalKey}`,
115
+ raw: rawKey,
116
+ });
117
+ return null;
118
+ }
119
+ current.entries[finalKey] = node;
120
+ return { parent: current, key: finalKey };
121
+ }
47
122
  function createObjectNode(line, value) {
48
123
  return { kind: 'object', line, value, entries: {} };
49
124
  }
@@ -175,12 +250,14 @@ function parseSyntaxToAst(input) {
175
250
  return;
176
251
  }
177
252
  const node = createObjectNode(lineNumber, parsed.value);
178
- parentNode.entries[parsed.key] = node;
253
+ const assigned = assignObjectEntry(parentNode, parsed.key, node, lineNumber, errors);
254
+ if (!assigned)
255
+ return;
179
256
  stack.push({
180
257
  indent,
181
258
  node,
182
- parent: parentNode,
183
- key: parsed.key,
259
+ parent: assigned.parent,
260
+ key: assigned.key,
184
261
  });
185
262
  });
186
263
  return { ast: root, errors };
@@ -3,8 +3,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.parseRelationsNode = parseRelationsNode;
4
4
  const mapper_1 = require("./mapper");
5
5
  const schema_1 = require("./schema");
6
- const RELATION_TOKEN = /[<>=o.x-]{2,}/;
7
- const ARROW_TOKEN = /[<>=o.x-]{2,}/g;
6
+ const RELATION_TOKEN = /(?:[<>o.x-]{2,}|[<>=]{2,})/;
7
+ const ARROW_TOKEN = /(?:[<>o.x-]{2,}|[<>=]{2,})/g;
8
8
  function normalizeLabel(text) {
9
9
  let label = text.trim();
10
10
  if (!label)
@@ -106,6 +106,30 @@ function readEdge(text, startIndex) {
106
106
  let label = labelPrefix || undefined;
107
107
  let directionToken = arrowToken;
108
108
  let index = arrowEnd;
109
+ // Detect split bidirectional arrow pattern: <- label ->
110
+ {
111
+ const leftHasLeft = directionToken.includes('<');
112
+ const leftHasRight = directionToken.includes('>');
113
+ if (leftHasLeft && !leftHasRight) {
114
+ const lookahead = new RegExp(ARROW_TOKEN.source, 'g');
115
+ lookahead.lastIndex = arrowEnd;
116
+ const rightMatch = lookahead.exec(text);
117
+ if (rightMatch &&
118
+ rightMatch[0].includes('>') &&
119
+ !rightMatch[0].includes('<')) {
120
+ const middleText = text.slice(arrowEnd, rightMatch.index).trim();
121
+ if (middleText) {
122
+ const splitLabel = normalizeLabel(middleText);
123
+ return {
124
+ label: splitLabel || label,
125
+ direction: 'both',
126
+ reverse: false,
127
+ nextIndex: rightMatch.index + rightMatch[0].length,
128
+ };
129
+ }
130
+ }
131
+ }
132
+ }
109
133
  index = skipSpaces(text, index);
110
134
  if (text[index] === '|') {
111
135
  const pipeEnd = text.indexOf('|', index + 1);
@@ -53,6 +53,7 @@ exports.RelationSchema = object({
53
53
  direction: enumOf(['forward', 'both', 'none']),
54
54
  showArrow: enumOf(['true', 'false']),
55
55
  arrowType: enumOf(['arrow', 'triangle', 'diamond']),
56
+ lineStyle: enumOf(['solid', 'dashed']),
56
57
  }, { allowUnknown: true });
57
58
  exports.ThemeSchema = object({
58
59
  type: string(),
@@ -8,9 +8,10 @@ const hierarchy_tree_1 = require("./hierarchy-tree");
8
8
  const list_zigzag_1 = require("./list-zigzag");
9
9
  const registry_1 = require("./registry");
10
10
  const relation_dagre_flow_1 = require("./relation-dagre-flow");
11
+ const sequence_interaction_1 = require("./sequence-interaction");
11
12
  const sequence_stairs_1 = require("./sequence-stairs");
12
13
  const word_cloud_1 = require("./word-cloud");
13
- const BUILT_IN_TEMPLATES = Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({ 'compare-hierarchy-left-right-circle-node-pill-badge': {
14
+ const BUILT_IN_TEMPLATES = Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({ 'compare-hierarchy-left-right-circle-node-pill-badge': {
14
15
  design: {
15
16
  structure: {
16
17
  type: 'compare-hierarchy-left-right',
@@ -182,7 +183,7 @@ const BUILT_IN_TEMPLATES = Object.assign(Object.assign(Object.assign(Object.assi
182
183
  }, 'sequence-timeline-plain-text': {
183
184
  design: {
184
185
  title: 'default',
185
- structure: { type: 'sequence-timeline' },
186
+ structure: { type: 'sequence-timeline', showStepLabels: false },
186
187
  items: [{ type: 'plain-text' }],
187
188
  },
188
189
  }, 'sequence-timeline-rounded-rect-node': {
@@ -200,7 +201,7 @@ const BUILT_IN_TEMPLATES = Object.assign(Object.assign(Object.assign(Object.assi
200
201
  }, 'sequence-timeline-simple': {
201
202
  design: {
202
203
  title: 'default',
203
- structure: { type: 'sequence-timeline', gap: 20 },
204
+ structure: { type: 'sequence-timeline', gap: 20, showStepLabels: false },
204
205
  items: [{ type: 'simple', positionV: 'middle' }],
205
206
  },
206
207
  }, 'sequence-cylinders-3d-simple': {
@@ -650,7 +651,7 @@ const BUILT_IN_TEMPLATES = Object.assign(Object.assign(Object.assign(Object.assi
650
651
  },
651
652
  ],
652
653
  },
653
- } }, chart_pie_1.chartPieTemplates), compare_quadrant_1.compareQuadrantTemplates), hierarchy_tree_1.hierarchyTreeTemplates), hierarchy_mindmap_1.hierarchyMindmapTemplates), sequence_stairs_1.sequenceStairsTemplates), word_cloud_1.wordCloudTemplate), list_zigzag_1.listZigzagTemplates), relation_dagre_flow_1.relationDagreFlowTemplates), hierarchy_structure_1.hierarchyStructureTemplates);
654
+ } }, chart_pie_1.chartPieTemplates), compare_quadrant_1.compareQuadrantTemplates), hierarchy_tree_1.hierarchyTreeTemplates), hierarchy_mindmap_1.hierarchyMindmapTemplates), sequence_stairs_1.sequenceStairsTemplates), word_cloud_1.wordCloudTemplate), list_zigzag_1.listZigzagTemplates), relation_dagre_flow_1.relationDagreFlowTemplates), sequence_interaction_1.sequenceInteractionTemplates), hierarchy_structure_1.hierarchyStructureTemplates);
654
655
  Object.entries(BUILT_IN_TEMPLATES).forEach(([name, options]) => {
655
656
  (0, registry_1.registerTemplate)(name, options);
656
657
  });
@@ -0,0 +1,2 @@
1
+ import type { TemplateOptions } from './types';
2
+ export declare const sequenceInteractionTemplates: Record<string, TemplateOptions>;
@@ -0,0 +1,79 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.sequenceInteractionTemplates = void 0;
4
+ // 多样化的节点样式
5
+ const items = {
6
+ 'badge-card': {
7
+ type: 'badge-card',
8
+ width: 160,
9
+ height: 60,
10
+ },
11
+ 'compact-card': {
12
+ type: 'compact-card',
13
+ width: 180,
14
+ height: 60,
15
+ },
16
+ 'capsule-item': {
17
+ type: 'capsule-item',
18
+ width: 150,
19
+ height: 60,
20
+ },
21
+ 'rounded-rect-node': {
22
+ type: 'rounded-rect-node',
23
+ width: 140,
24
+ height: 60,
25
+ },
26
+ };
27
+ // 基础结构属性
28
+ const baseStructureAttrs = {
29
+ type: 'sequence-interaction',
30
+ showLaneHeader: true,
31
+ arrowType: 'triangle',
32
+ };
33
+ // 箭头样式配置
34
+ const arrowStyles = {
35
+ default: {},
36
+ dashed: {
37
+ edgeStyle: 'dashed',
38
+ },
39
+ animated: {
40
+ edgeStyle: 'dashed',
41
+ animated: true,
42
+ },
43
+ };
44
+ // 结构布局配置
45
+ const structures = {
46
+ // 默认:带生命线
47
+ default: Object.assign(Object.assign({}, baseStructureAttrs), { showLifeline: true, nodeGap: 40 }),
48
+ // 紧凑:更小间距
49
+ compact: Object.assign(Object.assign({}, baseStructureAttrs), { showLifeline: true, nodeGap: 20 }),
50
+ // 宽松:更大间距
51
+ wide: Object.assign(Object.assign({}, baseStructureAttrs), { showLifeline: true, nodeGap: 60 }),
52
+ };
53
+ exports.sequenceInteractionTemplates = {};
54
+ // 排除某些不合适的组合
55
+ const omit = [
56
+ // 后续如果有不合适的可以排除掉
57
+ ];
58
+ Object.entries(structures).forEach(([strKey, strAttrs]) => {
59
+ Object.entries(arrowStyles).forEach(([arrowKey, arrowAttrs]) => {
60
+ Object.entries(items).forEach(([itemKey, itemAttrs]) => {
61
+ const parts = [strKey];
62
+ if (arrowKey !== 'default') {
63
+ parts.push(arrowKey);
64
+ }
65
+ parts.push(itemKey);
66
+ const appendix = parts.join('-');
67
+ if (omit.includes(appendix))
68
+ return;
69
+ const templateKey = `sequence-interaction-${appendix}`;
70
+ exports.sequenceInteractionTemplates[templateKey] = {
71
+ design: {
72
+ title: 'default',
73
+ structure: Object.assign(Object.assign({}, strAttrs), arrowAttrs),
74
+ item: itemAttrs,
75
+ },
76
+ };
77
+ });
78
+ });
79
+ });
@@ -49,6 +49,7 @@ export interface RelationEdgeDatum extends BaseDatum {
49
49
  direction?: 'forward' | 'both' | 'none';
50
50
  showArrow?: boolean;
51
51
  arrowType?: 'arrow' | 'triangle' | 'diamond';
52
+ lineStyle?: 'solid' | 'dashed';
52
53
  }
53
54
  /**
54
55
  * 统计型数据项
@@ -17,5 +17,6 @@ export * from './recognizer';
17
17
  export * from './style';
18
18
  export * from './svg';
19
19
  export * from './text';
20
+ export * from './types';
20
21
  export * from './uuid';
21
22
  export * from './viewbox';
@@ -33,5 +33,6 @@ __exportStar(require("./recognizer"), exports);
33
33
  __exportStar(require("./style"), exports);
34
34
  __exportStar(require("./svg"), exports);
35
35
  __exportStar(require("./text"), exports);
36
+ __exportStar(require("./types"), exports);
36
37
  __exportStar(require("./uuid"), exports);
37
38
  __exportStar(require("./viewbox"), exports);
@@ -6,15 +6,42 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.setFontExtendFactor = void 0;
7
7
  exports.measureText = measureText;
8
8
  const measury_1 = require("measury");
9
+ const _851tegakizatsu_Regular_1 = __importDefault(require("measury/fonts/851tegakizatsu-Regular"));
9
10
  const AlibabaPuHuiTi_Regular_1 = __importDefault(require("measury/fonts/AlibabaPuHuiTi-Regular"));
11
+ const Arial_Regular_1 = __importDefault(require("measury/fonts/Arial-Regular"));
12
+ const LXGWWenKai_Regular_1 = __importDefault(require("measury/fonts/LXGWWenKai-Regular"));
13
+ const SourceHanSans_Regular_1 = __importDefault(require("measury/fonts/SourceHanSans-Regular"));
14
+ const SourceHanSerif_Regular_1 = __importDefault(require("measury/fonts/SourceHanSerif-Regular"));
10
15
  const renderer_1 = require("../renderer");
11
16
  const font_1 = require("./font");
12
- let FONT_EXTEND_FACTOR = 1.01;
17
+ let FONT_EXTEND_FACTOR = 1.015;
13
18
  const setFontExtendFactor = (factor) => {
14
19
  FONT_EXTEND_FACTOR = factor;
15
20
  };
16
21
  exports.setFontExtendFactor = setFontExtendFactor;
17
22
  (0, measury_1.registerFont)(AlibabaPuHuiTi_Regular_1.default);
23
+ // Lazy-register extra measury fonts on first use (SSR only needs glyph data).
24
+ const EXTRA_MEASURY_FONTS = {
25
+ '851tegakizatsu': _851tegakizatsu_Regular_1.default,
26
+ Arial: Arial_Regular_1.default,
27
+ 'LXGW WenKai': LXGWWenKai_Regular_1.default,
28
+ 'Source Han Sans': SourceHanSans_Regular_1.default,
29
+ 'Source Han Serif': SourceHanSerif_Regular_1.default,
30
+ };
31
+ const registeredMeasuryFonts = new Set();
32
+ function ensureMeasuryFont(fontFamily) {
33
+ var _a, _b;
34
+ // decodeFontFamily: '"851tegakizatsu", sans-serif' → '851tegakizatsu, sans-serif'
35
+ // split by comma and take the first family name
36
+ const primary = (_b = (_a = (0, font_1.decodeFontFamily)(fontFamily)) === null || _a === void 0 ? void 0 : _a.split(',')[0]) === null || _b === void 0 ? void 0 : _b.trim();
37
+ if (!primary || registeredMeasuryFonts.has(primary))
38
+ return;
39
+ const data = EXTRA_MEASURY_FONTS[primary];
40
+ if (!data)
41
+ return;
42
+ (0, measury_1.registerFont)(data);
43
+ registeredMeasuryFonts.add(primary);
44
+ }
18
45
  let canvasContext = undefined;
19
46
  let measureSpan = null;
20
47
  function getCanvasContext() {
@@ -100,13 +127,14 @@ function measureText(text = '', attrs) {
100
127
  }
101
128
  const { fontFamily = renderer_1.DEFAULT_FONT, fontSize = 14, fontWeight = 'normal', lineHeight = 1.4, } = attrs;
102
129
  const content = text.toString();
130
+ ensureMeasuryFont(fontFamily);
103
131
  const options = {
104
132
  fontFamily,
105
133
  fontSize: parseFloat(fontSize.toString()),
106
134
  fontWeight,
107
135
  lineHeight,
108
136
  };
109
- const fallback = () => (0, measury_1.measureText)(content, options);
137
+ const fallback = () => (0, measury_1.measureText)(content, Object.assign(Object.assign({}, options), { fontFamily: (0, font_1.decodeFontFamily)(fontFamily) }));
110
138
  const metrics = (_a = measureTextInBrowser(content, options)) !== null && _a !== void 0 ? _a : fallback();
111
139
  // 额外添加 1% 宽高
112
140
  return {
@@ -0,0 +1,16 @@
1
+ type Prev = [never, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
2
+ type StopType = string | number | boolean | symbol | undefined | null | ((...args: any[]) => any) | Array<any>;
3
+ type Join<K, P> = K extends string | number ? P extends string | number ? `${K}${'' extends P ? '' : '.'}${P}` : never : never;
4
+ type ValidKey<T> = keyof {
5
+ [K in keyof T as string extends K ? never : number extends K ? never : K]: any;
6
+ };
7
+ /**
8
+ * 递归生成 T 的所有点语法路径 (例如 "design.structure" 或 "data.items")
9
+ * @template T 目标对象类型
10
+ * @template D 递归深度限制,默认 3 层 (足以覆盖大多数配置嵌套)
11
+ */
12
+ export type Path<T, D extends number = 3> = [D] extends [never] ? never : T extends StopType ? never : {
13
+ [K in ValidKey<T>]-?: K extends string | number ? // 生成: 当前路径 K 或 "K + 子路径"
14
+ K | Join<K, Path<NonNullable<T[K]>, Prev[D]>> : never;
15
+ }[ValidKey<T>];
16
+ export {};
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+ // =============================================================================
3
+ // Path Helper Types (路径生成工具类型)
4
+ //
5
+ // 作用:递归提取对象的所有可选路径(点语法),用于 SyncRegistry 等场景的类型安全与补全。
6
+ //
7
+ // [Input]:
8
+ // type Obj = { a: { b: { c: string } }, d: number };
9
+ //
10
+ // [Output]:
11
+ // "a" | "a.b" | "a.b.c" | "d"
12
+ // =============================================================================
13
+ Object.defineProperty(exports, "__esModule", { value: true });
package/lib/version.d.ts CHANGED
@@ -1 +1 @@
1
- export declare const VERSION = "0.2.14";
1
+ export declare const VERSION = "0.2.16";
package/lib/version.js CHANGED
@@ -1,4 +1,4 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.VERSION = void 0;
4
- exports.VERSION = '0.2.14';
4
+ exports.VERSION = '0.2.16';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@antv/infographic",
3
- "version": "0.2.14",
3
+ "version": "0.2.16",
4
4
  "description": "An Infographic Generation and Rendering Framework, bring words to life!",
5
5
  "keywords": [
6
6
  "antv",
@@ -31,6 +31,7 @@ export * from './sequence-cylinders-3d';
31
31
  export * from './sequence-filter-mesh';
32
32
  export * from './sequence-funnel';
33
33
  export * from './sequence-horizontal-zigzag';
34
+ export * from './sequence-interaction';
34
35
  export * from './sequence-mountain';
35
36
  export * from './sequence-pyramid';
36
37
  export * from './sequence-roadmap-vertical';
@@ -1,10 +1,18 @@
1
1
  import { DagreLayout } from '@antv/layout';
2
2
  import type { ComponentType, JSXElement } from '../../jsx';
3
- import { Defs, getElementBounds, Group, Path, Polygon, Text } from '../../jsx';
3
+ import { Defs, getElementBounds, Group, Path, Text } from '../../jsx';
4
4
  import type { ItemDatum, RelationData, RelationEdgeDatum } from '../../types';
5
5
  import { BtnAdd, BtnsGroup, ItemsGroup } from '../components';
6
6
  import { FlexLayout } from '../layouts';
7
- import { getColorPrimary, getPaletteColor, getThemeColors } from '../utils';
7
+ import {
8
+ createArrowElements,
9
+ createRoundedPath,
10
+ createStraightPath,
11
+ getColorPrimary,
12
+ getMidPoint,
13
+ getPaletteColor,
14
+ getThemeColors,
15
+ } from '../utils';
8
16
  import { registerStructure } from './registry';
9
17
  import type { BaseStructureProps } from './types';
10
18
 
@@ -332,183 +340,7 @@ export const RelationDagreFlow: ComponentType<RelationDagreFlowProps> = (
332
340
  : '1s';
333
341
 
334
342
  const straightCornerRadius = edgeCornerRadius;
335
- const createStraightPath = (
336
- points: [number, number][],
337
- dx: number,
338
- dy: number,
339
- ) =>
340
- points
341
- .map(([x, y], index) => {
342
- const prefix = index === 0 ? 'M' : 'L';
343
- return `${prefix} ${x + dx} ${y + dy}`;
344
- })
345
- .join(' ');
346
-
347
- const createRoundedPath = (
348
- points: [number, number][],
349
- radius: number,
350
- dx: number,
351
- dy: number,
352
- ) => {
353
- if (points.length < 2) return '';
354
- const clamp = (value: number, min: number, max: number) =>
355
- Math.min(max, Math.max(min, value));
356
- const toPoint = ([x, y]: [number, number]) => ({
357
- x: x + dx,
358
- y: y + dy,
359
- });
360
- const output: string[] = [];
361
- const first = toPoint(points[0]);
362
- output.push(`M ${first.x} ${first.y}`);
363
-
364
- if (points.length === 2) {
365
- const last = toPoint(points[1]);
366
- output.push(`L ${last.x} ${last.y}`);
367
- return output.join(' ');
368
- }
369
-
370
- for (let i = 1; i < points.length - 1; i += 1) {
371
- const prev = points[i - 1];
372
- const curr = points[i];
373
- const next = points[i + 1];
374
- const v0x = curr[0] - prev[0];
375
- const v0y = curr[1] - prev[1];
376
- const v1x = next[0] - curr[0];
377
- const v1y = next[1] - curr[1];
378
- const d0 = Math.hypot(v0x, v0y);
379
- const d1 = Math.hypot(v1x, v1y);
380
- if (d0 === 0 || d1 === 0) {
381
- const currPoint = toPoint(curr);
382
- output.push(`L ${currPoint.x} ${currPoint.y}`);
383
- continue;
384
- }
385
- const r = clamp(radius, 0, Math.min(d0, d1) / 2);
386
- if (r === 0) {
387
- const currPoint = toPoint(curr);
388
- output.push(`L ${currPoint.x} ${currPoint.y}`);
389
- continue;
390
- }
391
- const u0x = v0x / d0;
392
- const u0y = v0y / d0;
393
- const u1x = v1x / d1;
394
- const u1y = v1y / d1;
395
- const start = toPoint([curr[0] - u0x * r, curr[1] - u0y * r]);
396
- const end = toPoint([curr[0] + u1x * r, curr[1] + u1y * r]);
397
- output.push(`L ${start.x} ${start.y}`);
398
- const currPoint = toPoint(curr);
399
- output.push(`Q ${currPoint.x} ${currPoint.y} ${end.x} ${end.y}`);
400
- }
401
-
402
- const last = toPoint(points[points.length - 1]);
403
- output.push(`L ${last.x} ${last.y}`);
404
- return output.join(' ');
405
- };
406
- const createArrowElements = (
407
- x: number,
408
- y: number,
409
- angle: number,
410
- type: 'arrow' | 'triangle' | 'diamond',
411
- fillColor: string,
412
- ): JSXElement[] => {
413
- const ux = Math.cos(angle);
414
- const uy = Math.sin(angle);
415
- const px = -uy;
416
- const py = ux;
417
- const length = arrowSize;
418
- const halfWidth = arrowSize * 0.55;
419
-
420
- if (type === 'arrow') {
421
- const leftX = x - ux * length + px * halfWidth;
422
- const leftY = y - uy * length + py * halfWidth;
423
- const rightX = x - ux * length - px * halfWidth;
424
- const rightY = y - uy * length - py * halfWidth;
425
- return [
426
- <Path
427
- d={`M ${leftX} ${leftY} L ${x} ${y} L ${rightX} ${rightY}`}
428
- stroke={fillColor}
429
- strokeWidth={Math.max(1.5, edgeWidth)}
430
- strokeLinecap="round"
431
- strokeLinejoin="round"
432
- fill="none"
433
- />,
434
- ];
435
- }
436
343
 
437
- if (type === 'diamond') {
438
- const diamondLength = length * 1.25;
439
- const diamondWidth = halfWidth * 0.75;
440
- const midX = x - ux * diamondLength * 0.5;
441
- const midY = y - uy * diamondLength * 0.5;
442
- const diamondPoints = [
443
- { x, y },
444
- { x: midX + px * diamondWidth, y: midY + py * diamondWidth },
445
- { x: x - ux * diamondLength, y: y - uy * diamondLength },
446
- { x: midX - px * diamondWidth, y: midY - py * diamondWidth },
447
- ];
448
- return [
449
- <Polygon
450
- points={diamondPoints}
451
- fill={fillColor}
452
- stroke={fillColor}
453
- strokeWidth={Math.max(1, edgeWidth * 0.8)}
454
- />,
455
- ];
456
- }
457
-
458
- const trianglePoints = [
459
- { x, y },
460
- {
461
- x: x - ux * length + px * halfWidth,
462
- y: y - uy * length + py * halfWidth,
463
- },
464
- {
465
- x: x - ux * length - px * halfWidth,
466
- y: y - uy * length - py * halfWidth,
467
- },
468
- ];
469
- return [
470
- <Polygon
471
- points={trianglePoints}
472
- fill={fillColor}
473
- stroke={fillColor}
474
- strokeWidth={Math.max(1, edgeWidth * 0.8)}
475
- />,
476
- ];
477
- };
478
- const getMidPoint = (points: [number, number][]) => {
479
- if (points.length === 0) return null;
480
- if (points.length === 1) return points[0];
481
- let total = 0;
482
- const segments: {
483
- length: number;
484
- start: [number, number];
485
- end: [number, number];
486
- }[] = [];
487
- for (let i = 0; i < points.length - 1; i += 1) {
488
- const start = points[i];
489
- const end = points[i + 1];
490
- const length = Math.hypot(end[0] - start[0], end[1] - start[1]);
491
- segments.push({ length, start, end });
492
- total += length;
493
- }
494
- if (total === 0) return points[0];
495
- let target = total / 2;
496
- for (let i = 0; i < segments.length; i += 1) {
497
- const segment = segments[i];
498
- if (target <= segment.length || i === segments.length - 1) {
499
- const ratio =
500
- segment.length === 0
501
- ? 0
502
- : Math.max(0, Math.min(1, target / segment.length));
503
- return [
504
- segment.start[0] + (segment.end[0] - segment.start[0]) * ratio,
505
- segment.start[1] + (segment.end[1] - segment.start[1]) * ratio,
506
- ] as [number, number];
507
- }
508
- target -= segment.length;
509
- }
510
- return points[Math.floor(points.length / 2)];
511
- };
512
344
  const getOrthEdgeEndpoints = (sourceId: string, targetId: string) => {
513
345
  const source = nodeLayoutById.get(sourceId);
514
346
  const target = nodeLayoutById.get(targetId);
@@ -733,6 +565,8 @@ export const RelationDagreFlow: ComponentType<RelationDagreFlowProps> = (
733
565
  angle,
734
566
  edgeArrowType,
735
567
  arrowFill,
568
+ edgeWidth,
569
+ arrowSize,
736
570
  );
737
571
  decorElements.push(...arrowElements);
738
572
  }
@@ -748,6 +582,8 @@ export const RelationDagreFlow: ComponentType<RelationDagreFlowProps> = (
748
582
  angle,
749
583
  edgeArrowType,
750
584
  arrowFill,
585
+ edgeWidth,
586
+ arrowSize,
751
587
  );
752
588
  decorElements.push(...arrowElements);
753
589
  }