@classic-homes/charts-core 0.3.0 → 0.3.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 +43 -0
- package/dist/index.cjs +13 -5
- package/dist/index.d.cts +5 -1
- package/dist/index.d.ts +5 -1
- package/dist/index.js +13 -5
- package/package.json +25 -10
package/README.md
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# @classic-homes/charts-core
|
|
2
|
+
|
|
3
|
+
Framework-agnostic utilities, types, and ECharts themes for Classic Theme chart components. This package is the shared foundation for `@classic-homes/charts-react` and `@classic-homes/charts-svelte`.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @classic-homes/charts-core echarts
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
Peer dependency: `echarts@^5.5.0`.
|
|
12
|
+
|
|
13
|
+
## Exports
|
|
14
|
+
|
|
15
|
+
| Import | Contents |
|
|
16
|
+
| ---------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
17
|
+
| `@classic-homes/charts-core` | Themes, chart color helpers, prop and data types, formatting and data utilities |
|
|
18
|
+
| `@classic-homes/charts-core/theme` | `generateLightTheme`, `generateDarkTheme`, `lightTheme`, `darkTheme`, `THEME_LIGHT`, `THEME_DARK`, `lightChartColors`, `darkChartColors`, `getChartColors`, `colorWithAlpha` |
|
|
19
|
+
| `@classic-homes/charts-core/types` | Chart prop, data, and event types (`LineChartData`, `BarChartProps`, `ChartEventHandlers`, ...) |
|
|
20
|
+
|
|
21
|
+
## Usage
|
|
22
|
+
|
|
23
|
+
### Themes
|
|
24
|
+
|
|
25
|
+
```typescript
|
|
26
|
+
import { lightTheme, darkTheme } from '@classic-homes/charts-core/theme';
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
### Types
|
|
30
|
+
|
|
31
|
+
```typescript
|
|
32
|
+
import type { LineChartData, BarChartData, PieSliceData } from '@classic-homes/charts-core/types';
|
|
33
|
+
|
|
34
|
+
const revenue: LineChartData = {
|
|
35
|
+
categories: ['Jan', 'Feb', 'Mar'],
|
|
36
|
+
series: [{ name: '2025', data: [120, 132, 101] }],
|
|
37
|
+
};
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## Related Packages
|
|
41
|
+
|
|
42
|
+
- `@classic-homes/charts-react`: React ECharts components
|
|
43
|
+
- `@classic-homes/charts-svelte`: Svelte ECharts components
|
package/dist/index.cjs
CHANGED
|
@@ -1290,10 +1290,11 @@ function toSliceData(rows, options) {
|
|
|
1290
1290
|
nullLabel = "Unknown",
|
|
1291
1291
|
colors: colors3
|
|
1292
1292
|
} = options;
|
|
1293
|
+
const effective = value === void 0 ? "count" : aggregate;
|
|
1293
1294
|
const { categories, series } = fromRecords(rows, {
|
|
1294
1295
|
category: name,
|
|
1295
1296
|
value,
|
|
1296
|
-
aggregate:
|
|
1297
|
+
aggregate: effective,
|
|
1297
1298
|
nullLabel
|
|
1298
1299
|
});
|
|
1299
1300
|
const values = series[0]?.data ?? [];
|
|
@@ -1307,7 +1308,12 @@ function toSliceData(rows, options) {
|
|
|
1307
1308
|
const rest = slices.slice(topN);
|
|
1308
1309
|
slices = slices.slice(0, topN);
|
|
1309
1310
|
if (otherLabel !== void 0) {
|
|
1310
|
-
|
|
1311
|
+
const folded = new Set(rest.map((slice) => slice.name));
|
|
1312
|
+
const other = fromRecords(
|
|
1313
|
+
(rows ?? []).filter((row) => folded.has(toLabel(read(row, name), nullLabel))),
|
|
1314
|
+
{ category: () => otherLabel, value, aggregate: effective }
|
|
1315
|
+
).series[0]?.data[0];
|
|
1316
|
+
slices.push({ name: otherLabel, value: other ?? 0 });
|
|
1311
1317
|
}
|
|
1312
1318
|
}
|
|
1313
1319
|
return slices.map(
|
|
@@ -1468,15 +1474,17 @@ function formatTableCell(table, cell, column, format) {
|
|
|
1468
1474
|
return formatValue(cell, format);
|
|
1469
1475
|
}
|
|
1470
1476
|
}
|
|
1471
|
-
|
|
1477
|
+
var FORMULA_START = /^[=+\-@\t\r]/;
|
|
1478
|
+
function csvCell(cell, raw = cell) {
|
|
1472
1479
|
if (cell == null) return "";
|
|
1473
|
-
|
|
1480
|
+
let text = String(cell);
|
|
1481
|
+
if (typeof raw === "string" && FORMULA_START.test(text)) text = `'${text}`;
|
|
1474
1482
|
return /[",\r\n]/.test(text) ? `"${text.replace(/"/g, '""')}"` : text;
|
|
1475
1483
|
}
|
|
1476
1484
|
function tableToCsv(table, format) {
|
|
1477
1485
|
const lines = [table.headers, ...table.rows].map(
|
|
1478
1486
|
(row, rowIndex) => row.map(
|
|
1479
|
-
(cell, column) => csvCell(rowIndex > 0 && format ? formatTableCell(table, cell, column, format) : cell)
|
|
1487
|
+
(cell, column) => csvCell(rowIndex > 0 && format ? formatTableCell(table, cell, column, format) : cell, cell)
|
|
1480
1488
|
).join(",")
|
|
1481
1489
|
);
|
|
1482
1490
|
return lines.join("\r\n");
|
package/dist/index.d.cts
CHANGED
|
@@ -536,7 +536,11 @@ interface ToSliceDataOptions<T> {
|
|
|
536
536
|
sort?: 'desc' | 'asc' | 'none';
|
|
537
537
|
/** Keep only the largest N slices */
|
|
538
538
|
topN?: number;
|
|
539
|
-
/**
|
|
539
|
+
/**
|
|
540
|
+
* Fold slices beyond `topN` into one with this label; omit to drop them.
|
|
541
|
+
* The folded slice aggregates the folded records, so with 'avg' it is their
|
|
542
|
+
* average rather than a sum of averages.
|
|
543
|
+
*/
|
|
540
544
|
otherLabel?: string;
|
|
541
545
|
/** Label for a missing name (defaults to 'Unknown') */
|
|
542
546
|
nullLabel?: string;
|
package/dist/index.d.ts
CHANGED
|
@@ -536,7 +536,11 @@ interface ToSliceDataOptions<T> {
|
|
|
536
536
|
sort?: 'desc' | 'asc' | 'none';
|
|
537
537
|
/** Keep only the largest N slices */
|
|
538
538
|
topN?: number;
|
|
539
|
-
/**
|
|
539
|
+
/**
|
|
540
|
+
* Fold slices beyond `topN` into one with this label; omit to drop them.
|
|
541
|
+
* The folded slice aggregates the folded records, so with 'avg' it is their
|
|
542
|
+
* average rather than a sum of averages.
|
|
543
|
+
*/
|
|
540
544
|
otherLabel?: string;
|
|
541
545
|
/** Label for a missing name (defaults to 'Unknown') */
|
|
542
546
|
nullLabel?: string;
|
package/dist/index.js
CHANGED
|
@@ -969,10 +969,11 @@ function toSliceData(rows, options) {
|
|
|
969
969
|
nullLabel = "Unknown",
|
|
970
970
|
colors
|
|
971
971
|
} = options;
|
|
972
|
+
const effective = value === void 0 ? "count" : aggregate;
|
|
972
973
|
const { categories, series } = fromRecords(rows, {
|
|
973
974
|
category: name,
|
|
974
975
|
value,
|
|
975
|
-
aggregate:
|
|
976
|
+
aggregate: effective,
|
|
976
977
|
nullLabel
|
|
977
978
|
});
|
|
978
979
|
const values = series[0]?.data ?? [];
|
|
@@ -986,7 +987,12 @@ function toSliceData(rows, options) {
|
|
|
986
987
|
const rest = slices.slice(topN);
|
|
987
988
|
slices = slices.slice(0, topN);
|
|
988
989
|
if (otherLabel !== void 0) {
|
|
989
|
-
|
|
990
|
+
const folded = new Set(rest.map((slice) => slice.name));
|
|
991
|
+
const other = fromRecords(
|
|
992
|
+
(rows ?? []).filter((row) => folded.has(toLabel(read(row, name), nullLabel))),
|
|
993
|
+
{ category: () => otherLabel, value, aggregate: effective }
|
|
994
|
+
).series[0]?.data[0];
|
|
995
|
+
slices.push({ name: otherLabel, value: other ?? 0 });
|
|
990
996
|
}
|
|
991
997
|
}
|
|
992
998
|
return slices.map(
|
|
@@ -1147,15 +1153,17 @@ function formatTableCell(table, cell, column, format) {
|
|
|
1147
1153
|
return formatValue(cell, format);
|
|
1148
1154
|
}
|
|
1149
1155
|
}
|
|
1150
|
-
|
|
1156
|
+
var FORMULA_START = /^[=+\-@\t\r]/;
|
|
1157
|
+
function csvCell(cell, raw = cell) {
|
|
1151
1158
|
if (cell == null) return "";
|
|
1152
|
-
|
|
1159
|
+
let text = String(cell);
|
|
1160
|
+
if (typeof raw === "string" && FORMULA_START.test(text)) text = `'${text}`;
|
|
1153
1161
|
return /[",\r\n]/.test(text) ? `"${text.replace(/"/g, '""')}"` : text;
|
|
1154
1162
|
}
|
|
1155
1163
|
function tableToCsv(table, format) {
|
|
1156
1164
|
const lines = [table.headers, ...table.rows].map(
|
|
1157
1165
|
(row, rowIndex) => row.map(
|
|
1158
|
-
(cell, column) => csvCell(rowIndex > 0 && format ? formatTableCell(table, cell, column, format) : cell)
|
|
1166
|
+
(cell, column) => csvCell(rowIndex > 0 && format ? formatTableCell(table, cell, column, format) : cell, cell)
|
|
1159
1167
|
).join(",")
|
|
1160
1168
|
);
|
|
1161
1169
|
return lines.join("\r\n");
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@classic-homes/charts-core",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.2",
|
|
4
4
|
"description": "Core utilities and theme for Classic Theme charts",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.cjs",
|
|
@@ -8,19 +8,34 @@
|
|
|
8
8
|
"types": "dist/index.d.ts",
|
|
9
9
|
"exports": {
|
|
10
10
|
".": {
|
|
11
|
-
"
|
|
12
|
-
|
|
13
|
-
|
|
11
|
+
"import": {
|
|
12
|
+
"types": "./dist/index.d.ts",
|
|
13
|
+
"default": "./dist/index.js"
|
|
14
|
+
},
|
|
15
|
+
"require": {
|
|
16
|
+
"types": "./dist/index.d.cts",
|
|
17
|
+
"default": "./dist/index.cjs"
|
|
18
|
+
}
|
|
14
19
|
},
|
|
15
20
|
"./theme": {
|
|
16
|
-
"
|
|
17
|
-
|
|
18
|
-
|
|
21
|
+
"import": {
|
|
22
|
+
"types": "./dist/theme/index.d.ts",
|
|
23
|
+
"default": "./dist/theme/index.js"
|
|
24
|
+
},
|
|
25
|
+
"require": {
|
|
26
|
+
"types": "./dist/theme/index.d.cts",
|
|
27
|
+
"default": "./dist/theme/index.cjs"
|
|
28
|
+
}
|
|
19
29
|
},
|
|
20
30
|
"./types": {
|
|
21
|
-
"
|
|
22
|
-
|
|
23
|
-
|
|
31
|
+
"import": {
|
|
32
|
+
"types": "./dist/types/index.d.ts",
|
|
33
|
+
"default": "./dist/types/index.js"
|
|
34
|
+
},
|
|
35
|
+
"require": {
|
|
36
|
+
"types": "./dist/types/index.d.cts",
|
|
37
|
+
"default": "./dist/types/index.cjs"
|
|
38
|
+
}
|
|
24
39
|
}
|
|
25
40
|
},
|
|
26
41
|
"sideEffects": false,
|