@antv/infographic 0.2.14 → 0.2.15

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 (84) hide show
  1. package/README.md +12 -5
  2. package/README.zh-CN.md +12 -5
  3. package/dist/infographic.min.js +155 -153
  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 +440 -0
  10. package/esm/designs/utils/geometry.d.ts +44 -0
  11. package/esm/designs/utils/geometry.js +244 -0
  12. package/esm/designs/utils/index.d.ts +1 -0
  13. package/esm/designs/utils/index.js +1 -0
  14. package/esm/editor/managers/sync-registry.d.ts +2 -1
  15. package/esm/editor/types/editor.d.ts +2 -1
  16. package/esm/editor/types/sync.d.ts +2 -1
  17. package/esm/editor/utils/object.js +46 -39
  18. package/esm/options/types.d.ts +6 -0
  19. package/esm/runtime/Infographic.js +20 -7
  20. package/esm/syntax/index.js +40 -20
  21. package/esm/syntax/relations.js +26 -2
  22. package/esm/syntax/schema.js +1 -0
  23. package/esm/templates/built-in.js +3 -2
  24. package/esm/templates/sequence-interaction.d.ts +2 -0
  25. package/esm/templates/sequence-interaction.js +76 -0
  26. package/esm/types/data.d.ts +1 -0
  27. package/esm/utils/index.d.ts +1 -0
  28. package/esm/utils/index.js +1 -0
  29. package/esm/utils/measure-text.js +31 -3
  30. package/esm/utils/types.d.ts +16 -0
  31. package/esm/utils/types.js +12 -0
  32. package/esm/version.d.ts +1 -1
  33. package/esm/version.js +1 -1
  34. package/lib/designs/structures/index.d.ts +1 -0
  35. package/lib/designs/structures/index.js +1 -0
  36. package/lib/designs/structures/relation-dagre-flow.js +5 -140
  37. package/lib/designs/structures/sequence-interaction.d.ts +54 -0
  38. package/lib/designs/structures/sequence-interaction.js +444 -0
  39. package/lib/designs/utils/geometry.d.ts +44 -0
  40. package/lib/designs/utils/geometry.js +256 -0
  41. package/lib/designs/utils/index.d.ts +1 -0
  42. package/lib/designs/utils/index.js +1 -0
  43. package/lib/editor/managers/sync-registry.d.ts +2 -1
  44. package/lib/editor/types/editor.d.ts +2 -1
  45. package/lib/editor/types/sync.d.ts +2 -1
  46. package/lib/editor/utils/object.js +45 -38
  47. package/lib/options/types.d.ts +6 -0
  48. package/lib/runtime/Infographic.js +19 -6
  49. package/lib/syntax/index.js +40 -20
  50. package/lib/syntax/relations.js +26 -2
  51. package/lib/syntax/schema.js +1 -0
  52. package/lib/templates/built-in.js +3 -2
  53. package/lib/templates/sequence-interaction.d.ts +2 -0
  54. package/lib/templates/sequence-interaction.js +79 -0
  55. package/lib/types/data.d.ts +1 -0
  56. package/lib/utils/index.d.ts +1 -0
  57. package/lib/utils/index.js +1 -0
  58. package/lib/utils/measure-text.js +30 -2
  59. package/lib/utils/types.d.ts +16 -0
  60. package/lib/utils/types.js +13 -0
  61. package/lib/version.d.ts +1 -1
  62. package/lib/version.js +1 -1
  63. package/package.json +1 -1
  64. package/src/designs/structures/index.ts +1 -0
  65. package/src/designs/structures/relation-dagre-flow.tsx +14 -178
  66. package/src/designs/structures/sequence-interaction.tsx +885 -0
  67. package/src/designs/utils/geometry.tsx +315 -0
  68. package/src/designs/utils/index.ts +1 -0
  69. package/src/editor/managers/sync-registry.ts +2 -1
  70. package/src/editor/types/editor.ts +2 -1
  71. package/src/editor/types/sync.ts +3 -1
  72. package/src/editor/utils/object.ts +50 -40
  73. package/src/options/types.ts +7 -0
  74. package/src/runtime/Infographic.tsx +27 -17
  75. package/src/syntax/index.ts +51 -18
  76. package/src/syntax/relations.ts +29 -2
  77. package/src/syntax/schema.ts +1 -0
  78. package/src/templates/built-in.ts +2 -0
  79. package/src/templates/sequence-interaction.ts +101 -0
  80. package/src/types/data.ts +1 -0
  81. package/src/utils/index.ts +1 -0
  82. package/src/utils/measure-text.ts +35 -3
  83. package/src/utils/types.ts +61 -0
  84. package/src/version.ts +1 -1
@@ -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.15";
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.15';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@antv/infographic",
3
- "version": "0.2.14",
3
+ "version": "0.2.15",
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
  }