@epilot/spark-ui 0.20.0 → 0.20.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/dist/components/accordion.cjs +7 -7
- package/dist/components/accordion.cjs.map +1 -1
- package/dist/components/accordion.d.ts +1 -1
- package/dist/components/accordion.js +1 -1
- package/dist/components/alert-dialog.cjs +10 -10
- package/dist/components/alert-dialog.cjs.map +1 -1
- package/dist/components/alert-dialog.js +1 -1
- package/dist/components/attachment.cjs +10 -10
- package/dist/components/attachment.cjs.map +1 -1
- package/dist/components/attachment.d.cts +2 -2
- package/dist/components/attachment.d.ts +2 -2
- package/dist/components/autocomplete.cjs +13 -13
- package/dist/components/autocomplete.cjs.map +1 -1
- package/dist/components/autocomplete.js +1 -1
- package/dist/components/avatar.cjs +2 -2
- package/dist/components/avatar.cjs.map +1 -1
- package/dist/components/avatar.js +1 -1
- package/dist/components/badge.cjs +2 -2
- package/dist/components/badge.cjs.map +1 -1
- package/dist/components/badge.js +2 -2
- package/dist/components/badge.js.map +1 -1
- package/dist/components/bar-chart-with-total.d.cts +1 -1
- package/dist/components/bar-chart-with-total.d.ts +1 -1
- package/dist/components/bar-chart.cjs +4 -4
- package/dist/components/bar-chart.cjs.map +1 -1
- package/dist/components/bar-chart.js +2 -2
- package/dist/components/bar-chart.js.map +1 -1
- package/dist/components/box.cjs +2 -2
- package/dist/components/box.cjs.map +1 -1
- package/dist/components/box.js +1 -1
- package/dist/components/breadcrumbs.cjs +7 -7
- package/dist/components/breadcrumbs.cjs.map +1 -1
- package/dist/components/bubble.cjs +5 -5
- package/dist/components/bubble.cjs.map +1 -1
- package/dist/components/bubble.d.cts +1 -1
- package/dist/components/bubble.d.ts +1 -1
- package/dist/components/button-group.cjs +5 -5
- package/dist/components/button-group.cjs.map +1 -1
- package/dist/components/button-group.js +1 -1
- package/dist/components/button.cjs +2 -2
- package/dist/components/button.cjs.map +1 -1
- package/dist/components/button.d.cts +3 -3
- package/dist/components/button.d.ts +3 -3
- package/dist/components/button.js +1 -1
- package/dist/components/button.js.map +1 -1
- package/dist/components/calendar.cjs +12 -11
- package/dist/components/calendar.cjs.map +1 -1
- package/dist/components/calendar.js +5 -4
- package/dist/components/calendar.js.map +1 -1
- package/dist/components/callout.cjs +8 -8
- package/dist/components/callout.cjs.map +1 -1
- package/dist/components/callout.d.ts +1 -1
- package/dist/components/callout.js +1 -1
- package/dist/components/card.cjs +16 -16
- package/dist/components/card.cjs.map +1 -1
- package/dist/components/card.js +2 -2
- package/dist/components/card.js.map +1 -1
- package/dist/components/chart.cjs +2 -2
- package/dist/components/chart.cjs.map +1 -1
- package/dist/components/checkbox.cjs +2 -2
- package/dist/components/checkbox.cjs.map +1 -1
- package/dist/components/checkbox.js +1 -1
- package/dist/components/checkbox.js.map +1 -1
- package/dist/components/circular-gauge.cjs +3 -3
- package/dist/components/circular-gauge.cjs.map +1 -1
- package/dist/components/circular-gauge.js +1 -1
- package/dist/components/circular-gauge.js.map +1 -1
- package/dist/components/day-of-week-picker.cjs +4 -4
- package/dist/components/day-of-week-picker.cjs.map +1 -1
- package/dist/components/dialog.cjs +9 -9
- package/dist/components/dialog.cjs.map +1 -1
- package/dist/components/dialog.js +1 -1
- package/dist/components/donut-chart.cjs.map +1 -1
- package/dist/components/donut-chart.js.map +1 -1
- package/dist/components/drawer.cjs +8 -8
- package/dist/components/drawer.cjs.map +1 -1
- package/dist/components/drawer.js +2 -2
- package/dist/components/drawer.js.map +1 -1
- package/dist/components/dropdown-menu.cjs +11 -11
- package/dist/components/dropdown-menu.cjs.map +1 -1
- package/dist/components/dropdown-menu.js +1 -1
- package/dist/components/empty-state.d.ts +1 -1
- package/dist/components/energy-breakdown.cjs +80 -0
- package/dist/components/energy-breakdown.cjs.map +1 -0
- package/dist/components/energy-breakdown.d.cts +24 -0
- package/dist/components/energy-breakdown.d.ts +24 -0
- package/dist/components/energy-breakdown.js +79 -0
- package/dist/components/energy-breakdown.js.map +1 -0
- package/dist/components/energy-history-chart.cjs +63 -0
- package/dist/components/energy-history-chart.cjs.map +1 -0
- package/dist/components/energy-history-chart.d.cts +64 -0
- package/dist/components/energy-history-chart.d.ts +64 -0
- package/dist/components/energy-history-chart.js +62 -0
- package/dist/components/energy-history-chart.js.map +1 -0
- package/dist/components/entity-card.cjs +11 -11
- package/dist/components/entity-card.cjs.map +1 -1
- package/dist/components/entity-card.d.ts +1 -1
- package/dist/components/field.cjs +16 -16
- package/dist/components/field.cjs.map +1 -1
- package/dist/components/field.js +1 -1
- package/dist/components/field.js.map +1 -1
- package/dist/components/hero-metric.cjs +4 -4
- package/dist/components/hero-metric.cjs.map +1 -1
- package/dist/components/icon.cjs +6 -6
- package/dist/components/icon.cjs.map +1 -1
- package/dist/components/icon.js +5 -5
- package/dist/components/icon.js.map +1 -1
- package/dist/components/info-block.cjs +9 -9
- package/dist/components/info-block.cjs.map +1 -1
- package/dist/components/info-block.d.cts +1 -1
- package/dist/components/info-block.d.ts +1 -1
- package/dist/components/input-date.cjs +5 -4
- package/dist/components/input-date.cjs.map +1 -1
- package/dist/components/input-date.d.cts +3 -1
- package/dist/components/input-date.d.ts +3 -1
- package/dist/components/input-date.js +3 -2
- package/dist/components/input-date.js.map +1 -1
- package/dist/components/input-group.cjs +5 -5
- package/dist/components/input-group.cjs.map +1 -1
- package/dist/components/input-otp.cjs +3 -3
- package/dist/components/input-otp.cjs.map +1 -1
- package/dist/components/input-otp.js +1 -1
- package/dist/components/input.cjs +3 -3
- package/dist/components/input.cjs.map +1 -1
- package/dist/components/input.js +1 -1
- package/dist/components/label.cjs +2 -2
- package/dist/components/label.cjs.map +1 -1
- package/dist/components/layout.cjs +2 -2
- package/dist/components/layout.cjs.map +1 -1
- package/dist/components/line-chart.cjs +7 -7
- package/dist/components/line-chart.cjs.map +1 -1
- package/dist/components/line-chart.js +5 -5
- package/dist/components/line-chart.js.map +1 -1
- package/dist/components/list.cjs +11 -11
- package/dist/components/list.cjs.map +1 -1
- package/dist/components/list.d.cts +7 -2
- package/dist/components/list.d.ts +7 -2
- package/dist/components/list.js +2 -2
- package/dist/components/list.js.map +1 -1
- package/dist/components/marker.cjs +4 -4
- package/dist/components/marker.cjs.map +1 -1
- package/dist/components/marker.d.cts +1 -1
- package/dist/components/marker.d.ts +1 -1
- package/dist/components/message-scroller.cjs +8 -8
- package/dist/components/message-scroller.cjs.map +1 -1
- package/dist/components/message-scroller.js +4 -4
- package/dist/components/message-scroller.js.map +1 -1
- package/dist/components/message.cjs +7 -7
- package/dist/components/message.cjs.map +1 -1
- package/dist/components/number-flow.d.cts +2 -12
- package/dist/components/number-flow.d.ts +2 -12
- package/dist/components/page-header.cjs +6 -6
- package/dist/components/page-header.cjs.map +1 -1
- package/dist/components/page-header.js +1 -1
- package/dist/components/period-tabs.cjs +6 -6
- package/dist/components/period-tabs.cjs.map +1 -1
- package/dist/components/pill.cjs +4 -4
- package/dist/components/pill.cjs.map +1 -1
- package/dist/components/pill.js +4 -4
- package/dist/components/pill.js.map +1 -1
- package/dist/components/popover.cjs +2 -2
- package/dist/components/popover.cjs.map +1 -1
- package/dist/components/power-history-chart.cjs +498 -0
- package/dist/components/power-history-chart.cjs.map +1 -0
- package/dist/components/power-history-chart.d.cts +71 -0
- package/dist/components/power-history-chart.d.ts +71 -0
- package/dist/components/power-history-chart.js +496 -0
- package/dist/components/power-history-chart.js.map +1 -0
- package/dist/components/power-network.cjs +559 -0
- package/dist/components/power-network.cjs.map +1 -0
- package/dist/components/power-network.d.cts +80 -0
- package/dist/components/power-network.d.ts +80 -0
- package/dist/components/power-network.js +553 -0
- package/dist/components/power-network.js.map +1 -0
- package/dist/components/progress.cjs +3 -3
- package/dist/components/progress.cjs.map +1 -1
- package/dist/components/progress.js +1 -1
- package/dist/components/progress.js.map +1 -1
- package/dist/components/radio-card-group.cjs +3 -3
- package/dist/components/radio-card-group.cjs.map +1 -1
- package/dist/components/radio.cjs +3 -3
- package/dist/components/radio.cjs.map +1 -1
- package/dist/components/radio.js +1 -1
- package/dist/components/sankey-chart.cjs +15 -5
- package/dist/components/sankey-chart.cjs.map +1 -1
- package/dist/components/sankey-chart.d.cts +3 -2
- package/dist/components/sankey-chart.d.ts +3 -2
- package/dist/components/sankey-chart.js +13 -4
- package/dist/components/sankey-chart.js.map +1 -1
- package/dist/components/schedule-editor.cjs +9 -9
- package/dist/components/schedule-editor.cjs.map +1 -1
- package/dist/components/schedule-list.cjs +11 -11
- package/dist/components/schedule-list.cjs.map +1 -1
- package/dist/components/schedule-list.js +1 -1
- package/dist/components/scroll-area.cjs +3 -3
- package/dist/components/scroll-area.cjs.map +1 -1
- package/dist/components/segmented-control.cjs +8 -8
- package/dist/components/segmented-control.cjs.map +1 -1
- package/dist/components/segmented-control.d.cts +2 -16
- package/dist/components/segmented-control.d.ts +2 -16
- package/dist/components/segmented-control.js +5 -5
- package/dist/components/segmented-control.js.map +1 -1
- package/dist/components/select.cjs +13 -13
- package/dist/components/select.cjs.map +1 -1
- package/dist/components/select.js +2 -2
- package/dist/components/separator.cjs +3 -3
- package/dist/components/separator.cjs.map +1 -1
- package/dist/components/series-legend.cjs +4 -4
- package/dist/components/series-legend.cjs.map +1 -1
- package/dist/components/sheet.cjs +9 -9
- package/dist/components/sheet.cjs.map +1 -1
- package/dist/components/sheet.js +1 -1
- package/dist/components/skeleton.cjs +3 -3
- package/dist/components/skeleton.cjs.map +1 -1
- package/dist/components/slider.cjs +11 -11
- package/dist/components/slider.cjs.map +1 -1
- package/dist/components/slider.js.map +1 -1
- package/dist/components/solar-forecast-chart.cjs +108 -0
- package/dist/components/solar-forecast-chart.cjs.map +1 -0
- package/dist/components/solar-forecast-chart.d.cts +77 -0
- package/dist/components/solar-forecast-chart.d.ts +77 -0
- package/dist/components/solar-forecast-chart.js +103 -0
- package/dist/components/solar-forecast-chart.js.map +1 -0
- package/dist/components/sortable-list.cjs +3 -3
- package/dist/components/sortable-list.cjs.map +1 -1
- package/dist/components/spinner.cjs +2 -2
- package/dist/components/spinner.cjs.map +1 -1
- package/dist/components/stat-card.cjs +8 -8
- package/dist/components/stat-card.cjs.map +1 -1
- package/dist/components/stepper.cjs +3 -3
- package/dist/components/stepper.cjs.map +1 -1
- package/dist/components/stepper.js +1 -1
- package/dist/components/switch.cjs +3 -3
- package/dist/components/switch.cjs.map +1 -1
- package/dist/components/switch.js +2 -2
- package/dist/components/switch.js.map +1 -1
- package/dist/components/table.cjs +9 -9
- package/dist/components/table.cjs.map +1 -1
- package/dist/components/table.js +1 -1
- package/dist/components/tabs.cjs +10 -10
- package/dist/components/tabs.cjs.map +1 -1
- package/dist/components/tabs.d.cts +1 -8
- package/dist/components/tabs.d.ts +1 -8
- package/dist/components/tabs.js +3 -3
- package/dist/components/tabs.js.map +1 -1
- package/dist/components/textarea.cjs +3 -3
- package/dist/components/textarea.cjs.map +1 -1
- package/dist/components/textarea.js +1 -1
- package/dist/components/theme.cjs +2 -2
- package/dist/components/theme.cjs.map +1 -1
- package/dist/components/theme.js +1 -1
- package/dist/components/thumbnail.cjs +3 -3
- package/dist/components/thumbnail.cjs.map +1 -1
- package/dist/components/time-picker.cjs +3 -3
- package/dist/components/time-picker.cjs.map +1 -1
- package/dist/components/toast.cjs +40 -15
- package/dist/components/toast.cjs.map +1 -1
- package/dist/components/toast.d.cts +15 -2
- package/dist/components/toast.d.ts +15 -2
- package/dist/components/toast.js +33 -8
- package/dist/components/toast.js.map +1 -1
- package/dist/components/toggle-group.cjs +40 -0
- package/dist/components/toggle-group.cjs.map +1 -0
- package/dist/components/toggle-group.d.cts +28 -0
- package/dist/components/toggle-group.d.ts +28 -0
- package/dist/components/toggle-group.js +37 -0
- package/dist/components/toggle-group.js.map +1 -0
- package/dist/components/toggle.cjs +69 -0
- package/dist/components/toggle.cjs.map +1 -0
- package/dist/components/toggle.d.cts +23 -0
- package/dist/components/toggle.d.ts +23 -0
- package/dist/components/toggle.js +66 -0
- package/dist/components/toggle.js.map +1 -0
- package/dist/components/tooltip.cjs +4 -4
- package/dist/components/tooltip.cjs.map +1 -1
- package/dist/components/tooltip.js +2 -2
- package/dist/components/tooltip.js.map +1 -1
- package/dist/components/typography.cjs +6 -6
- package/dist/components/typography.cjs.map +1 -1
- package/dist/components/wizard-layout.cjs +8 -8
- package/dist/components/wizard-layout.cjs.map +1 -1
- package/dist/lib/generate-radix-colors.cjs +1 -1
- package/dist/lib/generate-radix-colors.cjs.map +1 -1
- package/dist/lib/generate-radix-colors.js +1 -1
- package/dist/lib/generate-radix-colors.js.map +1 -1
- package/dist/lib/input-box-variants.cjs +9 -9
- package/dist/lib/input-box-variants.cjs.map +1 -1
- package/dist/lib/toggle-group-context.cjs +12 -0
- package/dist/lib/toggle-group-context.cjs.map +1 -0
- package/dist/lib/toggle-group-context.d.cts +17 -0
- package/dist/lib/toggle-group-context.d.ts +17 -0
- package/dist/lib/toggle-group-context.js +9 -0
- package/dist/lib/toggle-group-context.js.map +1 -0
- package/dist/number-flow-Bch81ixZ.d.cts +14 -0
- package/dist/number-flow-Bch81ixZ.d.ts +14 -0
- package/dist/styles/spark-default.css +11 -0
- package/dist/styles/theme.css +15 -4
- package/dist/utils/build-sankey-nodes.cjs +72 -0
- package/dist/utils/build-sankey-nodes.cjs.map +1 -0
- package/dist/utils/build-sankey-nodes.d.cts +27 -0
- package/dist/utils/build-sankey-nodes.d.ts +27 -0
- package/dist/utils/build-sankey-nodes.js +71 -0
- package/dist/utils/build-sankey-nodes.js.map +1 -0
- package/dist/utils/cn.cjs +2 -2
- package/dist/utils/cn.d.cts +1 -1
- package/dist/utils/cn.d.ts +1 -1
- package/dist/utils/cn.js +1 -1
- package/dist/utils/format.cjs +14 -0
- package/dist/utils/format.cjs.map +1 -1
- package/dist/utils/format.d.cts +8 -1
- package/dist/utils/format.d.ts +8 -1
- package/dist/utils/format.js +12 -1
- package/dist/utils/format.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
+
//#region src/utils/build-sankey-nodes.ts
|
|
4
|
+
function buildSankeyNodes({ solarPower, batteryPower, gridPower, floorShares, deviceSharesByFloor }) {
|
|
5
|
+
const solar = Math.max(0, solarPower);
|
|
6
|
+
const gridImport = Math.max(0, gridPower);
|
|
7
|
+
const gridExport = Math.max(0, -gridPower);
|
|
8
|
+
const batteryDischarge = Math.max(0, batteryPower);
|
|
9
|
+
const batteryCharge = Math.max(0, -batteryPower);
|
|
10
|
+
const solarToBattery = Math.min(solar, batteryCharge);
|
|
11
|
+
const gridToBattery = Math.min(gridImport, batteryCharge - solarToBattery);
|
|
12
|
+
const solarToFeedIn = Math.min(solar - solarToBattery, gridExport);
|
|
13
|
+
const batteryToFeedIn = Math.min(batteryDischarge, gridExport - solarToFeedIn);
|
|
14
|
+
const links = [
|
|
15
|
+
{
|
|
16
|
+
source: "grid",
|
|
17
|
+
target: "home",
|
|
18
|
+
value: gridImport - gridToBattery
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
source: "solar",
|
|
22
|
+
target: "home",
|
|
23
|
+
value: solar - solarToBattery - solarToFeedIn
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
source: "battery",
|
|
27
|
+
target: "home",
|
|
28
|
+
value: batteryDischarge - batteryToFeedIn
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
source: "solar",
|
|
32
|
+
target: "battery",
|
|
33
|
+
value: solarToBattery
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
source: "grid",
|
|
37
|
+
target: "battery",
|
|
38
|
+
value: gridToBattery
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
source: "solar",
|
|
42
|
+
target: "gridFeedIn",
|
|
43
|
+
value: solarToFeedIn
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
source: "battery",
|
|
47
|
+
target: "gridFeedIn",
|
|
48
|
+
value: batteryToFeedIn
|
|
49
|
+
}
|
|
50
|
+
];
|
|
51
|
+
if (!floorShares) return links;
|
|
52
|
+
const homeWatts = solar - solarToBattery - solarToFeedIn + (gridImport - gridToBattery) + (batteryDischarge - batteryToFeedIn);
|
|
53
|
+
for (const [floorId, share] of Object.entries(floorShares)) {
|
|
54
|
+
const floorWatts = homeWatts * share;
|
|
55
|
+
links.push({
|
|
56
|
+
source: "home",
|
|
57
|
+
target: floorId,
|
|
58
|
+
value: floorWatts
|
|
59
|
+
});
|
|
60
|
+
const deviceShares = deviceSharesByFloor?.[floorId] ?? {};
|
|
61
|
+
for (const [deviceId, deviceShare] of Object.entries(deviceShares)) links.push({
|
|
62
|
+
source: floorId,
|
|
63
|
+
target: deviceId,
|
|
64
|
+
value: floorWatts * deviceShare
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
return links;
|
|
68
|
+
}
|
|
69
|
+
//#endregion
|
|
70
|
+
exports.buildSankeyNodes = buildSankeyNodes;
|
|
71
|
+
|
|
72
|
+
//# sourceMappingURL=build-sankey-nodes.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"build-sankey-nodes.cjs","names":[],"sources":["../../src/utils/build-sankey-nodes.ts"],"sourcesContent":["import type { SankeyChartLink } from '../components/sankey-chart'\n\ntype SankeyNodesArgs = {\n solarPower: number\n /**\n * Signed storage power: positive = discharging into the home, negative =\n * charging from solar/grid. Charging power is routed into the `battery`\n * node so it isn't mistakenly attributed to home consumption.\n */\n batteryPower: number\n gridPower: number\n floorShares?: Record<string, number>\n deviceSharesByFloor?: Record<string, Record<string, number>>\n}\n\nfunction buildSankeyNodes({\n solarPower,\n batteryPower,\n gridPower,\n floorShares,\n deviceSharesByFloor,\n}: SankeyNodesArgs): SankeyChartLink[] {\n const solar = Math.max(0, solarPower)\n const gridImport = Math.max(0, gridPower)\n const gridExport = Math.max(0, -gridPower)\n const batteryDischarge = Math.max(0, batteryPower)\n const batteryCharge = Math.max(0, -batteryPower)\n\n // Charge the battery from solar surplus first, then from the grid. Routing\n // the charge flow into the `battery` node (a sink while charging) keeps it\n // out of the `home` node, which should reflect actual consumption only.\n const solarToBattery = Math.min(solar, batteryCharge)\n const gridToBattery = Math.min(gridImport, batteryCharge - solarToBattery)\n\n // Grid feed-in (export). Cover it from the solar surplus first, then fall\n // back to battery discharge. Like battery charging, this must not land in the\n // `home` node — it's power leaving the house, not consumption.\n const solarToFeedIn = Math.min(solar - solarToBattery, gridExport)\n const batteryToFeedIn = Math.min(batteryDischarge, gridExport - solarToFeedIn)\n\n const links: SankeyChartLink[] = [\n { source: 'grid', target: 'home', value: gridImport - gridToBattery },\n {\n source: 'solar',\n target: 'home',\n value: solar - solarToBattery - solarToFeedIn,\n },\n {\n source: 'battery',\n target: 'home',\n value: batteryDischarge - batteryToFeedIn,\n },\n { source: 'solar', target: 'battery', value: solarToBattery },\n { source: 'grid', target: 'battery', value: gridToBattery },\n { source: 'solar', target: 'gridFeedIn', value: solarToFeedIn },\n { source: 'battery', target: 'gridFeedIn', value: batteryToFeedIn },\n ]\n\n if (!floorShares) return links\n\n const homeWatts =\n solar -\n solarToBattery -\n solarToFeedIn +\n (gridImport - gridToBattery) +\n (batteryDischarge - batteryToFeedIn)\n\n for (const [floorId, share] of Object.entries(floorShares)) {\n const floorWatts = homeWatts * share\n links.push({ source: 'home', target: floorId, value: floorWatts })\n\n const deviceShares = deviceSharesByFloor?.[floorId] ?? {}\n for (const [deviceId, deviceShare] of Object.entries(deviceShares)) {\n links.push({\n source: floorId,\n target: deviceId,\n value: floorWatts * deviceShare,\n })\n }\n }\n\n return links\n}\n\nexport { buildSankeyNodes }\n"],"mappings":";;;AAeA,SAAS,iBAAiB,EACxB,YACA,cACA,WACA,aACA,uBACqC;CACrC,MAAM,QAAQ,KAAK,IAAI,GAAG,UAAU;CACpC,MAAM,aAAa,KAAK,IAAI,GAAG,SAAS;CACxC,MAAM,aAAa,KAAK,IAAI,GAAG,CAAC,SAAS;CACzC,MAAM,mBAAmB,KAAK,IAAI,GAAG,YAAY;CACjD,MAAM,gBAAgB,KAAK,IAAI,GAAG,CAAC,YAAY;CAK/C,MAAM,iBAAiB,KAAK,IAAI,OAAO,aAAa;CACpD,MAAM,gBAAgB,KAAK,IAAI,YAAY,gBAAgB,cAAc;CAKzE,MAAM,gBAAgB,KAAK,IAAI,QAAQ,gBAAgB,UAAU;CACjE,MAAM,kBAAkB,KAAK,IAAI,kBAAkB,aAAa,aAAa;CAE7E,MAAM,QAA2B;EAC/B;GAAE,QAAQ;GAAQ,QAAQ;GAAQ,OAAO,aAAa;EAAc;EACpE;GACE,QAAQ;GACR,QAAQ;GACR,OAAO,QAAQ,iBAAiB;EAClC;EACA;GACE,QAAQ;GACR,QAAQ;GACR,OAAO,mBAAmB;EAC5B;EACA;GAAE,QAAQ;GAAS,QAAQ;GAAW,OAAO;EAAe;EAC5D;GAAE,QAAQ;GAAQ,QAAQ;GAAW,OAAO;EAAc;EAC1D;GAAE,QAAQ;GAAS,QAAQ;GAAc,OAAO;EAAc;EAC9D;GAAE,QAAQ;GAAW,QAAQ;GAAc,OAAO;EAAgB;CACpE;CAEA,IAAI,CAAC,aAAa,OAAO;CAEzB,MAAM,YACJ,QACA,iBACA,iBACC,aAAa,kBACb,mBAAmB;CAEtB,KAAK,MAAM,CAAC,SAAS,UAAU,OAAO,QAAQ,WAAW,GAAG;EAC1D,MAAM,aAAa,YAAY;EAC/B,MAAM,KAAK;GAAE,QAAQ;GAAQ,QAAQ;GAAS,OAAO;EAAW,CAAC;EAEjE,MAAM,eAAe,sBAAsB,YAAY,CAAC;EACxD,KAAK,MAAM,CAAC,UAAU,gBAAgB,OAAO,QAAQ,YAAY,GAC/D,MAAM,KAAK;GACT,QAAQ;GACR,QAAQ;GACR,OAAO,aAAa;EACtB,CAAC;CAEL;CAEA,OAAO;AACT"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { SankeyChartLink } from "../components/sankey-chart.cjs";
|
|
4
|
+
|
|
5
|
+
//#region src/utils/build-sankey-nodes.d.ts
|
|
6
|
+
type SankeyNodesArgs = {
|
|
7
|
+
solarPower: number;
|
|
8
|
+
/**
|
|
9
|
+
* Signed storage power: positive = discharging into the home, negative =
|
|
10
|
+
* charging from solar/grid. Charging power is routed into the `battery`
|
|
11
|
+
* node so it isn't mistakenly attributed to home consumption.
|
|
12
|
+
*/
|
|
13
|
+
batteryPower: number;
|
|
14
|
+
gridPower: number;
|
|
15
|
+
floorShares?: Record<string, number>;
|
|
16
|
+
deviceSharesByFloor?: Record<string, Record<string, number>>;
|
|
17
|
+
};
|
|
18
|
+
declare function buildSankeyNodes({
|
|
19
|
+
solarPower,
|
|
20
|
+
batteryPower,
|
|
21
|
+
gridPower,
|
|
22
|
+
floorShares,
|
|
23
|
+
deviceSharesByFloor
|
|
24
|
+
}: SankeyNodesArgs): SankeyChartLink[];
|
|
25
|
+
//#endregion
|
|
26
|
+
export { buildSankeyNodes };
|
|
27
|
+
//# sourceMappingURL=build-sankey-nodes.d.cts.map
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { SankeyChartLink } from "../components/sankey-chart.js";
|
|
4
|
+
|
|
5
|
+
//#region src/utils/build-sankey-nodes.d.ts
|
|
6
|
+
type SankeyNodesArgs = {
|
|
7
|
+
solarPower: number;
|
|
8
|
+
/**
|
|
9
|
+
* Signed storage power: positive = discharging into the home, negative =
|
|
10
|
+
* charging from solar/grid. Charging power is routed into the `battery`
|
|
11
|
+
* node so it isn't mistakenly attributed to home consumption.
|
|
12
|
+
*/
|
|
13
|
+
batteryPower: number;
|
|
14
|
+
gridPower: number;
|
|
15
|
+
floorShares?: Record<string, number>;
|
|
16
|
+
deviceSharesByFloor?: Record<string, Record<string, number>>;
|
|
17
|
+
};
|
|
18
|
+
declare function buildSankeyNodes({
|
|
19
|
+
solarPower,
|
|
20
|
+
batteryPower,
|
|
21
|
+
gridPower,
|
|
22
|
+
floorShares,
|
|
23
|
+
deviceSharesByFloor
|
|
24
|
+
}: SankeyNodesArgs): SankeyChartLink[];
|
|
25
|
+
//#endregion
|
|
26
|
+
export { buildSankeyNodes };
|
|
27
|
+
//# sourceMappingURL=build-sankey-nodes.d.ts.map
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
//#region src/utils/build-sankey-nodes.ts
|
|
3
|
+
function buildSankeyNodes({ solarPower, batteryPower, gridPower, floorShares, deviceSharesByFloor }) {
|
|
4
|
+
const solar = Math.max(0, solarPower);
|
|
5
|
+
const gridImport = Math.max(0, gridPower);
|
|
6
|
+
const gridExport = Math.max(0, -gridPower);
|
|
7
|
+
const batteryDischarge = Math.max(0, batteryPower);
|
|
8
|
+
const batteryCharge = Math.max(0, -batteryPower);
|
|
9
|
+
const solarToBattery = Math.min(solar, batteryCharge);
|
|
10
|
+
const gridToBattery = Math.min(gridImport, batteryCharge - solarToBattery);
|
|
11
|
+
const solarToFeedIn = Math.min(solar - solarToBattery, gridExport);
|
|
12
|
+
const batteryToFeedIn = Math.min(batteryDischarge, gridExport - solarToFeedIn);
|
|
13
|
+
const links = [
|
|
14
|
+
{
|
|
15
|
+
source: "grid",
|
|
16
|
+
target: "home",
|
|
17
|
+
value: gridImport - gridToBattery
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
source: "solar",
|
|
21
|
+
target: "home",
|
|
22
|
+
value: solar - solarToBattery - solarToFeedIn
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
source: "battery",
|
|
26
|
+
target: "home",
|
|
27
|
+
value: batteryDischarge - batteryToFeedIn
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
source: "solar",
|
|
31
|
+
target: "battery",
|
|
32
|
+
value: solarToBattery
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
source: "grid",
|
|
36
|
+
target: "battery",
|
|
37
|
+
value: gridToBattery
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
source: "solar",
|
|
41
|
+
target: "gridFeedIn",
|
|
42
|
+
value: solarToFeedIn
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
source: "battery",
|
|
46
|
+
target: "gridFeedIn",
|
|
47
|
+
value: batteryToFeedIn
|
|
48
|
+
}
|
|
49
|
+
];
|
|
50
|
+
if (!floorShares) return links;
|
|
51
|
+
const homeWatts = solar - solarToBattery - solarToFeedIn + (gridImport - gridToBattery) + (batteryDischarge - batteryToFeedIn);
|
|
52
|
+
for (const [floorId, share] of Object.entries(floorShares)) {
|
|
53
|
+
const floorWatts = homeWatts * share;
|
|
54
|
+
links.push({
|
|
55
|
+
source: "home",
|
|
56
|
+
target: floorId,
|
|
57
|
+
value: floorWatts
|
|
58
|
+
});
|
|
59
|
+
const deviceShares = deviceSharesByFloor?.[floorId] ?? {};
|
|
60
|
+
for (const [deviceId, deviceShare] of Object.entries(deviceShares)) links.push({
|
|
61
|
+
source: floorId,
|
|
62
|
+
target: deviceId,
|
|
63
|
+
value: floorWatts * deviceShare
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
return links;
|
|
67
|
+
}
|
|
68
|
+
//#endregion
|
|
69
|
+
export { buildSankeyNodes };
|
|
70
|
+
|
|
71
|
+
//# sourceMappingURL=build-sankey-nodes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"build-sankey-nodes.js","names":[],"sources":["../../src/utils/build-sankey-nodes.ts"],"sourcesContent":["import type { SankeyChartLink } from '../components/sankey-chart'\n\ntype SankeyNodesArgs = {\n solarPower: number\n /**\n * Signed storage power: positive = discharging into the home, negative =\n * charging from solar/grid. Charging power is routed into the `battery`\n * node so it isn't mistakenly attributed to home consumption.\n */\n batteryPower: number\n gridPower: number\n floorShares?: Record<string, number>\n deviceSharesByFloor?: Record<string, Record<string, number>>\n}\n\nfunction buildSankeyNodes({\n solarPower,\n batteryPower,\n gridPower,\n floorShares,\n deviceSharesByFloor,\n}: SankeyNodesArgs): SankeyChartLink[] {\n const solar = Math.max(0, solarPower)\n const gridImport = Math.max(0, gridPower)\n const gridExport = Math.max(0, -gridPower)\n const batteryDischarge = Math.max(0, batteryPower)\n const batteryCharge = Math.max(0, -batteryPower)\n\n // Charge the battery from solar surplus first, then from the grid. Routing\n // the charge flow into the `battery` node (a sink while charging) keeps it\n // out of the `home` node, which should reflect actual consumption only.\n const solarToBattery = Math.min(solar, batteryCharge)\n const gridToBattery = Math.min(gridImport, batteryCharge - solarToBattery)\n\n // Grid feed-in (export). Cover it from the solar surplus first, then fall\n // back to battery discharge. Like battery charging, this must not land in the\n // `home` node — it's power leaving the house, not consumption.\n const solarToFeedIn = Math.min(solar - solarToBattery, gridExport)\n const batteryToFeedIn = Math.min(batteryDischarge, gridExport - solarToFeedIn)\n\n const links: SankeyChartLink[] = [\n { source: 'grid', target: 'home', value: gridImport - gridToBattery },\n {\n source: 'solar',\n target: 'home',\n value: solar - solarToBattery - solarToFeedIn,\n },\n {\n source: 'battery',\n target: 'home',\n value: batteryDischarge - batteryToFeedIn,\n },\n { source: 'solar', target: 'battery', value: solarToBattery },\n { source: 'grid', target: 'battery', value: gridToBattery },\n { source: 'solar', target: 'gridFeedIn', value: solarToFeedIn },\n { source: 'battery', target: 'gridFeedIn', value: batteryToFeedIn },\n ]\n\n if (!floorShares) return links\n\n const homeWatts =\n solar -\n solarToBattery -\n solarToFeedIn +\n (gridImport - gridToBattery) +\n (batteryDischarge - batteryToFeedIn)\n\n for (const [floorId, share] of Object.entries(floorShares)) {\n const floorWatts = homeWatts * share\n links.push({ source: 'home', target: floorId, value: floorWatts })\n\n const deviceShares = deviceSharesByFloor?.[floorId] ?? {}\n for (const [deviceId, deviceShare] of Object.entries(deviceShares)) {\n links.push({\n source: floorId,\n target: deviceId,\n value: floorWatts * deviceShare,\n })\n }\n }\n\n return links\n}\n\nexport { buildSankeyNodes }\n"],"mappings":";;AAeA,SAAS,iBAAiB,EACxB,YACA,cACA,WACA,aACA,uBACqC;CACrC,MAAM,QAAQ,KAAK,IAAI,GAAG,UAAU;CACpC,MAAM,aAAa,KAAK,IAAI,GAAG,SAAS;CACxC,MAAM,aAAa,KAAK,IAAI,GAAG,CAAC,SAAS;CACzC,MAAM,mBAAmB,KAAK,IAAI,GAAG,YAAY;CACjD,MAAM,gBAAgB,KAAK,IAAI,GAAG,CAAC,YAAY;CAK/C,MAAM,iBAAiB,KAAK,IAAI,OAAO,aAAa;CACpD,MAAM,gBAAgB,KAAK,IAAI,YAAY,gBAAgB,cAAc;CAKzE,MAAM,gBAAgB,KAAK,IAAI,QAAQ,gBAAgB,UAAU;CACjE,MAAM,kBAAkB,KAAK,IAAI,kBAAkB,aAAa,aAAa;CAE7E,MAAM,QAA2B;EAC/B;GAAE,QAAQ;GAAQ,QAAQ;GAAQ,OAAO,aAAa;EAAc;EACpE;GACE,QAAQ;GACR,QAAQ;GACR,OAAO,QAAQ,iBAAiB;EAClC;EACA;GACE,QAAQ;GACR,QAAQ;GACR,OAAO,mBAAmB;EAC5B;EACA;GAAE,QAAQ;GAAS,QAAQ;GAAW,OAAO;EAAe;EAC5D;GAAE,QAAQ;GAAQ,QAAQ;GAAW,OAAO;EAAc;EAC1D;GAAE,QAAQ;GAAS,QAAQ;GAAc,OAAO;EAAc;EAC9D;GAAE,QAAQ;GAAW,QAAQ;GAAc,OAAO;EAAgB;CACpE;CAEA,IAAI,CAAC,aAAa,OAAO;CAEzB,MAAM,YACJ,QACA,iBACA,iBACC,aAAa,kBACb,mBAAmB;CAEtB,KAAK,MAAM,CAAC,SAAS,UAAU,OAAO,QAAQ,WAAW,GAAG;EAC1D,MAAM,aAAa,YAAY;EAC/B,MAAM,KAAK;GAAE,QAAQ;GAAQ,QAAQ;GAAS,OAAO;EAAW,CAAC;EAEjE,MAAM,eAAe,sBAAsB,YAAY,CAAC;EACxD,KAAK,MAAM,CAAC,UAAU,gBAAgB,OAAO,QAAQ,YAAY,GAC/D,MAAM,KAAK;GACT,QAAQ;GACR,QAAQ;GACR,OAAO,aAAa;EACtB,CAAC;CAEL;CAEA,OAAO;AACT"}
|
package/dist/utils/cn.cjs
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
-
let
|
|
3
|
+
let cn = require("cn");
|
|
4
4
|
Object.defineProperty(exports, "cn", {
|
|
5
5
|
enumerable: true,
|
|
6
6
|
get: function() {
|
|
7
|
-
return
|
|
7
|
+
return cn.cn;
|
|
8
8
|
}
|
|
9
9
|
});
|
package/dist/utils/cn.d.cts
CHANGED
package/dist/utils/cn.d.ts
CHANGED
package/dist/utils/cn.js
CHANGED
package/dist/utils/format.cjs
CHANGED
|
@@ -23,6 +23,17 @@ const integerFormat = decimalsFormat(0);
|
|
|
23
23
|
const oneDecimalFormat = decimalsFormat(1);
|
|
24
24
|
const twoDecimalFormat = decimalsFormat(2);
|
|
25
25
|
const formatThousands = (n) => integerFormat.format(n);
|
|
26
|
+
const formatEnergy = (v) => {
|
|
27
|
+
if (v >= 1e6) return `${twoDecimalFormat.format(v / 1e3)} MWh`;
|
|
28
|
+
if (v >= 1e3) return `${integerFormat.format(v)} kWh`;
|
|
29
|
+
if (v >= 10) return `${oneDecimalFormat.format(v)} kWh`;
|
|
30
|
+
return `${twoDecimalFormat.format(v)} kWh`;
|
|
31
|
+
};
|
|
32
|
+
const formatPower = (value, { signed = false } = {}) => {
|
|
33
|
+
if (value == null) return "—";
|
|
34
|
+
const rounded = Math.round(value);
|
|
35
|
+
return `${signed && rounded > 0 ? "+" : ""}${integerFormat.format(rounded)} W`;
|
|
36
|
+
};
|
|
26
37
|
const formatPercent = (value) => {
|
|
27
38
|
if (value == null) return "—";
|
|
28
39
|
return `${integerFormat.format(value)} %`;
|
|
@@ -33,9 +44,12 @@ const formatRatio = (value) => {
|
|
|
33
44
|
};
|
|
34
45
|
//#endregion
|
|
35
46
|
exports.decimalsFormat = decimalsFormat;
|
|
47
|
+
exports.formatEnergy = formatEnergy;
|
|
36
48
|
exports.formatPercent = formatPercent;
|
|
49
|
+
exports.formatPower = formatPower;
|
|
37
50
|
exports.formatRatio = formatRatio;
|
|
38
51
|
exports.formatThousands = formatThousands;
|
|
52
|
+
exports.getDocumentLang = getDocumentLang;
|
|
39
53
|
exports.integerFormat = integerFormat;
|
|
40
54
|
exports.localeNumberFormat = localeNumberFormat;
|
|
41
55
|
exports.oneDecimalFormat = oneDecimalFormat;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"format.cjs","names":[],"sources":["../../src/utils/format.ts"],"sourcesContent":["import { EM_DASH, NARROW_NBSP } from './chars'\n\ninterface LocaleNumberFormat {\n format: (value: number) => string\n}\n\nfunction getDocumentLang(): string | undefined {\n return typeof document === 'undefined'\n ? undefined\n : document.documentElement.lang || undefined\n}\n\nconst localeNumberFormat = (\n options?: Intl.NumberFormatOptions,\n): LocaleNumberFormat => {\n const cache = new Map<string, Intl.NumberFormat>()\n return {\n format: (value) => {\n const locale = getDocumentLang()\n const key = locale ?? ''\n let formatter = cache.get(key)\n if (!formatter) {\n formatter = new Intl.NumberFormat(locale, options)\n cache.set(key, formatter)\n }\n return formatter.format(value)\n },\n }\n}\n\nconst decimalsFormat = (decimals: number) =>\n localeNumberFormat({ maximumFractionDigits: decimals })\n\nconst integerFormat = decimalsFormat(0)\nconst oneDecimalFormat = decimalsFormat(1)\nconst twoDecimalFormat = decimalsFormat(2)\n\nconst formatThousands = (n: number) => integerFormat.format(n)\n\nconst formatPercent = (value: number | null): string => {\n if (value == null) return EM_DASH\n return `${integerFormat.format(value)}${NARROW_NBSP}%`\n}\n\nconst formatRatio = (value: number | null): string => {\n if (value == null) return EM_DASH\n return `${integerFormat.format(value * 100)}${NARROW_NBSP}%`\n}\n\nexport {\n formatThousands,\n formatPercent,\n formatRatio,\n localeNumberFormat,\n decimalsFormat,\n integerFormat,\n oneDecimalFormat,\n twoDecimalFormat,\n}\n"],"mappings":";;;;AAMA,SAAS,kBAAsC;CAC7C,OAAO,OAAO,aAAa,cACvB,KAAA,IACA,SAAS,gBAAgB,QAAQ,KAAA;AACvC;AAEA,MAAM,sBACJ,YACuB;CACvB,MAAM,wBAAQ,IAAI,IAA+B;CACjD,OAAO,EACL,SAAS,UAAU;EACjB,MAAM,SAAS,gBAAgB;EAC/B,MAAM,MAAM,UAAU;EACtB,IAAI,YAAY,MAAM,IAAI,GAAG;EAC7B,IAAI,CAAC,WAAW;GACd,YAAY,IAAI,KAAK,aAAa,QAAQ,OAAO;GACjD,MAAM,IAAI,KAAK,SAAS;EAC1B;EACA,OAAO,UAAU,OAAO,KAAK;CAC/B,EACF;AACF;AAEA,MAAM,kBAAkB,aACtB,mBAAmB,EAAE,uBAAuB,SAAS,CAAC;AAExD,MAAM,gBAAgB,eAAe,CAAC;AACtC,MAAM,mBAAmB,eAAe,CAAC;AACzC,MAAM,mBAAmB,eAAe,CAAC;AAEzC,MAAM,mBAAmB,MAAc,cAAc,OAAO,CAAC;AAE7D,MAAM,iBAAiB,UAAiC;CACtD,IAAI,SAAS,MAAM,OAAA;CACnB,OAAO,GAAG,cAAc,OAAO,KAAK;AACtC;AAEA,MAAM,eAAe,UAAiC;CACpD,IAAI,SAAS,MAAM,OAAA;CACnB,OAAO,GAAG,cAAc,OAAO,QAAQ,GAAG;AAC5C"}
|
|
1
|
+
{"version":3,"file":"format.cjs","names":[],"sources":["../../src/utils/format.ts"],"sourcesContent":["import { EM_DASH, NARROW_NBSP } from './chars'\n\ninterface LocaleNumberFormat {\n format: (value: number) => string\n}\n\nfunction getDocumentLang(): string | undefined {\n return typeof document === 'undefined'\n ? undefined\n : document.documentElement.lang || undefined\n}\n\nconst localeNumberFormat = (\n options?: Intl.NumberFormatOptions,\n): LocaleNumberFormat => {\n const cache = new Map<string, Intl.NumberFormat>()\n return {\n format: (value) => {\n const locale = getDocumentLang()\n const key = locale ?? ''\n let formatter = cache.get(key)\n if (!formatter) {\n formatter = new Intl.NumberFormat(locale, options)\n cache.set(key, formatter)\n }\n return formatter.format(value)\n },\n }\n}\n\nconst decimalsFormat = (decimals: number) =>\n localeNumberFormat({ maximumFractionDigits: decimals })\n\nconst integerFormat = decimalsFormat(0)\nconst oneDecimalFormat = decimalsFormat(1)\nconst twoDecimalFormat = decimalsFormat(2)\n\nconst formatThousands = (n: number) => integerFormat.format(n)\n\nconst formatEnergy = (v: number) => {\n if (v >= 1_000_000) {\n return `${twoDecimalFormat.format(v / 1000)}${NARROW_NBSP}MWh`\n }\n if (v >= 1_000) return `${integerFormat.format(v)}${NARROW_NBSP}kWh`\n if (v >= 10) return `${oneDecimalFormat.format(v)}${NARROW_NBSP}kWh`\n return `${twoDecimalFormat.format(v)}${NARROW_NBSP}kWh`\n}\n\nconst formatPower = (\n value: number | null,\n { signed = false }: { signed?: boolean } = {},\n): string => {\n if (value == null) return EM_DASH\n const rounded = Math.round(value)\n const sign = signed && rounded > 0 ? '+' : ''\n return `${sign}${integerFormat.format(rounded)}${NARROW_NBSP}W`\n}\n\nconst formatPercent = (value: number | null): string => {\n if (value == null) return EM_DASH\n return `${integerFormat.format(value)}${NARROW_NBSP}%`\n}\n\nconst formatRatio = (value: number | null): string => {\n if (value == null) return EM_DASH\n return `${integerFormat.format(value * 100)}${NARROW_NBSP}%`\n}\n\nexport {\n getDocumentLang,\n formatThousands,\n formatEnergy,\n formatPower,\n formatPercent,\n formatRatio,\n localeNumberFormat,\n decimalsFormat,\n integerFormat,\n oneDecimalFormat,\n twoDecimalFormat,\n}\n"],"mappings":";;;;AAMA,SAAS,kBAAsC;CAC7C,OAAO,OAAO,aAAa,cACvB,KAAA,IACA,SAAS,gBAAgB,QAAQ,KAAA;AACvC;AAEA,MAAM,sBACJ,YACuB;CACvB,MAAM,wBAAQ,IAAI,IAA+B;CACjD,OAAO,EACL,SAAS,UAAU;EACjB,MAAM,SAAS,gBAAgB;EAC/B,MAAM,MAAM,UAAU;EACtB,IAAI,YAAY,MAAM,IAAI,GAAG;EAC7B,IAAI,CAAC,WAAW;GACd,YAAY,IAAI,KAAK,aAAa,QAAQ,OAAO;GACjD,MAAM,IAAI,KAAK,SAAS;EAC1B;EACA,OAAO,UAAU,OAAO,KAAK;CAC/B,EACF;AACF;AAEA,MAAM,kBAAkB,aACtB,mBAAmB,EAAE,uBAAuB,SAAS,CAAC;AAExD,MAAM,gBAAgB,eAAe,CAAC;AACtC,MAAM,mBAAmB,eAAe,CAAC;AACzC,MAAM,mBAAmB,eAAe,CAAC;AAEzC,MAAM,mBAAmB,MAAc,cAAc,OAAO,CAAC;AAE7D,MAAM,gBAAgB,MAAc;CAClC,IAAI,KAAK,KACP,OAAO,GAAG,iBAAiB,OAAO,IAAI,GAAI;CAE5C,IAAI,KAAK,KAAO,OAAO,GAAG,cAAc,OAAO,CAAC;CAChD,IAAI,KAAK,IAAI,OAAO,GAAG,iBAAiB,OAAO,CAAC;CAChD,OAAO,GAAG,iBAAiB,OAAO,CAAC;AACrC;AAEA,MAAM,eACJ,OACA,EAAE,SAAS,UAAgC,CAAC,MACjC;CACX,IAAI,SAAS,MAAM,OAAA;CACnB,MAAM,UAAU,KAAK,MAAM,KAAK;CAEhC,OAAO,GADM,UAAU,UAAU,IAAI,MAAM,KAC1B,cAAc,OAAO,OAAO;AAC/C;AAEA,MAAM,iBAAiB,UAAiC;CACtD,IAAI,SAAS,MAAM,OAAA;CACnB,OAAO,GAAG,cAAc,OAAO,KAAK;AACtC;AAEA,MAAM,eAAe,UAAiC;CACpD,IAAI,SAAS,MAAM,OAAA;CACnB,OAAO,GAAG,cAAc,OAAO,QAAQ,GAAG;AAC5C"}
|
package/dist/utils/format.d.cts
CHANGED
|
@@ -4,14 +4,21 @@
|
|
|
4
4
|
interface LocaleNumberFormat {
|
|
5
5
|
format: (value: number) => string;
|
|
6
6
|
}
|
|
7
|
+
declare function getDocumentLang(): string | undefined;
|
|
7
8
|
declare const localeNumberFormat: (options?: Intl.NumberFormatOptions) => LocaleNumberFormat;
|
|
8
9
|
declare const decimalsFormat: (decimals: number) => LocaleNumberFormat;
|
|
9
10
|
declare const integerFormat: LocaleNumberFormat;
|
|
10
11
|
declare const oneDecimalFormat: LocaleNumberFormat;
|
|
11
12
|
declare const twoDecimalFormat: LocaleNumberFormat;
|
|
12
13
|
declare const formatThousands: (n: number) => string;
|
|
14
|
+
declare const formatEnergy: (v: number) => string;
|
|
15
|
+
declare const formatPower: (value: number | null, {
|
|
16
|
+
signed
|
|
17
|
+
}?: {
|
|
18
|
+
signed?: boolean;
|
|
19
|
+
}) => string;
|
|
13
20
|
declare const formatPercent: (value: number | null) => string;
|
|
14
21
|
declare const formatRatio: (value: number | null) => string;
|
|
15
22
|
//#endregion
|
|
16
|
-
export { decimalsFormat, formatPercent, formatRatio, formatThousands, integerFormat, localeNumberFormat, oneDecimalFormat, twoDecimalFormat };
|
|
23
|
+
export { decimalsFormat, formatEnergy, formatPercent, formatPower, formatRatio, formatThousands, getDocumentLang, integerFormat, localeNumberFormat, oneDecimalFormat, twoDecimalFormat };
|
|
17
24
|
//# sourceMappingURL=format.d.cts.map
|
package/dist/utils/format.d.ts
CHANGED
|
@@ -4,14 +4,21 @@
|
|
|
4
4
|
interface LocaleNumberFormat {
|
|
5
5
|
format: (value: number) => string;
|
|
6
6
|
}
|
|
7
|
+
declare function getDocumentLang(): string | undefined;
|
|
7
8
|
declare const localeNumberFormat: (options?: Intl.NumberFormatOptions) => LocaleNumberFormat;
|
|
8
9
|
declare const decimalsFormat: (decimals: number) => LocaleNumberFormat;
|
|
9
10
|
declare const integerFormat: LocaleNumberFormat;
|
|
10
11
|
declare const oneDecimalFormat: LocaleNumberFormat;
|
|
11
12
|
declare const twoDecimalFormat: LocaleNumberFormat;
|
|
12
13
|
declare const formatThousands: (n: number) => string;
|
|
14
|
+
declare const formatEnergy: (v: number) => string;
|
|
15
|
+
declare const formatPower: (value: number | null, {
|
|
16
|
+
signed
|
|
17
|
+
}?: {
|
|
18
|
+
signed?: boolean;
|
|
19
|
+
}) => string;
|
|
13
20
|
declare const formatPercent: (value: number | null) => string;
|
|
14
21
|
declare const formatRatio: (value: number | null) => string;
|
|
15
22
|
//#endregion
|
|
16
|
-
export { decimalsFormat, formatPercent, formatRatio, formatThousands, integerFormat, localeNumberFormat, oneDecimalFormat, twoDecimalFormat };
|
|
23
|
+
export { decimalsFormat, formatEnergy, formatPercent, formatPower, formatRatio, formatThousands, getDocumentLang, integerFormat, localeNumberFormat, oneDecimalFormat, twoDecimalFormat };
|
|
17
24
|
//# sourceMappingURL=format.d.ts.map
|
package/dist/utils/format.js
CHANGED
|
@@ -22,6 +22,17 @@ const integerFormat = decimalsFormat(0);
|
|
|
22
22
|
const oneDecimalFormat = decimalsFormat(1);
|
|
23
23
|
const twoDecimalFormat = decimalsFormat(2);
|
|
24
24
|
const formatThousands = (n) => integerFormat.format(n);
|
|
25
|
+
const formatEnergy = (v) => {
|
|
26
|
+
if (v >= 1e6) return `${twoDecimalFormat.format(v / 1e3)} MWh`;
|
|
27
|
+
if (v >= 1e3) return `${integerFormat.format(v)} kWh`;
|
|
28
|
+
if (v >= 10) return `${oneDecimalFormat.format(v)} kWh`;
|
|
29
|
+
return `${twoDecimalFormat.format(v)} kWh`;
|
|
30
|
+
};
|
|
31
|
+
const formatPower = (value, { signed = false } = {}) => {
|
|
32
|
+
if (value == null) return "—";
|
|
33
|
+
const rounded = Math.round(value);
|
|
34
|
+
return `${signed && rounded > 0 ? "+" : ""}${integerFormat.format(rounded)} W`;
|
|
35
|
+
};
|
|
25
36
|
const formatPercent = (value) => {
|
|
26
37
|
if (value == null) return "—";
|
|
27
38
|
return `${integerFormat.format(value)} %`;
|
|
@@ -31,6 +42,6 @@ const formatRatio = (value) => {
|
|
|
31
42
|
return `${integerFormat.format(value * 100)} %`;
|
|
32
43
|
};
|
|
33
44
|
//#endregion
|
|
34
|
-
export { decimalsFormat, formatPercent, formatRatio, formatThousands, integerFormat, localeNumberFormat, oneDecimalFormat, twoDecimalFormat };
|
|
45
|
+
export { decimalsFormat, formatEnergy, formatPercent, formatPower, formatRatio, formatThousands, getDocumentLang, integerFormat, localeNumberFormat, oneDecimalFormat, twoDecimalFormat };
|
|
35
46
|
|
|
36
47
|
//# sourceMappingURL=format.js.map
|
package/dist/utils/format.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"format.js","names":[],"sources":["../../src/utils/format.ts"],"sourcesContent":["import { EM_DASH, NARROW_NBSP } from './chars'\n\ninterface LocaleNumberFormat {\n format: (value: number) => string\n}\n\nfunction getDocumentLang(): string | undefined {\n return typeof document === 'undefined'\n ? undefined\n : document.documentElement.lang || undefined\n}\n\nconst localeNumberFormat = (\n options?: Intl.NumberFormatOptions,\n): LocaleNumberFormat => {\n const cache = new Map<string, Intl.NumberFormat>()\n return {\n format: (value) => {\n const locale = getDocumentLang()\n const key = locale ?? ''\n let formatter = cache.get(key)\n if (!formatter) {\n formatter = new Intl.NumberFormat(locale, options)\n cache.set(key, formatter)\n }\n return formatter.format(value)\n },\n }\n}\n\nconst decimalsFormat = (decimals: number) =>\n localeNumberFormat({ maximumFractionDigits: decimals })\n\nconst integerFormat = decimalsFormat(0)\nconst oneDecimalFormat = decimalsFormat(1)\nconst twoDecimalFormat = decimalsFormat(2)\n\nconst formatThousands = (n: number) => integerFormat.format(n)\n\nconst formatPercent = (value: number | null): string => {\n if (value == null) return EM_DASH\n return `${integerFormat.format(value)}${NARROW_NBSP}%`\n}\n\nconst formatRatio = (value: number | null): string => {\n if (value == null) return EM_DASH\n return `${integerFormat.format(value * 100)}${NARROW_NBSP}%`\n}\n\nexport {\n formatThousands,\n formatPercent,\n formatRatio,\n localeNumberFormat,\n decimalsFormat,\n integerFormat,\n oneDecimalFormat,\n twoDecimalFormat,\n}\n"],"mappings":";;;AAMA,SAAS,kBAAsC;CAC7C,OAAO,OAAO,aAAa,cACvB,KAAA,IACA,SAAS,gBAAgB,QAAQ,KAAA;AACvC;AAEA,MAAM,sBACJ,YACuB;CACvB,MAAM,wBAAQ,IAAI,IAA+B;CACjD,OAAO,EACL,SAAS,UAAU;EACjB,MAAM,SAAS,gBAAgB;EAC/B,MAAM,MAAM,UAAU;EACtB,IAAI,YAAY,MAAM,IAAI,GAAG;EAC7B,IAAI,CAAC,WAAW;GACd,YAAY,IAAI,KAAK,aAAa,QAAQ,OAAO;GACjD,MAAM,IAAI,KAAK,SAAS;EAC1B;EACA,OAAO,UAAU,OAAO,KAAK;CAC/B,EACF;AACF;AAEA,MAAM,kBAAkB,aACtB,mBAAmB,EAAE,uBAAuB,SAAS,CAAC;AAExD,MAAM,gBAAgB,eAAe,CAAC;AACtC,MAAM,mBAAmB,eAAe,CAAC;AACzC,MAAM,mBAAmB,eAAe,CAAC;AAEzC,MAAM,mBAAmB,MAAc,cAAc,OAAO,CAAC;AAE7D,MAAM,iBAAiB,UAAiC;CACtD,IAAI,SAAS,MAAM,OAAA;CACnB,OAAO,GAAG,cAAc,OAAO,KAAK;AACtC;AAEA,MAAM,eAAe,UAAiC;CACpD,IAAI,SAAS,MAAM,OAAA;CACnB,OAAO,GAAG,cAAc,OAAO,QAAQ,GAAG;AAC5C"}
|
|
1
|
+
{"version":3,"file":"format.js","names":[],"sources":["../../src/utils/format.ts"],"sourcesContent":["import { EM_DASH, NARROW_NBSP } from './chars'\n\ninterface LocaleNumberFormat {\n format: (value: number) => string\n}\n\nfunction getDocumentLang(): string | undefined {\n return typeof document === 'undefined'\n ? undefined\n : document.documentElement.lang || undefined\n}\n\nconst localeNumberFormat = (\n options?: Intl.NumberFormatOptions,\n): LocaleNumberFormat => {\n const cache = new Map<string, Intl.NumberFormat>()\n return {\n format: (value) => {\n const locale = getDocumentLang()\n const key = locale ?? ''\n let formatter = cache.get(key)\n if (!formatter) {\n formatter = new Intl.NumberFormat(locale, options)\n cache.set(key, formatter)\n }\n return formatter.format(value)\n },\n }\n}\n\nconst decimalsFormat = (decimals: number) =>\n localeNumberFormat({ maximumFractionDigits: decimals })\n\nconst integerFormat = decimalsFormat(0)\nconst oneDecimalFormat = decimalsFormat(1)\nconst twoDecimalFormat = decimalsFormat(2)\n\nconst formatThousands = (n: number) => integerFormat.format(n)\n\nconst formatEnergy = (v: number) => {\n if (v >= 1_000_000) {\n return `${twoDecimalFormat.format(v / 1000)}${NARROW_NBSP}MWh`\n }\n if (v >= 1_000) return `${integerFormat.format(v)}${NARROW_NBSP}kWh`\n if (v >= 10) return `${oneDecimalFormat.format(v)}${NARROW_NBSP}kWh`\n return `${twoDecimalFormat.format(v)}${NARROW_NBSP}kWh`\n}\n\nconst formatPower = (\n value: number | null,\n { signed = false }: { signed?: boolean } = {},\n): string => {\n if (value == null) return EM_DASH\n const rounded = Math.round(value)\n const sign = signed && rounded > 0 ? '+' : ''\n return `${sign}${integerFormat.format(rounded)}${NARROW_NBSP}W`\n}\n\nconst formatPercent = (value: number | null): string => {\n if (value == null) return EM_DASH\n return `${integerFormat.format(value)}${NARROW_NBSP}%`\n}\n\nconst formatRatio = (value: number | null): string => {\n if (value == null) return EM_DASH\n return `${integerFormat.format(value * 100)}${NARROW_NBSP}%`\n}\n\nexport {\n getDocumentLang,\n formatThousands,\n formatEnergy,\n formatPower,\n formatPercent,\n formatRatio,\n localeNumberFormat,\n decimalsFormat,\n integerFormat,\n oneDecimalFormat,\n twoDecimalFormat,\n}\n"],"mappings":";;;AAMA,SAAS,kBAAsC;CAC7C,OAAO,OAAO,aAAa,cACvB,KAAA,IACA,SAAS,gBAAgB,QAAQ,KAAA;AACvC;AAEA,MAAM,sBACJ,YACuB;CACvB,MAAM,wBAAQ,IAAI,IAA+B;CACjD,OAAO,EACL,SAAS,UAAU;EACjB,MAAM,SAAS,gBAAgB;EAC/B,MAAM,MAAM,UAAU;EACtB,IAAI,YAAY,MAAM,IAAI,GAAG;EAC7B,IAAI,CAAC,WAAW;GACd,YAAY,IAAI,KAAK,aAAa,QAAQ,OAAO;GACjD,MAAM,IAAI,KAAK,SAAS;EAC1B;EACA,OAAO,UAAU,OAAO,KAAK;CAC/B,EACF;AACF;AAEA,MAAM,kBAAkB,aACtB,mBAAmB,EAAE,uBAAuB,SAAS,CAAC;AAExD,MAAM,gBAAgB,eAAe,CAAC;AACtC,MAAM,mBAAmB,eAAe,CAAC;AACzC,MAAM,mBAAmB,eAAe,CAAC;AAEzC,MAAM,mBAAmB,MAAc,cAAc,OAAO,CAAC;AAE7D,MAAM,gBAAgB,MAAc;CAClC,IAAI,KAAK,KACP,OAAO,GAAG,iBAAiB,OAAO,IAAI,GAAI;CAE5C,IAAI,KAAK,KAAO,OAAO,GAAG,cAAc,OAAO,CAAC;CAChD,IAAI,KAAK,IAAI,OAAO,GAAG,iBAAiB,OAAO,CAAC;CAChD,OAAO,GAAG,iBAAiB,OAAO,CAAC;AACrC;AAEA,MAAM,eACJ,OACA,EAAE,SAAS,UAAgC,CAAC,MACjC;CACX,IAAI,SAAS,MAAM,OAAA;CACnB,MAAM,UAAU,KAAK,MAAM,KAAK;CAEhC,OAAO,GADM,UAAU,UAAU,IAAI,MAAM,KAC1B,cAAc,OAAO,OAAO;AAC/C;AAEA,MAAM,iBAAiB,UAAiC;CACtD,IAAI,SAAS,MAAM,OAAA;CACnB,OAAO,GAAG,cAAc,OAAO,KAAK;AACtC;AAEA,MAAM,eAAe,UAAiC;CACpD,IAAI,SAAS,MAAM,OAAA;CACnB,OAAO,GAAG,cAAc,OAAO,QAAQ,GAAG;AAC5C"}
|