@memberjunction/core-actions 2.107.0 → 2.109.0

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 (85) hide show
  1. package/dist/custom/ai/find-best-action.action.d.ts +53 -0
  2. package/dist/custom/ai/find-best-action.action.d.ts.map +1 -0
  3. package/dist/custom/ai/find-best-action.action.js +211 -0
  4. package/dist/custom/ai/find-best-action.action.js.map +1 -0
  5. package/dist/custom/ai/find-best-agent.action.d.ts +53 -0
  6. package/dist/custom/ai/find-best-agent.action.d.ts.map +1 -0
  7. package/dist/custom/ai/find-best-agent.action.js +194 -0
  8. package/dist/custom/ai/find-best-agent.action.js.map +1 -0
  9. package/dist/custom/ai/summarize-content.action.d.ts +3 -3
  10. package/dist/custom/ai/summarize-content.action.d.ts.map +1 -1
  11. package/dist/custom/ai/summarize-content.action.js +51 -143
  12. package/dist/custom/ai/summarize-content.action.js.map +1 -1
  13. package/dist/custom/code-execution/execute-code.action.d.ts +61 -0
  14. package/dist/custom/code-execution/execute-code.action.d.ts.map +1 -0
  15. package/dist/custom/code-execution/execute-code.action.js +172 -0
  16. package/dist/custom/code-execution/execute-code.action.js.map +1 -0
  17. package/dist/custom/data/csv-parser.action.js +1 -1
  18. package/dist/custom/data/csv-parser.action.js.map +1 -1
  19. package/dist/custom/data/execute-research-query.action.d.ts +36 -18
  20. package/dist/custom/data/execute-research-query.action.d.ts.map +1 -1
  21. package/dist/custom/data/execute-research-query.action.js +221 -114
  22. package/dist/custom/data/execute-research-query.action.js.map +1 -1
  23. package/dist/custom/data/explore-database-schema.action.d.ts +4 -0
  24. package/dist/custom/data/explore-database-schema.action.d.ts.map +1 -1
  25. package/dist/custom/data/explore-database-schema.action.js +101 -8
  26. package/dist/custom/data/explore-database-schema.action.js.map +1 -1
  27. package/dist/custom/data/get-entity-details.action.d.ts +63 -0
  28. package/dist/custom/data/get-entity-details.action.d.ts.map +1 -0
  29. package/dist/custom/data/get-entity-details.action.js +284 -0
  30. package/dist/custom/data/get-entity-details.action.js.map +1 -0
  31. package/dist/custom/data/get-entity-list.action.d.ts +57 -0
  32. package/dist/custom/data/get-entity-list.action.d.ts.map +1 -0
  33. package/dist/custom/data/get-entity-list.action.js +177 -0
  34. package/dist/custom/data/get-entity-list.action.js.map +1 -0
  35. package/dist/custom/visualization/create-svg-chart.action.d.ts +97 -0
  36. package/dist/custom/visualization/create-svg-chart.action.d.ts.map +1 -0
  37. package/dist/custom/visualization/create-svg-chart.action.js +326 -0
  38. package/dist/custom/visualization/create-svg-chart.action.js.map +1 -0
  39. package/dist/custom/visualization/create-svg-diagram.action.d.ts +151 -0
  40. package/dist/custom/visualization/create-svg-diagram.action.d.ts.map +1 -0
  41. package/dist/custom/visualization/create-svg-diagram.action.js +764 -0
  42. package/dist/custom/visualization/create-svg-diagram.action.js.map +1 -0
  43. package/dist/custom/visualization/create-svg-infographic.action.d.ts +72 -0
  44. package/dist/custom/visualization/create-svg-infographic.action.d.ts.map +1 -0
  45. package/dist/custom/visualization/create-svg-infographic.action.js +343 -0
  46. package/dist/custom/visualization/create-svg-infographic.action.js.map +1 -0
  47. package/dist/custom/visualization/create-svg-network.action.d.ts +106 -0
  48. package/dist/custom/visualization/create-svg-network.action.d.ts.map +1 -0
  49. package/dist/custom/visualization/create-svg-network.action.js +687 -0
  50. package/dist/custom/visualization/create-svg-network.action.js.map +1 -0
  51. package/dist/custom/visualization/create-svg-sketch-diagram.action.d.ts +97 -0
  52. package/dist/custom/visualization/create-svg-sketch-diagram.action.d.ts.map +1 -0
  53. package/dist/custom/visualization/create-svg-sketch-diagram.action.js +730 -0
  54. package/dist/custom/visualization/create-svg-sketch-diagram.action.js.map +1 -0
  55. package/dist/custom/visualization/create-svg-word-cloud.action.d.ts +94 -0
  56. package/dist/custom/visualization/create-svg-word-cloud.action.d.ts.map +1 -0
  57. package/dist/custom/visualization/create-svg-word-cloud.action.js +497 -0
  58. package/dist/custom/visualization/create-svg-word-cloud.action.js.map +1 -0
  59. package/dist/custom/visualization/shared/svg-theming.d.ts +91 -0
  60. package/dist/custom/visualization/shared/svg-theming.d.ts.map +1 -0
  61. package/dist/custom/visualization/shared/svg-theming.js +235 -0
  62. package/dist/custom/visualization/shared/svg-theming.js.map +1 -0
  63. package/dist/custom/visualization/shared/svg-types.d.ts +354 -0
  64. package/dist/custom/visualization/shared/svg-types.d.ts.map +1 -0
  65. package/dist/custom/visualization/shared/svg-types.js +11 -0
  66. package/dist/custom/visualization/shared/svg-types.js.map +1 -0
  67. package/dist/custom/visualization/shared/svg-utils.d.ts +166 -0
  68. package/dist/custom/visualization/shared/svg-utils.d.ts.map +1 -0
  69. package/dist/custom/visualization/shared/svg-utils.js +555 -0
  70. package/dist/custom/visualization/shared/svg-utils.js.map +1 -0
  71. package/dist/custom/web/google-custom-search.action.d.ts +6 -1
  72. package/dist/custom/web/google-custom-search.action.d.ts.map +1 -1
  73. package/dist/custom/web/google-custom-search.action.js +78 -10
  74. package/dist/custom/web/google-custom-search.action.js.map +1 -1
  75. package/dist/custom/web/web-page-content.action.d.ts +24 -0
  76. package/dist/custom/web/web-page-content.action.d.ts.map +1 -1
  77. package/dist/custom/web/web-page-content.action.js +90 -9
  78. package/dist/custom/web/web-page-content.action.js.map +1 -1
  79. package/dist/generated/action_subclasses.d.ts +4 -4
  80. package/dist/generated/action_subclasses.js +13 -13
  81. package/dist/index.d.ts +12 -0
  82. package/dist/index.d.ts.map +1 -1
  83. package/dist/index.js +34 -0
  84. package/dist/index.js.map +1 -1
  85. package/package.json +30 -12
