@watt-ui/react 0.0.0-stage → 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 +21 -0
- package/NOTICE +43 -0
- package/README.md +48 -2
- package/dist/chart/data.d.ts +13 -0
- package/dist/chart/data.d.ts.map +1 -0
- package/dist/chart/data.js +92 -0
- package/dist/chart/data.js.map +1 -0
- package/dist/chart/engine.d.ts +2 -0
- package/dist/chart/engine.d.ts.map +1 -0
- package/dist/chart/engine.js +16 -0
- package/dist/chart/engine.js.map +1 -0
- package/dist/chart/options.d.ts +18 -0
- package/dist/chart/options.d.ts.map +1 -0
- package/dist/chart/options.js +136 -0
- package/dist/chart/options.js.map +1 -0
- package/dist/components/alarm-feed.d.ts +18 -0
- package/dist/components/alarm-feed.d.ts.map +1 -0
- package/dist/components/alarm-feed.js +45 -0
- package/dist/components/alarm-feed.js.map +1 -0
- package/dist/components/asset-tree.d.ts +33 -0
- package/dist/components/asset-tree.d.ts.map +1 -0
- package/dist/components/asset-tree.js +149 -0
- package/dist/components/asset-tree.js.map +1 -0
- package/dist/components/battery-soc.d.ts +11 -0
- package/dist/components/battery-soc.d.ts.map +1 -0
- package/dist/components/battery-soc.js +34 -0
- package/dist/components/battery-soc.js.map +1 -0
- package/dist/components/data-freshness.d.ts +26 -0
- package/dist/components/data-freshness.d.ts.map +1 -0
- package/dist/components/data-freshness.js +45 -0
- package/dist/components/data-freshness.js.map +1 -0
- package/dist/components/energy-flow.d.ts +39 -0
- package/dist/components/energy-flow.d.ts.map +1 -0
- package/dist/components/energy-flow.js +176 -0
- package/dist/components/energy-flow.js.map +1 -0
- package/dist/components/flow-geometry.d.ts +24 -0
- package/dist/components/flow-geometry.d.ts.map +1 -0
- package/dist/components/flow-geometry.js +57 -0
- package/dist/components/flow-geometry.js.map +1 -0
- package/dist/components/power-metric.d.ts +14 -0
- package/dist/components/power-metric.d.ts.map +1 -0
- package/dist/components/power-metric.js +25 -0
- package/dist/components/power-metric.js.map +1 -0
- package/dist/components/status-indicator.d.ts +10 -0
- package/dist/components/status-indicator.d.ts.map +1 -0
- package/dist/components/status-indicator.js +15 -0
- package/dist/components/status-indicator.js.map +1 -0
- package/dist/components/telemetry-chart.d.ts +50 -0
- package/dist/components/telemetry-chart.d.ts.map +1 -0
- package/dist/components/telemetry-chart.js +256 -0
- package/dist/components/telemetry-chart.js.map +1 -0
- package/dist/domain.d.ts +6 -0
- package/dist/domain.d.ts.map +1 -0
- package/dist/domain.js +43 -0
- package/dist/domain.js.map +1 -0
- package/dist/icons/index.d.ts +7 -0
- package/dist/icons/index.d.ts.map +1 -0
- package/dist/icons/index.js +38 -0
- package/dist/icons/index.js.map +1 -0
- package/dist/index.d.ts +19 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +10 -0
- package/dist/index.js.map +1 -0
- package/dist/internal.d.ts +6 -0
- package/dist/internal.d.ts.map +1 -0
- package/dist/internal.js +45 -0
- package/dist/internal.js.map +1 -0
- package/dist/server.d.ts +10 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +32 -0
- package/dist/server.js.map +1 -0
- package/dist/styles.css +130 -0
- package/dist/theme/shadcn.css +14 -0
- package/dist/types.d.ts +61 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/package.json +118 -4
- package/src/chart/data.ts +103 -0
- package/src/chart/engine.ts +19 -0
- package/src/chart/options.ts +178 -0
- package/src/components/alarm-feed.tsx +126 -0
- package/src/components/asset-tree.tsx +258 -0
- package/src/components/battery-soc.tsx +84 -0
- package/src/components/data-freshness.tsx +109 -0
- package/src/components/energy-flow.tsx +364 -0
- package/src/components/flow-geometry.ts +82 -0
- package/src/components/power-metric.tsx +71 -0
- package/src/components/status-indicator.tsx +31 -0
- package/src/components/telemetry-chart.tsx +476 -0
- package/src/domain.ts +64 -0
- package/src/icons/index.tsx +49 -0
- package/src/index.ts +37 -0
- package/src/internal.tsx +57 -0
- package/src/server.ts +47 -0
- package/src/styles.css +130 -0
- package/src/theme/shadcn.css +14 -0
- package/src/types.ts +64 -0
package/src/server.ts
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { init, use } from "echarts/core";
|
|
2
|
+
import { LineChart } from "echarts/charts";
|
|
3
|
+
import {
|
|
4
|
+
GridComponent,
|
|
5
|
+
TooltipComponent,
|
|
6
|
+
DataZoomComponent,
|
|
7
|
+
} from "echarts/components";
|
|
8
|
+
import { SVGRenderer } from "echarts/renderers";
|
|
9
|
+
import { prepareSeries } from "./chart/data.js";
|
|
10
|
+
import { chartOption, type ChartConfig } from "./chart/options.js";
|
|
11
|
+
import type { TelemetrySeries } from "./types.js";
|
|
12
|
+
export interface ServerChartProps extends Omit<ChartConfig, "series"> {
|
|
13
|
+
series: readonly TelemetrySeries[];
|
|
14
|
+
width: number;
|
|
15
|
+
height: number;
|
|
16
|
+
}
|
|
17
|
+
/** Render on the server and pass this trusted output to TelemetryChart.Canvas previewSvg. */
|
|
18
|
+
export function renderTelemetrySVG({
|
|
19
|
+
width,
|
|
20
|
+
height,
|
|
21
|
+
series,
|
|
22
|
+
...config
|
|
23
|
+
}: ServerChartProps): string {
|
|
24
|
+
if (![width, height].every((v) => Number.isFinite(v) && v > 0))
|
|
25
|
+
throw new Error("SSR charts require positive width and height");
|
|
26
|
+
use([
|
|
27
|
+
LineChart,
|
|
28
|
+
GridComponent,
|
|
29
|
+
TooltipComponent,
|
|
30
|
+
DataZoomComponent,
|
|
31
|
+
SVGRenderer,
|
|
32
|
+
]);
|
|
33
|
+
const chart = init(null, undefined, {
|
|
34
|
+
renderer: "svg",
|
|
35
|
+
ssr: true,
|
|
36
|
+
width,
|
|
37
|
+
height,
|
|
38
|
+
});
|
|
39
|
+
try {
|
|
40
|
+
chart.setOption(
|
|
41
|
+
chartOption({ ...config, series: prepareSeries(series) }, width),
|
|
42
|
+
);
|
|
43
|
+
return chart.renderToSVGString();
|
|
44
|
+
} finally {
|
|
45
|
+
chart.dispose();
|
|
46
|
+
}
|
|
47
|
+
}
|
package/src/styles.css
ADDED
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
@source "./**/*.js";
|
|
2
|
+
@theme inline {
|
|
3
|
+
--color-watt-positive: var(--watt-positive);
|
|
4
|
+
--color-watt-warning: var(--watt-warning);
|
|
5
|
+
--color-watt-critical: var(--watt-critical);
|
|
6
|
+
--color-watt-accent: var(--watt-accent);
|
|
7
|
+
--color-watt-surface: var(--watt-surface);
|
|
8
|
+
--color-watt-foreground: var(--watt-foreground);
|
|
9
|
+
--color-watt-muted: var(--watt-muted);
|
|
10
|
+
--color-watt-border: var(--watt-border);
|
|
11
|
+
--color-watt-subtle: var(--watt-subtle);
|
|
12
|
+
}
|
|
13
|
+
:root,
|
|
14
|
+
.watt-theme {
|
|
15
|
+
--watt-surface: #ffffff;
|
|
16
|
+
--watt-foreground: #20232c;
|
|
17
|
+
--watt-muted: #626b7b;
|
|
18
|
+
--watt-border: #e3e6ec;
|
|
19
|
+
--watt-subtle: #f1f3f7;
|
|
20
|
+
--watt-accent: #355dff;
|
|
21
|
+
--watt-positive: #16806b;
|
|
22
|
+
--watt-warning: #996009;
|
|
23
|
+
--watt-critical: #c43b40;
|
|
24
|
+
--watt-radius: 12px;
|
|
25
|
+
}
|
|
26
|
+
.dark,
|
|
27
|
+
[data-theme="dark"] {
|
|
28
|
+
--watt-surface: #17191f;
|
|
29
|
+
--watt-foreground: #eef0f5;
|
|
30
|
+
--watt-muted: #a4adbe;
|
|
31
|
+
--watt-border: #333743;
|
|
32
|
+
--watt-subtle: #252932;
|
|
33
|
+
--watt-accent: #8ba3ff;
|
|
34
|
+
--watt-positive: #61d4b7;
|
|
35
|
+
--watt-warning: #f1bd65;
|
|
36
|
+
--watt-critical: #ff898d;
|
|
37
|
+
}
|
|
38
|
+
.watt-root {
|
|
39
|
+
color: var(--watt-foreground);
|
|
40
|
+
font-variant-numeric: tabular-nums;
|
|
41
|
+
}
|
|
42
|
+
.watt-status {
|
|
43
|
+
color: var(--watt-muted);
|
|
44
|
+
}
|
|
45
|
+
.watt-status[data-status="normal"] {
|
|
46
|
+
color: var(--watt-positive);
|
|
47
|
+
}
|
|
48
|
+
.watt-status[data-status="warning"] {
|
|
49
|
+
color: var(--watt-warning);
|
|
50
|
+
}
|
|
51
|
+
.watt-status[data-status="fault"] {
|
|
52
|
+
color: var(--watt-critical);
|
|
53
|
+
}
|
|
54
|
+
.watt-status-dot {
|
|
55
|
+
display: inline-block;
|
|
56
|
+
width: 0.5rem;
|
|
57
|
+
height: 0.5rem;
|
|
58
|
+
border-radius: 50%;
|
|
59
|
+
background: currentColor;
|
|
60
|
+
flex-shrink: 0;
|
|
61
|
+
}
|
|
62
|
+
[data-status="standby"] .watt-status-dot {
|
|
63
|
+
background: transparent;
|
|
64
|
+
border: 1.5px solid currentColor;
|
|
65
|
+
}
|
|
66
|
+
[data-status="stopped"] .watt-status-dot {
|
|
67
|
+
border-radius: 1px;
|
|
68
|
+
}
|
|
69
|
+
[data-status="warning"] .watt-status-dot {
|
|
70
|
+
border-radius: 1px;
|
|
71
|
+
transform: rotate(45deg);
|
|
72
|
+
}
|
|
73
|
+
[data-status="fault"] .watt-status-dot {
|
|
74
|
+
border-radius: 0;
|
|
75
|
+
clip-path: polygon(
|
|
76
|
+
25% 0,
|
|
77
|
+
75% 0,
|
|
78
|
+
100% 25%,
|
|
79
|
+
100% 75%,
|
|
80
|
+
75% 100%,
|
|
81
|
+
25% 100%,
|
|
82
|
+
0 75%,
|
|
83
|
+
0 25%
|
|
84
|
+
);
|
|
85
|
+
}
|
|
86
|
+
[data-status="offline"] .watt-status-dot {
|
|
87
|
+
background: transparent;
|
|
88
|
+
border: 1px dashed currentColor;
|
|
89
|
+
}
|
|
90
|
+
.watt-flow-dash {
|
|
91
|
+
stroke-dasharray: 7 6;
|
|
92
|
+
animation: watt-flow-dash 3s linear infinite;
|
|
93
|
+
}
|
|
94
|
+
.watt-flow-pulse {
|
|
95
|
+
animation: watt-flow-pulse 3s ease-in-out infinite;
|
|
96
|
+
}
|
|
97
|
+
.watt-flow-particle {
|
|
98
|
+
animation: watt-flow-particle 3s linear infinite;
|
|
99
|
+
}
|
|
100
|
+
.watt-chart-preview svg {
|
|
101
|
+
width: 100%;
|
|
102
|
+
height: 100%;
|
|
103
|
+
}
|
|
104
|
+
@keyframes watt-flow-dash {
|
|
105
|
+
to {
|
|
106
|
+
stroke-dashoffset: -26;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
@keyframes watt-flow-pulse {
|
|
110
|
+
50% {
|
|
111
|
+
opacity: 0.35;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
@keyframes watt-flow-particle {
|
|
115
|
+
from {
|
|
116
|
+
offset-distance: 0%;
|
|
117
|
+
}
|
|
118
|
+
to {
|
|
119
|
+
offset-distance: 100%;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
@media (prefers-reduced-motion: reduce) {
|
|
123
|
+
.watt-flow-dash,
|
|
124
|
+
.watt-flow-pulse {
|
|
125
|
+
animation: none !important;
|
|
126
|
+
}
|
|
127
|
+
.watt-flow-particle {
|
|
128
|
+
display: none;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/* Import after @watt-ui/react/styles.css inside a shadcn project. */
|
|
2
|
+
:root,
|
|
3
|
+
.dark,
|
|
4
|
+
[data-theme],
|
|
5
|
+
.watt-theme {
|
|
6
|
+
--watt-surface: var(--background);
|
|
7
|
+
--watt-foreground: var(--foreground);
|
|
8
|
+
--watt-muted: var(--muted-foreground);
|
|
9
|
+
--watt-border: var(--border);
|
|
10
|
+
--watt-subtle: var(--muted);
|
|
11
|
+
--watt-accent: var(--primary);
|
|
12
|
+
--watt-critical: var(--destructive);
|
|
13
|
+
--watt-radius: var(--radius);
|
|
14
|
+
}
|
package/src/types.ts
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import type { HTMLAttributes } from "react";
|
|
2
|
+
|
|
3
|
+
export type PowerUnit = "W" | "kW" | "MW";
|
|
4
|
+
export type EnergyUnit = "Wh" | "kWh" | "MWh";
|
|
5
|
+
export type MeasurementUnit =
|
|
6
|
+
PowerUnit | EnergyUnit | "V" | "A" | "Hz" | "°C" | "%" | "W/m²";
|
|
7
|
+
export type Timestamp = string | number;
|
|
8
|
+
export type DataQuality =
|
|
9
|
+
"good" | "uncertain" | "stale" | "missing" | "bad" | "offline";
|
|
10
|
+
export type EquipmentStatus =
|
|
11
|
+
"normal" | "standby" | "stopped" | "warning" | "fault" | "offline";
|
|
12
|
+
export type Density = "compact" | "comfortable";
|
|
13
|
+
export interface PartProps extends HTMLAttributes<HTMLElement> {
|
|
14
|
+
asChild?: boolean;
|
|
15
|
+
}
|
|
16
|
+
export interface RootProps extends PartProps {
|
|
17
|
+
density?: Density;
|
|
18
|
+
}
|
|
19
|
+
export interface Measurement<U extends MeasurementUnit = MeasurementUnit> {
|
|
20
|
+
value: number | null;
|
|
21
|
+
unit: U;
|
|
22
|
+
timestamp: Timestamp;
|
|
23
|
+
quality?: DataQuality;
|
|
24
|
+
}
|
|
25
|
+
export interface TimeSeriesPoint {
|
|
26
|
+
timestamp: Timestamp;
|
|
27
|
+
value: number | null;
|
|
28
|
+
quality?: DataQuality;
|
|
29
|
+
}
|
|
30
|
+
export interface TelemetrySeries {
|
|
31
|
+
id: string;
|
|
32
|
+
label: string;
|
|
33
|
+
unit: string;
|
|
34
|
+
points: readonly TimeSeriesPoint[];
|
|
35
|
+
color?: string;
|
|
36
|
+
axis?: 0 | 1;
|
|
37
|
+
area?: boolean;
|
|
38
|
+
}
|
|
39
|
+
export type TimeRange = readonly [number, number];
|
|
40
|
+
export interface AlarmEvent {
|
|
41
|
+
id: string;
|
|
42
|
+
severity: "critical" | "warning" | "info";
|
|
43
|
+
status: "active" | "acknowledged" | "resolved";
|
|
44
|
+
timestamp: Timestamp;
|
|
45
|
+
message: string;
|
|
46
|
+
asset?: string;
|
|
47
|
+
description?: string;
|
|
48
|
+
}
|
|
49
|
+
export interface EnergyFlowNode {
|
|
50
|
+
id: string;
|
|
51
|
+
}
|
|
52
|
+
export interface EnergyFlowEdge {
|
|
53
|
+
source: string;
|
|
54
|
+
target: string;
|
|
55
|
+
sourcePort?: string;
|
|
56
|
+
targetPort?: string;
|
|
57
|
+
}
|
|
58
|
+
export interface PlantAsset {
|
|
59
|
+
id: string;
|
|
60
|
+
label: string;
|
|
61
|
+
children?: readonly PlantAsset[];
|
|
62
|
+
status?: EquipmentStatus;
|
|
63
|
+
measurement?: Measurement;
|
|
64
|
+
}
|