@devicechain/widgets 0.24.0-rc.1 → 0.25.0-rc.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 +11 -1
- package/dist/absolute-range-picker.d.ts +22 -0
- package/dist/binding-policy.d.ts +1 -0
- package/dist/builtin-descriptors.d.ts +69 -0
- package/dist/builtin-registry.d.ts +68 -0
- package/dist/chunks/absolute-range-picker-E57G2TPX.js +139 -0
- package/dist/chunks/absolute-range-picker-E57G2TPX.js.map +7 -0
- package/dist/chunks/{aggregate-feed-4FSBQYJL.js → aggregate-feed-XX36GNY6.js} +2 -2
- package/dist/chunks/{aggregate-widgets-2ZQBW3YF.js → aggregate-widgets-72HMPMBU.js} +99 -57
- package/dist/chunks/aggregate-widgets-72HMPMBU.js.map +7 -0
- package/dist/chunks/{chunk-USRYKW2J.js → chunk-7BUCJQFP.js} +10 -2
- package/dist/chunks/chunk-7BUCJQFP.js.map +7 -0
- package/dist/chunks/chunk-AF4M5OXQ.js +23 -0
- package/dist/chunks/chunk-AF4M5OXQ.js.map +7 -0
- package/dist/chunks/{chunk-XQQQNTBX.js → chunk-EQOWBDS7.js} +1 -1
- package/dist/chunks/{chunk-XQQQNTBX.js.map → chunk-EQOWBDS7.js.map} +1 -1
- package/dist/chunks/chunk-JVC6JYUR.js +48 -0
- package/dist/chunks/chunk-JVC6JYUR.js.map +7 -0
- package/dist/chunks/{chunk-JFH4QMLA.js → chunk-NYHNQ5VR.js} +5 -1
- package/dist/chunks/{chunk-JFH4QMLA.js.map → chunk-NYHNQ5VR.js.map} +2 -2
- package/dist/chunks/chunk-VTGKDO44.js +87 -0
- package/dist/chunks/chunk-VTGKDO44.js.map +7 -0
- package/dist/chunks/chunk-XJ7UF2CP.js +90 -0
- package/dist/chunks/chunk-XJ7UF2CP.js.map +7 -0
- package/dist/chunks/{compare-feed-AY3CVKUZ.js → compare-feed-5OLZHFRL.js} +48 -23
- package/dist/chunks/compare-feed-5OLZHFRL.js.map +7 -0
- package/dist/chunks/{event-markers-feed-GEGTIHXT.js → event-markers-feed-B3MVFYUT.js} +4 -4
- package/dist/chunks/export-rows-OEWIBIUY.js +11 -0
- package/dist/chunks/{fleet-feed-2SKDR6ZQ.js → fleet-feed-D4T3LC25.js} +10 -10
- package/dist/chunks/history-widgets-NSNXDKEC.js +336 -0
- package/dist/chunks/history-widgets-NSNXDKEC.js.map +7 -0
- package/dist/chunks/{level-widgets-MJB7TOLU.js → level-widgets-HE6EDSWC.js} +13 -9
- package/dist/chunks/level-widgets-HE6EDSWC.js.map +7 -0
- package/dist/chunks/no-reading-B4MPXAS2.js +22 -0
- package/dist/chunks/no-reading-B4MPXAS2.js.map +7 -0
- package/dist/chunks/{presence-widgets-2LIUKN4Y.js → presence-widgets-M5VGG3OO.js} +12 -8
- package/dist/chunks/presence-widgets-M5VGG3OO.js.map +7 -0
- package/dist/chunks/table-CEVB3JZS.js +8 -0
- package/dist/chunks/table-CEVB3JZS.js.map +7 -0
- package/dist/compare-model.d.ts +1 -1
- package/dist/documented-descriptors.d.ts +206 -0
- package/dist/export-rows.d.ts +24 -0
- package/dist/history-feed.d.ts +10 -0
- package/dist/history-model.d.ts +45 -0
- package/dist/history-strings.d.ts +20 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +544 -189
- package/dist/index.js.map +4 -4
- package/dist/level-reading.d.ts +1 -0
- package/dist/no-reading-core.d.ts +25 -0
- package/dist/no-reading.d.ts +10 -0
- package/dist/time-range-bar.d.ts +26 -2
- package/dist/widgets/history-lazy.d.ts +70 -0
- package/dist/widgets/history-table.d.ts +7 -0
- package/dist/widgets/history-widgets.d.ts +2 -0
- package/dist/widgets/no-reading-lazy.d.ts +7 -0
- package/package.json +8 -8
- package/dist/chunks/aggregate-widgets-2ZQBW3YF.js.map +0 -7
- package/dist/chunks/chunk-USRYKW2J.js.map +0 -7
- package/dist/chunks/compare-feed-AY3CVKUZ.js.map +0 -7
- package/dist/chunks/level-widgets-MJB7TOLU.js.map +0 -7
- package/dist/chunks/presence-widgets-2LIUKN4Y.js.map +0 -7
- package/dist/chunks/table-6EVV7QZH.js +0 -7
- /package/dist/chunks/{aggregate-feed-4FSBQYJL.js.map → aggregate-feed-XX36GNY6.js.map} +0 -0
- /package/dist/chunks/{event-markers-feed-GEGTIHXT.js.map → event-markers-feed-B3MVFYUT.js.map} +0 -0
- /package/dist/chunks/{table-6EVV7QZH.js.map → export-rows-OEWIBIUY.js.map} +0 -0
- /package/dist/chunks/{fleet-feed-2SKDR6ZQ.js.map → fleet-feed-D4T3LC25.js.map} +0 -0
|
@@ -0,0 +1,336 @@
|
|
|
1
|
+
import {
|
|
2
|
+
measurementSpan
|
|
3
|
+
} from "./chunk-NYHNQ5VR.js";
|
|
4
|
+
import {
|
|
5
|
+
ACCESS_STRINGS
|
|
6
|
+
} from "./chunk-BRH66T5F.js";
|
|
7
|
+
import {
|
|
8
|
+
LevelEmpty
|
|
9
|
+
} from "./chunk-EQOWBDS7.js";
|
|
10
|
+
import {
|
|
11
|
+
DEFAULT_PAGE_SIZE,
|
|
12
|
+
bucketLabel,
|
|
13
|
+
columnHeading,
|
|
14
|
+
historyColumns,
|
|
15
|
+
historyExport,
|
|
16
|
+
historyRefreshMs,
|
|
17
|
+
historyRows,
|
|
18
|
+
historyWindow,
|
|
19
|
+
observedNames,
|
|
20
|
+
spansDays
|
|
21
|
+
} from "./chunk-XJ7UF2CP.js";
|
|
22
|
+
import {
|
|
23
|
+
clampPage,
|
|
24
|
+
pageCount
|
|
25
|
+
} from "./chunk-62CHYCHI.js";
|
|
26
|
+
|
|
27
|
+
// src/widgets/history-table.tsx
|
|
28
|
+
import {
|
|
29
|
+
css,
|
|
30
|
+
fontVar,
|
|
31
|
+
formatDateTime,
|
|
32
|
+
formatTimestamp,
|
|
33
|
+
formatValue,
|
|
34
|
+
optBoolean,
|
|
35
|
+
optNumber,
|
|
36
|
+
optString,
|
|
37
|
+
spaceVar,
|
|
38
|
+
useWidgetScale,
|
|
39
|
+
useWidgetTimeZone,
|
|
40
|
+
WidgetFrame
|
|
41
|
+
} from "@devicechain/widget-sdk";
|
|
42
|
+
import { useMemo, useState } from "react";
|
|
43
|
+
|
|
44
|
+
// src/history-strings.ts
|
|
45
|
+
import { viewerLocale } from "@devicechain/widget-sdk";
|
|
46
|
+
var HISTORY_STRINGS = {
|
|
47
|
+
en: {
|
|
48
|
+
time: "Time",
|
|
49
|
+
exportTime: "Bucket start (UTC)",
|
|
50
|
+
average: (bucket) => `avg per ${bucket}`,
|
|
51
|
+
averageTitle: (bucket) => `Each figure is the average of the readings in a ${bucket} bucket, not a reading: the time is the start of its bucket.`,
|
|
52
|
+
loading: "Loading",
|
|
53
|
+
unbound: "Choose a device for this widget",
|
|
54
|
+
forbidden: ACCESS_STRINGS.en.forbidden,
|
|
55
|
+
unsupported: "This data source cannot read stored history",
|
|
56
|
+
failed: "The history could not be read",
|
|
57
|
+
empty: "No readings in this range",
|
|
58
|
+
noReadings: "no readings in this bucket",
|
|
59
|
+
newestFirst: "newest first",
|
|
60
|
+
oldestFirst: "oldest first",
|
|
61
|
+
range: (from, to, of) => `${from}\u2013${to} of ${of}`,
|
|
62
|
+
previous: "Previous page",
|
|
63
|
+
next: "Next page"
|
|
64
|
+
},
|
|
65
|
+
es: {
|
|
66
|
+
time: "Hora",
|
|
67
|
+
exportTime: "Inicio del intervalo (UTC)",
|
|
68
|
+
average: (bucket) => `prom. por ${bucket}`,
|
|
69
|
+
averageTitle: (bucket) => `Cada cifra es el promedio de las lecturas de un intervalo de ${bucket}, no una lectura: la hora es el inicio de su intervalo.`,
|
|
70
|
+
loading: "Cargando",
|
|
71
|
+
unbound: "Elija un dispositivo para este widget",
|
|
72
|
+
forbidden: ACCESS_STRINGS.es.forbidden,
|
|
73
|
+
unsupported: "Esta fuente de datos no puede leer el historial almacenado",
|
|
74
|
+
failed: "No se pudo leer el historial",
|
|
75
|
+
empty: "No hay lecturas en este intervalo",
|
|
76
|
+
noReadings: "sin lecturas en este intervalo",
|
|
77
|
+
newestFirst: "m\xE1s recientes primero",
|
|
78
|
+
oldestFirst: "m\xE1s antiguas primero",
|
|
79
|
+
range: (from, to, of) => `${from}\u2013${to} de ${of}`,
|
|
80
|
+
previous: "P\xE1gina anterior",
|
|
81
|
+
next: "P\xE1gina siguiente"
|
|
82
|
+
}
|
|
83
|
+
};
|
|
84
|
+
function historyStrings() {
|
|
85
|
+
return viewerLocale()?.toLowerCase().startsWith("es") ? HISTORY_STRINGS.es : HISTORY_STRINGS.en;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// src/widgets/history-table.tsx
|
|
89
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
90
|
+
var STACK_BELOW_PX = 480;
|
|
91
|
+
function authoredColumns(raw) {
|
|
92
|
+
if (!Array.isArray(raw)) return [];
|
|
93
|
+
const out = [];
|
|
94
|
+
for (const item of raw) {
|
|
95
|
+
if (typeof item !== "object" || item === null || Array.isArray(item)) continue;
|
|
96
|
+
const entry = item;
|
|
97
|
+
if (typeof entry.measurement !== "string" || entry.measurement === "") continue;
|
|
98
|
+
const column = { name: entry.measurement };
|
|
99
|
+
if (typeof entry.label === "string" && entry.label !== "") column.label = entry.label;
|
|
100
|
+
if (typeof entry.unit === "string" && entry.unit !== "") column.unit = entry.unit;
|
|
101
|
+
if (typeof entry.precision === "number" && Number.isInteger(entry.precision) && entry.precision >= 0 && entry.precision <= 100) {
|
|
102
|
+
column.precision = entry.precision;
|
|
103
|
+
}
|
|
104
|
+
out.push(column);
|
|
105
|
+
}
|
|
106
|
+
return out;
|
|
107
|
+
}
|
|
108
|
+
var cellBox = { padding: `${spaceVar(1)} ${spaceVar(3)}`, textAlign: "left", whiteSpace: "nowrap", verticalAlign: "top" };
|
|
109
|
+
var headBox = {
|
|
110
|
+
...cellBox,
|
|
111
|
+
fontSize: fontVar("xs"),
|
|
112
|
+
fontWeight: 600,
|
|
113
|
+
letterSpacing: "0.04em",
|
|
114
|
+
color: css("muted-foreground"),
|
|
115
|
+
borderBottom: `1px solid ${css("border")}`,
|
|
116
|
+
background: css("card"),
|
|
117
|
+
position: "sticky",
|
|
118
|
+
top: 0,
|
|
119
|
+
zIndex: 1
|
|
120
|
+
};
|
|
121
|
+
var stickyFirst = { position: "sticky", left: 0, background: css("card") };
|
|
122
|
+
var pagerButton = {
|
|
123
|
+
minWidth: "2em",
|
|
124
|
+
padding: `0 ${spaceVar(2)}`,
|
|
125
|
+
border: `1px solid ${css("border")}`,
|
|
126
|
+
borderRadius: 4,
|
|
127
|
+
background: "none",
|
|
128
|
+
color: "inherit",
|
|
129
|
+
font: "inherit",
|
|
130
|
+
cursor: "pointer"
|
|
131
|
+
};
|
|
132
|
+
function HistoryTable({ widget, history }) {
|
|
133
|
+
const strings = historyStrings();
|
|
134
|
+
const title = optString(widget.options, "title");
|
|
135
|
+
const message = (text) => /* @__PURE__ */ jsx(WidgetFrame, { title, flush: true, children: /* @__PURE__ */ jsx(LevelEmpty, { message: text }) });
|
|
136
|
+
if (!history) return message(strings.loading);
|
|
137
|
+
if (history.status !== "ready") return message(strings[history.status]);
|
|
138
|
+
return /* @__PURE__ */ jsx(Ready, { widget, history, strings });
|
|
139
|
+
}
|
|
140
|
+
function Ready({
|
|
141
|
+
widget,
|
|
142
|
+
history,
|
|
143
|
+
strings
|
|
144
|
+
}) {
|
|
145
|
+
const timeZone = useWidgetTimeZone();
|
|
146
|
+
const title = optString(widget.options, "title");
|
|
147
|
+
const precision = optNumber(widget.options, "precision");
|
|
148
|
+
const oldestFirst = optBoolean(widget.options, "oldestFirst") === true;
|
|
149
|
+
const pageSize = optNumber(widget.options, "pageSize") ?? DEFAULT_PAGE_SIZE;
|
|
150
|
+
const authored = useMemo(() => authoredColumns(widget.options?.columns), [widget.options?.columns]);
|
|
151
|
+
const columns = useMemo(
|
|
152
|
+
() => historyColumns(authored, widget.datasource?.measurements ?? [], observedNames(history.buckets)),
|
|
153
|
+
[authored, widget.datasource, history.buckets]
|
|
154
|
+
);
|
|
155
|
+
const rows = useMemo(() => historyRows(history.buckets, columns.map((c) => c.name), oldestFirst), [history.buckets, columns, oldestFirst]);
|
|
156
|
+
const [page, setPage] = useState(0);
|
|
157
|
+
const shown = clampPage(page, rows.length, pageSize);
|
|
158
|
+
const pages = pageCount(rows.length, pageSize);
|
|
159
|
+
const pageRows = rows.slice(shown * pageSize, (shown + 1) * pageSize);
|
|
160
|
+
const bucket = bucketLabel(history.window.intervalSeconds);
|
|
161
|
+
const dated = spansDays(rows, timeZone);
|
|
162
|
+
const timeOf = (row) => dated ? formatDateTime(row.bucketStart, timeZone) : formatTimestamp(row.bucketStart, timeZone);
|
|
163
|
+
const subject = [title ?? "history", widget.datasource?.kind === "device" ? widget.datasource.deviceToken : void 0].filter(Boolean).join("-");
|
|
164
|
+
const exportRows = () => historyExport({
|
|
165
|
+
subject,
|
|
166
|
+
columns,
|
|
167
|
+
rows,
|
|
168
|
+
window: history.window,
|
|
169
|
+
precision,
|
|
170
|
+
heading: { time: strings.exportTime, average: strings.average }
|
|
171
|
+
});
|
|
172
|
+
const cell = (row, c) => {
|
|
173
|
+
const v = row.averages.get(c.name);
|
|
174
|
+
if (v === void 0) {
|
|
175
|
+
return /* @__PURE__ */ jsx("span", { style: { color: css("muted-foreground") }, title: strings.noReadings, "data-cell-empty": "", children: "\u2014" });
|
|
176
|
+
}
|
|
177
|
+
return /* @__PURE__ */ jsx("span", { style: { fontVariantNumeric: "tabular-nums" }, children: formatValue(v, c.precision ?? precision) });
|
|
178
|
+
};
|
|
179
|
+
const wide = /* @__PURE__ */ jsxs("table", { style: { width: "100%", borderCollapse: "collapse", fontSize: fontVar("md"), color: css("foreground") }, children: [
|
|
180
|
+
/* @__PURE__ */ jsx("thead", { children: /* @__PURE__ */ jsxs("tr", { children: [
|
|
181
|
+
/* @__PURE__ */ jsx("th", { scope: "col", style: { ...headBox, ...stickyFirst, zIndex: 2 }, children: strings.time }),
|
|
182
|
+
columns.map((c) => /* @__PURE__ */ jsx("th", { scope: "col", style: headBox, children: columnHeading(c) }, c.name))
|
|
183
|
+
] }) }),
|
|
184
|
+
/* @__PURE__ */ jsx("tbody", { children: pageRows.map((row) => /* @__PURE__ */ jsxs("tr", { "data-bucket": row.bucketStart, style: { borderBottom: `1px solid ${css("border")}` }, children: [
|
|
185
|
+
/* @__PURE__ */ jsx("th", { scope: "row", style: { ...cellBox, ...stickyFirst, fontWeight: 500, fontVariantNumeric: "tabular-nums" }, children: timeOf(row) }),
|
|
186
|
+
columns.map((c) => /* @__PURE__ */ jsx("td", { "data-measurement": c.name, style: cellBox, children: cell(row, c) }, c.name))
|
|
187
|
+
] }, row.bucketStart)) })
|
|
188
|
+
] });
|
|
189
|
+
const narrow = /* @__PURE__ */ jsx("div", { "data-history-stacked": "", style: { color: css("foreground"), fontSize: fontVar("md") }, children: pageRows.map((row) => /* @__PURE__ */ jsxs("div", { "data-bucket": row.bucketStart, style: { padding: `${spaceVar(2)} ${spaceVar(3)}`, borderTop: `1px solid ${css("border")}` }, children: [
|
|
190
|
+
/* @__PURE__ */ jsx("div", { style: { fontWeight: 500, overflowWrap: "anywhere" }, children: timeOf(row) }),
|
|
191
|
+
columns.map((c) => /* @__PURE__ */ jsxs("div", { "data-measurement": c.name, style: { display: "flex", justifyContent: "space-between", gap: spaceVar(3), alignItems: "baseline" }, children: [
|
|
192
|
+
/* @__PURE__ */ jsx("span", { style: { color: css("muted-foreground"), fontSize: fontVar("sm"), overflowWrap: "anywhere" }, children: columnHeading(c) }),
|
|
193
|
+
/* @__PURE__ */ jsx("span", { style: { textAlign: "right", overflowWrap: "anywhere" }, children: cell(row, c) })
|
|
194
|
+
] }, c.name))
|
|
195
|
+
] }, row.bucketStart)) });
|
|
196
|
+
return /* @__PURE__ */ jsx(WidgetFrame, { title, flush: true, exportRows, children: /* @__PURE__ */ jsxs("div", { style: { display: "flex", flexDirection: "column", height: "100%", minHeight: 0 }, children: [
|
|
197
|
+
rows.length === 0 ? /* @__PURE__ */ jsx(LevelEmpty, { message: strings.empty }) : (
|
|
198
|
+
// A focusable scroll region: a keyboard user can scroll a wide table sideways.
|
|
199
|
+
/* @__PURE__ */ jsx("div", { role: "region", "aria-label": title ?? strings.time, tabIndex: 0, "data-history-scroll": "", style: { flex: 1, minHeight: 0, overflow: "auto" }, children: /* @__PURE__ */ jsx(Responsive, { wide, narrow }) })
|
|
200
|
+
),
|
|
201
|
+
/* @__PURE__ */ jsx(
|
|
202
|
+
Footer,
|
|
203
|
+
{
|
|
204
|
+
strings,
|
|
205
|
+
bucket,
|
|
206
|
+
oldestFirst,
|
|
207
|
+
pages,
|
|
208
|
+
shown,
|
|
209
|
+
from: shown * pageSize + 1,
|
|
210
|
+
to: shown * pageSize + pageRows.length,
|
|
211
|
+
of: rows.length,
|
|
212
|
+
onPage: setPage
|
|
213
|
+
}
|
|
214
|
+
)
|
|
215
|
+
] }) });
|
|
216
|
+
}
|
|
217
|
+
function Responsive({ wide, narrow }) {
|
|
218
|
+
const { width } = useWidgetScale().size;
|
|
219
|
+
return width > 0 && width < STACK_BELOW_PX ? narrow : wide;
|
|
220
|
+
}
|
|
221
|
+
var COMPACT_FOOTER_BELOW_PX = 260;
|
|
222
|
+
function Footer({
|
|
223
|
+
strings,
|
|
224
|
+
bucket,
|
|
225
|
+
oldestFirst,
|
|
226
|
+
pages,
|
|
227
|
+
shown,
|
|
228
|
+
from,
|
|
229
|
+
to,
|
|
230
|
+
of,
|
|
231
|
+
onPage
|
|
232
|
+
}) {
|
|
233
|
+
const { width } = useWidgetScale().size;
|
|
234
|
+
const compact = width > 0 && width < COMPACT_FOOTER_BELOW_PX;
|
|
235
|
+
const order = oldestFirst ? strings.oldestFirst : strings.newestFirst;
|
|
236
|
+
const range = strings.range(from, to, of);
|
|
237
|
+
return /* @__PURE__ */ jsxs(
|
|
238
|
+
"div",
|
|
239
|
+
{
|
|
240
|
+
"data-history-footer": "",
|
|
241
|
+
style: {
|
|
242
|
+
display: "flex",
|
|
243
|
+
flexWrap: "wrap",
|
|
244
|
+
alignItems: "center",
|
|
245
|
+
justifyContent: "space-between",
|
|
246
|
+
gap: spaceVar(2),
|
|
247
|
+
padding: `${spaceVar(1)} ${spaceVar(3)}`,
|
|
248
|
+
fontSize: fontVar("sm"),
|
|
249
|
+
color: css("muted-foreground"),
|
|
250
|
+
borderTop: `1px solid ${css("border")}`
|
|
251
|
+
},
|
|
252
|
+
children: [
|
|
253
|
+
/* @__PURE__ */ jsx("span", { "data-history-bucket": bucket, title: `${strings.averageTitle(bucket)} (${order})`, children: compact ? strings.average(bucket) : `${strings.average(bucket)} \xB7 ${order}` }),
|
|
254
|
+
pages > 1 && /* @__PURE__ */ jsxs("span", { style: { display: "inline-flex", alignItems: "center", gap: spaceVar(2) }, title: compact ? range : void 0, children: [
|
|
255
|
+
/* @__PURE__ */ jsx("button", { type: "button", style: pagerButton, disabled: shown === 0, onClick: () => onPage(shown - 1), "aria-label": strings.previous, children: "\u2039" }),
|
|
256
|
+
compact ? null : /* @__PURE__ */ jsx("span", { children: range }),
|
|
257
|
+
/* @__PURE__ */ jsx("button", { type: "button", style: pagerButton, disabled: shown >= pages - 1, onClick: () => onPage(shown + 1), "aria-label": strings.next, children: "\u203A" })
|
|
258
|
+
] })
|
|
259
|
+
]
|
|
260
|
+
}
|
|
261
|
+
);
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
// src/history-feed.tsx
|
|
265
|
+
import { DEFAULT_TIME_RANGE_SECONDS } from "@devicechain/dashboards";
|
|
266
|
+
import { isForbiddenError } from "@devicechain/client";
|
|
267
|
+
import { resolveStaleAfterSeconds, useWidgetTimeRange, WidgetFreshnessProvider } from "@devicechain/widget-sdk";
|
|
268
|
+
import { useEffect, useMemo as useMemo2, useState as useState2 } from "react";
|
|
269
|
+
import { jsx as jsx2 } from "react/jsx-runtime";
|
|
270
|
+
function HistoryFeed({ hub, widget, descriptor, Component, actions }) {
|
|
271
|
+
const range = useWidgetTimeRange();
|
|
272
|
+
const now = useMemo2(() => hub.now ? () => hub.now() : Date.now, [hub]);
|
|
273
|
+
const spanSeconds = measurementSpan(descriptor, widget, range?.spanSeconds) ?? DEFAULT_TIME_RANGE_SECONDS;
|
|
274
|
+
const pausedAt = range?.paused ? range.pausedAt : void 0;
|
|
275
|
+
const ds = widget.datasource;
|
|
276
|
+
const key = JSON.stringify([ds ?? null, spanSeconds, pausedAt ?? null]);
|
|
277
|
+
const supported = hub.bucketMeasurements !== void 0;
|
|
278
|
+
const [read, setRead] = useState2({ key, view: { status: "loading" }, readAt: null });
|
|
279
|
+
useEffect(() => {
|
|
280
|
+
if (!supported || !ds || ds.kind === "unbound") return;
|
|
281
|
+
let current = true;
|
|
282
|
+
const run = () => {
|
|
283
|
+
const window = historyWindow(spanSeconds, pausedAt ?? now());
|
|
284
|
+
hub.bucketMeasurements(ds, window).then(
|
|
285
|
+
(buckets) => {
|
|
286
|
+
if (current) setRead({ key, view: { status: "ready", buckets, window }, readAt: Date.now() });
|
|
287
|
+
},
|
|
288
|
+
(err) => {
|
|
289
|
+
if (!current) return;
|
|
290
|
+
const status = isForbiddenError(err) ? "forbidden" : "failed";
|
|
291
|
+
setRead((prev) => status === "failed" && prev.key === key && prev.view.status === "ready" ? prev : { key, view: { status }, readAt: null });
|
|
292
|
+
}
|
|
293
|
+
);
|
|
294
|
+
};
|
|
295
|
+
run();
|
|
296
|
+
if (pausedAt !== void 0) return () => void (current = false);
|
|
297
|
+
const every = historyRefreshMs(spanSeconds);
|
|
298
|
+
let timer;
|
|
299
|
+
const schedule = () => {
|
|
300
|
+
timer = setTimeout(
|
|
301
|
+
() => {
|
|
302
|
+
if (!document.hidden) run();
|
|
303
|
+
schedule();
|
|
304
|
+
},
|
|
305
|
+
every - now() % every
|
|
306
|
+
);
|
|
307
|
+
};
|
|
308
|
+
schedule();
|
|
309
|
+
const shown = () => {
|
|
310
|
+
if (!document.hidden) run();
|
|
311
|
+
};
|
|
312
|
+
document.addEventListener("visibilitychange", shown);
|
|
313
|
+
return () => {
|
|
314
|
+
current = false;
|
|
315
|
+
clearTimeout(timer);
|
|
316
|
+
document.removeEventListener("visibilitychange", shown);
|
|
317
|
+
};
|
|
318
|
+
}, [hub, supported, key]);
|
|
319
|
+
let view;
|
|
320
|
+
let readAt = null;
|
|
321
|
+
if (!supported) view = { status: "unsupported" };
|
|
322
|
+
else if (!ds || ds.kind === "unbound") view = { status: "unbound" };
|
|
323
|
+
else if (read.key === key) ({ view, readAt } = read);
|
|
324
|
+
else view = { status: "loading" };
|
|
325
|
+
const freshness = useMemo2(
|
|
326
|
+
() => descriptor.freshness === true ? { at: readAt ?? void 0, staleAfterSeconds: resolveStaleAfterSeconds(widget.options) } : void 0,
|
|
327
|
+
[descriptor, widget.options, readAt]
|
|
328
|
+
);
|
|
329
|
+
const data = { latest: {}, samples: [], error: null };
|
|
330
|
+
return /* @__PURE__ */ jsx2(WidgetFreshnessProvider, { freshness, children: /* @__PURE__ */ jsx2(Component, { widget, data, actions, history: view }) });
|
|
331
|
+
}
|
|
332
|
+
export {
|
|
333
|
+
HistoryFeed,
|
|
334
|
+
HistoryTable
|
|
335
|
+
};
|
|
336
|
+
//# sourceMappingURL=history-widgets-NSNXDKEC.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/widgets/history-table.tsx", "../../src/history-strings.ts", "../../src/history-feed.tsx"],
|
|
4
|
+
"sourcesContent": ["// Copyright The DeviceChain Authors\n// SPDX-License-Identifier: Apache-2.0\n\n// history-table -- one device's stored history as rows: a row per time bucket over the board's span,\n// a column per measurement, each cell the AVERAGE of that measurement's readings in the bucket. It\n// answers \"give me the numbers\" without leaving the board, and its frame menu exports them as CSV.\n//\n// \uD83D\uDD34 A BUCKET AVERAGE IS NOT A READING. The table says so wherever a figure could be taken for one:\n// the footer reads \"avg per 5m\" (with the sentence in its title), the time is the START of the\n// bucket, and the export's headings and file name carry the same words. There is no live tail: the\n// newest row is a bucket that is still filling, and the table reads it again on the bucket's\n// boundaries (history-feed.tsx).\n//\n// - a cell with no number is \"\u2014\" with a reason: that measurement has no readings in that bucket;\n// - newest first unless `oldestFirst`; long histories are paged (`pageSize`), and the export holds\n// every row, not the page on screen;\n// - on a narrow board the table becomes a card per bucket, so nothing is cut off at the right edge.\n\nimport {\n css,\n fontVar,\n formatDateTime,\n formatTimestamp,\n formatValue,\n optBoolean,\n optNumber,\n optString,\n spaceVar,\n useWidgetScale,\n useWidgetTimeZone,\n WidgetFrame,\n type WidgetProps,\n} from '@devicechain/widget-sdk';\nimport { useMemo, useState, type CSSProperties, type ReactNode } from 'react';\n\nimport {\n DEFAULT_PAGE_SIZE,\n bucketLabel,\n clampPage,\n columnHeading,\n historyColumns,\n historyExport,\n historyRows,\n observedNames,\n pageCount,\n spansDays,\n type HistoryColumn,\n type HistoryRow,\n type HistoryView,\n} from '../history-model';\nimport { historyStrings, type HistoryStrings } from '../history-strings';\nimport { LevelEmpty } from '../level-readout';\n\n// Below this width (px of the widget body) the table becomes a card per bucket.\nexport const STACK_BELOW_PX = 480;\n\n// The author's column list, read defensively: a hand-edited definition may carry anything, and an\n// entry that cannot be read drops out rather than take the table down.\nexport function authoredColumns(raw: unknown): HistoryColumn[] {\n if (!Array.isArray(raw)) return [];\n const out: HistoryColumn[] = [];\n for (const item of raw) {\n if (typeof item !== 'object' || item === null || Array.isArray(item)) continue;\n const entry = item as Record<string, unknown>;\n if (typeof entry.measurement !== 'string' || entry.measurement === '') continue;\n const column: HistoryColumn = { name: entry.measurement };\n if (typeof entry.label === 'string' && entry.label !== '') column.label = entry.label;\n if (typeof entry.unit === 'string' && entry.unit !== '') column.unit = entry.unit;\n if (typeof entry.precision === 'number' && Number.isInteger(entry.precision) && entry.precision >= 0 && entry.precision <= 100) {\n column.precision = entry.precision;\n }\n out.push(column);\n }\n return out;\n}\n\nconst cellBox: CSSProperties = { padding: `${spaceVar(1)} ${spaceVar(3)}`, textAlign: 'left', whiteSpace: 'nowrap', verticalAlign: 'top' };\nconst headBox: CSSProperties = {\n ...cellBox,\n fontSize: fontVar('xs'),\n fontWeight: 600,\n letterSpacing: '0.04em',\n color: css('muted-foreground'),\n borderBottom: `1px solid ${css('border')}`,\n background: css('card'),\n position: 'sticky',\n top: 0,\n zIndex: 1,\n};\n// The time column stays in view while the measurement columns scroll under it.\nconst stickyFirst: CSSProperties = { position: 'sticky', left: 0, background: css('card') };\nconst pagerButton: CSSProperties = {\n minWidth: '2em',\n padding: `0 ${spaceVar(2)}`,\n border: `1px solid ${css('border')}`,\n borderRadius: 4,\n background: 'none',\n color: 'inherit',\n font: 'inherit',\n cursor: 'pointer',\n};\n\nexport function HistoryTable({ widget, history }: WidgetProps & { history?: HistoryView }) {\n const strings = historyStrings();\n const title = optString(widget.options, 'title');\n const message = (text: string) => (\n <WidgetFrame title={title} flush>\n <LevelEmpty message={text} />\n </WidgetFrame>\n );\n if (!history) return message(strings.loading);\n if (history.status !== 'ready') return message(strings[history.status]);\n return <Ready widget={widget} history={history} strings={strings} />;\n}\n\nfunction Ready({\n widget,\n history,\n strings,\n}: {\n widget: WidgetProps['widget'];\n history: Extract<HistoryView, { status: 'ready' }>;\n strings: HistoryStrings;\n}) {\n const timeZone = useWidgetTimeZone();\n const title = optString(widget.options, 'title');\n const precision = optNumber(widget.options, 'precision');\n const oldestFirst = optBoolean(widget.options, 'oldestFirst') === true;\n const pageSize = optNumber(widget.options, 'pageSize') ?? DEFAULT_PAGE_SIZE;\n const authored = useMemo(() => authoredColumns(widget.options?.columns), [widget.options?.columns]);\n const columns = useMemo(\n () => historyColumns(authored, widget.datasource?.measurements ?? [], observedNames(history.buckets)),\n [authored, widget.datasource, history.buckets],\n );\n const rows = useMemo(() => historyRows(history.buckets, columns.map((c) => c.name), oldestFirst), [history.buckets, columns, oldestFirst]);\n const [page, setPage] = useState(0);\n const shown = clampPage(page, rows.length, pageSize);\n const pages = pageCount(rows.length, pageSize);\n const pageRows = rows.slice(shown * pageSize, (shown + 1) * pageSize);\n const bucket = bucketLabel(history.window.intervalSeconds);\n const dated = spansDays(rows, timeZone);\n const timeOf = (row: HistoryRow): string => (dated ? formatDateTime(row.bucketStart, timeZone) : formatTimestamp(row.bucketStart, timeZone));\n\n const subject = [title ?? 'history', widget.datasource?.kind === 'device' ? widget.datasource.deviceToken : undefined].filter(Boolean).join('-');\n // Built when the viewer picks the export, from the rows the table holds now: every row, in the order\n // on screen, over the window these buckets were read for.\n const exportRows = () =>\n historyExport({\n subject,\n columns,\n rows,\n window: history.window,\n precision,\n heading: { time: strings.exportTime, average: strings.average },\n });\n\n const cell = (row: HistoryRow, c: HistoryColumn): ReactNode => {\n const v = row.averages.get(c.name);\n if (v === undefined) {\n return (\n <span style={{ color: css('muted-foreground') }} title={strings.noReadings} data-cell-empty=\"\">\n \u2014\n </span>\n );\n }\n return <span style={{ fontVariantNumeric: 'tabular-nums' }}>{formatValue(v, c.precision ?? precision)}</span>;\n };\n\n const wide = (\n <table style={{ width: '100%', borderCollapse: 'collapse', fontSize: fontVar('md'), color: css('foreground') }}>\n <thead>\n <tr>\n <th scope=\"col\" style={{ ...headBox, ...stickyFirst, zIndex: 2 }}>\n {strings.time}\n </th>\n {columns.map((c) => (\n <th key={c.name} scope=\"col\" style={headBox}>\n {columnHeading(c)}\n </th>\n ))}\n </tr>\n </thead>\n <tbody>\n {pageRows.map((row) => (\n <tr key={row.bucketStart} data-bucket={row.bucketStart} style={{ borderBottom: `1px solid ${css('border')}` }}>\n <th scope=\"row\" style={{ ...cellBox, ...stickyFirst, fontWeight: 500, fontVariantNumeric: 'tabular-nums' }}>\n {timeOf(row)}\n </th>\n {columns.map((c) => (\n <td key={c.name} data-measurement={c.name} style={cellBox}>\n {cell(row, c)}\n </td>\n ))}\n </tr>\n ))}\n </tbody>\n </table>\n );\n\n const narrow = (\n <div data-history-stacked=\"\" style={{ color: css('foreground'), fontSize: fontVar('md') }}>\n {pageRows.map((row) => (\n <div key={row.bucketStart} data-bucket={row.bucketStart} style={{ padding: `${spaceVar(2)} ${spaceVar(3)}`, borderTop: `1px solid ${css('border')}` }}>\n <div style={{ fontWeight: 500, overflowWrap: 'anywhere' }}>{timeOf(row)}</div>\n {columns.map((c) => (\n <div key={c.name} data-measurement={c.name} style={{ display: 'flex', justifyContent: 'space-between', gap: spaceVar(3), alignItems: 'baseline' }}>\n <span style={{ color: css('muted-foreground'), fontSize: fontVar('sm'), overflowWrap: 'anywhere' }}>{columnHeading(c)}</span>\n <span style={{ textAlign: 'right', overflowWrap: 'anywhere' }}>{cell(row, c)}</span>\n </div>\n ))}\n </div>\n ))}\n </div>\n );\n\n return (\n <WidgetFrame title={title} flush exportRows={exportRows}>\n <div style={{ display: 'flex', flexDirection: 'column', height: '100%', minHeight: 0 }}>\n {rows.length === 0 ? (\n <LevelEmpty message={strings.empty} />\n ) : (\n // A focusable scroll region: a keyboard user can scroll a wide table sideways.\n <div role=\"region\" aria-label={title ?? strings.time} tabIndex={0} data-history-scroll=\"\" style={{ flex: 1, minHeight: 0, overflow: 'auto' }}>\n <Responsive wide={wide} narrow={narrow} />\n </div>\n )}\n <Footer\n strings={strings}\n bucket={bucket}\n oldestFirst={oldestFirst}\n pages={pages}\n shown={shown}\n from={shown * pageSize + 1}\n to={shown * pageSize + pageRows.length}\n of={rows.length}\n onPage={setPage}\n />\n </div>\n </WidgetFrame>\n );\n}\n\nfunction Responsive({ wide, narrow }: { wide: ReactNode; narrow: ReactNode }) {\n const { width } = useWidgetScale().size;\n // An unmeasured body (width 0: before the first layout, or under a test renderer) takes the table.\n return width > 0 && width < STACK_BELOW_PX ? narrow : wide;\n}\n\n// Below this width (px of the widget body) the footer keeps only what cannot be left out: the basis of\n// the figures and the page buttons. The rest moves to their titles, so a table at the smallest span\n// still has a footer that fits on one line.\nconst COMPACT_FOOTER_BELOW_PX = 260;\n\nfunction Footer({\n strings,\n bucket,\n oldestFirst,\n pages,\n shown,\n from,\n to,\n of,\n onPage,\n}: {\n strings: HistoryStrings;\n bucket: string;\n oldestFirst: boolean;\n pages: number;\n shown: number;\n from: number;\n to: number;\n of: number;\n onPage: (page: number) => void;\n}) {\n const { width } = useWidgetScale().size;\n const compact = width > 0 && width < COMPACT_FOOTER_BELOW_PX;\n const order = oldestFirst ? strings.oldestFirst : strings.newestFirst;\n const range = strings.range(from, to, of);\n return (\n <div\n data-history-footer=\"\"\n style={{\n display: 'flex',\n flexWrap: 'wrap',\n alignItems: 'center',\n justifyContent: 'space-between',\n gap: spaceVar(2),\n padding: `${spaceVar(1)} ${spaceVar(3)}`,\n fontSize: fontVar('sm'),\n color: css('muted-foreground'),\n borderTop: `1px solid ${css('border')}`,\n }}\n >\n <span data-history-bucket={bucket} title={`${strings.averageTitle(bucket)} (${order})`}>\n {compact ? strings.average(bucket) : `${strings.average(bucket)} \u00B7 ${order}`}\n </span>\n {pages > 1 && (\n <span style={{ display: 'inline-flex', alignItems: 'center', gap: spaceVar(2) }} title={compact ? range : undefined}>\n <button type=\"button\" style={pagerButton} disabled={shown === 0} onClick={() => onPage(shown - 1)} aria-label={strings.previous}>\n \u2039\n </button>\n {compact ? null : <span>{range}</span>}\n <button type=\"button\" style={pagerButton} disabled={shown >= pages - 1} onClick={() => onPage(shown + 1)} aria-label={strings.next}>\n \u203A\n </button>\n </span>\n )}\n </div>\n );\n}\n", "// Copyright The DeviceChain Authors\n// SPDX-License-Identifier: Apache-2.0\n\n// The fixed words the history table renders itself and exports with. The widget packages carry no i18n\n// runtime, so this is the one small per-language table (modelled on fleet-strings.ts); the option labels\n// are translated in the console's catalogs, not here. Loaded with the history table's chunk, never by a\n// board without one.\n\nimport { viewerLocale } from '@devicechain/widget-sdk';\n\nimport { ACCESS_STRINGS } from './access-strings';\n\nexport interface HistoryStrings {\n time: string;\n // The export's first heading: the instant is a bucket's START (written ISO 8601, in UTC).\n exportTime: string;\n // \"avg per 5m\": what every figure in the table is.\n average: (bucket: string) => string;\n averageTitle: (bucket: string) => string;\n loading: string;\n unbound: string;\n forbidden: string;\n unsupported: string;\n failed: string;\n empty: string;\n // A cell for a measurement with no readings in that bucket.\n noReadings: string;\n newestFirst: string;\n oldestFirst: string;\n range: (from: number, to: number, of: number) => string;\n previous: string;\n next: string;\n}\n\nexport const HISTORY_STRINGS: Record<'en' | 'es', HistoryStrings> = {\n en: {\n time: 'Time',\n exportTime: 'Bucket start (UTC)',\n average: (bucket) => `avg per ${bucket}`,\n averageTitle: (bucket) =>\n `Each figure is the average of the readings in a ${bucket} bucket, not a reading: the time is the start of its bucket.`,\n loading: 'Loading',\n unbound: 'Choose a device for this widget',\n forbidden: ACCESS_STRINGS.en.forbidden,\n unsupported: 'This data source cannot read stored history',\n failed: 'The history could not be read',\n empty: 'No readings in this range',\n noReadings: 'no readings in this bucket',\n newestFirst: 'newest first',\n oldestFirst: 'oldest first',\n range: (from, to, of) => `${from}\u2013${to} of ${of}`,\n previous: 'Previous page',\n next: 'Next page',\n },\n es: {\n time: 'Hora',\n exportTime: 'Inicio del intervalo (UTC)',\n average: (bucket) => `prom. por ${bucket}`,\n averageTitle: (bucket) =>\n `Cada cifra es el promedio de las lecturas de un intervalo de ${bucket}, no una lectura: la hora es el inicio de su intervalo.`,\n loading: 'Cargando',\n unbound: 'Elija un dispositivo para este widget',\n forbidden: ACCESS_STRINGS.es.forbidden,\n unsupported: 'Esta fuente de datos no puede leer el historial almacenado',\n failed: 'No se pudo leer el historial',\n empty: 'No hay lecturas en este intervalo',\n noReadings: 'sin lecturas en este intervalo',\n newestFirst: 'm\u00E1s recientes primero',\n oldestFirst: 'm\u00E1s antiguas primero',\n range: (from, to, of) => `${from}\u2013${to} de ${of}`,\n previous: 'P\u00E1gina anterior',\n next: 'P\u00E1gina siguiente',\n },\n};\n\nexport function historyStrings(): HistoryStrings {\n return viewerLocale()?.toLowerCase().startsWith('es') ? HISTORY_STRINGS.es : HISTORY_STRINGS.en;\n}\n", "// Copyright The DeviceChain Authors\n// SPDX-License-Identifier: Apache-2.0\n\n// The data feed of the history table: one device's stored history over its span, in time buckets.\n// Loaded with the table's chunk (connected-widget.tsx imports it dynamically), so a board without a\n// history table never downloads it.\n//\n// - the span is the widget's pinned one, else the board's (DEFAULT_TIME_RANGE_SECONDS off a board);\n// - the window is whole minutes ending at the last minute boundary, in the buckets of the span's chart\n// (bucketSecondsFor), read through the source's own bucketMeasurements: the same call a stat card\n// makes, so the hub shares identical reads. The table shows each bucket's AVERAGE and says so;\n// - there is no live tail. A reading that arrived since the last bucket read belongs to a bucket that\n// is still filling, and a figure that moved under the viewer between two reads would be a reading\n// passed off as an average. The table reads again on the boundaries of its bucket (live) and says\n// how old its read is (the frame's freshness is the last SUCCESSFUL read);\n// - paused, the window ends at the freeze instant and is read once;\n// - a hidden tab does not read; it reads once when it is shown again;\n// - a read for a different selector, span or freeze instant is not shown under the new one: a result\n// is tagged with the key it was read for, and a mismatch reads as loading. A read that fails keeps\n// the buckets it would have replaced (they are still true) and the frame ages from the last good one.\n\nimport { DEFAULT_TIME_RANGE_SECONDS, type WidgetActions, type WidgetDataSource, type WidgetDescriptor, type WidgetInstance } from '@devicechain/dashboards';\nimport { isForbiddenError } from '@devicechain/client';\nimport { resolveStaleAfterSeconds, useWidgetTimeRange, WidgetFreshnessProvider } from '@devicechain/widget-sdk';\nimport { useEffect, useMemo, useState, type ComponentType } from 'react';\n\nimport { measurementSpan } from './binding-policy';\nimport { historyRefreshMs, historyWindow, type HistoryView } from './history-model';\n\nexport interface HistoryFeedProps {\n hub: WidgetDataSource;\n widget: WidgetInstance;\n descriptor: WidgetDescriptor;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n Component: ComponentType<any>;\n actions: WidgetActions | undefined;\n}\n\ninterface Read {\n key: string;\n view: HistoryView;\n // When the last successful read landed (epoch ms): the age of the figures on screen.\n readAt: number | null;\n}\n\nexport default function HistoryFeed({ hub, widget, descriptor, Component, actions }: HistoryFeedProps) {\n const range = useWidgetTimeRange();\n const now = useMemo(() => (hub.now ? () => hub.now!() : Date.now), [hub]);\n const spanSeconds = measurementSpan(descriptor, widget, range?.spanSeconds) ?? DEFAULT_TIME_RANGE_SECONDS;\n const pausedAt = range?.paused ? range.pausedAt : undefined;\n const ds = widget.datasource;\n const key = JSON.stringify([ds ?? null, spanSeconds, pausedAt ?? null]);\n const supported = hub.bucketMeasurements !== undefined;\n const [read, setRead] = useState<Read>({ key, view: { status: 'loading' }, readAt: null });\n\n useEffect(() => {\n if (!supported || !ds || ds.kind === 'unbound') return;\n let current = true;\n const run = (): void => {\n const window = historyWindow(spanSeconds, pausedAt ?? now());\n hub.bucketMeasurements!(ds, window).then(\n (buckets) => {\n if (current) setRead({ key, view: { status: 'ready', buckets, window }, readAt: Date.now() });\n },\n (err: unknown) => {\n if (!current) return;\n // A refusal is a state, not a failure; a failure keeps what is on screen for THIS read's key.\n const status = isForbiddenError(err) ? 'forbidden' : 'failed';\n setRead((prev) => (status === 'failed' && prev.key === key && prev.view.status === 'ready' ? prev : { key, view: { status }, readAt: null }));\n },\n );\n };\n run();\n // Paused, the window is fixed at the freeze instant: nothing new can land in it.\n if (pausedAt !== undefined) return () => void (current = false);\n const every = historyRefreshMs(spanSeconds);\n let timer: ReturnType<typeof setTimeout>;\n const schedule = (): void => {\n timer = setTimeout(\n () => {\n if (!document.hidden) run();\n schedule();\n },\n every - (now() % every),\n );\n };\n schedule();\n const shown = (): void => {\n if (!document.hidden) run();\n };\n document.addEventListener('visibilitychange', shown);\n return () => {\n current = false;\n clearTimeout(timer);\n document.removeEventListener('visibilitychange', shown);\n };\n // `ds` is read through `key` (value identity), not by reference.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [hub, supported, key]);\n\n let view: HistoryView;\n let readAt: number | null = null;\n if (!supported) view = { status: 'unsupported' };\n else if (!ds || ds.kind === 'unbound') view = { status: 'unbound' };\n else if (read.key === key) ({ view, readAt } = read);\n else view = { status: 'loading' };\n\n const freshness = useMemo(\n () => (descriptor.freshness === true ? { at: readAt ?? undefined, staleAfterSeconds: resolveStaleAfterSeconds(widget.options) } : undefined),\n [descriptor, widget.options, readAt],\n );\n const data = { latest: {}, samples: [], error: null };\n return (\n <WidgetFreshnessProvider freshness={freshness}>\n <Component widget={widget} data={data} actions={actions} history={view} />\n </WidgetFreshnessProvider>\n );\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["useMemo", "useState", "jsx", "useMemo", "useState"]
|
|
7
|
+
}
|
|
@@ -4,10 +4,14 @@ import {
|
|
|
4
4
|
litBars,
|
|
5
5
|
readRange
|
|
6
6
|
} from "./chunk-ZR74ORIT.js";
|
|
7
|
+
import {
|
|
8
|
+
LevelEmptyFor
|
|
9
|
+
} from "./chunk-AF4M5OXQ.js";
|
|
10
|
+
import "./chunk-JVC6JYUR.js";
|
|
7
11
|
import {
|
|
8
12
|
LevelEmpty,
|
|
9
13
|
LevelReadout
|
|
10
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-EQOWBDS7.js";
|
|
11
15
|
|
|
12
16
|
// src/widgets/battery.tsx
|
|
13
17
|
import { useMemo } from "react";
|
|
@@ -72,6 +76,7 @@ function useLevelReading(widget, data, input) {
|
|
|
72
76
|
const bandColor = levelColor(severity, band?.level);
|
|
73
77
|
return {
|
|
74
78
|
name,
|
|
79
|
+
unbound: widget.datasource?.kind === "unbound",
|
|
75
80
|
sample,
|
|
76
81
|
value,
|
|
77
82
|
unit,
|
|
@@ -89,7 +94,6 @@ function useLevelReading(widget, data, input) {
|
|
|
89
94
|
}
|
|
90
95
|
function emptyReason(r) {
|
|
91
96
|
if (r.range && !r.range.ok) return r.range.reason === "missing" ? r.strings.setRange : r.strings.badRange;
|
|
92
|
-
if (r.value === void 0) return r.strings.noData;
|
|
93
97
|
return void 0;
|
|
94
98
|
}
|
|
95
99
|
|
|
@@ -114,7 +118,7 @@ function Battery({ widget, data }) {
|
|
|
114
118
|
}
|
|
115
119
|
function BatteryBody({ reading: r, scale: ws }) {
|
|
116
120
|
const reason = emptyReason(r);
|
|
117
|
-
if (reason !== void 0 || !r.range?.ok || !r.fill) return /* @__PURE__ */ jsx(
|
|
121
|
+
if (reason !== void 0 || !r.range?.ok || !r.fill) return /* @__PURE__ */ jsx(LevelEmptyFor, { reading: r, reason });
|
|
118
122
|
const range = r.range.range;
|
|
119
123
|
const fill = r.fill;
|
|
120
124
|
const readoutHeight = Math.max(ws.px("font-md") * 1.6, ws.size.height * 0.4);
|
|
@@ -229,7 +233,7 @@ function CompassBody({ reading: r, title, scale: ws }) {
|
|
|
229
233
|
[r.value, theme, r.strings, r.thresholds, ws.scale, ws.size]
|
|
230
234
|
);
|
|
231
235
|
const reason = emptyReason(r);
|
|
232
|
-
if (reason !== void 0 || r.value === void 0) return /* @__PURE__ */ jsx2(
|
|
236
|
+
if (reason !== void 0 || r.value === void 0) return /* @__PURE__ */ jsx2(LevelEmptyFor, { reading: r, reason });
|
|
233
237
|
const point = cardinalOf(r.value, r.strings.cardinals);
|
|
234
238
|
const stripHeight = Math.max(ws.px("font-md") * 1.6, ws.size.height * READOUT_SHARE);
|
|
235
239
|
return /* @__PURE__ */ jsxs2(
|
|
@@ -283,7 +287,7 @@ function LevelGauge({ widget, data }) {
|
|
|
283
287
|
}
|
|
284
288
|
function TankBody({ reading: r, percent, scale: ws }) {
|
|
285
289
|
const reason = emptyReason(r);
|
|
286
|
-
if (reason !== void 0 || !r.range?.ok || !r.fill) return /* @__PURE__ */ jsx3(
|
|
290
|
+
if (reason !== void 0 || !r.range?.ok || !r.fill) return /* @__PURE__ */ jsx3(LevelEmptyFor, { reading: r, reason });
|
|
287
291
|
const range = r.range.range;
|
|
288
292
|
const fill = r.fill;
|
|
289
293
|
const wall = 2;
|
|
@@ -403,7 +407,7 @@ function LinearGauge({ widget, data }) {
|
|
|
403
407
|
}
|
|
404
408
|
function LinearBody({ reading: r, thermometer, vertical, scale: ws }) {
|
|
405
409
|
const reason = emptyReason(r);
|
|
406
|
-
if (reason !== void 0 || !r.range?.ok || !r.fill) return /* @__PURE__ */ jsx4(
|
|
410
|
+
if (reason !== void 0 || !r.range?.ok || !r.fill) return /* @__PURE__ */ jsx4(LevelEmptyFor, { reading: r, reason });
|
|
407
411
|
const range = r.range.range;
|
|
408
412
|
const fill = r.fill;
|
|
409
413
|
const { size, scale } = ws;
|
|
@@ -594,7 +598,7 @@ function ProgressRing({ widget, data }) {
|
|
|
594
598
|
}
|
|
595
599
|
function RingBody({ reading: r, percent, scale: ws }) {
|
|
596
600
|
const reason = emptyReason(r);
|
|
597
|
-
if (reason !== void 0 || !r.range?.ok || !r.fill) return /* @__PURE__ */ jsx5(
|
|
601
|
+
if (reason !== void 0 || !r.range?.ok || !r.fill) return /* @__PURE__ */ jsx5(LevelEmptyFor, { reading: r, reason });
|
|
598
602
|
const range = r.range.range;
|
|
599
603
|
const fill = r.fill;
|
|
600
604
|
const text = percent ? formatValue4(fill.ratio * 100, r.precision ?? 0) : r.display;
|
|
@@ -672,7 +676,7 @@ function SignalBars({ widget, data }) {
|
|
|
672
676
|
function BarsBody({ reading: r, scale: ws }) {
|
|
673
677
|
if (r.thresholds.length < SIGNAL_MIN_BARS) return /* @__PURE__ */ jsx6(LevelEmpty, { message: r.strings.setThresholds });
|
|
674
678
|
const bars = litBars(r.thresholds, r.value);
|
|
675
|
-
if (!bars) return /* @__PURE__ */ jsx6(
|
|
679
|
+
if (!bars) return /* @__PURE__ */ jsx6(LevelEmptyFor, { reading: r, reason: void 0 });
|
|
676
680
|
const n = bars.total;
|
|
677
681
|
const barW = VIEW2.w / (n + (n - 1) / 3);
|
|
678
682
|
const gapW = barW / 3;
|
|
@@ -830,4 +834,4 @@ export {
|
|
|
830
834
|
SignalBars,
|
|
831
835
|
StatusLight
|
|
832
836
|
};
|
|
833
|
-
//# sourceMappingURL=level-widgets-
|
|
837
|
+
//# sourceMappingURL=level-widgets-HE6EDSWC.js.map
|