@@ -0,0 +1,687 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
19
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
20
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
21
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
22
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
23
+ };
24
+ var __importStar = (this && this.__importStar) || function (mod) {
25
+ if (mod && mod.__esModule) return mod;
26
+ var result = {};
27
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
28
+ __setModuleDefault(result, mod);
29
+ return result;
30
+ };
31
+ Object.defineProperty(exports, "__esModule", { value: true });
32
+ exports.LoadCreateSVGNetworkAction = exports.CreateSVGNetworkAction = void 0;
33
+ const actions_1 = require("@memberjunction/actions");
34
+ const global_1 = require("@memberjunction/global");
35
+ const d3Force = __importStar(require("d3-force"));
36
+ const d3Hierarchy = __importStar(require("d3-hierarchy"));
37
+ const svg_utils_1 = require("./shared/svg-utils");
38
+ const svg_theming_1 = require("./shared/svg-theming");
39
+ /**
40
+ * Action that generates SVG network graphs including force-directed layouts, decision trees, and radial networks.
41
+ *
42
+ * This action provides server-side SVG generation for network visualizations, designed for
43
+ * AI agents and workflows to create publication-quality graphs from structured data.
44
+ *
45
+ * @example
46
+ * ```typescript
47
+ * // Force-directed network example
48
+ * await runAction({
49
+ * ActionName: 'Create SVG Network',
50
+ * Params: [
51
+ * { Name: 'NetworkType', Value: 'force' },
52
+ * { Name: 'Nodes', Value: JSON.stringify([
53
+ * { id: '1', label: 'Node A', group: 'A' },
54
+ * { id: '2', label: 'Node B', group: 'B' },
55
+ * { id: '3', label: 'Node C', group: 'A' }
56
+ * ]) },
57
+ * { Name: 'Edges', Value: JSON.stringify([
58
+ * { source: '1', target: '2', weight: 1, directed: true },
59
+ * { source: '2', target: '3', weight: 0.5 }
60
+ * ]) },
61
+ * { Name: 'ShowLabels', Value: 'true' },
62
+ * { Name: 'ShowLegend', Value: 'true' }
63
+ * ]
64
+ * });
65
+ *
66
+ * // Decision tree example
67
+ * await runAction({
68
+ * ActionName: 'Create SVG Network',
69
+ * Params: [
70
+ * { Name: 'NetworkType', Value: 'tree' },
71
+ * { Name: 'Nodes', Value: JSON.stringify({
72
+ * id: 'root',
73
+ * label: 'Decision',
74
+ * children: [
75
+ * { id: '1', label: 'Option A', value: 0.6 },
76
+ * { id: '2', label: 'Option B', value: 0.4 }
77
+ * ]
78
+ * }) }
79
+ * ]
80
+ * });
81
+ * ```
82
+ */
83
+ let CreateSVGNetworkAction = class CreateSVGNetworkAction extends actions_1.BaseAction {
84
+ /**
85
+ * Generates an SVG network graph from the provided data and configuration
86
+ *
87
+ * @param params - The action parameters containing:
88
+ * - NetworkType: Type of network ('force' | 'tree' | 'radial')
89
+ * - Nodes: JSON array or object of nodes
90
+ * - Edges: JSON array of edges (for force and radial)
91
+ * - Physics: Physics parameters (charge, linkDistance, iterations)
92
+ * - ShowLabels: Show node labels (default: true)
93
+ * - ShowLegend: Show group legend (default: false)
94
+ * - NodeShape: Shape for tree nodes ('rect' | 'circle' | 'pill')
95
+ * - Width: Width in pixels (optional, default: 800)
96
+ * - Height: Height in pixels (optional, default: 600)
97
+ * - Title: Network title (optional)
98
+ * - Palette: Color palette name (optional)
99
+ * - Seed: Random seed for deterministic layouts (optional)
100
+ *
101
+ * @returns A promise resolving to an SVGActionResult
102
+ */
103
+ async InternalRunAction(params) {
104
+ try {
105
+ const networkTypeParam = this.getParamValue(params, 'NetworkType');
106
+ if (!networkTypeParam) {
107
+ return {
108
+ Success: false,
109
+ Message: 'NetworkType parameter is required. Must be "force", "tree", or "radial"',
110
+ ResultCode: 'MISSING_PARAMETERS',
111
+ };
112
+ }
113
+ const networkType = this.ensureString(networkTypeParam, 'NetworkType').toLowerCase();
114
+ if (!['force', 'tree', 'radial'].includes(networkType)) {
115
+ return {
116
+ Success: false,
117
+ Message: 'NetworkType must be "force", "tree", or "radial"',
118
+ ResultCode: 'INVALID_NETWORK_TYPE',
119
+ };
120
+ }
121
+ // Parse common parameters
122
+ const width = parseInt(this.ensureString(this.getParamValue(params, 'Width') || '800', 'Width'));
123
+ const height = parseInt(this.ensureString(this.getParamValue(params, 'Height') || '600', 'Height'));
124
+ const title = this.ensureString(this.getParamValue(params, 'Title') || '', 'Title');
125
+ const paletteName = this.ensureString(this.getParamValue(params, 'Palette') || 'mjDefault', 'Palette');
126
+ const seed = parseInt(this.ensureString(this.getParamValue(params, 'Seed') || String(Date.now()), 'Seed'));
127
+ const showLabelsParam = this.getParamValue(params, 'ShowLabels');
128
+ const showLabels = showLabelsParam ? this.ensureString(showLabelsParam, 'ShowLabels').toLowerCase() !== 'false' : true;
129
+ const showLegendParam = this.getParamValue(params, 'ShowLegend');
130
+ const showLegend = showLegendParam ? this.ensureString(showLegendParam, 'ShowLegend').toLowerCase() === 'true' : false;
131
+ // Parse interactivity parameters
132
+ const enableTooltipsParam = this.getParamValue(params, 'EnableTooltips');
133
+ const enableTooltips = enableTooltipsParam ? this.ensureString(enableTooltipsParam, 'EnableTooltips').toLowerCase() === 'true' : false;
134
+ const enablePanZoomParam = this.getParamValue(params, 'EnablePanZoom');
135
+ const enablePanZoom = enablePanZoomParam ? this.ensureString(enablePanZoomParam, 'EnablePanZoom').toLowerCase() === 'true' : false;
136
+ const showZoomControlsParam = this.getParamValue(params, 'ShowZoomControls');
137
+ const showZoomControls = showZoomControlsParam ? this.ensureString(showZoomControlsParam, 'ShowZoomControls').toLowerCase() === 'true' : false;
138
+ const wrapWithContainerParam = this.getParamValue(params, 'WrapWithContainer');
139
+ const wrapWithContainer = wrapWithContainerParam ? this.ensureString(wrapWithContainerParam, 'WrapWithContainer').toLowerCase() === 'true' : false;
140
+ const maxContainerWidth = parseInt(this.ensureString(this.getParamValue(params, 'MaxContainerWidth') || '1200', 'MaxContainerWidth'));
141
+ const maxContainerHeight = parseInt(this.ensureString(this.getParamValue(params, 'MaxContainerHeight') || '800', 'MaxContainerHeight'));
142
+ // Create branding configuration
143
+ const branding = {
144
+ palette: { type: 'named', name: paletteName },
145
+ };
146
+ // Create viewBox configuration
147
+ const viewBox = {
148
+ width,
149
+ height,
150
+ padding: 40,
151
+ };
152
+ // Generate network based on type
153
+ let svg;
154
+ const warnings = [];
155
+ switch (networkType) {
156
+ case 'force':
157
+ svg = await this.renderForceNetwork(params, viewBox, branding, title, seed, showLabels, showLegend, enableTooltips, enablePanZoom, showZoomControls, warnings);
158
+ break;
159
+ case 'tree':
160
+ svg = await this.renderDecisionTree(params, viewBox, branding, title, showLabels, enableTooltips, enablePanZoom, showZoomControls);
161
+ break;
162
+ case 'radial':
163
+ svg = await this.renderRadialNetwork(params, viewBox, branding, title, seed, showLabels, enableTooltips, enablePanZoom, showZoomControls, warnings);
164
+ break;
165
+ default:
166
+ return {
167
+ Success: false,
168
+ Message: `Unsupported network type: ${networkType}`,
169
+ ResultCode: 'INVALID_NETWORK_TYPE',
170
+ };
171
+ }
172
+ // Apply scroll container wrapping if requested
173
+ if (wrapWithContainer) {
174
+ svg = svg_utils_1.SVGUtils.wrapWithScrollContainer(svg, maxContainerWidth, maxContainerHeight);
175
+ }
176
+ return {
177
+ Success: true,
178
+ ResultCode: 'SUCCESS',
179
+ Message: svg,
180
+ svg,
181
+ width,
182
+ height,
183
+ warnings: warnings.length > 0 ? warnings : undefined,
184
+ };
185
+ }
186
+ catch (error) {
187
+ return {
188
+ Success: false,
189
+ Message: `Failed to generate network: ${error instanceof Error ? error.message : String(error)}`,
190
+ ResultCode: 'NETWORK_GENERATION_FAILED',
191
+ };
192
+ }
193
+ }
194
+ /**
195
+ * Renders a force-directed network using d3-force
196
+ */
197
+ async renderForceNetwork(params, viewBox, branding, title, seed, showLabels, showLegend, enableTooltips, enablePanZoom, showZoomControls, warnings) {
198
+ // Parse nodes and edges
199
+ const nodesParam = this.getParamValue(params, 'Nodes');
200
+ const edgesParam = this.getParamValue(params, 'Edges');
201
+ if (!nodesParam) {
202
+ throw new Error('Nodes parameter is required for force networks');
203
+ }
204
+ const nodes = this.parseJSON(nodesParam, 'Nodes');
205
+ const edges = edgesParam ? this.parseJSON(edgesParam, 'Edges') : [];
206
+ // Parse physics parameters
207
+ const physicsParam = this.getParamValue(params, 'Physics');
208
+ const physics = physicsParam ? this.parseJSON(physicsParam, 'Physics') : {};
209
+ const charge = physics.charge || -300;
210
+ const linkDistance = physics.linkDistance || 100;
211
+ const iterations = physics.iterations || 300;
212
+ // Warn if graph is too large
213
+ if (nodes.length > 500) {
214
+ warnings.push(`Large graph with ${nodes.length} nodes may have performance issues`);
215
+ }
216
+ // Create seeded random generator
217
+ const random = svg_utils_1.SVGUtils.seededRandom(seed);
218
+ // Initialize node positions randomly
219
+ const vb = svg_utils_1.SVGUtils.calculateViewBox(viewBox);
220
+ const simNodes = nodes.map((n) => ({
221
+ ...n,
222
+ x: vb.x + random() * vb.contentWidth,
223
+ y: vb.y + random() * vb.contentHeight,
224
+ vx: 0,
225
+ vy: 0,
226
+ }));
227
+ // Create force simulation
228
+ const simulation = d3Force
229
+ .forceSimulation(simNodes)
230
+ .force('link', d3Force
231
+ .forceLink(edges)
232
+ .id((d) => d.id)
233
+ .distance(linkDistance))
234
+ .force('charge', d3Force.forceManyBody().strength(charge))
235
+ .force('center', d3Force.forceCenter(vb.x + vb.contentWidth / 2, vb.y + vb.contentHeight / 2))
236
+ .force('collide', d3Force.forceCollide(20))
237
+ .stop();
238
+ // Run simulation headless
239
+ for (let i = 0; i < iterations; i++) {
240
+ simulation.tick();
241
+ }
242
+ // Create SVG
243
+ const doc = svg_utils_1.SVGUtils.createSVG(viewBox.width, viewBox.height, 'force-network');
244
+ const svg = doc.querySelector('svg');
245
+ // Add accessibility
246
+ if (title) {
247
+ svg_utils_1.SVGUtils.addA11y(svg, {
248
+ title,
249
+ ariaRole: 'img',
250
+ });
251
+ }
252
+ // Add styles
253
+ const css = (0, svg_theming_1.generateCSS)(branding);
254
+ svg_utils_1.SVGUtils.addStyles(svg, css);
255
+ // Get palette
256
+ const palette = (0, svg_theming_1.getPalette)(branding.palette);
257
+ const ns = svg.namespaceURI;
258
+ // Build group-to-color mapping
259
+ const groups = [...new Set(nodes.map((n) => n.group).filter((g) => g != null))];
260
+ const groupColorMap = new Map(groups.map((g, i) => [g, (0, svg_theming_1.getColorForIndex)(i, branding.palette)]));
261
+ // Wrap content in pan/zoom container if needed
262
+ const contentContainer = doc.createElementNS(ns, 'g');
263
+ contentContainer.setAttribute('id', enablePanZoom ? 'pan-zoom-container' : 'content-container');
264
+ svg.appendChild(contentContainer);
265
+ // Render edges
266
+ const edgesGroup = doc.createElementNS(ns, 'g');
267
+ edgesGroup.setAttribute('id', 'edges');
268
+ contentContainer.appendChild(edgesGroup);
269
+ for (const edge of edges) {
270
+ const sourceSim = simNodes.find((n) => n.id === edge.source.id || n.id === edge.source);
271
+ const targetSim = simNodes.find((n) => n.id === edge.target.id || n.id === edge.target);
272
+ if (!sourceSim || !targetSim)
273
+ continue;
274
+ const line = doc.createElementNS(ns, 'line');
275
+ line.setAttribute('x1', String(sourceSim.x));
276
+ line.setAttribute('y1', String(sourceSim.y));
277
+ line.setAttribute('x2', String(targetSim.x));
278
+ line.setAttribute('y2', String(targetSim.y));
279
+ line.setAttribute('stroke', palette.foreground);
280
+ line.setAttribute('stroke-width', String((edge.weight || 1) * 2));
281
+ line.setAttribute('opacity', '0.6');
282
+ if (edge.directed) {
283
+ const markerId = svg_utils_1.SVGUtils.addArrowMarker(svg, 'arrow-force', palette.foreground);
284
+ line.setAttribute('marker-end', markerId);
285
+ }
286
+ edgesGroup.appendChild(line);
287
+ }
288
+ // Render nodes
289
+ const nodesGroup = doc.createElementNS(ns, 'g');
290
+ nodesGroup.setAttribute('id', 'nodes');
291
+ contentContainer.appendChild(nodesGroup);
292
+ for (const node of simNodes) {
293
+ const g = doc.createElementNS(ns, 'g');
294
+ g.setAttribute('transform', `translate(${node.x}, ${node.y})`);
295
+ g.setAttribute('data-node-id', node.id);
296
+ // Add tooltip data if enabled
297
+ if (enableTooltips) {
298
+ const tooltipText = `${node.label || node.id}${node.group ? ' (' + node.group + ')' : ''}`;
299
+ g.setAttribute('data-tooltip', tooltipText);
300
+ }
301
+ const radius = node.size || 10;
302
+ const color = node.group ? groupColorMap.get(node.group) || palette.categorical[0] : palette.categorical[0];
303
+ const circle = doc.createElementNS(ns, 'circle');
304
+ circle.setAttribute('r', String(radius));
305
+ circle.setAttribute('fill', color);
306
+ circle.setAttribute('stroke', '#FFF');
307
+ circle.setAttribute('stroke-width', '2');
308
+ circle.setAttribute('class', 'node-circle');
309
+ g.appendChild(circle);
310
+ if (showLabels && node.label) {
311
+ const text = doc.createElementNS(ns, 'text');
312
+ text.setAttribute('y', String(radius + 15));
313
+ text.setAttribute('text-anchor', 'middle');
314
+ text.setAttribute('font-size', '11');
315
+ text.setAttribute('fill', palette.foreground);
316
+ text.textContent = node.label;
317
+ g.appendChild(text);
318
+ }
319
+ nodesGroup.appendChild(g);
320
+ }
321
+ // Add legend if requested
322
+ if (showLegend && groups.length > 0) {
323
+ this.addLegend(doc, svg, groups, groupColorMap, vb, (0, svg_theming_1.getFontSpec)(branding.font));
324
+ }
325
+ // Add title if present
326
+ if (title) {
327
+ this.addTitle(doc, svg, title, vb.width, (0, svg_theming_1.getFontSpec)(branding.font));
328
+ }
329
+ // Add interactivity features
330
+ if (enableTooltips) {
331
+ svg_utils_1.SVGUtils.addTooltipSupport(svg, doc);
332
+ }
333
+ if (enablePanZoom) {
334
+ const panZoomScript = doc.createElementNS(ns, 'script');
335
+ panZoomScript.setAttribute('type', 'text/javascript');
336
+ panZoomScript.textContent = svg_utils_1.SVGUtils.generatePanZoomScript('pan-zoom-container', 0.5, 3, showZoomControls).replace(/<script[^>]*>|<\/script>/gi, '');
337
+ svg.appendChild(panZoomScript);
338
+ }
339
+ // Sanitize and return
340
+ return svg_utils_1.SVGUtils.sanitizeSVG(svg.outerHTML);
341
+ }
342
+ /**
343
+ * Renders a decision tree using d3-hierarchy
344
+ */
345
+ async renderDecisionTree(params, viewBox, branding, title, showLabels, enableTooltips, enablePanZoom, showZoomControls) {
346
+ // Parse tree
347
+ const nodesParam = this.getParamValue(params, 'Nodes');
348
+ if (!nodesParam) {
349
+ throw new Error('Nodes parameter is required for decision trees');
350
+ }
351
+ const rootNode = this.parseJSON(nodesParam, 'Nodes');
352
+ const nodeShapeParam = this.getParamValue(params, 'NodeShape');
353
+ const nodeShape = (nodeShapeParam ? this.ensureString(nodeShapeParam, 'NodeShape') : 'rect');
354
+ // Create hierarchy
355
+ const hierarchy = d3Hierarchy.hierarchy(rootNode);
356
+ // Create tree layout
357
+ const vb = svg_utils_1.SVGUtils.calculateViewBox(viewBox);
358
+ const treeLayout = d3Hierarchy.tree().size([vb.contentWidth, vb.contentHeight]);
359
+ // Calculate layout
360
+ const treeData = treeLayout(hierarchy);
361
+ // Create SVG
362
+ const doc = svg_utils_1.SVGUtils.createSVG(viewBox.width, viewBox.height, 'decision-tree');
363
+ const svg = doc.querySelector('svg');
364
+ // Add accessibility
365
+ if (title) {
366
+ svg_utils_1.SVGUtils.addA11y(svg, {
367
+ title,
368
+ ariaRole: 'img',
369
+ });
370
+ }
371
+ // Add styles
372
+ const css = (0, svg_theming_1.generateCSS)(branding);
373
+ svg_utils_1.SVGUtils.addStyles(svg, css);
374
+ // Get palette
375
+ const palette = (0, svg_theming_1.getPalette)(branding.palette);
376
+ const ns = svg.namespaceURI;
377
+ // Create container group with offset for padding
378
+ const container = doc.createElementNS(ns, 'g');
379
+ container.setAttribute('transform', `translate(${vb.x}, ${vb.y})`);
380
+ svg.appendChild(container);
381
+ // Render links
382
+ treeData.links().forEach((link) => {
383
+ const path = doc.createElementNS(ns, 'path');
384
+ // Diagonal path
385
+ const d = `M ${link.source.x},${link.source.y}
386
+ C ${link.source.x},${(link.source.y + link.target.y) / 2}
387
+ ${link.target.x},${(link.source.y + link.target.y) / 2}
388
+ ${link.target.x},${link.target.y}`;
389
+ path.setAttribute('d', d);
390
+ path.setAttribute('fill', 'none');
391
+ path.setAttribute('stroke', palette.foreground);
392
+ path.setAttribute('stroke-width', '2');
393
+ path.setAttribute('opacity', '0.6');
394
+ container.appendChild(path);
395
+ });
396
+ // Render nodes
397
+ treeData.descendants().forEach((node) => {
398
+ const g = doc.createElementNS(ns, 'g');
399
+ g.setAttribute('transform', `translate(${node.x}, ${node.y})`);
400
+ const colorIndex = node.depth % palette.categorical.length;
401
+ const fillColor = palette.categorical[colorIndex];
402
+ // Render shape based on nodeShape
403
+ switch (nodeShape) {
404
+ case 'circle':
405
+ const circle = doc.createElementNS(ns, 'circle');
406
+ circle.setAttribute('r', '25');
407
+ circle.setAttribute('fill', fillColor);
408
+ circle.setAttribute('stroke', '#333');
409
+ circle.setAttribute('stroke-width', '2');
410
+ g.appendChild(circle);
411
+ break;
412
+ case 'pill':
413
+ const pill = doc.createElementNS(ns, 'path');
414
+ pill.setAttribute('d', svg_utils_1.SVGUtils.roundedRectPath(-40, -20, 80, 40, 20));
415
+ pill.setAttribute('fill', fillColor);
416
+ pill.setAttribute('stroke', '#333');
417
+ pill.setAttribute('stroke-width', '2');
418
+ g.appendChild(pill);
419
+ break;
420
+ default: // rect
421
+ const rect = doc.createElementNS(ns, 'rect');
422
+ rect.setAttribute('x', '-30');
423
+ rect.setAttribute('y', '-20');
424
+ rect.setAttribute('width', '60');
425
+ rect.setAttribute('height', '40');
426
+ rect.setAttribute('fill', fillColor);
427
+ rect.setAttribute('stroke', '#333');
428
+ rect.setAttribute('stroke-width', '2');
429
+ rect.setAttribute('rx', '5');
430
+ g.appendChild(rect);
431
+ break;
432
+ }
433
+ // Add label
434
+ if (showLabels) {
435
+ const labelText = doc.createElementNS(ns, 'text');
436
+ labelText.setAttribute('y', node.data.value != null ? '-5' : '0');
437
+ labelText.setAttribute('text-anchor', 'middle');
438
+ labelText.setAttribute('dominant-baseline', 'middle');
439
+ labelText.setAttribute('font-size', '11');
440
+ labelText.setAttribute('font-weight', 'bold');
441
+ labelText.setAttribute('fill', '#FFF');
442
+ labelText.textContent = node.data.label;
443
+ g.appendChild(labelText);
444
+ // Add value if present
445
+ if (node.data.value != null) {
446
+ const valueText = doc.createElementNS(ns, 'text');
447
+ valueText.setAttribute('y', '8');
448
+ valueText.setAttribute('text-anchor', 'middle');
449
+ valueText.setAttribute('font-size', '9');
450
+ valueText.setAttribute('fill', '#FFF');
451
+ valueText.setAttribute('opacity', '0.9');
452
+ valueText.textContent = String(node.data.value);
453
+ g.appendChild(valueText);
454
+ }
455
+ }
456
+ container.appendChild(g);
457
+ });
458
+ // Add title if present
459
+ if (title) {
460
+ this.addTitle(doc, svg, title, vb.width, (0, svg_theming_1.getFontSpec)(branding.font));
461
+ }
462
+ // Sanitize and return
463
+ return svg_utils_1.SVGUtils.sanitizeSVG(svg.outerHTML);
464
+ }
465
+ /**
466
+ * Renders a radial network using d3-force with radial constraint
467
+ */
468
+ async renderRadialNetwork(params, viewBox, branding, title, seed, showLabels, enableTooltips, enablePanZoom, showZoomControls, warnings) {
469
+ // Parse nodes and edges
470
+ const nodesParam = this.getParamValue(params, 'Nodes');
471
+ const edgesParam = this.getParamValue(params, 'Edges');
472
+ if (!nodesParam) {
473
+ throw new Error('Nodes parameter is required for radial networks');
474
+ }
475
+ const nodes = this.parseJSON(nodesParam, 'Nodes');
476
+ const edges = edgesParam ? this.parseJSON(edgesParam, 'Edges') : [];
477
+ // Identify central node (first node or node with most connections)
478
+ const degreeMap = new Map();
479
+ for (const edge of edges) {
480
+ degreeMap.set(edge.source, (degreeMap.get(edge.source) || 0) + 1);
481
+ degreeMap.set(edge.target, (degreeMap.get(edge.target) || 0) + 1);
482
+ }
483
+ const centralNodeId = nodes.length > 0 ? [...degreeMap.entries()].sort((a, b) => b[1] - a[1])[0]?.[0] || nodes[0].id : nodes[0].id;
484
+ // Create seeded random generator
485
+ const random = svg_utils_1.SVGUtils.seededRandom(seed);
486
+ // Initialize node positions
487
+ const vb = svg_utils_1.SVGUtils.calculateViewBox(viewBox);
488
+ const centerX = vb.x + vb.contentWidth / 2;
489
+ const centerY = vb.y + vb.contentHeight / 2;
490
+ const simNodes = nodes.map((n, i) => ({
491
+ ...n,
492
+ x: centerX + (random() - 0.5) * 100,
493
+ y: centerY + (random() - 0.5) * 100,
494
+ vx: 0,
495
+ vy: 0,
496
+ isCentral: n.id === centralNodeId,
497
+ }));
498
+ // Create force simulation with radial force
499
+ const simulation = d3Force
500
+ .forceSimulation(simNodes)
501
+ .force('link', d3Force
502
+ .forceLink(edges)
503
+ .id((d) => d.id)
504
+ .distance(80))
505
+ .force('charge', d3Force.forceManyBody().strength(-200))
506
+ .force('radial', d3Force.forceRadial((d) => (d.isCentral ? 0 : 150), centerX, centerY))
507
+ .force('collide', d3Force.forceCollide(25))
508
+ .stop();
509
+ // Run simulation headless
510
+ for (let i = 0; i < 300; i++) {
511
+ simulation.tick();
512
+ }
513
+ // Create SVG (reuse force network rendering logic)
514
+ const doc = svg_utils_1.SVGUtils.createSVG(viewBox.width, viewBox.height, 'radial-network');
515
+ const svg = doc.querySelector('svg');
516
+ // Add accessibility
517
+ if (title) {
518
+ svg_utils_1.SVGUtils.addA11y(svg, {
519
+ title,
520
+ ariaRole: 'img',
521
+ });
522
+ }
523
+ // Add styles
524
+ const css = (0, svg_theming_1.generateCSS)(branding);
525
+ svg_utils_1.SVGUtils.addStyles(svg, css);
526
+ // Get palette
527
+ const palette = (0, svg_theming_1.getPalette)(branding.palette);
528
+ const ns = svg.namespaceURI;
529
+ // Render edges
530
+ const edgesGroup = doc.createElementNS(ns, 'g');
531
+ edgesGroup.setAttribute('id', 'edges');
532
+ svg.appendChild(edgesGroup);
533
+ for (const edge of edges) {
534
+ const sourceSim = simNodes.find((n) => n.id === edge.source.id || n.id === edge.source);
535
+ const targetSim = simNodes.find((n) => n.id === edge.target.id || n.id === edge.target);
536
+ if (!sourceSim || !targetSim)
537
+ continue;
538
+ const line = doc.createElementNS(ns, 'line');
539
+ line.setAttribute('x1', String(sourceSim.x));
540
+ line.setAttribute('y1', String(sourceSim.y));
541
+ line.setAttribute('x2', String(targetSim.x));
542
+ line.setAttribute('y2', String(targetSim.y));
543
+ line.setAttribute('stroke', palette.foreground);
544
+ line.setAttribute('stroke-width', '2');
545
+ line.setAttribute('opacity', '0.4');
546
+ edgesGroup.appendChild(line);
547
+ }
548
+ // Render nodes
549
+ const nodesGroup = doc.createElementNS(ns, 'g');
550
+ nodesGroup.setAttribute('id', 'nodes');
551
+ svg.appendChild(nodesGroup);
552
+ for (const node of simNodes) {
553
+ const g = doc.createElementNS(ns, 'g');
554
+ g.setAttribute('transform', `translate(${node.x}, ${node.y})`);
555
+ const radius = node.isCentral ? 20 : node.size || 12;
556
+ const color = node.isCentral ? palette.categorical[4] : palette.categorical[0];
557
+ const circle = doc.createElementNS(ns, 'circle');
558
+ circle.setAttribute('r', String(radius));
559
+ circle.setAttribute('fill', color);
560
+ circle.setAttribute('stroke', '#FFF');
561
+ circle.setAttribute('stroke-width', node.isCentral ? '3' : '2');
562
+ g.appendChild(circle);
563
+ if (showLabels && node.label) {
564
+ const text = doc.createElementNS(ns, 'text');
565
+ text.setAttribute('y', String(radius + 15));
566
+ text.setAttribute('text-anchor', 'middle');
567
+ text.setAttribute('font-size', node.isCentral ? '12' : '10');
568
+ text.setAttribute('font-weight', node.isCentral ? 'bold' : 'normal');
569
+ text.setAttribute('fill', palette.foreground);
570
+ text.textContent = node.label;
571
+ g.appendChild(text);
572
+ }
573
+ nodesGroup.appendChild(g);
574
+ }
575
+ // Add title if present
576
+ if (title) {
577
+ this.addTitle(doc, svg, title, vb.width, (0, svg_theming_1.getFontSpec)(branding.font));
578
+ }
579
+ // Sanitize and return
580
+ return svg_utils_1.SVGUtils.sanitizeSVG(svg.outerHTML);
581
+ }
582
+ /**
583
+ * Adds a legend to the SVG
584
+ */
585
+ addLegend(doc, svg, groups, groupColorMap, vb, font) {
586
+ const ns = svg.namespaceURI;
587
+ const legendGroup = doc.createElementNS(ns, 'g');
588
+ legendGroup.setAttribute('id', 'legend');
589
+ legendGroup.setAttribute('transform', `translate(${vb.width - 150}, 50)`);
590
+ groups.forEach((group, i) => {
591
+ const g = doc.createElementNS(ns, 'g');
592
+ g.setAttribute('transform', `translate(0, ${i * 25})`);
593
+ const circle = doc.createElementNS(ns, 'circle');
594
+ circle.setAttribute('cx', '10');
595
+ circle.setAttribute('cy', '10');
596
+ circle.setAttribute('r', '8');
597
+ circle.setAttribute('fill', groupColorMap.get(group));
598
+ circle.setAttribute('stroke', '#333');
599
+ g.appendChild(circle);
600
+ const text = doc.createElementNS(ns, 'text');
601
+ text.setAttribute('x', '25');
602
+ text.setAttribute('y', '15');
603
+ text.setAttribute('font-size', String(font.size - 2));
604
+ text.textContent = group;
605
+ g.appendChild(text);
606
+ legendGroup.appendChild(g);
607
+ });
608
+ svg.appendChild(legendGroup);
609
+ }
610
+ /**
611
+ * Adds a title to the SVG
612
+ */
613
+ addTitle(doc, svg, title, width, font) {
614
+ const ns = svg.namespaceURI;
615
+ const text = doc.createElementNS(ns, 'text');
616
+ text.setAttribute('x', String(width / 2));
617
+ text.setAttribute('y', '25');
618
+ text.setAttribute('text-anchor', 'middle');
619
+ text.setAttribute('font-family', font.family);
620
+ text.setAttribute('font-size', String(font.size + 4));
621
+ text.setAttribute('font-weight', 'bold');
622
+ text.textContent = title;
623
+ svg.appendChild(text);
624
+ }
625
+ /**
626
+ * Helper to safely parse JSON that might already be an object
627
+ */
628
+ parseJSON(value, paramName) {
629
+ // If it's already an object/array, return it
630
+ if (typeof value === 'object' && value !== null) {
631
+ return value;
632
+ }
633
+ // If it's a string, parse it
634
+ if (typeof value === 'string') {
635
+ try {
636
+ return JSON.parse(value);
637
+ }
638
+ catch (error) {
639
+ throw new Error(`Parameter '${paramName}' contains invalid JSON: ${error instanceof Error ? error.message : String(error)}`);
640
+ }
641
+ }
642
+ // For other types, error
643
+ throw new Error(`Parameter '${paramName}' must be a JSON string or object. Received ${typeof value}.`);
644
+ }
645
+ /**
646
+ * Helper to ensure a parameter value is a string, with type conversion and validation
647
+ */
648
+ ensureString(value, paramName) {
649
+ if (value == null) {
650
+ return '';
651
+ }
652
+ if (typeof value === 'string') {
653
+ return value;
654
+ }
655
+ // Convert numbers and booleans to strings
656
+ if (typeof value === 'number' || typeof value === 'boolean') {
657
+ return String(value);
658
+ }
659
+ // For objects/arrays, reject with descriptive error
660
+ throw new Error(`Parameter '${paramName}' must be a string, number, or boolean. ` +
661
+ `Received ${typeof value}. If providing JSON data, ensure it's passed as a string.`);
662
+ }
663
+ /**
664
+ * Helper to get parameter value by name (case-insensitive)
665
+ */
666
+ getParamValue(params, paramName) {
667
+ const param = params.Params.find((p) => p.Name.trim().toLowerCase() === paramName.toLowerCase());
668
+ if (param?.Value && typeof param.Value === 'string') {
669
+ return param?.Value?.trim() || null;
670
+ }
671
+ else {
672
+ return param?.Value || null;
673
+ }
674
+ }
675
+ };
676
+ exports.CreateSVGNetworkAction = CreateSVGNetworkAction;
677
+ exports.CreateSVGNetworkAction = CreateSVGNetworkAction = __decorate([
678
+ (0, global_1.RegisterClass)(actions_1.BaseAction, '__CreateSVGNetwork')
679
+ ], CreateSVGNetworkAction);
680
+ /**
681
+ * Loader function to ensure the CreateSVGNetworkAction class is included in the bundle.
682
+ */
683
+ function LoadCreateSVGNetworkAction() {
684
+ // this function is a stub that is used to force the bundler to include the above class in the final bundle and not tree shake them out
685
+ }
686
+ exports.LoadCreateSVGNetworkAction = LoadCreateSVGNetworkAction;
687
+ //# sourceMappingURL=create-svg-network.action.js.map