eleventy-plugin-uncharted 0.1.1 → 0.1.2
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/README.md +4 -4
- package/css/uncharted.css +4 -0
- package/package.json +1 -1
- package/src/index.js +1 -1
- package/src/renderers/donut.js +13 -9
- package/src/renderers/dot.js +5 -4
- package/src/renderers/stacked-bar.js +4 -3
- package/src/renderers/stacked-column.js +5 -4
- package/src/utils.js +22 -2
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Uncharted
|
|
2
2
|
|
|
3
|
-
A CSS-based
|
|
3
|
+
A CSS-based chart plugin for Eleventy. Renders charts as pure HTML/CSS with no JavaScript dependencies.
|
|
4
4
|
|
|
5
5
|
## Installation
|
|
6
6
|
|
|
@@ -110,10 +110,10 @@ charts:
|
|
|
110
110
|
|
|
111
111
|
## CSV Format
|
|
112
112
|
|
|
113
|
-
CSV files use the first column as labels and subsequent columns as data series:
|
|
113
|
+
CSV files use the first column as labels and subsequent columns as data series. The column names can be anything descriptive:
|
|
114
114
|
|
|
115
115
|
```csv
|
|
116
|
-
|
|
116
|
+
department,existing,new
|
|
117
117
|
Finance,11,11
|
|
118
118
|
Sales,16,2
|
|
119
119
|
Core,8,0
|
|
@@ -135,7 +135,7 @@ Stacked column, dot, and scatter charts support negative values. When negative v
|
|
|
135
135
|
For stacked columns, positive values stack upward from zero and negative values stack downward:
|
|
136
136
|
|
|
137
137
|
```csv
|
|
138
|
-
|
|
138
|
+
quarter,Cost,Profit
|
|
139
139
|
Q1,20,10
|
|
140
140
|
Q2,25,-10
|
|
141
141
|
Q3,15,25
|
package/css/uncharted.css
CHANGED
|
@@ -201,6 +201,7 @@
|
|
|
201
201
|
height: 100%;
|
|
202
202
|
width: var(--value);
|
|
203
203
|
transition: width 0.3s ease;
|
|
204
|
+
background-color: var(--color);
|
|
204
205
|
}
|
|
205
206
|
|
|
206
207
|
.chart-stacked-bar .bar-value {
|
|
@@ -243,6 +244,7 @@
|
|
|
243
244
|
width: 100%;
|
|
244
245
|
height: var(--value);
|
|
245
246
|
transition: height 0.3s ease;
|
|
247
|
+
background-color: var(--color);
|
|
246
248
|
}
|
|
247
249
|
|
|
248
250
|
.chart-stacked-column .column-labels {
|
|
@@ -381,6 +383,7 @@
|
|
|
381
383
|
bottom: var(--value);
|
|
382
384
|
transform: translate(-50%, 50%);
|
|
383
385
|
cursor: default;
|
|
386
|
+
background-color: var(--color);
|
|
384
387
|
}
|
|
385
388
|
|
|
386
389
|
.chart-dot .dot[title]:hover {
|
|
@@ -443,6 +446,7 @@
|
|
|
443
446
|
bottom: var(--value);
|
|
444
447
|
transform: translate(-50%, 50%);
|
|
445
448
|
cursor: default;
|
|
449
|
+
background-color: var(--color);
|
|
446
450
|
}
|
|
447
451
|
|
|
448
452
|
.chart-scatter .dot[title]:hover {
|
package/package.json
CHANGED
package/src/index.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
export { renderers } from './renderers/index.js';
|
|
2
2
|
export { loadCSV, parseCSV } from './csv.js';
|
|
3
|
-
export { slugify, calculatePercentages, getSeriesNames, escapeHtml } from './utils.js';
|
|
3
|
+
export { slugify, calculatePercentages, getLabelKey, getValueKey, getSeriesNames, escapeHtml } from './utils.js';
|
package/src/renderers/donut.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { slugify, escapeHtml } from '../utils.js';
|
|
1
|
+
import { slugify, escapeHtml, getLabelKey, getValueKey, getSeriesNames } from '../utils.js';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Render a donut/pie chart using conic-gradient
|
|
@@ -22,18 +22,22 @@ export function renderDonut(config) {
|
|
|
22
22
|
|
|
23
23
|
const animateClass = animate ? ' chart-animate' : '';
|
|
24
24
|
|
|
25
|
-
//
|
|
25
|
+
// Get column keys positionally
|
|
26
|
+
const labelKey = getLabelKey(data);
|
|
27
|
+
const valueKey = getValueKey(data);
|
|
28
|
+
const seriesKeys = getSeriesNames(data);
|
|
29
|
+
|
|
30
|
+
// Extract values - support both label/value format and series format
|
|
26
31
|
let segments = [];
|
|
27
|
-
if (
|
|
28
|
-
//
|
|
32
|
+
if (seriesKeys.length === 1) {
|
|
33
|
+
// Two columns: first is label, second is value (multiple rows)
|
|
29
34
|
segments = data.map(item => ({
|
|
30
|
-
label: item
|
|
31
|
-
value: typeof item
|
|
35
|
+
label: item[labelKey],
|
|
36
|
+
value: typeof item[valueKey] === 'number' ? item[valueKey] : parseFloat(item[valueKey]) || 0
|
|
32
37
|
}));
|
|
33
38
|
} else {
|
|
34
|
-
// Series format - first row only
|
|
35
|
-
|
|
36
|
-
segments = seriesNames.map(name => ({
|
|
39
|
+
// Series format - first row only, columns after the first are series
|
|
40
|
+
segments = seriesKeys.map(name => ({
|
|
37
41
|
label: name,
|
|
38
42
|
value: typeof data[0][name] === 'number' ? data[0][name] : parseFloat(data[0][name]) || 0
|
|
39
43
|
}));
|
package/src/renderers/dot.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { slugify, escapeHtml, getSeriesNames } from '../utils.js';
|
|
1
|
+
import { slugify, escapeHtml, getLabelKey, getSeriesNames } from '../utils.js';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Render a categorical dot chart (columns with dots at different Y positions)
|
|
@@ -20,7 +20,8 @@ export function renderDot(config) {
|
|
|
20
20
|
return `<!-- Dot chart: no data provided -->`;
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
-
// Get
|
|
23
|
+
// Get label key (first column) and series keys (remaining columns)
|
|
24
|
+
const labelKey = getLabelKey(data);
|
|
24
25
|
const seriesKeys = getSeriesNames(data);
|
|
25
26
|
const legendLabels = legend ?? seriesKeys;
|
|
26
27
|
const animateClass = animate ? ' chart-animate' : '';
|
|
@@ -82,7 +83,7 @@ export function renderDot(config) {
|
|
|
82
83
|
|
|
83
84
|
// Each row becomes a column with dots for each series
|
|
84
85
|
data.forEach(row => {
|
|
85
|
-
const label = row
|
|
86
|
+
const label = row[labelKey] ?? '';
|
|
86
87
|
|
|
87
88
|
html += `<div class="dot-col">`;
|
|
88
89
|
|
|
@@ -110,7 +111,7 @@ export function renderDot(config) {
|
|
|
110
111
|
// X-axis labels
|
|
111
112
|
html += `<div class="dot-labels">`;
|
|
112
113
|
data.forEach(row => {
|
|
113
|
-
const label = row
|
|
114
|
+
const label = row[labelKey] ?? '';
|
|
114
115
|
html += `<span class="dot-label">${escapeHtml(label)}</span>`;
|
|
115
116
|
});
|
|
116
117
|
html += `</div>`;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { slugify, calculatePercentages, getSeriesNames, escapeHtml } from '../utils.js';
|
|
1
|
+
import { slugify, calculatePercentages, getLabelKey, getSeriesNames, escapeHtml } from '../utils.js';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Render a stacked bar chart (horizontal)
|
|
@@ -18,7 +18,8 @@ export function renderStackedBar(config) {
|
|
|
18
18
|
return `<!-- Stacked bar chart: no data provided -->`;
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
-
// Get
|
|
21
|
+
// Get label key (first column) and series keys (remaining columns)
|
|
22
|
+
const labelKey = getLabelKey(data);
|
|
22
23
|
const seriesKeys = getSeriesNames(data);
|
|
23
24
|
// Use legend for display labels, fall back to data keys
|
|
24
25
|
const legendLabels = legend ?? seriesKeys;
|
|
@@ -49,7 +50,7 @@ export function renderStackedBar(config) {
|
|
|
49
50
|
html += `<div class="chart-bars">`;
|
|
50
51
|
|
|
51
52
|
data.forEach(row => {
|
|
52
|
-
const label = row
|
|
53
|
+
const label = row[labelKey] ?? '';
|
|
53
54
|
const values = seriesKeys.map(key => {
|
|
54
55
|
const val = row[key];
|
|
55
56
|
return typeof val === 'number' ? val : parseFloat(val) || 0;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { slugify, getSeriesNames, escapeHtml } from '../utils.js';
|
|
1
|
+
import { slugify, getLabelKey, getSeriesNames, escapeHtml } from '../utils.js';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Render a stacked column chart (vertical)
|
|
@@ -19,7 +19,8 @@ export function renderStackedColumn(config) {
|
|
|
19
19
|
return `<!-- Stacked column chart: no data provided -->`;
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
-
// Get
|
|
22
|
+
// Get label key (first column) and series keys (remaining columns)
|
|
23
|
+
const labelKey = getLabelKey(data);
|
|
23
24
|
const seriesKeys = getSeriesNames(data);
|
|
24
25
|
// Use legend for display labels, fall back to data keys
|
|
25
26
|
const legendLabels = legend ?? seriesKeys;
|
|
@@ -90,7 +91,7 @@ export function renderStackedColumn(config) {
|
|
|
90
91
|
html += `<div class="chart-columns"${columnsStyle}>`;
|
|
91
92
|
|
|
92
93
|
data.forEach(row => {
|
|
93
|
-
const label = row
|
|
94
|
+
const label = row[labelKey] ?? '';
|
|
94
95
|
html += `<div class="column-track" title="${escapeHtml(label)}">`;
|
|
95
96
|
|
|
96
97
|
if (hasNegativeY) {
|
|
@@ -173,7 +174,7 @@ export function renderStackedColumn(config) {
|
|
|
173
174
|
// X-axis labels
|
|
174
175
|
html += `<div class="column-labels">`;
|
|
175
176
|
data.forEach(row => {
|
|
176
|
-
const label = row
|
|
177
|
+
const label = row[labelKey] ?? '';
|
|
177
178
|
html += `<span class="column-label">${escapeHtml(label)}</span>`;
|
|
178
179
|
});
|
|
179
180
|
html += `</div>`;
|
package/src/utils.js
CHANGED
|
@@ -25,13 +25,33 @@ export function calculatePercentages(values, max) {
|
|
|
25
25
|
}
|
|
26
26
|
|
|
27
27
|
/**
|
|
28
|
-
*
|
|
28
|
+
* Get the label key (first column name) from CSV data
|
|
29
|
+
* @param {Object[]} data - Array of data objects
|
|
30
|
+
* @returns {string|undefined} - The first column name, or undefined if no data
|
|
31
|
+
*/
|
|
32
|
+
export function getLabelKey(data) {
|
|
33
|
+
if (!data || data.length === 0) return undefined;
|
|
34
|
+
return Object.keys(data[0])[0];
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Get the value key (second column name) from CSV data
|
|
39
|
+
* @param {Object[]} data - Array of data objects
|
|
40
|
+
* @returns {string|undefined} - The second column name, or undefined if no data
|
|
41
|
+
*/
|
|
42
|
+
export function getValueKey(data) {
|
|
43
|
+
if (!data || data.length === 0) return undefined;
|
|
44
|
+
return Object.keys(data[0])[1];
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Extract series names from CSV data (all columns except the first)
|
|
29
49
|
* @param {Object[]} data - Array of data objects
|
|
30
50
|
* @returns {string[]} - Array of series names
|
|
31
51
|
*/
|
|
32
52
|
export function getSeriesNames(data) {
|
|
33
53
|
if (!data || data.length === 0) return [];
|
|
34
|
-
return Object.keys(data[0]).
|
|
54
|
+
return Object.keys(data[0]).slice(1);
|
|
35
55
|
}
|
|
36
56
|
|
|
37
57
|
/**
|