@mapcreator/sdk 0.0.9 → 0.0.10

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 (120) hide show
  1. package/dist/{esm/HighlightManager.d.ts → HighlightManager.d.ts} +2 -2
  2. package/dist/{esm/MCMap.d.ts → MCMap.d.ts} +1 -1
  3. package/dist/{esm/PopupManager.d.ts → PopupManager.d.ts} +4 -4
  4. package/dist/{esm/Registry.d.ts → Registry.d.ts} +3 -3
  5. package/dist/{esm/adornments → adornments}/categoricalLegend.d.ts +1 -1
  6. package/dist/{esm/adornments → adornments}/connectedLegend.d.ts +2 -2
  7. package/dist/{esm/adornments → adornments}/customAdornment.d.ts +1 -1
  8. package/dist/{esm/adornments → adornments}/heading.d.ts +1 -1
  9. package/dist/adornments/insetMap.d.ts +3 -0
  10. package/dist/{esm/adornments → adornments}/manualLegend.d.ts +1 -1
  11. package/dist/adornments/northArrow.d.ts +3 -0
  12. package/dist/adornments/scalebar.d.ts +3 -0
  13. package/dist/{esm/constants → constants}/index.d.ts +2 -2
  14. package/dist/{esm/controls → controls}/fullscreenControls.d.ts +1 -1
  15. package/dist/{esm/controls → controls}/geocoderControl.d.ts +1 -1
  16. package/dist/{esm/controls → controls}/geolocationControls.d.ts +1 -1
  17. package/dist/controls/refreshMapControls.d.ts +3 -0
  18. package/dist/controls/webControls.d.ts +4 -0
  19. package/dist/{esm/controls → controls}/zoomControls.d.ts +1 -1
  20. package/dist/index.d.ts +3 -0
  21. package/dist/locales/da_DK/strings.json.d.ts +10 -0
  22. package/dist/locales/de_DE/strings.json.d.ts +10 -0
  23. package/dist/locales/en_GB/strings.json.d.ts +10 -0
  24. package/dist/locales/es_ES/strings.json.d.ts +10 -0
  25. package/dist/locales/fr_FR/strings.json.d.ts +10 -0
  26. package/dist/locales/it_IT/strings.json.d.ts +10 -0
  27. package/dist/locales/nl_NL/strings.json.d.ts +10 -0
  28. package/dist/mapcreator-sdk.js +39590 -0
  29. package/dist/models/area.d.ts +5 -0
  30. package/dist/models/circle.d.ts +5 -0
  31. package/dist/models/dot.d.ts +3 -0
  32. package/dist/models/line.d.ts +4 -0
  33. package/dist/models/marker.d.ts +5 -0
  34. package/dist/models/polygon.d.ts +5 -0
  35. package/dist/{esm/renderAdornments.d.ts → renderAdornments.d.ts} +3 -3
  36. package/dist/{esm/types → types}/index.d.ts +1 -1
  37. package/dist/{esm/types → types}/mapstyle.d.ts +2 -6
  38. package/dist/{esm/utils → utils}/choropleth.d.ts +3 -3
  39. package/dist/{esm/utils → utils}/geolocation.d.ts +1 -1
  40. package/dist/{esm/utils → utils}/graphhopper.d.ts +1 -1
  41. package/dist/{esm/utils → utils}/helpers.d.ts +2 -2
  42. package/dist/{esm/utils → utils}/language.d.ts +1 -1
  43. package/dist/{esm/utils → utils}/models.d.ts +4 -4
  44. package/dist/{esm/utils → utils}/overlays.d.ts +1 -1
  45. package/dist/{esm/utils → utils}/svgHelpers.d.ts +3 -4
  46. package/dist/{esm/utils → utils}/template.d.ts +2 -2
  47. package/dist/{esm/utils → utils}/youtube.d.ts +1 -1
  48. package/package.json +7 -6
  49. package/dist/esm/HighlightManager.js +0 -203
  50. package/dist/esm/MCMap.js +0 -254
  51. package/dist/esm/PopupManager.js +0 -297
  52. package/dist/esm/Registry.js +0 -74
  53. package/dist/esm/adornments/categoricalLegend.js +0 -141
  54. package/dist/esm/adornments/connectedLegend.js +0 -393
  55. package/dist/esm/adornments/customAdornment.js +0 -29
  56. package/dist/esm/adornments/heading.js +0 -71
  57. package/dist/esm/adornments/insetMap.d.ts +0 -3
  58. package/dist/esm/adornments/insetMap.js +0 -351
  59. package/dist/esm/adornments/manualLegend.js +0 -15
  60. package/dist/esm/adornments/northArrow.d.ts +0 -3
  61. package/dist/esm/adornments/northArrow.js +0 -24
  62. package/dist/esm/adornments/scalebar.d.ts +0 -3
  63. package/dist/esm/adornments/scalebar.js +0 -176
  64. package/dist/esm/constants/index.js +0 -53
  65. package/dist/esm/controls/controls.js +0 -7
  66. package/dist/esm/controls/fullscreenControls.js +0 -29
  67. package/dist/esm/controls/geocoderControl.js +0 -202
  68. package/dist/esm/controls/geolocationControls.js +0 -65
  69. package/dist/esm/controls/refreshMapControls.d.ts +0 -3
  70. package/dist/esm/controls/refreshMapControls.js +0 -26
  71. package/dist/esm/controls/webControls.d.ts +0 -4
  72. package/dist/esm/controls/webControls.js +0 -40
  73. package/dist/esm/controls/zoomControls.js +0 -23
  74. package/dist/esm/i18n.js +0 -21
  75. package/dist/esm/index.d.ts +0 -5
  76. package/dist/esm/index.js +0 -5
  77. package/dist/esm/locales/da_DK/strings.json +0 -7
  78. package/dist/esm/locales/de_DE/strings.json +0 -7
  79. package/dist/esm/locales/en_GB/strings.json +0 -7
  80. package/dist/esm/locales/es_ES/strings.json +0 -7
  81. package/dist/esm/locales/fr_FR/strings.json +0 -7
  82. package/dist/esm/locales/it_IT/strings.json +0 -7
  83. package/dist/esm/locales/nl_NL/strings.json +0 -7
  84. package/dist/esm/models/area.d.ts +0 -5
  85. package/dist/esm/models/area.js +0 -165
  86. package/dist/esm/models/circle.d.ts +0 -5
  87. package/dist/esm/models/circle.js +0 -110
  88. package/dist/esm/models/dot.d.ts +0 -3
  89. package/dist/esm/models/dot.js +0 -42
  90. package/dist/esm/models/line.d.ts +0 -4
  91. package/dist/esm/models/line.js +0 -117
  92. package/dist/esm/models/marker.d.ts +0 -5
  93. package/dist/esm/models/marker.js +0 -179
  94. package/dist/esm/models/polygon.d.ts +0 -5
  95. package/dist/esm/models/polygon.js +0 -80
  96. package/dist/esm/renderAdornments.js +0 -129
  97. package/dist/esm/types/geometry.js +0 -1
  98. package/dist/esm/types/index.js +0 -1
  99. package/dist/esm/types/jobObject.js +0 -1
  100. package/dist/esm/types/mapstyle.js +0 -1
  101. package/dist/esm/utils/browser.js +0 -6
  102. package/dist/esm/utils/choropleth.js +0 -110
  103. package/dist/esm/utils/fullscreen.js +0 -40
  104. package/dist/esm/utils/geolocation.js +0 -93
  105. package/dist/esm/utils/graphhopper.js +0 -41
  106. package/dist/esm/utils/helpers.js +0 -116
  107. package/dist/esm/utils/language.js +0 -170
  108. package/dist/esm/utils/models.js +0 -103
  109. package/dist/esm/utils/overlays.js +0 -87
  110. package/dist/esm/utils/scalebar.js +0 -52
  111. package/dist/esm/utils/svgHelpers.js +0 -1512
  112. package/dist/esm/utils/template.js +0 -120
  113. package/dist/esm/utils/youtube.js +0 -64
  114. /package/dist/{esm/controls → controls}/controls.d.ts +0 -0
  115. /package/dist/{esm/i18n.d.ts → i18n.d.ts} +0 -0
  116. /package/dist/{esm/types → types}/geometry.d.ts +0 -0
  117. /package/dist/{esm/types → types}/jobObject.d.ts +0 -0
  118. /package/dist/{esm/utils → utils}/browser.d.ts +0 -0
  119. /package/dist/{esm/utils → utils}/fullscreen.d.ts +0 -0
  120. /package/dist/{esm/utils → utils}/scalebar.d.ts +0 -0
