@teamflojo/floimg-d3 0.1.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.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 Brett Cooke
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,449 @@
1
+ # imgflo-d3
2
+
3
+ D3 data visualization generator for imgflo using server-side rendering.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install imgflo imgflo-d3
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ ```typescript
14
+ import createClient from 'imgflo';
15
+ import d3viz from 'imgflo-d3';
16
+
17
+ const imgflo = createClient();
18
+ imgflo.registerGenerator(d3viz());
19
+
20
+ // Create a bar chart
21
+ const chart = await imgflo.generate({
22
+ generator: 'd3',
23
+ params: {
24
+ width: 600,
25
+ height: 400,
26
+ render: (svg, d3, data) => {
27
+ // Use D3 directly - full API available
28
+ svg.selectAll('rect')
29
+ .data(data)
30
+ .join('rect')
31
+ .attr('x', (d, i) => i * 60)
32
+ .attr('y', d => 400 - d.value * 3)
33
+ .attr('width', 50)
34
+ .attr('height', d => d.value * 3)
35
+ .attr('fill', 'steelblue');
36
+ },
37
+ data: [
38
+ { value: 30 },
39
+ { value: 80 },
40
+ { value: 45 },
41
+ { value: 60 },
42
+ { value: 20 }
43
+ ]
44
+ }
45
+ });
46
+
47
+ // Upload to S3
48
+ await imgflo.save(chart, './output/bar.svg');
49
+ ```
50
+
51
+ ## Examples
52
+
53
+ ### Bar Chart
54
+
55
+ ```typescript
56
+ const barChart = await imgflo.generate({
57
+ generator: 'd3',
58
+ params: {
59
+ width: 800,
60
+ height: 400,
61
+ render: (svg, d3, data) => {
62
+ const margin = { top: 20, right: 20, bottom: 30, left: 40 };
63
+ const width = 800 - margin.left - margin.right;
64
+ const height = 400 - margin.top - margin.bottom;
65
+
66
+ const g = svg.append('g')
67
+ .attr('transform', `translate(${margin.left},${margin.top})`);
68
+
69
+ const x = d3.scaleBand()
70
+ .domain(data.map(d => d.name))
71
+ .range([0, width])
72
+ .padding(0.1);
73
+
74
+ const y = d3.scaleLinear()
75
+ .domain([0, d3.max(data, d => d.value)])
76
+ .range([height, 0]);
77
+
78
+ g.selectAll('rect')
79
+ .data(data)
80
+ .join('rect')
81
+ .attr('x', d => x(d.name))
82
+ .attr('y', d => y(d.value))
83
+ .attr('width', x.bandwidth())
84
+ .attr('height', d => height - y(d.value))
85
+ .attr('fill', 'steelblue');
86
+
87
+ g.append('g')
88
+ .attr('transform', `translate(0,${height})`)
89
+ .call(d3.axisBottom(x));
90
+
91
+ g.append('g')
92
+ .call(d3.axisLeft(y));
93
+ },
94
+ data: [
95
+ { name: 'Q1', value: 120 },
96
+ { name: 'Q2', value: 200 },
97
+ { name: 'Q3', value: 150 },
98
+ { name: 'Q4', value: 170 }
99
+ ]
100
+ }
101
+ });
102
+ ```
103
+
104
+ ### Line Chart
105
+
106
+ ```typescript
107
+ const lineChart = await imgflo.generate({
108
+ generator: 'd3',
109
+ params: {
110
+ width: 800,
111
+ height: 400,
112
+ render: (svg, d3, data) => {
113
+ const margin = { top: 20, right: 20, bottom: 30, left: 50 };
114
+ const width = 800 - margin.left - margin.right;
115
+ const height = 400 - margin.top - margin.bottom;
116
+
117
+ const g = svg.append('g')
118
+ .attr('transform', `translate(${margin.left},${margin.top})`);
119
+
120
+ const x = d3.scaleLinear()
121
+ .domain([0, data.length - 1])
122
+ .range([0, width]);
123
+
124
+ const y = d3.scaleLinear()
125
+ .domain([0, d3.max(data, d => d.value)])
126
+ .range([height, 0]);
127
+
128
+ const line = d3.line()
129
+ .x((d, i) => x(i))
130
+ .y(d => y(d.value));
131
+
132
+ g.append('path')
133
+ .datum(data)
134
+ .attr('fill', 'none')
135
+ .attr('stroke', 'steelblue')
136
+ .attr('stroke-width', 2)
137
+ .attr('d', line);
138
+
139
+ g.append('g')
140
+ .attr('transform', `translate(0,${height})`)
141
+ .call(d3.axisBottom(x));
142
+
143
+ g.append('g')
144
+ .call(d3.axisLeft(y));
145
+ },
146
+ data: [
147
+ { value: 30 },
148
+ { value: 50 },
149
+ { value: 45 },
150
+ { value: 80 },
151
+ { value: 70 },
152
+ { value: 90 }
153
+ ]
154
+ }
155
+ });
156
+ ```
157
+
158
+ ### Pie Chart
159
+
160
+ ```typescript
161
+ const pieChart = await imgflo.generate({
162
+ generator: 'd3',
163
+ params: {
164
+ width: 500,
165
+ height: 500,
166
+ render: (svg, d3, data) => {
167
+ const width = 500;
168
+ const height = 500;
169
+ const radius = Math.min(width, height) / 2;
170
+
171
+ const g = svg.append('g')
172
+ .attr('transform', `translate(${width / 2},${height / 2})`);
173
+
174
+ const color = d3.scaleOrdinal(d3.schemeCategory10);
175
+
176
+ const pie = d3.pie()
177
+ .value(d => d.value);
178
+
179
+ const arc = d3.arc()
180
+ .innerRadius(0)
181
+ .outerRadius(radius);
182
+
183
+ const arcs = g.selectAll('arc')
184
+ .data(pie(data))
185
+ .join('g')
186
+ .attr('class', 'arc');
187
+
188
+ arcs.append('path')
189
+ .attr('d', arc)
190
+ .attr('fill', (d, i) => color(i));
191
+
192
+ arcs.append('text')
193
+ .attr('transform', d => `translate(${arc.centroid(d)})`)
194
+ .attr('text-anchor', 'middle')
195
+ .text(d => d.data.label);
196
+ },
197
+ data: [
198
+ { label: 'A', value: 30 },
199
+ { label: 'B', value: 70 },
200
+ { label: 'C', value: 45 },
201
+ { label: 'D', value: 60 }
202
+ ]
203
+ }
204
+ });
205
+ ```
206
+
207
+ ### Scatter Plot
208
+
209
+ ```typescript
210
+ const scatterPlot = await imgflo.generate({
211
+ generator: 'd3',
212
+ params: {
213
+ width: 600,
214
+ height: 400,
215
+ render: (svg, d3, data) => {
216
+ const margin = { top: 20, right: 20, bottom: 30, left: 40 };
217
+ const width = 600 - margin.left - margin.right;
218
+ const height = 400 - margin.top - margin.bottom;
219
+
220
+ const g = svg.append('g')
221
+ .attr('transform', `translate(${margin.left},${margin.top})`);
222
+
223
+ const x = d3.scaleLinear()
224
+ .domain([0, d3.max(data, d => d.x)])
225
+ .range([0, width]);
226
+
227
+ const y = d3.scaleLinear()
228
+ .domain([0, d3.max(data, d => d.y)])
229
+ .range([height, 0]);
230
+
231
+ g.selectAll('circle')
232
+ .data(data)
233
+ .join('circle')
234
+ .attr('cx', d => x(d.x))
235
+ .attr('cy', d => y(d.y))
236
+ .attr('r', 5)
237
+ .attr('fill', 'steelblue')
238
+ .attr('opacity', 0.7);
239
+
240
+ g.append('g')
241
+ .attr('transform', `translate(0,${height})`)
242
+ .call(d3.axisBottom(x));
243
+
244
+ g.append('g')
245
+ .call(d3.axisLeft(y));
246
+ },
247
+ data: [
248
+ { x: 10, y: 20 },
249
+ { x: 20, y: 40 },
250
+ { x: 30, y: 25 },
251
+ { x: 40, y: 60 },
252
+ { x: 50, y: 45 }
253
+ ]
254
+ }
255
+ });
256
+ ```
257
+
258
+ ### Area Chart
259
+
260
+ ```typescript
261
+ const areaChart = await imgflo.generate({
262
+ generator: 'd3',
263
+ params: {
264
+ width: 800,
265
+ height: 400,
266
+ render: (svg, d3, data) => {
267
+ const margin = { top: 20, right: 20, bottom: 30, left: 50 };
268
+ const width = 800 - margin.left - margin.right;
269
+ const height = 400 - margin.top - margin.bottom;
270
+
271
+ const g = svg.append('g')
272
+ .attr('transform', `translate(${margin.left},${margin.top})`);
273
+
274
+ const x = d3.scaleLinear()
275
+ .domain([0, data.length - 1])
276
+ .range([0, width]);
277
+
278
+ const y = d3.scaleLinear()
279
+ .domain([0, d3.max(data, d => d.value)])
280
+ .range([height, 0]);
281
+
282
+ const area = d3.area()
283
+ .x((d, i) => x(i))
284
+ .y0(height)
285
+ .y1(d => y(d.value));
286
+
287
+ g.append('path')
288
+ .datum(data)
289
+ .attr('fill', 'steelblue')
290
+ .attr('opacity', 0.7)
291
+ .attr('d', area);
292
+
293
+ g.append('g')
294
+ .attr('transform', `translate(0,${height})`)
295
+ .call(d3.axisBottom(x));
296
+
297
+ g.append('g')
298
+ .call(d3.axisLeft(y));
299
+ },
300
+ data: [
301
+ { value: 30 },
302
+ { value: 50 },
303
+ { value: 45 },
304
+ { value: 80 },
305
+ { value: 70 },
306
+ { value: 90 }
307
+ ]
308
+ }
309
+ });
310
+ ```
311
+
312
+ ### Heatmap
313
+
314
+ ```typescript
315
+ const heatmap = await imgflo.generate({
316
+ generator: 'd3',
317
+ params: {
318
+ width: 600,
319
+ height: 400,
320
+ render: (svg, d3, data) => {
321
+ const cellSize = 50;
322
+ const rows = data.length;
323
+ const cols = data[0].length;
324
+
325
+ const color = d3.scaleSequential(d3.interpolateBlues)
326
+ .domain([0, d3.max(data.flat())]);
327
+
328
+ for (let i = 0; i < rows; i++) {
329
+ for (let j = 0; j < cols; j++) {
330
+ svg.append('rect')
331
+ .attr('x', j * cellSize)
332
+ .attr('y', i * cellSize)
333
+ .attr('width', cellSize)
334
+ .attr('height', cellSize)
335
+ .attr('fill', color(data[i][j]))
336
+ .attr('stroke', 'white');
337
+
338
+ svg.append('text')
339
+ .attr('x', j * cellSize + cellSize / 2)
340
+ .attr('y', i * cellSize + cellSize / 2)
341
+ .attr('text-anchor', 'middle')
342
+ .attr('dominant-baseline', 'middle')
343
+ .attr('fill', data[i][j] > 5 ? 'white' : 'black')
344
+ .text(data[i][j]);
345
+ }
346
+ }
347
+ },
348
+ data: [
349
+ [1, 3, 5, 7],
350
+ [2, 4, 6, 8],
351
+ [9, 7, 5, 3],
352
+ [8, 6, 4, 2]
353
+ ]
354
+ }
355
+ });
356
+ ```
357
+
358
+ ## Parameters
359
+
360
+ | Parameter | Type | Default | Description |
361
+ |-----------|------|---------|-------------|
362
+ | `width` | number | 800 | Output width in pixels |
363
+ | `height` | number | 600 | Output height in pixels |
364
+ | `backgroundColor` | string | 'white' | Background color |
365
+ | `render` | function | *required* | Function that receives (svg, d3, data) |
366
+ | `renderString` | string | - | String version of render function (for serialization) |
367
+ | `data` | any | [] | Data to pass to render function |
368
+
369
+ ## Configuration
370
+
371
+ ```typescript
372
+ imgflo.registerGenerator(d3viz({
373
+ width: 1000, // Default width
374
+ height: 600, // Default height
375
+ backgroundColor: '#f0f0f0' // Default background
376
+ }));
377
+ ```
378
+
379
+ ## Features
380
+
381
+ - **Full D3 API**: Complete access to all D3 capabilities
382
+ - **Server-side rendering**: No browser required
383
+ - **SVG output**: Scalable vector graphics
384
+ - **Pass-through pattern**: Zero abstraction, pure D3 code
385
+ - **Type-safe**: Full TypeScript support
386
+
387
+ ## D3 Documentation
388
+
389
+ For full D3 capabilities and examples:
390
+ - https://d3js.org/
391
+ - https://observablehq.com/@d3/gallery
392
+
393
+ ## Performance
394
+
395
+ - **Generation time**: ~10-100ms depending on complexity
396
+ - **Memory**: Minimal (~5-20MB)
397
+ - **No external dependencies**: Pure Node.js
398
+
399
+ ## Use Cases
400
+
401
+ ### Data Reports
402
+
403
+ ```typescript
404
+ // Generate multiple charts for a report
405
+ const charts = await Promise.all([
406
+ imgflo.generate({ generator: 'd3', params: salesChartConfig }),
407
+ imgflo.generate({ generator: 'd3', params: revenueChartConfig }),
408
+ imgflo.generate({ generator: 'd3', params: growthChartConfig })
409
+ ]);
410
+ ```
411
+
412
+ ### Real-time Dashboards
413
+
414
+ ```typescript
415
+ // Update charts with live data
416
+ setInterval(async () => {
417
+ const liveData = await fetchLiveData();
418
+ const chart = await imgflo.generate({
419
+ generator: 'd3',
420
+ params: {
421
+ render: createChartRenderer(),
422
+ data: liveData
423
+ }
424
+ });
425
+ await imgflo.save(chart, './output/dashboard-live.svg');
426
+ }, 60000);
427
+ ```
428
+
429
+ ### API Endpoints
430
+
431
+ ```typescript
432
+ app.get('/api/chart/:type', async (req, res) => {
433
+ const data = await fetchData(req.params.type);
434
+ const chart = await imgflo.generate({
435
+ generator: 'd3',
436
+ params: { render: getRenderer(req.params.type), data }
437
+ });
438
+ res.type('image/svg+xml').send(chart.bytes);
439
+ });
440
+ ```
441
+
442
+ ## License
443
+
444
+ MIT
445
+
446
+ ## See Also
447
+
448
+ - [imgflo](https://github.com/bcooke/imgflo) - Core library
449
+ - [D3.js](https://d3js.org/) - Data visualization library
@@ -0,0 +1,81 @@
1
+ import type { ImageGenerator, GeneratorSchema } from "@teamflojo/floimg";
2
+ /**
3
+ * Schema for the D3 visualization generator
4
+ */
5
+ export declare const d3Schema: GeneratorSchema;
6
+ /**
7
+ * D3 data visualization generator using server-side rendering
8
+ *
9
+ * This generator accepts D3 code directly (pass-through pattern).
10
+ * You provide a render function that uses D3 to create visualizations.
11
+ * No imgflo abstraction - you get full D3 capabilities.
12
+ *
13
+ * @see https://d3js.org/ - D3 documentation
14
+ *
15
+ * @example
16
+ * ```typescript
17
+ * import createClient from '@teamflojo/floimg';
18
+ * import d3viz from '@teamflojo/floimg-d3';
19
+ *
20
+ * const floimg = createClient();
21
+ * floimg.registerGenerator(d3viz());
22
+ *
23
+ * const chart = await floimg.generate({
24
+ * generator: 'd3',
25
+ * params: {
26
+ * width: 600,
27
+ * height: 400,
28
+ * render: (svg, d3, data) => {
29
+ * // Use D3 directly
30
+ * svg.selectAll('rect')
31
+ * .data(data)
32
+ * .join('rect')
33
+ * .attr('x', (d, i) => i * 50)
34
+ * .attr('y', d => 400 - d.value * 10)
35
+ * .attr('width', 40)
36
+ * .attr('height', d => d.value * 10)
37
+ * .attr('fill', 'steelblue');
38
+ * },
39
+ * data: [
40
+ * { value: 10 },
41
+ * { value: 20 },
42
+ * { value: 15 }
43
+ * ]
44
+ * }
45
+ * });
46
+ * ```
47
+ */
48
+ export interface D3Config {
49
+ /** Default width (default: 800) */
50
+ width?: number;
51
+ /** Default height (default: 600) */
52
+ height?: number;
53
+ /** Default background color */
54
+ backgroundColor?: string;
55
+ }
56
+ export interface D3Params extends Record<string, unknown> {
57
+ /** Width of the visualization */
58
+ width?: number;
59
+ /** Height of the visualization */
60
+ height?: number;
61
+ /** Background color */
62
+ backgroundColor?: string;
63
+ /**
64
+ * Render function that receives (svg, d3, data) and creates the visualization
65
+ * The svg is a D3 selection of the root SVG element
66
+ */
67
+ render?: (svg: any, d3: typeof import('d3'), data: any) => void;
68
+ /**
69
+ * String version of render function (for serialization)
70
+ * Will be eval'd in a safe context
71
+ */
72
+ renderString?: string;
73
+ /** Data to pass to the render function */
74
+ data?: any;
75
+ }
76
+ /**
77
+ * Create a D3 generator instance
78
+ */
79
+ export default function d3viz(config?: D3Config): ImageGenerator;
80
+ export { d3viz };
81
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAa,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAEpF;;GAEG;AACH,eAAO,MAAM,QAAQ,EAAE,eAuCtB,CAAC;AAIF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyCG;AACH,MAAM,WAAW,QAAQ;IACvB,mCAAmC;IACnC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,oCAAoC;IACpC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,+BAA+B;IAC/B,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,QAAS,SAAQ,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IACvD,iCAAiC;IACjC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,kCAAkC;IAClC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,uBAAuB;IACvB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB;;;OAGG;IACH,MAAM,CAAC,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,EAAE,cAAc,IAAI,CAAC,EAAE,IAAI,EAAE,GAAG,KAAK,IAAI,CAAC;IAChE;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,0CAA0C;IAC1C,IAAI,CAAC,EAAE,GAAG,CAAC;CACZ;AAED;;GAEG;AACH,MAAM,CAAC,OAAO,UAAU,KAAK,CAAC,MAAM,GAAE,QAAa,GAAG,cAAc,CA0EnE;AAGD,OAAO,EAAE,KAAK,EAAE,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,108 @@
1
+ /**
2
+ * Schema for the D3 visualization generator
3
+ */
4
+ export const d3Schema = {
5
+ name: "d3",
6
+ description: "Create custom data visualizations using D3.js with server-side rendering",
7
+ category: "Charts",
8
+ parameters: {
9
+ width: {
10
+ type: "number",
11
+ title: "Width",
12
+ description: "Width of the visualization in pixels",
13
+ default: 800,
14
+ minimum: 100,
15
+ maximum: 4096,
16
+ },
17
+ height: {
18
+ type: "number",
19
+ title: "Height",
20
+ description: "Height of the visualization in pixels",
21
+ default: 600,
22
+ minimum: 100,
23
+ maximum: 4096,
24
+ },
25
+ backgroundColor: {
26
+ type: "string",
27
+ title: "Background Color",
28
+ description: "Background color (hex, rgb, or named color)",
29
+ default: "white",
30
+ },
31
+ renderString: {
32
+ type: "string",
33
+ title: "Render Function",
34
+ description: "JavaScript code that receives (svg, d3, data) and creates the visualization",
35
+ },
36
+ data: {
37
+ type: "object",
38
+ title: "Data",
39
+ description: "Data to pass to the render function",
40
+ },
41
+ },
42
+ requiredParameters: ["renderString"],
43
+ };
44
+ import * as d3 from "d3";
45
+ import { JSDOM } from "jsdom";
46
+ /**
47
+ * Create a D3 generator instance
48
+ */
49
+ export default function d3viz(config = {}) {
50
+ const { width: defaultWidth = 800, height: defaultHeight = 600, backgroundColor: defaultBgColor = 'white', } = config;
51
+ return {
52
+ name: "d3",
53
+ schema: d3Schema,
54
+ async generate(params) {
55
+ const { width = defaultWidth, height = defaultHeight, backgroundColor = defaultBgColor, render, renderString, data = [], } = params;
56
+ if (!render && !renderString) {
57
+ throw new Error("D3 generator requires either 'render' function or 'renderString' parameter");
58
+ }
59
+ // Create a fake DOM using jsdom
60
+ const dom = new JSDOM('<!DOCTYPE html><html><body></body></html>');
61
+ const document = dom.window.document;
62
+ // Create SVG element
63
+ const body = d3.select(document.body);
64
+ const svg = body
65
+ .append('svg')
66
+ .attr('xmlns', 'http://www.w3.org/2000/svg')
67
+ .attr('width', width)
68
+ .attr('height', height)
69
+ .style('background-color', backgroundColor);
70
+ // Execute render function
71
+ try {
72
+ if (render) {
73
+ // Direct function call
74
+ await render(svg, d3, data);
75
+ }
76
+ else if (renderString) {
77
+ // Eval string (for serialization scenarios like MCP)
78
+ const renderFn = new Function('svg', 'd3', 'data', renderString);
79
+ await renderFn(svg, d3, data);
80
+ }
81
+ }
82
+ catch (error) {
83
+ throw new Error(`D3 render function failed: ${error.message}`);
84
+ }
85
+ // Get the SVG string
86
+ const svgNode = svg.node();
87
+ if (!svgNode) {
88
+ throw new Error('Failed to create SVG element');
89
+ }
90
+ const svgString = svgNode.outerHTML;
91
+ const bytes = Buffer.from(svgString, 'utf-8');
92
+ return {
93
+ bytes,
94
+ mime: 'image/svg+xml',
95
+ width: width,
96
+ height: height,
97
+ source: "d3",
98
+ metadata: {
99
+ backgroundColor,
100
+ dataPoints: Array.isArray(data) ? data.length : undefined,
101
+ },
102
+ };
103
+ },
104
+ };
105
+ }
106
+ // Also export as named export for convenience
107
+ export { d3viz };
108
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,59 @@
1
+ {
2
+ "name": "@teamflojo/floimg-d3",
3
+ "version": "0.1.0",
4
+ "description": "D3 data visualization generator for floimg using server-side rendering",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "import": "./dist/index.js",
11
+ "types": "./dist/index.d.ts"
12
+ }
13
+ },
14
+ "files": [
15
+ "dist",
16
+ "README.md",
17
+ "LICENSE"
18
+ ],
19
+ "keywords": [
20
+ "floimg",
21
+ "d3",
22
+ "data-visualization",
23
+ "charts",
24
+ "svg",
25
+ "image-generation"
26
+ ],
27
+ "author": "Brett Cooke",
28
+ "license": "MIT",
29
+ "repository": {
30
+ "type": "git",
31
+ "url": "https://github.com/TeamFlojo/floimg.git",
32
+ "directory": "packages/floimg-d3"
33
+ },
34
+ "peerDependencies": {
35
+ "@teamflojo/floimg": "^0.1.0"
36
+ },
37
+ "dependencies": {
38
+ "d3": "^7.9.0",
39
+ "jsdom": "^25.0.1"
40
+ },
41
+ "devDependencies": {
42
+ "@types/d3": "^7.4.3",
43
+ "@types/jsdom": "^21.1.7",
44
+ "@types/node": "^22.10.2",
45
+ "typescript": "^5.7.2",
46
+ "vitest": "^2.1.8",
47
+ "@teamflojo/floimg": "0.1.0"
48
+ },
49
+ "engines": {
50
+ "node": ">=18.0.0"
51
+ },
52
+ "scripts": {
53
+ "build": "tsc",
54
+ "dev": "tsc --watch",
55
+ "test": "vitest",
56
+ "typecheck": "tsc --noEmit",
57
+ "clean": "rm -rf dist"
58
+ }
59
+ }