@antv/infographic 0.2.16 → 0.2.18

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 (131) hide show
  1. package/README.md +1 -1
  2. package/README.zh-CN.md +1 -1
  3. package/dist/infographic.min.js +121 -120
  4. package/dist/infographic.min.js.map +1 -1
  5. package/esm/constants/service.d.ts +1 -1
  6. package/esm/constants/service.js +1 -1
  7. package/esm/designs/structures/chart-line.js +7 -4
  8. package/esm/editor/interactions/dblclick-edit-text.js +3 -3
  9. package/esm/editor/managers/interaction.js +6 -4
  10. package/esm/editor/plugins/components/button.d.ts +2 -1
  11. package/esm/editor/plugins/components/button.js +4 -4
  12. package/esm/editor/plugins/components/color-picker.d.ts +1 -0
  13. package/esm/editor/plugins/components/color-picker.js +3 -3
  14. package/esm/editor/plugins/components/popover.d.ts +3 -1
  15. package/esm/editor/plugins/components/popover.js +29 -9
  16. package/esm/editor/plugins/edit-bar/edit-bar.d.ts +3 -1
  17. package/esm/editor/plugins/edit-bar/edit-bar.js +17 -7
  18. package/esm/editor/plugins/edit-bar/edit-items/align-elements.js +6 -4
  19. package/esm/editor/plugins/edit-bar/edit-items/font-align.js +8 -5
  20. package/esm/editor/plugins/edit-bar/edit-items/font-color.js +7 -4
  21. package/esm/editor/plugins/edit-bar/edit-items/font-family.js +11 -9
  22. package/esm/editor/plugins/edit-bar/edit-items/font-size.js +8 -5
  23. package/esm/editor/plugins/edit-bar/edit-items/icon-color.js +7 -4
  24. package/esm/editor/plugins/edit-bar/edit-items/types.d.ts +5 -1
  25. package/esm/editor/plugins/reset-viewbox.d.ts +4 -1
  26. package/esm/editor/plugins/reset-viewbox.js +12 -6
  27. package/esm/editor/utils/index.d.ts +1 -0
  28. package/esm/editor/utils/index.js +1 -0
  29. package/esm/editor/utils/root.d.ts +3 -0
  30. package/esm/editor/utils/root.js +18 -0
  31. package/esm/exporter/svg.js +229 -3
  32. package/esm/options/parser.js +8 -6
  33. package/esm/options/types.d.ts +3 -3
  34. package/esm/renderer/renderer.js +1 -1
  35. package/esm/resource/loaders/search.js +2 -6
  36. package/esm/runtime/options.js +1 -1
  37. package/esm/syntax/index.js +56 -10
  38. package/esm/syntax/mapper.js +20 -6
  39. package/esm/syntax/parser.js +9 -0
  40. package/esm/syntax/types.d.ts +1 -1
  41. package/esm/templates/registry.d.ts +1 -0
  42. package/esm/templates/registry.js +6 -0
  43. package/esm/templates/utils.d.ts +1 -0
  44. package/esm/templates/utils.js +68 -0
  45. package/esm/themes/built-in.js +3 -0
  46. package/esm/utils/padding.js +1 -1
  47. package/esm/utils/style.d.ts +3 -1
  48. package/esm/utils/style.js +27 -4
  49. package/esm/version.d.ts +1 -1
  50. package/esm/version.js +1 -1
  51. package/lib/constants/service.d.ts +1 -1
  52. package/lib/constants/service.js +1 -1
  53. package/lib/designs/structures/chart-line.js +7 -4
  54. package/lib/editor/interactions/dblclick-edit-text.js +3 -3
  55. package/lib/editor/managers/interaction.js +7 -5
  56. package/lib/editor/plugins/components/button.d.ts +2 -1
  57. package/lib/editor/plugins/components/button.js +4 -4
  58. package/lib/editor/plugins/components/color-picker.d.ts +1 -0
  59. package/lib/editor/plugins/components/color-picker.js +3 -3
  60. package/lib/editor/plugins/components/popover.d.ts +3 -1
  61. package/lib/editor/plugins/components/popover.js +32 -12
  62. package/lib/editor/plugins/edit-bar/edit-bar.d.ts +3 -1
  63. package/lib/editor/plugins/edit-bar/edit-bar.js +17 -7
  64. package/lib/editor/plugins/edit-bar/edit-items/align-elements.js +6 -4
  65. package/lib/editor/plugins/edit-bar/edit-items/font-align.js +8 -5
  66. package/lib/editor/plugins/edit-bar/edit-items/font-color.js +7 -4
  67. package/lib/editor/plugins/edit-bar/edit-items/font-family.js +11 -9
  68. package/lib/editor/plugins/edit-bar/edit-items/font-size.js +8 -5
  69. package/lib/editor/plugins/edit-bar/edit-items/icon-color.js +7 -4
  70. package/lib/editor/plugins/edit-bar/edit-items/types.d.ts +5 -1
  71. package/lib/editor/plugins/reset-viewbox.d.ts +4 -1
  72. package/lib/editor/plugins/reset-viewbox.js +12 -6
  73. package/lib/editor/utils/index.d.ts +1 -0
  74. package/lib/editor/utils/index.js +1 -0
  75. package/lib/editor/utils/root.d.ts +3 -0
  76. package/lib/editor/utils/root.js +22 -0
  77. package/lib/exporter/svg.js +229 -3
  78. package/lib/options/parser.js +7 -5
  79. package/lib/options/types.d.ts +3 -3
  80. package/lib/renderer/renderer.js +1 -1
  81. package/lib/resource/loaders/search.js +2 -6
  82. package/lib/runtime/options.js +1 -1
  83. package/lib/syntax/index.js +56 -10
  84. package/lib/syntax/mapper.js +20 -6
  85. package/lib/syntax/parser.js +9 -0
  86. package/lib/syntax/types.d.ts +1 -1
  87. package/lib/templates/registry.d.ts +1 -0
  88. package/lib/templates/registry.js +7 -0
  89. package/lib/templates/utils.d.ts +1 -0
  90. package/lib/templates/utils.js +71 -0
  91. package/lib/themes/built-in.js +3 -0
  92. package/lib/utils/padding.js +1 -1
  93. package/lib/utils/style.d.ts +3 -1
  94. package/lib/utils/style.js +27 -4
  95. package/lib/version.d.ts +1 -1
  96. package/lib/version.js +1 -1
  97. package/package.json +1 -1
  98. package/src/constants/service.ts +1 -1
  99. package/src/designs/structures/chart-line.tsx +8 -4
  100. package/src/editor/interactions/dblclick-edit-text.ts +3 -2
  101. package/src/editor/managers/interaction.ts +9 -7
  102. package/src/editor/plugins/components/button.ts +5 -2
  103. package/src/editor/plugins/components/color-picker.ts +4 -2
  104. package/src/editor/plugins/components/popover.ts +31 -12
  105. package/src/editor/plugins/edit-bar/edit-bar.ts +26 -11
  106. package/src/editor/plugins/edit-bar/edit-items/align-elements.ts +7 -2
  107. package/src/editor/plugins/edit-bar/edit-items/font-align.ts +8 -3
  108. package/src/editor/plugins/edit-bar/edit-items/font-color.ts +7 -2
  109. package/src/editor/plugins/edit-bar/edit-items/font-family.ts +11 -7
  110. package/src/editor/plugins/edit-bar/edit-items/font-size.ts +8 -3
  111. package/src/editor/plugins/edit-bar/edit-items/icon-color.ts +7 -2
  112. package/src/editor/plugins/edit-bar/edit-items/types.ts +6 -1
  113. package/src/editor/plugins/reset-viewbox.ts +17 -8
  114. package/src/editor/utils/index.ts +1 -0
  115. package/src/editor/utils/root.ts +26 -0
  116. package/src/exporter/svg.ts +274 -3
  117. package/src/options/parser.ts +7 -6
  118. package/src/options/types.ts +3 -3
  119. package/src/renderer/renderer.ts +1 -1
  120. package/src/resource/loaders/search.ts +2 -5
  121. package/src/runtime/options.ts +1 -1
  122. package/src/syntax/index.ts +71 -10
  123. package/src/syntax/mapper.ts +20 -6
  124. package/src/syntax/parser.ts +10 -0
  125. package/src/syntax/types.ts +1 -0
  126. package/src/templates/registry.ts +6 -0
  127. package/src/templates/utils.ts +111 -0
  128. package/src/themes/built-in.ts +4 -0
  129. package/src/utils/padding.ts +1 -1
  130. package/src/utils/style.ts +31 -4
  131. package/src/version.ts +1 -1