@@ -1,297 +0,0 @@
1
- import { Popup, } from '@mapcreator/maplibre-gl';
2
- import { buildTemplate, closeButtonHtml, cycleButtonsHtml } from '@/utils/template';
3
- import { Registry } from '@/Registry';
4
- import { HighlightManager } from '@/HighlightManager';
5
- export class PopupManager {
6
- map;
7
- popupPosition = 'bottomLeft';
8
- mapContainer;
9
- popupContainer;
10
- feature;
11
- currentFeatureId;
12
- currentModelId;
13
- popupElements = [];
14
- language = 'en';
15
- promoteIdCache = new Map();
16
- publication;
17
- floatingPopup;
18
- registry;
19
- highlightManager;
20
- mode;
21
- restrictMapMovement;
22
- center;
23
- constructor(map, mode) {
24
- this.map = map;
25
- this.mode = mode;
26
- this.mapContainer = this.map.getContainer();
27
- this.popupContainer = document.createElement('div');
28
- this.popupContainer.classList.add('popup-container');
29
- this.map.on('mousemove', e => this.onMouseMove(e));
30
- this.map.on('click', e => this.onClick(e));
31
- }
32
- setJobObject(jobObject) {
33
- this.registry = new Registry(jobObject);
34
- }
35
- setParams(popupPosition, language, restrictMapMovement, center) {
36
- this.popupPosition = popupPosition;
37
- this.language = language;
38
- this.restrictMapMovement = restrictMapMovement;
39
- this.center = center;
40
- }
41
- setPublication(publication) {
42
- this.publication = publication;
43
- }
44
- setpopupElements() {
45
- this.popupElements = this.registry.getPopupElements();
46
- }
47
- setHighlightManager() {
48
- this.highlightManager = new HighlightManager(this.map, this.registry.getPopupElements());
49
- }
50
- onMouseMove(e) {
51
- this.feature = this.getInteractiveFeature(e);
52
- if (this.feature) {
53
- this.map.getCanvas().style.cursor = 'pointer';
54
- }
55
- else {
56
- this.map.getCanvas().style.cursor = '';
57
- }
58
- }
59
- onClick(e) {
60
- this.feature = this.getInteractiveFeature(e);
61
- this.currentModelId = this.feature?.properties?.id;
62
- if (this.feature &&
63
- (!this.mapContainer.contains(this.popupContainer) ||
64
- this.feature?.id !== this.currentFeatureId)) {
65
- this.addPopup(e);
66
- this.highlightManager?.highlight(this.getPopupElementFromFeature(this.feature));
67
- }
68
- else {
69
- this.hidePopup();
70
- this.highlightManager?.highlight(undefined);
71
- }
72
- }
73
- getPopupElementFromFeature(feature) {
74
- return this.popupElements.find(item => item.modelId === feature.properties.id);
75
- }
76
- getInteractiveFeature(e) {
77
- const features = this.map.queryRenderedFeatures(e.point);
78
- return features.find(feature => {
79
- // Overlay interactive feature
80
- if (Object.keys(feature.layer.metadata ?? {}).some(key => key.startsWith('mc-interactivity-template'))) {
81
- return true;
82
- }
83
- // User-created interactive feature
84
- const model = this.registry.getModel(feature);
85
- return !!(model?.popup ?? model?.popupMedia);
86
- });
87
- }
88
- addPopup(e) {
89
- if (!this.feature) {
90
- return;
91
- }
92
- this.floatingPopup?.remove();
93
- const toNumber = Number(this.feature.id);
94
- this.currentFeatureId = isNaN(toNumber) ? this.feature.id : toNumber;
95
- const template = this.getTemplate(this.feature);
96
- if (!template) {
97
- return;
98
- }
99
- if (this.popupPosition === 'mapElement') {
100
- if (this.feature.geometry.type === 'Point') {
101
- this.addFloatingPopup(template, this.feature.geometry.coordinates);
102
- }
103
- else {
104
- const { lng, lat } = this.map.unproject(e.point);
105
- this.addFloatingPopup(template, [lng, lat]);
106
- }
107
- return;
108
- }
109
- this.popupContainer.innerHTML = template;
110
- const currentPopup = this.popupElements.find(popup => popup.modelId === this.currentModelId);
111
- if (currentPopup) {
112
- this.addPopupControls();
113
- }
114
- this.mapContainer.appendChild(this.popupContainer);
115
- }
116
- addFloatingPopup(template, lngLat) {
117
- const anchor = this.restrictMapMovement ? this.getAnchor(lngLat) : undefined;
118
- this.floatingPopup = new Popup({
119
- maxWidth: 'none',
120
- closeButton: false,
121
- offset: 20,
122
- ...(anchor !== undefined && { anchor }),
123
- })
124
- .setLngLat(lngLat)
125
- .setHTML(template)
126
- .addTo(this.map);
127
- }
128
- getAnchor(lngLat) {
129
- const point = this.map.projectWithScaleCorrection(lngLat);
130
- const width = this.map.getContainer().clientWidth;
131
- const height = this.map.getContainer().clientHeight;
132
- let vertical;
133
- let horizontal;
134
- if (point.y < height * 0.33) {
135
- vertical = 'top';
136
- }
137
- else if (point.y > height * 0.66) {
138
- vertical = 'bottom';
139
- }
140
- else {
141
- vertical = 'center';
142
- }
143
- if (point.x < width * 0.33) {
144
- horizontal = 'left';
145
- }
146
- else if (point.x > width * 0.66) {
147
- horizontal = 'right';
148
- }
149
- else {
150
- horizontal = 'center';
151
- }
152
- if (vertical === 'center' && horizontal === 'center') {
153
- return 'bottom';
154
- }
155
- else if (vertical === 'center') {
156
- return horizontal;
157
- }
158
- else if (horizontal === 'center') {
159
- return vertical;
160
- }
161
- return `${vertical}-${horizontal}`;
162
- }
163
- hidePopup() {
164
- if (this.popupContainer) {
165
- this.popupContainer.remove();
166
- this.feature = undefined;
167
- this.currentFeatureId = undefined;
168
- }
169
- if (this.restrictMapMovement && this.center) {
170
- this.map.easeTo({ center: this.center });
171
- }
172
- }
173
- getTemplate(feature) {
174
- const { layer } = feature;
175
- let template;
176
- const model = this.registry.getModel(feature);
177
- const modelTemplate = model?.popup || model?.popupMedia;
178
- if (modelTemplate) {
179
- template = buildTemplate(model.popup, model.popupMedia, model.dataBindings ?? {}, this.mode);
180
- }
181
- else {
182
- const options = [];
183
- if (this.publication) {
184
- options.push(`:${this.publication}-${this.language}`);
185
- options.push(`:${this.publication}-:en`);
186
- }
187
- options.push(`:${this.language}`);
188
- options.push(`:en`);
189
- options.push('');
190
- for (const option of options) {
191
- const layerTemplate = layer.metadata?.[`mc-interactivity-template${option}`];
192
- if (layerTemplate) {
193
- template = this.fillDatalayerTemplate(feature, layerTemplate, option);
194
- break;
195
- }
196
- }
197
- if (template) {
198
- template = `
199
- <div class="popup-scroll-wrapper">
200
- <div class="mc-popup data-layer text-content">${template}</div>
201
- </div>
202
- `;
203
- }
204
- }
205
- return template;
206
- }
207
- htmlToElement(html) {
208
- const template = document.createElement('template');
209
- template.innerHTML = html.trim();
210
- return template.content.firstElementChild;
211
- }
212
- addPopupControls() {
213
- const closeButton = this.htmlToElement(closeButtonHtml);
214
- if (closeButton) {
215
- closeButton.addEventListener('click', () => {
216
- this.hidePopup();
217
- this.highlightManager.highlight(undefined);
218
- });
219
- this.popupContainer.appendChild(closeButton);
220
- }
221
- if (this.popupElements.length < 2) {
222
- return;
223
- }
224
- const cycleButtons = this.htmlToElement(cycleButtonsHtml);
225
- if (cycleButtons) {
226
- cycleButtons.querySelector('.prev')?.addEventListener('click', () => this.cyclePopups(false));
227
- cycleButtons.querySelector('.next')?.addEventListener('click', () => this.cyclePopups());
228
- this.popupContainer.appendChild(cycleButtons);
229
- }
230
- }
231
- fillDatalayerTemplate(feature, html, language) {
232
- const attr = 'data-mention-id';
233
- const dom = new DOMParser().parseFromString(html, 'text/html').body;
234
- for (const el of dom.querySelectorAll(`[${attr}]`)) {
235
- const value = this.getProperty(feature, el.getAttribute(attr), language);
236
- if (value !== undefined) {
237
- el.innerText = value;
238
- }
239
- }
240
- return dom.innerHTML;
241
- }
242
- getProperty(feature, name, language) {
243
- if (!name) {
244
- return undefined;
245
- }
246
- const options = name.endsWith(':en') ? [name.replace(':en', language), name] : [name];
247
- for (const option of options) {
248
- const property = feature.properties[option] ?? this.getVectorProperty(feature, option);
249
- if (property !== undefined) {
250
- return property;
251
- }
252
- }
253
- return undefined;
254
- }
255
- getVectorProperty(feature, name) {
256
- let promoteId = this.promoteIdCache.get(feature.source);
257
- if (promoteId === undefined) {
258
- promoteId = (this.map.getSource(feature.source)?.serialize().promoteId || 'id');
259
- this.promoteIdCache.set(feature.source, promoteId);
260
- }
261
- try {
262
- const id = feature.properties[promoteId];
263
- return feature.layer.metadata.properties[name][id];
264
- }
265
- catch (e) {
266
- return undefined;
267
- }
268
- }
269
- cyclePopups(forward = true) {
270
- const index = this.popupElements?.findIndex(model => model.modelId === this.currentModelId);
271
- if (index !== -1) {
272
- let nextIndex = 0;
273
- if (forward) {
274
- nextIndex = index === this.popupElements.length - 1 ? 0 : index + 1;
275
- }
276
- else {
277
- nextIndex = index === 0 ? this.popupElements.length - 1 : index - 1;
278
- }
279
- const next = this.popupElements?.[nextIndex];
280
- this.highlightManager.highlight(next);
281
- const template = buildTemplate(next.popup, next.popupMedia, next.dataBindings ?? {}, this.mode);
282
- const temp = this.popupContainer;
283
- this.popupContainer.remove();
284
- temp.innerHTML = template;
285
- this.mapContainer.appendChild(temp);
286
- this.currentModelId = next.modelId;
287
- this.addPopupControls();
288
- if (forward) {
289
- this.popupContainer.querySelector('.mc-popup-button.next')?.focus();
290
- }
291
- else {
292
- this.popupContainer.querySelector('.mc-popup-button.prev')?.focus();
293
- }
294
- this.currentFeatureId = undefined;
295
- }
296
- }
297
- }
@@ -1,74 +0,0 @@
1
- const allModelTypes = ['area', 'circle', 'dot', 'line', 'marker', 'polygon'];
2
- export class Registry {
3
- data;
4
- customGroupIds;
5
- constructor(jobObject) {
6
- this.data = {
7
- area: {},
8
- circle: {},
9
- dot: {},
10
- line: {},
11
- marker: {},
12
- polygon: {},
13
- };
14
- for (const modelType of allModelTypes) {
15
- for (const group of jobObject.registry?.models?.[modelType] ?? []) {
16
- this.data[modelType][group.id] = {};
17
- for (const model of group.models) {
18
- // MC-2870 Convert the old format area without multiple vector-source group support to the new format
19
- if (modelType === 'area') {
20
- const area = model;
21
- if (area.featureId === undefined) {
22
- area.featureId = Number(area.id);
23
- area.id = `${area.vectorUrl}-${area.id}`;
24
- }
25
- }
26
- this.data[modelType][group.id][model.id] = model;
27
- }
28
- }
29
- }
30
- const { beforeWaters = [], beforeBoundaries = [], beforeNames = [], beforeNone = [], } = jobObject.registry?.slots ?? {};
31
- this.customGroupIds = [...beforeWaters, ...beforeBoundaries, ...beforeNames, ...beforeNone].map(item => item.groupId);
32
- }
33
- getModel(feature) {
34
- let modelId = String(feature.properties?.id);
35
- const metadata = feature.layer.metadata;
36
- const groupId = metadata?.['mc-group-id'];
37
- const modelType = metadata?.['mc-model-type'];
38
- const prefix = metadata?.['mc-model-id-prefix'];
39
- if (prefix) {
40
- modelId = `${prefix}-${modelId}`;
41
- }
42
- if (groupId === undefined || modelId === undefined || modelType === undefined) {
43
- return undefined;
44
- }
45
- return this.data[modelType]?.[groupId]?.[modelId];
46
- }
47
- getPopupElements() {
48
- const result = [];
49
- const elementTypes = ['circle', 'dot', 'line', 'marker', 'polygon'];
50
- for (const groupId of this.customGroupIds) {
51
- for (const type of elementTypes) {
52
- const groupModels = this.data[type]?.[groupId];
53
- if (groupModels) {
54
- for (const [modelId, model] of Object.entries(groupModels)) {
55
- if (model.popup || model.popupMedia) {
56
- result.push({
57
- groupId,
58
- modelId,
59
- popup: model.popup,
60
- popupMedia: model.popupMedia,
61
- lngLat: model.lngLat,
62
- center: model.center,
63
- radius: model.radius,
64
- anchorPoints: model.anchorPoints,
65
- dataBindings: model.dataBindings,
66
- });
67
- }
68
- }
69
- }
70
- }
71
- }
72
- return result.reverse();
73
- }
74
- }
@@ -1,141 +0,0 @@
1
- import { escapeXML, measureTextBlock } from '@/utils/svgHelpers';
2
- export function getCategoricalLegendSvg(legend, defaultFont) {
3
- const padding = 15;
4
- const swatchSize = 15;
5
- const entryMargin = 20;
6
- const swatchMargin = 10;
7
- const { title = '', titleFontColor = '#000000', titleFont = defaultFont, titleFontSize = 24, entries, entryFontColor = '#000000', entryFont = defaultFont, entryFontSize = 13, entryShape = 'rectangle', layout = 'vertical', background = '#ffffff', showBackground = false, } = legend;
8
- const titleBox = measureTextBlock([title], titleFont, titleFontSize);
9
- const entryBoxes = entries.map(entry => measureTextBlock([entry.label], entryFont, entryFontSize));
10
- const hasTitle = title.trim().length > 0;
11
- let width;
12
- let height;
13
- if (layout === 'vertical') {
14
- width =
15
- Math.max(titleBox.width, ...entryBoxes.map(b => b.width + swatchSize + swatchMargin)) +
16
- padding * 2;
17
- height =
18
- padding * 2 +
19
- (hasTitle ? titleBox.height + entryMargin : 0) +
20
- entryBoxes.reduce((sum, box) => sum + box.height, 0) +
21
- Math.max(entryBoxes.length - 1, 0) * entryMargin;
22
- }
23
- else {
24
- width = Math.max(titleBox.width + padding * 2, padding * 2 +
25
- entryBoxes.reduce((sum, box) => sum + box.width + swatchSize + swatchMargin, 0) +
26
- Math.max(entryBoxes.length - 1, 0) * entryMargin);
27
- height =
28
- padding * 2 +
29
- (hasTitle ? titleBox.height + entryMargin : 0) +
30
- Math.max(0, ...entryBoxes.map(b => b.height));
31
- }
32
- const children = [];
33
- if (showBackground) {
34
- children.push(`
35
- <rect
36
- x="0"
37
- y="0"
38
- rx="10"
39
- ry="10"
40
- width="${width}"
41
- height="${height}"
42
- fill="${background}"
43
- />
44
- `);
45
- }
46
- let x = padding;
47
- let y = padding;
48
- if (hasTitle) {
49
- children.push(`
50
- <text
51
- x="${x}"
52
- y="${y + titleBox.ascent}"
53
- font-family="${titleFont}"
54
- font-size="${titleFontSize}"
55
- fill="${titleFontColor}"
56
- >
57
- ${escapeXML(title)}
58
- </text>
59
- `);
60
- y += titleBox.height + entryMargin;
61
- }
62
- for (let i = 0; i < entries.length; i++) {
63
- const entry = entries[i];
64
- const entryBox = entryBoxes[i];
65
- if (entryShape === 'rectangle') {
66
- children.push(`
67
- <rect
68
- x="${x}"
69
- y="${y + entryBox.height / 2 - swatchSize / 2}"
70
- rx="2"
71
- ry="2"
72
- width="${swatchSize}"
73
- height="${swatchSize}"
74
- fill="${entry.color}"
75
- />
76
- `);
77
- }
78
- else if (entryShape === 'circle') {
79
- children.push(`
80
- <circle
81
- cx="${x + swatchSize / 2}"
82
- cy="${y + entryBox.height / 2}"
83
- r="${swatchSize / 2}"
84
- fill="${entry.color}"
85
- />
86
- `);
87
- }
88
- else if (entryShape === 'line') {
89
- children.push(`
90
- <line
91
- x1="${x}"
92
- y1="${y + entryBox.height / 2}"
93
- x2="${x + swatchSize}"
94
- y2="${y + entryBox.height / 2}"
95
- stroke="${entry.color}"
96
- stroke-width="2"
97
- stroke-linecap="round"
98
- />
99
- `);
100
- }
101
- else if (entryShape === 'icon' && entry.svg.length > 0) {
102
- const svgEl = new DOMParser()
103
- .parseFromString(entry.svg, 'image/svg+xml')
104
- .querySelector('svg');
105
- if (svgEl) {
106
- svgEl.setAttribute('width', String(swatchSize));
107
- svgEl.setAttribute('height', String(swatchSize));
108
- svgEl.setAttribute('transform', `translate(${x}, ${y + entryBox.height / 2 - swatchSize / 2})`);
109
- children.push(svgEl.outerHTML);
110
- }
111
- }
112
- children.push(`
113
- <text
114
- x="${x + swatchSize + swatchMargin}"
115
- y="${y + entryBox.ascent}"
116
- font-family="${entryFont}"
117
- font-size="${entryFontSize}"
118
- fill="${entryFontColor}"
119
- >
120
- ${escapeXML(entry.label)}
121
- </text>
122
- `);
123
- if (layout === 'vertical') {
124
- y += entryBox.height + entryMargin;
125
- }
126
- else {
127
- x += entryBox.width + swatchSize + swatchMargin + entryMargin;
128
- }
129
- }
130
- return `
131
- <svg
132
- xmlns="http://www.w3.org/2000/svg"
133
- width="${width}"
134
- height="${height}"
135
- viewBox="0 0 ${width} ${height}"
136
- style="display: block;"
137
- >
138
- ${children.join('')}
139
- </svg>
140
- `;
141
- }