@@ -4,8 +4,8 @@ import type { ThemeConfig } from '../themes';
4
4
  import type { Data, Padding, ParsedData } from '../types';
5
5
  import type { Path } from '../utils';
6
6
  export interface InfographicOptions {
7
- /** 容器,可以是选择器或者 HTMLElement */
8
- container?: string | HTMLElement;
7
+ /** 容器,可以是选择器、Element ShadowRoot */
8
+ container?: string | Element | ShadowRoot;
9
9
  /** 宽度 */
10
10
  width?: number | string;
11
11
  /** 高度 */
@@ -34,7 +34,7 @@ export interface InfographicOptions {
34
34
  elements?: ElementProps[];
35
35
  }
36
36
  export interface ParsedInfographicOptions {
37
- container: HTMLElement;
37
+ container: Element | ShadowRoot;
38
38
  width?: number | string;
39
39
  height?: number | string;
40
40
  padding?: Padding;
@@ -50,7 +50,7 @@ class Renderer {
50
50
  });
51
51
  });
52
52
  try {
53
- observer.observe(document, {
53
+ observer.observe(this.options.container, {
54
54
  childList: true,
55
55
  subtree: true,
56
56
  });
@@ -16,7 +16,6 @@ const image_1 = require("./image");
16
16
  const remote_1 = require("./remote");
17
17
  const svg_1 = require("./svg");
18
18
  const queryIcon = (query) => __awaiter(void 0, void 0, void 0, function* () {
19
- var _a;
20
19
  try {
21
20
  const params = new URLSearchParams({ text: query, topK: '1' });
22
21
  const url = `${constants_1.ICON_SERVICE_URL}?${params.toString()}`;
@@ -24,9 +23,9 @@ const queryIcon = (query) => __awaiter(void 0, void 0, void 0, function* () {
24
23
  if (!response.ok)
25
24
  return null;
26
25
  const result = yield response.json();
27
- if (!(result === null || result === void 0 ? void 0 : result.status) || !Array.isArray((_a = result.data) === null || _a === void 0 ? void 0 : _a.data))
26
+ if (!(result === null || result === void 0 ? void 0 : result.success) || !Array.isArray(result.data))
28
27
  return null;
29
- return result.data.data[0] || null;
28
+ return result.data[0] || null;
30
29
  }
31
30
  catch (error) {
32
31
  console.error(`Failed to query icon for "${query}":`, error);
@@ -58,9 +57,6 @@ function loadSearchResource(query, format) {
58
57
  const svgText = commaIndex >= 0 ? result.slice(commaIndex + 1) : result;
59
58
  return (0, svg_1.loadSVGResource)(svgText);
60
59
  }
61
- if (mimeType === 'image/svg+xml' && format === 'svg' && isBase64) {
62
- return (0, image_1.loadImageBase64Resource)(result);
63
- }
64
60
  return (0, image_1.loadImageBase64Resource)(result);
65
61
  }
66
62
  return (0, remote_1.loadRemoteResource)(result, format);
@@ -19,7 +19,7 @@ const createDefaultInteractions = () => [
19
19
  ];
20
20
  exports.DEFAULT_OPTIONS = {
21
21
  padding: 20,
22
- theme: 'light',
22
+ theme: 'default',
23
23
  themeConfig: {
24
24
  palette: 'antv',
25
25
  },
@@ -16,6 +16,15 @@ const mapper_1 = require("./mapper");
16
16
  const parser_1 = require("./parser");
17
17
  const relations_1 = require("./relations");
18
18
  const schema_1 = require("./schema");
19
+ const ALLOWED_ROOT_KEYS = new Set([
20
+ 'infographic',
21
+ 'template',
22
+ 'design',
23
+ 'data',
24
+ 'theme',
25
+ 'width',
26
+ 'height',
27
+ ]);
19
28
  function normalizeItems(items) {
20
29
  var _a;
21
30
  const seen = new Set();
@@ -36,6 +45,13 @@ function normalizeItems(items) {
36
45
  }
37
46
  return normalized.reverse();
38
47
  }
48
+ function assignMissingNodeIds(items) {
49
+ items.forEach((item) => {
50
+ if (!item.id && item.label) {
51
+ item.id = item.label;
52
+ }
53
+ });
54
+ }
39
55
  function resolveTemplate(node, errors) {
40
56
  if (!node)
41
57
  return undefined;
@@ -49,12 +65,42 @@ function resolveTemplate(node, errors) {
49
65
  }
50
66
  return undefined;
51
67
  }
68
+ function inferTemplateFromBareFirstLine(entries, warnings) {
69
+ if ('infographic' in entries || 'template' in entries) {
70
+ return undefined;
71
+ }
72
+ const [firstEntry] = Object.entries(entries);
73
+ if (!firstEntry)
74
+ return undefined;
75
+ const [key, node] = firstEntry;
76
+ if (ALLOWED_ROOT_KEYS.has(key) || node.kind !== 'object') {
77
+ return undefined;
78
+ }
79
+ if (node.value !== undefined || Object.keys(node.entries).length > 0) {
80
+ return undefined;
81
+ }
82
+ warnings.push({
83
+ path: 'template',
84
+ line: node.line,
85
+ code: 'implicit_template',
86
+ message: 'Inferred template from a bare first line. Prefix it with "infographic" or "template" to make the syntax explicit.',
87
+ raw: key,
88
+ });
89
+ return {
90
+ template: key,
91
+ inferredKey: key,
92
+ };
93
+ }
52
94
  function parseSyntax(input) {
53
95
  var _a;
54
96
  const { ast, errors } = (0, parser_1.parseSyntaxToAst)(input);
55
97
  const warnings = [];
56
98
  const options = {};
57
99
  const mergedEntries = Object.assign({}, ast.entries);
100
+ const inferredTemplate = inferTemplateFromBareFirstLine(ast.entries, warnings);
101
+ if (inferredTemplate) {
102
+ delete mergedEntries[inferredTemplate.inferredKey];
103
+ }
58
104
  const infographicNode = ast.entries.infographic;
59
105
  let templateFromInfographic;
60
106
  if (infographicNode && infographicNode.kind === 'object') {
@@ -65,17 +111,8 @@ function parseSyntax(input) {
65
111
  mergedEntries[key] = value;
66
112
  });
67
113
  }
68
- const allowedRootKeys = new Set([
69
- 'infographic',
70
- 'template',
71
- 'design',
72
- 'data',
73
- 'theme',
74
- 'width',
75
- 'height',
76
- ]);
77
114
  Object.keys(mergedEntries).forEach((key) => {
78
- if (!allowedRootKeys.has(key)) {
115
+ if (!ALLOWED_ROOT_KEYS.has(key)) {
79
116
  errors.push({
80
117
  path: key,
81
118
  line: mergedEntries[key].line,
@@ -92,6 +129,9 @@ function parseSyntax(input) {
92
129
  if (!options.template && templateFromInfographic) {
93
130
  options.template = templateFromInfographic;
94
131
  }
132
+ if (!options.template && inferredTemplate) {
133
+ options.template = inferredTemplate.template;
134
+ }
95
135
  const designNode = mergedEntries.design;
96
136
  if (designNode) {
97
137
  const design = (0, mapper_1.mapWithSchema)(designNode, schema_1.DesignSchema, 'design', errors);
@@ -114,6 +154,12 @@ function parseSyntax(input) {
114
154
  const parsed = (0, relations_1.parseRelationsNode)(relationsNode, errors, 'data.relations');
115
155
  if (parsed.relations.length > 0 || parsed.items.length > 0) {
116
156
  const current = ((_a = options.data) !== null && _a !== void 0 ? _a : {});
157
+ if (Array.isArray(current.items)) {
158
+ assignMissingNodeIds(current.items);
159
+ }
160
+ if (Array.isArray(current.nodes)) {
161
+ assignMissingNodeIds(current.nodes);
162
+ }
117
163
  // 优先使用已存在的数据列表 (sequences, lists, etc.)
118
164
  const dataKeys = Object.keys(schema_1.DataSchema.fields).filter((key) => key !== 'items' && key !== 'relations');
119
165
  let hasStructuredData = false;
@@ -12,11 +12,20 @@ function createValueNode(value, line) {
12
12
  }
13
13
  const HEX_COLOR_PATTERN = /^(#[0-9a-f]{8}|#[0-9a-f]{6}|#[0-9a-f]{4}|#[0-9a-f]{3})/i;
14
14
  const FUNCTION_COLOR_PATTERN = /^((?:rgb|rgba|hsl|hsla)\([^)]*\))/i;
15
+ function normalizeBooleanLiteral(value) {
16
+ const trimmed = value.trim();
17
+ if (/^true$/i.test(trimmed))
18
+ return 'true';
19
+ if (/^false$/i.test(trimmed))
20
+ return 'false';
21
+ return undefined;
22
+ }
15
23
  function parseScalar(value) {
16
24
  const trimmed = value.trim();
17
- if (trimmed === 'true')
25
+ const normalizedBoolean = normalizeBooleanLiteral(trimmed);
26
+ if (normalizedBoolean === 'true')
18
27
  return true;
19
- if (trimmed === 'false')
28
+ if (normalizedBoolean === 'false')
20
29
  return false;
21
30
  if (/^-?\d+(\.\d+)?$/.test(trimmed))
22
31
  return parseFloat(trimmed);
@@ -182,11 +191,12 @@ function mapWithSchema(node, schema, path, errors) {
182
191
  addError(errors, node, path, 'schema_mismatch', 'Expected boolean value.');
183
192
  return undefined;
184
193
  }
185
- if (value !== 'true' && value !== 'false') {
194
+ const normalizedBoolean = normalizeBooleanLiteral(value);
195
+ if (!normalizedBoolean) {
186
196
  addError(errors, node, path, 'invalid_value', 'Invalid boolean value.', value);
187
197
  return undefined;
188
198
  }
189
- return value === 'true';
199
+ return normalizedBoolean === 'true';
190
200
  }
191
201
  case 'enum': {
192
202
  const value = readScalar(node);
@@ -194,11 +204,15 @@ function mapWithSchema(node, schema, path, errors) {
194
204
  addError(errors, node, path, 'schema_mismatch', 'Expected enum value.');
195
205
  return undefined;
196
206
  }
197
- if (!schema.values.includes(value)) {
207
+ const normalizedBoolean = normalizeBooleanLiteral(value);
208
+ const enumValue = normalizedBoolean && schema.values.includes(normalizedBoolean)
209
+ ? normalizedBoolean
210
+ : value;
211
+ if (!schema.values.includes(enumValue)) {
198
212
  addError(errors, node, path, 'invalid_value', 'Invalid enum value.', value);
199
213
  return undefined;
200
214
  }
201
- return value;
215
+ return enumValue;
202
216
  }
203
217
  case 'array': {
204
218
  if (node.kind === 'array') {
@@ -27,6 +27,13 @@ function getIndentInfo(line) {
27
27
  function stripComments(content) {
28
28
  return content.trimEnd();
29
29
  }
30
+ function isCommentLine(content) {
31
+ const trimmed = content.trimStart();
32
+ return trimmed.startsWith('#') || trimmed.startsWith('//');
33
+ }
34
+ function isCodeFenceLine(content) {
35
+ return /^```[\w-]*\s*$/.test(content.trim());
36
+ }
30
37
  function looksLikeRelationExpression(text) {
31
38
  return /[<>=o.x-]{2,}/.test(text);
32
39
  }
@@ -137,6 +144,8 @@ function parseSyntaxToAst(input) {
137
144
  if (!line.trim())
138
145
  return;
139
146
  const { indent, content } = getIndentInfo(line);
147
+ if (isCommentLine(content) || isCodeFenceLine(content))
148
+ return;
140
149
  const stripped = stripComments(content);
141
150
  if (!stripped.trim())
142
151
  return;
@@ -16,7 +16,7 @@ export interface ArrayNode {
16
16
  line: number;
17
17
  items: SyntaxNode[];
18
18
  }
19
- export type SyntaxErrorCode = 'unknown_key' | 'schema_mismatch' | 'invalid_value' | 'bad_indent' | 'bad_list' | 'bad_syntax';
19
+ export type SyntaxErrorCode = 'implicit_template' | 'unknown_key' | 'schema_mismatch' | 'invalid_value' | 'bad_indent' | 'bad_list' | 'bad_syntax';
20
20
  export interface SyntaxError {
21
21
  path: string;
22
22
  line: number;
@@ -1,4 +1,5 @@
1
1
  import type { TemplateOptions } from './types';
2
2
  export declare function registerTemplate(type: string, template: TemplateOptions): void;
3
+ export declare function resolveTemplateKey(type: string): string | undefined;
3
4
  export declare function getTemplate(type: string): TemplateOptions | undefined;
4
5
  export declare function getTemplates(): string[];
@@ -1,12 +1,19 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.registerTemplate = registerTemplate;
4
+ exports.resolveTemplateKey = resolveTemplateKey;
4
5
  exports.getTemplate = getTemplate;
5
6
  exports.getTemplates = getTemplates;
7
+ const utils_1 = require("./utils");
6
8
  const TEMPLATE_REGISTRY = new Map();
7
9
  function registerTemplate(type, template) {
8
10
  TEMPLATE_REGISTRY.set(type, template);
9
11
  }
12
+ function resolveTemplateKey(type) {
13
+ if (TEMPLATE_REGISTRY.has(type))
14
+ return type;
15
+ return (0, utils_1.findClosestTemplateKey)(type, TEMPLATE_REGISTRY.keys());
16
+ }
10
17
  function getTemplate(type) {
11
18
  return TEMPLATE_REGISTRY.get(type);
12
19
  }
@@ -0,0 +1 @@
1
+ export declare function findClosestTemplateKey(type: string, keys: Iterable<string>): string | undefined;
@@ -0,0 +1,71 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.findClosestTemplateKey = findClosestTemplateKey;
4
+ function normalizeTemplateKey(type) {
5
+ return type
6
+ .trim()
7
+ .toLowerCase()
8
+ .replace(/[_\s]+/g, '-')
9
+ .replace(/-+/g, '-');
10
+ }
11
+ function getLevenshteinDistance(source, target) {
12
+ if (source === target)
13
+ return 0;
14
+ if (!source.length)
15
+ return target.length;
16
+ if (!target.length)
17
+ return source.length;
18
+ const previous = Array.from({ length: target.length + 1 }, (_, index) => index);
19
+ const current = new Array(target.length + 1);
20
+ for (let sourceIndex = 1; sourceIndex <= source.length; sourceIndex += 1) {
21
+ current[0] = sourceIndex;
22
+ const sourceCode = source.charCodeAt(sourceIndex - 1);
23
+ for (let targetIndex = 1; targetIndex <= target.length; targetIndex += 1) {
24
+ const replaceCost = sourceCode === target.charCodeAt(targetIndex - 1) ? 0 : 1;
25
+ current[targetIndex] = Math.min(previous[targetIndex] + 1, current[targetIndex - 1] + 1, previous[targetIndex - 1] + replaceCost);
26
+ }
27
+ for (let index = 0; index < current.length; index += 1) {
28
+ previous[index] = current[index];
29
+ }
30
+ }
31
+ return previous[target.length];
32
+ }
33
+ function getCommonPrefixLength(source, target) {
34
+ const limit = Math.min(source.length, target.length);
35
+ let index = 0;
36
+ while (index < limit &&
37
+ source.charCodeAt(index) === target.charCodeAt(index)) {
38
+ index += 1;
39
+ }
40
+ return index;
41
+ }
42
+ function isBetterMatch(bestMatch, bestDistance, bestPrefixLength, candidateKey, candidateDistance, candidatePrefixLength) {
43
+ return (candidateDistance < bestDistance ||
44
+ (candidateDistance === bestDistance &&
45
+ candidatePrefixLength > bestPrefixLength) ||
46
+ (candidateDistance === bestDistance &&
47
+ candidatePrefixLength === bestPrefixLength &&
48
+ (!bestMatch || candidateKey < bestMatch)));
49
+ }
50
+ function findClosestTemplateKey(type, keys) {
51
+ const normalizedType = normalizeTemplateKey(type);
52
+ if (!normalizedType)
53
+ return undefined;
54
+ let bestMatch;
55
+ let bestDistance = Number.POSITIVE_INFINITY;
56
+ let bestPrefixLength = -1;
57
+ for (const key of keys) {
58
+ const normalizedKey = normalizeTemplateKey(key);
59
+ if (normalizedKey === normalizedType) {
60
+ return key;
61
+ }
62
+ const distance = getLevenshteinDistance(normalizedType, normalizedKey);
63
+ const prefixLength = getCommonPrefixLength(normalizedType, normalizedKey);
64
+ if (isBetterMatch(bestMatch, bestDistance, bestPrefixLength, key, distance, prefixLength)) {
65
+ bestMatch = key;
66
+ bestDistance = distance;
67
+ bestPrefixLength = prefixLength;
68
+ }
69
+ }
70
+ return bestMatch;
71
+ }
@@ -1,6 +1,9 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const registry_1 = require("./registry");
4
+ (0, registry_1.registerTheme)('light', {
5
+ colorBg: '#ffffff',
6
+ });
4
7
  (0, registry_1.registerTheme)('dark', {
5
8
  colorBg: '#1F1F1F',
6
9
  base: {
@@ -31,7 +31,7 @@ function setSVGPadding(svg, padding) {
31
31
  setSVGPaddingInNode(svg, padding);
32
32
  }
33
33
  else {
34
- if (document.contains(svg)) {
34
+ if (svg.isConnected) {
35
35
  setSVGPaddingInBrowser(svg, padding);
36
36
  }
37
37
  else {
@@ -1 +1,3 @@
1
- export declare function injectStyleOnce(id: string, styles: string): void;
1
+ type StyleTarget = Document | ShadowRoot | Node | null | undefined;
2
+ export declare function injectStyleOnce(id: string, styles: string, target?: StyleTarget): void;
3
+ export {};
@@ -1,11 +1,34 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.injectStyleOnce = injectStyleOnce;
4
- function injectStyleOnce(id, styles) {
5
- if (document.getElementById(id))
4
+ function resolveStyleRoot(target) {
5
+ if (!target)
6
+ return document;
7
+ if (target instanceof Document || target instanceof ShadowRoot)
8
+ return target;
9
+ if (!target.isConnected)
10
+ return document;
11
+ const root = target.getRootNode();
12
+ return root instanceof ShadowRoot ? root : document;
13
+ }
14
+ function hasStyle(root, id) {
15
+ if (root instanceof Document)
16
+ return Boolean(root.getElementById(id));
17
+ return Boolean(root.querySelector(`#${id}`));
18
+ }
19
+ function injectStyleOnce(id, styles, target) {
20
+ var _a;
21
+ const root = resolveStyleRoot(target);
22
+ if (hasStyle(root, id))
6
23
  return;
7
- const style = document.createElement('style');
24
+ const doc = root instanceof Document ? root : ((_a = root.ownerDocument) !== null && _a !== void 0 ? _a : document);
25
+ const style = doc.createElement('style');
8
26
  style.id = id;
9
27
  style.textContent = styles;
10
- document.head.appendChild(style);
28
+ if (root instanceof Document) {
29
+ root.head.appendChild(style);
30
+ }
31
+ else {
32
+ root.appendChild(style);
33
+ }
11
34
  }
package/lib/version.d.ts CHANGED
@@ -1 +1 @@
1
- export declare const VERSION = "0.2.16";
1
+ export declare const VERSION = "0.2.18";
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.16';
4
+ exports.VERSION = '0.2.18';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@antv/infographic",
3
- "version": "0.2.16",
3
+ "version": "0.2.18",
4
4
  "description": "An Infographic Generation and Rendering Framework, bring words to life!",
5
5
  "keywords": [
6
6
  "antv",
@@ -1 +1 @@
1
- export const ICON_SERVICE_URL = 'https://www.weavefox.cn/api/open/v1/icon';
1
+ export const ICON_SERVICE_URL = 'https://www.weavefox.cn/api/v1/infographic/icon';
@@ -18,6 +18,9 @@ export interface ChartLineProps extends BaseStructureProps {
18
18
  valueFormatter?: (value: number, datum: ItemDatum) => string;
19
19
  }
20
20
 
21
+ const ITEM_POSITION_H = 'center' as const;
22
+ const ITEM_POSITION_V = 'normal' as const;
23
+
21
24
  export const ChartLine: ComponentType<ChartLineProps> = (props) => {
22
25
  const {
23
26
  Title,
@@ -55,8 +58,8 @@ export const ChartLine: ComponentType<ChartLineProps> = (props) => {
55
58
  indexes: [0],
56
59
  datum: items[0],
57
60
  data,
58
- positionH: 'center',
59
- positionV: 'normal',
61
+ positionH: ITEM_POSITION_H,
62
+ positionV: ITEM_POSITION_V,
60
63
  };
61
64
  const sampleBounds = getElementBounds(<Item {...itemProps} />);
62
65
  const labelWidth = sampleBounds.width;
@@ -121,6 +124,8 @@ export const ChartLine: ComponentType<ChartLineProps> = (props) => {
121
124
  const tickElements: JSXElement[] = [];
122
125
 
123
126
  const ticksY = scaleY.ticks(6);
127
+ const formatTickY = scaleY.tickFormat(6);
128
+
124
129
  ticksY.forEach((tick) => {
125
130
  const yPos = chartOriginY + scaleY(tick);
126
131
  gridElements.push(
@@ -145,7 +150,7 @@ export const ChartLine: ComponentType<ChartLineProps> = (props) => {
145
150
  fontSize={12}
146
151
  fill={axisColor}
147
152
  >
148
- {Number.isInteger(tick) ? tick.toString() : tick.toFixed(1)}
153
+ {formatTickY(tick)}
149
154
  </Text>,
150
155
  );
151
156
  });
@@ -394,7 +399,6 @@ export const ChartLine: ComponentType<ChartLineProps> = (props) => {
394
399
  </linearGradient>
395
400
  <linearGradient id={gradientAreaId} x1="0%" y1="0%" x2="100%" y2="0%">
396
401
  {areaStops}
397
- <stop offset="100%" stopColor={colorPrimary} stopOpacity="0.04" />
398
402
  </linearGradient>
399
403
  </Defs>
400
404
  <Group>{gridElements}</Group>
@@ -92,7 +92,7 @@ function editText(text: TextElement, options?: EditTextOptions) {
92
92
  const entity = getTextEntity(text);
93
93
  if (!entity) return;
94
94
 
95
- ensureEditorStyles();
95
+ ensureEditorStyles(entity);
96
96
  new InlineTextEditor(entity, options).start();
97
97
  }
98
98
 
@@ -240,7 +240,7 @@ class InlineTextEditor {
240
240
  }
241
241
  }
242
242
 
243
- function ensureEditorStyles() {
243
+ function ensureEditorStyles(target?: Node) {
244
244
  injectStyleOnce(
245
245
  EDITOR_STYLE_ID,
246
246
  `
@@ -256,5 +256,6 @@ function ensureEditorStyles() {
256
256
  background-color: #b3d4fc;
257
257
  }
258
258
  `,
259
+ target,
259
260
  );
260
261
  }
@@ -16,6 +16,7 @@ import type {
16
16
  SelectionChangePayload,
17
17
  SelectMode,
18
18
  } from '../types';
19
+ import { eventPathContains } from '../utils';
19
20
  import { Extension } from '../utils';
20
21
 
21
22
  export class InteractionManager implements IInteractionManager {
@@ -129,18 +130,19 @@ export class InteractionManager implements IInteractionManager {
129
130
 
130
131
  private handleClick = (event: MouseEvent) => {
131
132
  const doc = this.editor.getDocument();
132
- const target = event.target;
133
+ const path = typeof event.composedPath === 'function' ? event.composedPath() : [];
134
+ const insideInfographic =
135
+ eventPathContains(event, doc) ||
136
+ path.some(
137
+ (node) => node instanceof HTMLElement && isInfographicComponent(node),
138
+ );
133
139
 
134
- if (!target) {
140
+ if (!event.target) {
135
141
  this.deactivate();
136
142
  return;
137
143
  }
138
144
  // 点击画布 SVG 或者标记为组件的元素
139
- if (
140
- doc.contains(target as Node) ||
141
- isInfographicComponent(target as HTMLElement)
142
- )
143
- this.activate();
145
+ if (insideInfographic) this.activate();
144
146
  else this.deactivate();
145
147
  };
146
148
 
@@ -7,6 +7,7 @@ export interface IconButtonProps {
7
7
  icon: Icon;
8
8
  onClick?: () => void;
9
9
  activate?: boolean;
10
+ root?: Node;
10
11
  }
11
12
 
12
13
  export interface IconButtonHandle {
@@ -18,8 +19,9 @@ export const IconButton = ({
18
19
  icon,
19
20
  onClick,
20
21
  activate = false,
22
+ root,
21
23
  }: IconButtonProps): Button => {
22
- ensureIconButtonStyle();
24
+ ensureIconButtonStyle(root);
23
25
 
24
26
  const button = document.createElement('button');
25
27
  button.type = 'button';
@@ -44,7 +46,7 @@ export const IconButton = ({
44
46
  const ICON_BUTTON_CLASS = 'infographic-edit-bar-icon-btn';
45
47
  const ICON_BUTTON_STYLE_ID = 'infographic-edit-bar-icon-btn-style';
46
48
 
47
- function ensureIconButtonStyle() {
49
+ function ensureIconButtonStyle(target?: Node) {
48
50
  injectStyleOnce(
49
51
  ICON_BUTTON_STYLE_ID,
50
52
  `
@@ -73,5 +75,6 @@ function ensureIconButtonStyle() {
73
75
  background-color: #d9d9d9;
74
76
  }
75
77
  `,
78
+ target,
76
79
  );
77
80
  }
@@ -6,6 +6,7 @@ export type ColorPickerProps = {
6
6
  value?: string;
7
7
  swatches?: string[];
8
8
  onChange?: (value: string) => void;
9
+ root?: Node;
9
10
  };
10
11
 
11
12
  export type ColorPickerHandle = {
@@ -66,7 +67,7 @@ export function ColorPicker(
66
67
  throw new Error('ColorPicker can only be used in the browser.');
67
68
  }
68
69
 
69
- ensureColorPickerStyles();
70
+ ensureColorPickerStyles(props.root);
70
71
 
71
72
  const container = document.createElement('div');
72
73
  container.classList.add(COLOR_PICKER_CLASS);
@@ -279,7 +280,7 @@ function createSwitchLabel(text: string): HTMLSpanElement {
279
280
  return span;
280
281
  }
281
282
 
282
- function ensureColorPickerStyles() {
283
+ function ensureColorPickerStyles(target?: Node) {
283
284
  injectStyleOnce(
284
285
  COLOR_PICKER_STYLE_ID,
285
286
  `
@@ -393,5 +394,6 @@ function ensureColorPickerStyles() {
393
394
  color: #ffffff;
394
395
  }
395
396
  `,
397
+ target,
396
398
  );
397
399
  }