@devicechain/widgets 0.22.0 → 0.23.0-rc.1

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.
Files changed (54) hide show
  1. package/README.md +15 -0
  2. package/dist/access-strings.d.ts +6 -0
  3. package/dist/chunks/{aggregate-feed-6ZYKOQOB.js → aggregate-feed-BD3CHNFU.js} +5 -4
  4. package/dist/chunks/aggregate-feed-BD3CHNFU.js.map +7 -0
  5. package/dist/chunks/{aggregate-widgets-WVXAW3UL.js → aggregate-widgets-HZQI5HTX.js} +3 -2
  6. package/dist/chunks/{aggregate-widgets-WVXAW3UL.js.map → aggregate-widgets-HZQI5HTX.js.map} +1 -1
  7. package/dist/chunks/alarm-widgets-7UY6MIYZ.js +9 -0
  8. package/dist/chunks/alarm-widgets-7UY6MIYZ.js.map +7 -0
  9. package/dist/chunks/chunk-6OGI4UFJ.js +367 -0
  10. package/dist/chunks/chunk-6OGI4UFJ.js.map +7 -0
  11. package/dist/chunks/chunk-BRH66T5F.js +15 -0
  12. package/dist/chunks/chunk-BRH66T5F.js.map +7 -0
  13. package/dist/chunks/chunk-FM7OI5TQ.js +87 -0
  14. package/dist/chunks/chunk-FM7OI5TQ.js.map +7 -0
  15. package/dist/chunks/chunk-USRYKW2J.js +55 -0
  16. package/dist/chunks/chunk-USRYKW2J.js.map +7 -0
  17. package/dist/chunks/{chunk-S2OMBJLI.js → chunk-WBKHYZU2.js} +7 -3
  18. package/dist/chunks/{chunk-S2OMBJLI.js.map → chunk-WBKHYZU2.js.map} +2 -2
  19. package/dist/chunks/chunk-XSLFHCNI.js +419 -0
  20. package/dist/chunks/chunk-XSLFHCNI.js.map +7 -0
  21. package/dist/chunks/{control-widgets-UDS4ET3T.js → control-widgets-3V2LSSRF.js} +4 -2
  22. package/dist/chunks/{control-widgets-UDS4ET3T.js.map → control-widgets-3V2LSSRF.js.map} +1 -1
  23. package/dist/chunks/entity-selector-3JJFI4DT.js +7 -0
  24. package/dist/chunks/entity-selector-3JJFI4DT.js.map +7 -0
  25. package/dist/chunks/{fleet-feed-FK4ZMKIK.js → fleet-feed-5QGDLOV5.js} +27 -7
  26. package/dist/chunks/fleet-feed-5QGDLOV5.js.map +7 -0
  27. package/dist/chunks/table-6EVV7QZH.js +7 -0
  28. package/dist/chunks/table-6EVV7QZH.js.map +7 -0
  29. package/dist/connected-widget.d.ts +2 -0
  30. package/dist/dashboard-renderer.d.ts +1 -0
  31. package/dist/fleet-feed.d.ts +1 -0
  32. package/dist/index.d.ts +1 -0
  33. package/dist/index.js +478 -1142
  34. package/dist/index.js.map +4 -4
  35. package/dist/preload.d.ts +2 -0
  36. package/dist/widgets/alarm-count.d.ts +0 -46
  37. package/dist/widgets/alarm-lazy.d.ts +123 -0
  38. package/dist/widgets/alarm-table.d.ts +0 -76
  39. package/dist/widgets/alarm-widgets.d.ts +2 -0
  40. package/dist/widgets/command-button.d.ts +0 -38
  41. package/dist/widgets/control-lazy.d.ts +38 -0
  42. package/dist/widgets/control-widgets.d.ts +1 -0
  43. package/dist/widgets/entity-selector.d.ts +0 -15
  44. package/dist/widgets/gauge.d.ts +4 -0
  45. package/dist/widgets/lazy-chunk.d.ts +2 -1
  46. package/dist/widgets/selection-lazy.d.ts +16 -0
  47. package/dist/widgets/table-lazy.d.ts +39 -0
  48. package/dist/widgets/table.d.ts +0 -38
  49. package/dist/widgets/time-series-chart.d.ts +4 -0
  50. package/package.json +10 -7
  51. package/dist/chunks/aggregate-feed-6ZYKOQOB.js.map +0 -7
  52. package/dist/chunks/chunk-YPFB6DAL.js +0 -157
  53. package/dist/chunks/chunk-YPFB6DAL.js.map +0 -7
  54. package/dist/chunks/fleet-feed-FK4ZMKIK.js.map +0 -7
package/dist/index.js CHANGED
@@ -1,27 +1,44 @@
1
1
  import {
2
+ Table
3
+ } from "./chunks/chunk-USRYKW2J.js";
4
+ import {
5
+ alarmSubscription,
6
+ commandSubscription,
7
+ measurementSpan,
8
+ measurementWindow,
9
+ membersMode
10
+ } from "./chunks/chunk-2D7JNKFE.js";
11
+ import {
12
+ accessStrings
13
+ } from "./chunks/chunk-BRH66T5F.js";
14
+ import {
15
+ AlarmCount,
16
+ AlarmTable,
17
+ highestSeverity,
18
+ severityColor,
19
+ severityLabel,
20
+ severityRank
21
+ } from "./chunks/chunk-6OGI4UFJ.js";
22
+ import {
23
+ CommandButton,
2
24
  buildPayload,
3
25
  commandStatusColor,
4
26
  commandStatusLabel,
5
27
  defaultValues,
6
28
  isScalar,
7
29
  isTerminalStatus,
8
- parseBool,
9
30
  parseParameterSchema,
10
31
  validateParams
11
- } from "./chunks/chunk-YPFB6DAL.js";
32
+ } from "./chunks/chunk-XSLFHCNI.js";
33
+ import {
34
+ EntitySelector
35
+ } from "./chunks/chunk-FM7OI5TQ.js";
12
36
  import {
13
37
  readRange
14
38
  } from "./chunks/chunk-ZR74ORIT.js";
15
39
  import {
16
40
  LevelReadout
17
41
  } from "./chunks/chunk-XQQQNTBX.js";
18
- import {
19
- alarmSubscription,
20
- commandSubscription,
21
- measurementSpan,
22
- measurementWindow,
23
- membersMode
24
- } from "./chunks/chunk-2D7JNKFE.js";
25
42
 
26
43
  // src/dashboard-renderer.tsx
27
44
  import {
@@ -47,7 +64,7 @@ import {
47
64
  WidgetTimeRangeProvider,
48
65
  WidgetTokenStyles
49
66
  } from "@devicechain/widget-sdk";
50
- import { Fragment as Fragment5, useCallback as useCallback2, useEffect as useEffect5, useLayoutEffect, useMemo as useMemo6, useRef as useRef3, useState as useState8 } from "react";
67
+ import { Fragment, useCallback as useCallback2, useEffect as useEffect4, useLayoutEffect, useMemo as useMemo5, useRef as useRef2, useState as useState6 } from "react";
51
68
 
52
69
  // src/connected-widget.tsx
53
70
  import {
@@ -61,7 +78,8 @@ import {
61
78
  WidgetSelectProvider,
62
79
  useWidgetTimeRange as useWidgetTimeRange2
63
80
  } from "@devicechain/widget-sdk";
64
- import { useMemo as useMemo5 } from "react";
81
+ import { isForbiddenError } from "@devicechain/client";
82
+ import { useEffect as useEffect3, useMemo as useMemo4, useState as useState5 } from "react";
65
83
 
66
84
  // src/use-held.ts
67
85
  import { useState } from "react";
@@ -1095,7 +1113,7 @@ function lazyChunk(importer) {
1095
1113
  throw err;
1096
1114
  }
1097
1115
  ));
1098
- function component(name) {
1116
+ function component(name, alsoPreload) {
1099
1117
  function LazyChunkWidget(props) {
1100
1118
  const [mod, setMod] = useState2(loaded);
1101
1119
  const [error, setError] = useState2();
@@ -1108,13 +1126,14 @@ function lazyChunk(importer) {
1108
1126
  return /* @__PURE__ */ jsx(Component2, { ...props });
1109
1127
  }
1110
1128
  LazyChunkWidget.displayName = `Lazy(${name})`;
1129
+ LazyChunkWidget.preload = alsoPreload ? () => Promise.all([load(), alsoPreload()]).then(([m]) => m) : load;
1111
1130
  return LazyChunkWidget;
1112
1131
  }
1113
1132
  return { load, component };
1114
1133
  }
1115
1134
 
1116
1135
  // src/widgets/aggregate-lazy.tsx
1117
- var chunk = lazyChunk(() => import("./chunks/aggregate-widgets-WVXAW3UL.js"));
1136
+ var chunk = lazyChunk(() => import("./chunks/aggregate-widgets-HZQI5HTX.js"));
1118
1137
  var loadAggregateWidgets = chunk.load;
1119
1138
  var statCardWidget = defineWidget({
1120
1139
  descriptor: builtinWidgetDescriptors["stat-card"],
@@ -1133,784 +1152,85 @@ var fleetTableWidget = defineWidget({
1133
1152
  implementation: { kind: "trusted-react", component: chunk.component("FleetTable") }
1134
1153
  });
1135
1154
 
1136
- // src/widgets/alarm-count.tsx
1137
- import {
1138
- css as css2,
1139
- defineWidget as defineWidget2,
1140
- fitValueFont,
1141
- fitValueFontCss,
1142
- FIT_MIN_FONT_PX,
1143
- fontVar,
1144
- optString,
1145
- spaceVar,
1146
- useSeverityColors,
1147
- useStickyChars,
1148
- useWidgetScale,
1149
- WidgetFrame
1150
- } from "@devicechain/widget-sdk";
1151
-
1152
- // src/widgets/severity.ts
1153
- import { css } from "@devicechain/widget-sdk";
1154
- var LEVEL_OF = {
1155
- CRITICAL: "critical",
1156
- MAJOR: "major",
1157
- MINOR: "minor",
1158
- WARNING: "warning"
1159
- };
1160
- var SEVERITY_ORDER = {
1161
- CRITICAL: 0,
1162
- MAJOR: 1,
1163
- MINOR: 2,
1164
- WARNING: 3,
1165
- INDETERMINATE: 4
1166
- };
1167
- function severityColor(colors, severity) {
1168
- const level = LEVEL_OF[severity];
1169
- return level ? colors[level] : css("muted-foreground");
1170
- }
1171
- function severityRank(severity) {
1172
- return SEVERITY_ORDER[severity] ?? 99;
1173
- }
1174
- function severityLabel(severity) {
1175
- if (!severity) return "";
1176
- return severity.charAt(0).toUpperCase() + severity.slice(1).toLowerCase();
1177
- }
1178
- function highestSeverity(severities) {
1179
- let best;
1180
- for (const s of severities) {
1181
- if (best === void 0 || severityRank(s) < severityRank(best)) best = s;
1182
- }
1183
- return best;
1184
- }
1185
-
1186
- // src/widgets/alarm-count.tsx
1187
- import { jsx as jsx2, jsxs } from "react/jsx-runtime";
1188
- var ALARM_COUNT_CAPTION_ROOM_PX = 20;
1189
- function AlarmCountBody({ data }) {
1190
- const { size, scale } = useWidgetScale();
1191
- const severity = useSeverityColors();
1192
- const { total, alarms, loading } = data;
1193
- const worst = highestSeverity(alarms.map((a) => a.severity));
1194
- const alerting = total > 0 && worst != null;
1195
- const color = alerting ? severityColor(severity, worst) : css2("muted-foreground");
1196
- const display = loading && total === 0 ? "\u2014" : String(total);
1197
- const chars = useStickyChars(display.length);
1198
- const floor = Math.round(FIT_MIN_FONT_PX * scale);
1199
- const measured = size.width > 0 && size.height > 0;
1200
- const valueFont = measured ? fitValueFont(
1201
- { width: size.width, height: Math.max(1, size.height - ALARM_COUNT_CAPTION_ROOM_PX * scale) },
1202
- chars,
1203
- { floor }
1204
- ) : (
1205
- // First frame: the same curve in cq units, resolved by the browser against the frame's
1206
- // column (it does not take the caption's room off; the first measure does).
1207
- fitValueFontCss(chars, { floor })
1208
- );
1209
- const unit = total === 1 ? "alarm" : "alarms";
1210
- const ariaLabel = alerting ? `${total} ${unit}, worst severity ${severityLabel(worst)}` : `${total} ${unit}`;
1211
- return /* @__PURE__ */ jsxs(
1212
- "div",
1213
- {
1214
- style: {
1215
- display: "flex",
1216
- flexDirection: "column",
1217
- justifyContent: "safe center",
1218
- alignItems: "center",
1219
- height: "100%",
1220
- boxSizing: "border-box",
1221
- overflow: "hidden",
1222
- textAlign: "center"
1223
- },
1224
- children: [
1225
- /* @__PURE__ */ jsx2(
1226
- "div",
1227
- {
1228
- "aria-label": ariaLabel,
1229
- style: {
1230
- fontSize: valueFont,
1231
- fontWeight: 700,
1232
- lineHeight: 1,
1233
- whiteSpace: "nowrap",
1234
- fontVariantNumeric: "tabular-nums",
1235
- color
1236
- },
1237
- children: display
1238
- }
1239
- ),
1240
- /* @__PURE__ */ jsxs(
1241
- "div",
1242
- {
1243
- style: {
1244
- fontSize: fontVar("xs"),
1245
- color: css2("muted-foreground"),
1246
- marginTop: spaceVar(1),
1247
- textTransform: "uppercase",
1248
- letterSpacing: "0.05em"
1249
- },
1250
- children: [
1251
- /* @__PURE__ */ jsx2("span", { children: unit }),
1252
- alerting ? /* @__PURE__ */ jsx2("span", { children: ` \xB7 worst ${severityLabel(worst)}` }) : null
1253
- ]
1254
- }
1255
- )
1256
- ]
1257
- }
1258
- );
1259
- }
1260
- function AlarmCount({ widget, data }) {
1261
- return /* @__PURE__ */ jsx2(WidgetFrame, { title: optString(widget.options, "title"), children: /* @__PURE__ */ jsx2(AlarmCountBody, { data }) });
1262
- }
1263
- var alarmCountWidget = defineWidget2({
1264
- descriptor: builtinWidgetDescriptors["alarm-count"],
1265
- implementation: { kind: "trusted-react", component: AlarmCount }
1266
- });
1267
-
1268
- // src/widgets/alarm-table.tsx
1269
- import { Fragment, useState as useState3 } from "react";
1270
- import {
1271
- css as css3,
1272
- fontVar as fontVar2,
1273
- defineWidget as defineWidget3,
1274
- FlashValue,
1275
- formatDateTime,
1276
- optBoolean,
1277
- optNumber,
1278
- optString as optString2,
1279
- useElementSize,
1280
- useSeverityColors as useSeverityColors2,
1281
- useWidgetSelect,
1282
- useWidgetTimeZone,
1283
- WidgetFrame as WidgetFrame2
1284
- } from "@devicechain/widget-sdk";
1285
- import { Fragment as Fragment2, jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
1286
- var cell = { padding: "6px 10px", textAlign: "left", whiteSpace: "nowrap" };
1287
- var headCell = {
1288
- ...cell,
1289
- position: "sticky",
1290
- top: 0,
1291
- background: css3("card"),
1292
- fontSize: fontVar2("xs"),
1293
- fontWeight: 600,
1294
- textTransform: "uppercase",
1295
- letterSpacing: "0.04em",
1296
- color: css3("muted-foreground"),
1297
- borderBottom: `1px solid ${css3("border")}`
1298
- };
1299
- var ALARM_TABLE_NARROW_PX = 480;
1300
- var narrowCell = {
1301
- ...cell,
1302
- padding: "6px 6px",
1303
- whiteSpace: "normal",
1304
- overflowWrap: "break-word",
1305
- wordBreak: "normal"
1306
- };
1307
- function hyphenBreaks(text) {
1308
- const parts = text.split("-").map((p, i, all) => i < all.length - 1 ? `${p}-` : p);
1309
- return parts.map((part, i) => /* @__PURE__ */ jsxs2(Fragment, { children: [
1310
- i > 0 ? /* @__PURE__ */ jsx3("wbr", {}) : null,
1311
- part
1312
- ] }, i));
1313
- }
1314
- function statusLabel(alarm) {
1315
- if (alarm.state === "CLEARED") return "Cleared";
1316
- return alarm.acknowledged ? "Acknowledged" : "Active";
1317
- }
1318
- function AlarmTable({ widget, data, actions }) {
1319
- const { alarms, total, loading } = data;
1320
- const canAct = actions?.can("alarm:write") ?? false;
1321
- const [sizeRef, size] = useElementSize();
1322
- const severity = useSeverityColors2();
1323
- const narrow = size.width > 0 && size.width < ALARM_TABLE_NARROW_PX;
1324
- const columns = 5 + (narrow ? 0 : 2) + (canAct ? 1 : 0);
1325
- const text = narrow ? narrowCell : cell;
1326
- const precision = optNumber(widget.options, "precision");
1327
- const flash = optBoolean(widget.options, "flashOnChange");
1328
- const select = useWidgetSelect();
1329
- const timeZone = useWidgetTimeZone();
1330
- const selectionTarget = optString2(widget.options, "selectionTarget");
1331
- const drillTo = select && selectionTarget ? { select, slot: selectionTarget } : void 0;
1332
- return /* @__PURE__ */ jsx3(WidgetFrame2, { title: optString2(widget.options, "title"), flush: true, children: /* @__PURE__ */ jsxs2("div", { style: { display: "flex", flexDirection: "column", height: "100%" }, children: [
1333
- /* @__PURE__ */ jsx3("div", { ref: sizeRef, style: { flex: 1, minHeight: 0, overflow: "auto" }, children: /* @__PURE__ */ jsxs2(
1334
- "table",
1335
- {
1336
- style: {
1337
- width: "100%",
1338
- borderCollapse: "collapse",
1339
- fontSize: fontVar2("md"),
1340
- color: css3("foreground"),
1341
- fontVariantNumeric: "tabular-nums"
1342
- },
1343
- children: [
1344
- /* @__PURE__ */ jsx3("thead", { children: /* @__PURE__ */ jsxs2("tr", { children: [
1345
- /* @__PURE__ */ jsx3("th", { style: { ...headCell, width: 4, padding: 0 }, "aria-hidden": "true" }),
1346
- /* @__PURE__ */ jsx3("th", { scope: "col", style: headCell, children: "Severity" }),
1347
- narrow ? null : /* @__PURE__ */ jsx3("th", { scope: "col", style: headCell, children: "Status" }),
1348
- /* @__PURE__ */ jsx3("th", { scope: "col", style: headCell, children: "Originator" }),
1349
- /* @__PURE__ */ jsx3("th", { scope: "col", style: headCell, children: "Alarm" }),
1350
- /* @__PURE__ */ jsx3("th", { scope: "col", style: { ...headCell, textAlign: "right" }, children: "Value" }),
1351
- narrow ? null : /* @__PURE__ */ jsx3("th", { scope: "col", style: headCell, children: "Raised" }),
1352
- canAct ? /* @__PURE__ */ jsx3("th", { scope: "col", style: { ...headCell, textAlign: "right" }, children: "Actions" }) : null
1353
- ] }) }),
1354
- /* @__PURE__ */ jsx3("tbody", { children: alarms.length === 0 ? /* @__PURE__ */ jsx3("tr", { children: /* @__PURE__ */ jsx3("td", { colSpan: columns, style: { ...cell, textAlign: "center", color: css3("muted-foreground") }, children: loading ? "Loading\u2026" : "No alarms" }) }) : alarms.map((alarm) => {
1355
- const color = severityColor(severity, alarm.severity);
1356
- return /* @__PURE__ */ jsxs2("tr", { style: { borderBottom: `1px solid ${css3("border")}` }, children: [
1357
- /* @__PURE__ */ jsx3("td", { "aria-hidden": "true", style: { padding: 0, width: 4, background: color } }),
1358
- /* @__PURE__ */ jsx3("td", { style: cell, children: /* @__PURE__ */ jsxs2("span", { style: { display: "inline-flex", alignItems: "center", gap: 6 }, children: [
1359
- /* @__PURE__ */ jsx3(
1360
- "span",
1361
- {
1362
- "aria-hidden": "true",
1363
- style: { width: 8, height: 8, borderRadius: "50%", background: color, flexShrink: 0 }
1364
- }
1365
- ),
1366
- severityLabel(alarm.severity)
1367
- ] }) }),
1368
- narrow ? null : /* @__PURE__ */ jsx3("td", { style: { ...cell, color: css3("muted-foreground") }, children: statusLabel(alarm) }),
1369
- /* @__PURE__ */ jsx3("td", { style: text, children: /* @__PURE__ */ jsx3(OriginatorCell, { alarm, drillTo }) }),
1370
- /* @__PURE__ */ jsx3("td", { style: text, children: hyphenBreaks(alarm.alarmKey) }),
1371
- /* @__PURE__ */ jsx3("td", { style: { ...cell, textAlign: "right" }, children: /* @__PURE__ */ jsx3(
1372
- FlashValue,
1373
- {
1374
- value: alarm.lastValue,
1375
- precision,
1376
- enabled: flash,
1377
- identity: alarm.token
1378
- }
1379
- ) }),
1380
- narrow ? null : /* @__PURE__ */ jsx3("td", { style: { ...cell, color: css3("muted-foreground") }, children: formatDateTime(alarm.raisedTime, timeZone) }),
1381
- canAct ? /* @__PURE__ */ jsx3("td", { style: { ...cell, textAlign: "right" }, children: /* @__PURE__ */ jsx3(AlarmRowActions, { alarm, actions }) }) : null
1382
- ] }, alarm.token);
1383
- }) })
1384
- ]
1385
- }
1386
- ) }),
1387
- total > alarms.length ? /* @__PURE__ */ jsxs2(
1388
- "div",
1389
- {
1390
- style: {
1391
- padding: "4px 10px",
1392
- fontSize: fontVar2("xs"),
1393
- color: css3("muted-foreground"),
1394
- borderTop: `1px solid ${css3("border")}`
1395
- },
1396
- children: [
1397
- "Showing ",
1398
- alarms.length,
1399
- " of ",
1400
- total
1401
- ]
1402
- }
1403
- ) : null
1404
- ] }) });
1405
- }
1406
- function OriginatorCell({
1407
- alarm,
1408
- drillTo
1409
- }) {
1410
- if (drillTo && alarm.originatorType === "device" && alarm.originatorToken) {
1411
- const token = alarm.originatorToken;
1412
- return /* @__PURE__ */ jsx3(
1413
- "button",
1414
- {
1415
- type: "button",
1416
- onClick: () => drillTo.select({ slot: drillTo.slot, binding: { kind: "device", deviceToken: token } }),
1417
- title: `Show ${token} in the linked widgets`,
1418
- style: {
1419
- padding: 0,
1420
- border: "none",
1421
- background: "none",
1422
- font: "inherit",
1423
- color: css3("primary"),
1424
- cursor: "pointer",
1425
- textDecoration: "underline",
1426
- textUnderlineOffset: 2
1427
- },
1428
- children: hyphenBreaks(token)
1429
- }
1430
- );
1431
- }
1432
- return /* @__PURE__ */ jsx3(Fragment2, { children: hyphenBreaks(alarm.originatorToken ?? alarm.originatorType) });
1433
- }
1434
- var actionButton = {
1435
- padding: "2px 8px",
1436
- fontSize: fontVar2("sm"),
1437
- lineHeight: 1.4,
1438
- borderRadius: 4,
1439
- border: `1px solid ${css3("border")}`,
1440
- background: css3("card"),
1441
- color: css3("foreground"),
1442
- cursor: "pointer"
1443
- };
1444
- function AlarmRowActions({ alarm, actions }) {
1445
- const severity = useSeverityColors2();
1446
- const [pending, setPending] = useState3(null);
1447
- const [failed, setFailed] = useState3(false);
1448
- if (alarm.state !== "ACTIVE") {
1449
- return /* @__PURE__ */ jsx3("span", { style: { color: css3("muted-foreground") }, children: "\u2014" });
1450
- }
1451
- const run = (kind, op) => {
1452
- setPending(kind);
1453
- setFailed(false);
1454
- let promise;
1455
- try {
1456
- promise = op();
1457
- } catch {
1458
- setFailed(true);
1459
- setPending(null);
1460
- return;
1461
- }
1462
- promise.catch(() => setFailed(true)).finally(() => setPending(null));
1463
- };
1464
- return /* @__PURE__ */ jsxs2("span", { style: { display: "inline-flex", gap: 6, justifyContent: "flex-end", alignItems: "center" }, children: [
1465
- failed ? /* @__PURE__ */ jsx3(
1466
- "span",
1467
- {
1468
- role: "img",
1469
- "aria-label": "Action failed \u2014 retry",
1470
- title: "Action failed \u2014 retry",
1471
- style: { color: severityColor(severity, "CRITICAL"), fontSize: fontVar2("sm") },
1472
- children: "\u26A0"
1473
- }
1474
- ) : null,
1475
- !alarm.acknowledged ? /* @__PURE__ */ jsx3(
1476
- "button",
1477
- {
1478
- type: "button",
1479
- style: { ...actionButton, opacity: pending ? 0.6 : 1 },
1480
- disabled: pending !== null,
1481
- "aria-busy": pending === "ack",
1482
- "aria-label": `Acknowledge alarm ${alarm.alarmKey}`,
1483
- onClick: () => run("ack", () => actions.acknowledgeAlarm(alarm.token)),
1484
- children: pending === "ack" ? "\u2026" : "Ack"
1485
- }
1486
- ) : null,
1487
- /* @__PURE__ */ jsx3(
1488
- "button",
1489
- {
1490
- type: "button",
1491
- style: { ...actionButton, opacity: pending ? 0.6 : 1 },
1492
- disabled: pending !== null,
1493
- "aria-busy": pending === "clear",
1494
- "aria-label": `Clear alarm ${alarm.alarmKey}`,
1495
- onClick: () => run("clear", () => actions.clearAlarm(alarm.token)),
1496
- children: pending === "clear" ? "\u2026" : "Clear"
1497
- }
1498
- )
1499
- ] });
1500
- }
1501
- var alarmTableWidget = defineWidget3({
1155
+ // src/widgets/alarm-lazy.tsx
1156
+ import { defineWidget as defineWidget2 } from "@devicechain/widget-sdk";
1157
+ var chunk2 = lazyChunk(() => import("./chunks/alarm-widgets-7UY6MIYZ.js"));
1158
+ var loadAlarmWidgets = chunk2.load;
1159
+ var alarmTableWidget = defineWidget2({
1502
1160
  descriptor: builtinWidgetDescriptors["alarm-table"],
1503
- implementation: { kind: "trusted-react", component: AlarmTable }
1161
+ implementation: { kind: "trusted-react", component: chunk2.component("AlarmTable") }
1504
1162
  });
1505
-
1506
- // src/widgets/command-button.tsx
1507
- import { useEffect as useEffect2, useMemo, useRef, useState as useState4 } from "react";
1508
- import {
1509
- css as css4,
1510
- fontVar as fontVar3,
1511
- defineWidget as defineWidget4,
1512
- formatDateTime as formatDateTime2,
1513
- optString as optString3,
1514
- useWidgetTimeZone as useWidgetTimeZone2,
1515
- WidgetFrame as WidgetFrame3
1516
- } from "@devicechain/widget-sdk";
1517
- import { Fragment as Fragment3, jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
1518
- function CommandButton({ widget, data, actions }) {
1519
- const commandName = optString3(widget.options, "commandName");
1520
- const commandLabel = optString3(widget.options, "commandLabel") ?? commandName;
1521
- const parameterSchema = optString3(widget.options, "parameterSchema") ?? null;
1522
- const params = useMemo(() => parseParameterSchema(parameterSchema), [parameterSchema]);
1523
- const schemaKey = `${commandName ?? ""}::${parameterSchema ?? ""}`;
1524
- const [values, setValues] = useState4(() => defaultValues(params));
1525
- const [errors, setErrors] = useState4({});
1526
- const [pending, setPending] = useState4(false);
1527
- const [sendError, setSendError] = useState4(null);
1528
- const [sentToken, setSentToken] = useState4(null);
1529
- const sendGen = useRef(0);
1530
- useEffect2(() => {
1531
- sendGen.current += 1;
1532
- setValues(defaultValues(params));
1533
- setErrors({});
1534
- setSendError(null);
1535
- setSentToken(null);
1536
- }, [schemaKey]);
1537
- const canWrite = actions?.can("command:write") ?? false;
1538
- const hasSeam = typeof actions?.sendCommand === "function";
1539
- const deviceToken = data.deviceToken;
1540
- const formDisabled = !canWrite || !hasSeam || pending;
1541
- const canSend = !formDisabled && !!deviceToken && !!commandName;
1542
- const setField = (name, value) => {
1543
- setValues((prev) => ({ ...prev, [name]: value }));
1544
- setErrors((prev) => prev[name] ? { ...prev, [name]: "" } : prev);
1545
- setSendError(null);
1546
- };
1547
- const send = () => {
1548
- if (!deviceToken || !commandName || !actions?.sendCommand) return;
1549
- const found = validateParams(params, values);
1550
- const active = Object.fromEntries(Object.entries(found).filter(([, v]) => v));
1551
- if (Object.keys(active).length > 0) {
1552
- setErrors(active);
1553
- return;
1554
- }
1555
- const payload = buildPayload(params, values);
1556
- const gen = sendGen.current;
1557
- setPending(true);
1558
- setSendError(null);
1559
- let promise;
1560
- try {
1561
- promise = actions.sendCommand(deviceToken, commandName, payload);
1562
- } catch {
1563
- setSendError(SEND_FAILED);
1564
- setPending(false);
1565
- return;
1566
- }
1567
- promise.then((dispatch) => {
1568
- if (gen !== sendGen.current) return;
1569
- if (dispatch.status === "rejected") {
1570
- setSendError(dispatch.reason);
1571
- return;
1572
- }
1573
- setSentToken(dispatch.token);
1574
- }).catch(() => {
1575
- if (gen === sendGen.current) setSendError(SEND_FAILED);
1576
- }).finally(() => {
1577
- if (gen === sendGen.current) setPending(false);
1578
- });
1579
- };
1580
- return /* @__PURE__ */ jsx4(WidgetFrame3, { title: optString3(widget.options, "title"), children: /* @__PURE__ */ jsx4("div", { style: { display: "flex", flexDirection: "column", height: "100%", gap: 10, overflowY: "auto" }, children: !commandName ? /* @__PURE__ */ jsx4("div", { style: { ...hint, margin: "auto" }, children: "No command configured." }) : /* @__PURE__ */ jsxs3(Fragment3, { children: [
1581
- /* @__PURE__ */ jsxs3("div", { style: { display: "flex", flexDirection: "column", gap: 8, flexShrink: 0 }, children: [
1582
- params.map(
1583
- (param) => isScalar(param) ? /* @__PURE__ */ jsx4(
1584
- ParamField,
1585
- {
1586
- widgetId: widget.id,
1587
- param,
1588
- value: values[param.name] ?? "",
1589
- error: errors[param.name],
1590
- disabled: formDisabled,
1591
- onChange: (v) => setField(param.name, v)
1592
- },
1593
- param.name
1594
- ) : (
1595
- // A structured (OBJECT) parameter isn't form-editable. A REQUIRED one
1596
- // blocks sending (validateParams flags it); flag that in the note.
1597
- /* @__PURE__ */ jsxs3("div", { style: { ...hint, color: param.required ? commandStatusColor("FAILED") : css4("muted-foreground") }, children: [
1598
- param.name,
1599
- ": ",
1600
- param.required ? "required " : "",
1601
- "structured parameter \u2014 not supported here."
1602
- ] }, param.name)
1603
- )
1604
- ),
1605
- /* @__PURE__ */ jsx4(
1606
- "button",
1607
- {
1608
- type: "button",
1609
- style: { ...sendButton, opacity: canSend ? 1 : 0.55, cursor: canSend ? "pointer" : "not-allowed" },
1610
- disabled: !canSend,
1611
- "aria-busy": pending,
1612
- onClick: send,
1613
- children: pending ? "Sending\u2026" : `Send ${commandLabel}`
1614
- }
1615
- ),
1616
- !canWrite ? /* @__PURE__ */ jsx4("div", { style: hint, children: "You don\u2019t have permission to issue commands." }) : !hasSeam ? /* @__PURE__ */ jsx4("div", { style: hint, children: "Commands aren\u2019t available in this view." }) : !deviceToken ? /* @__PURE__ */ jsx4("div", { style: hint, children: "No device is selected for this command." }) : null,
1617
- sendError ? /* @__PURE__ */ jsx4("div", { role: "alert", style: { ...hint, color: commandStatusColor("FAILED") }, children: sendError }) : null
1618
- ] }),
1619
- /* @__PURE__ */ jsx4(CommandHistory, { commands: data.commands, sentToken, loading: data.loading, error: data.error })
1620
- ] }) }) });
1621
- }
1622
- function ParamField({
1623
- widgetId,
1624
- param,
1625
- value,
1626
- error,
1627
- disabled,
1628
- onChange
1629
- }) {
1630
- const labelId = `cmd-${widgetId}-${param.name}`;
1631
- const unit = param.unit ? ` (${param.unit})` : "";
1632
- return /* @__PURE__ */ jsxs3("label", { htmlFor: labelId, style: { display: "flex", flexDirection: "column", gap: 3 }, children: [
1633
- /* @__PURE__ */ jsxs3("span", { style: { fontSize: fontVar3("sm"), color: css4("muted-foreground") }, children: [
1634
- param.name,
1635
- unit,
1636
- param.required ? /* @__PURE__ */ jsx4("span", { style: { color: commandStatusColor("FAILED") }, children: " *" }) : null
1637
- ] }),
1638
- /* @__PURE__ */ jsx4(ParamInput, { id: labelId, param, value, disabled, onChange }),
1639
- error ? /* @__PURE__ */ jsx4("span", { style: { fontSize: fontVar3("xs"), color: commandStatusColor("FAILED") }, children: error }) : null
1640
- ] });
1641
- }
1642
- function ParamInput({
1643
- id,
1644
- param,
1645
- value,
1646
- disabled,
1647
- onChange
1648
- }) {
1649
- if (param.enum && param.enum.length > 0) {
1650
- return /* @__PURE__ */ jsxs3("select", { id, style: inputStyle, value, disabled, onChange: (e) => onChange(e.target.value), children: [
1651
- !param.required ? /* @__PURE__ */ jsx4("option", { value: "", children: "\u2014" }) : null,
1652
- param.enum.map((opt) => /* @__PURE__ */ jsx4("option", { value: opt, children: opt }, opt))
1653
- ] });
1654
- }
1655
- if (param.dataType === "BOOLEAN") {
1656
- return /* @__PURE__ */ jsx4(
1657
- "input",
1658
- {
1659
- id,
1660
- type: "checkbox",
1661
- style: { width: 16, height: 16 },
1662
- checked: parseBool(value),
1663
- disabled,
1664
- onChange: (e) => onChange(e.target.checked ? "true" : "false")
1665
- }
1666
- );
1667
- }
1668
- const numeric = param.dataType === "INT" || param.dataType === "DOUBLE";
1669
- return /* @__PURE__ */ jsx4(
1670
- "input",
1671
- {
1672
- id,
1673
- type: numeric ? "number" : "text",
1674
- style: inputStyle,
1675
- value,
1676
- disabled,
1677
- min: param.minValue ?? void 0,
1678
- max: param.maxValue ?? void 0,
1679
- step: param.dataType === "INT" ? 1 : "any",
1680
- placeholder: param.default ?? void 0,
1681
- onChange: (e) => onChange(e.target.value)
1682
- }
1683
- );
1684
- }
1685
- function CommandHistory({
1686
- commands,
1687
- sentToken,
1688
- loading,
1689
- error
1690
- }) {
1691
- const empty = commands.length === 0;
1692
- const timeZone = useWidgetTimeZone2();
1693
- return /* @__PURE__ */ jsx4(
1694
- "div",
1695
- {
1696
- style: {
1697
- flex: 1,
1698
- minHeight: 0,
1699
- overflow: "auto",
1700
- borderTop: `1px solid ${css4("border")}`,
1701
- paddingTop: 6
1702
- },
1703
- children: empty ? /* @__PURE__ */ jsx4("div", { style: { ...hint, textAlign: "center", color: error ? commandStatusColor("FAILED") : css4("muted-foreground") }, children: error ? "Couldn\u2019t load command history." : loading ? "Loading\u2026" : "No commands issued yet." }) : /* @__PURE__ */ jsx4("ul", { style: { listStyle: "none", margin: 0, padding: 0, display: "flex", flexDirection: "column", gap: 4 }, children: commands.map((command) => /* @__PURE__ */ jsxs3(
1704
- "li",
1705
- {
1706
- style: {
1707
- display: "flex",
1708
- alignItems: "center",
1709
- gap: 8,
1710
- fontSize: fontVar3("sm"),
1711
- // Highlight the command just issued from this widget.
1712
- fontWeight: command.token === sentToken ? 600 : 400
1713
- },
1714
- children: [
1715
- /* @__PURE__ */ jsx4(StatusBadge, { status: command.status }),
1716
- /* @__PURE__ */ jsx4("span", { style: { color: css4("foreground"), whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis" }, children: command.name }),
1717
- /* @__PURE__ */ jsx4("span", { style: { marginLeft: "auto", color: css4("muted-foreground"), whiteSpace: "nowrap" }, children: formatDateTime2(command.queuedTime, timeZone) })
1718
- ]
1719
- },
1720
- command.token
1721
- )) })
1722
- }
1723
- );
1724
- }
1725
- function StatusBadge({ status }) {
1726
- const color = commandStatusColor(status);
1727
- return /* @__PURE__ */ jsxs3(
1728
- "span",
1729
- {
1730
- style: {
1731
- display: "inline-flex",
1732
- alignItems: "center",
1733
- gap: 4,
1734
- flexShrink: 0,
1735
- fontSize: fontVar3("xs"),
1736
- fontWeight: 600,
1737
- color
1738
- },
1739
- children: [
1740
- /* @__PURE__ */ jsx4("span", { "aria-hidden": "true", style: { width: 7, height: 7, borderRadius: "50%", background: color } }),
1741
- commandStatusLabel(status)
1742
- ]
1743
- }
1744
- );
1745
- }
1746
- var hint = { fontSize: fontVar3("xs"), color: css4("muted-foreground") };
1747
- var SEND_FAILED = "Couldn\u2019t issue the command. Try again.";
1748
- var inputStyle = {
1749
- width: "100%",
1750
- boxSizing: "border-box",
1751
- padding: "4px 8px",
1752
- fontSize: fontVar3("md"),
1753
- borderRadius: 4,
1754
- border: `1px solid ${css4("border")}`,
1755
- background: css4("background"),
1756
- color: css4("foreground")
1757
- };
1758
- var sendButton = {
1759
- padding: "6px 12px",
1760
- fontSize: fontVar3("md"),
1761
- fontWeight: 600,
1762
- borderRadius: 4,
1763
- border: "none",
1764
- background: css4("primary"),
1765
- color: css4("background"),
1766
- marginTop: 2
1767
- };
1768
- var commandButtonWidget = defineWidget4({
1769
- descriptor: builtinWidgetDescriptors["command-button"],
1770
- implementation: { kind: "trusted-react", component: CommandButton }
1163
+ var alarmCountWidget = defineWidget2({
1164
+ descriptor: builtinWidgetDescriptors["alarm-count"],
1165
+ implementation: { kind: "trusted-react", component: chunk2.component("AlarmCount") }
1771
1166
  });
1772
1167
 
1773
1168
  // src/widgets/control-lazy.tsx
1774
- import { defineWidget as defineWidget5 } from "@devicechain/widget-sdk";
1775
- var chunk2 = lazyChunk(() => import("./chunks/control-widgets-UDS4ET3T.js"));
1776
- var loadControlWidgets = chunk2.load;
1777
- var commandSliderWidget = defineWidget5({
1169
+ import { defineWidget as defineWidget3 } from "@devicechain/widget-sdk";
1170
+ var chunk3 = lazyChunk(() => import("./chunks/control-widgets-3V2LSSRF.js"));
1171
+ var loadControlWidgets = chunk3.load;
1172
+ var commandSliderWidget = defineWidget3({
1778
1173
  descriptor: builtinWidgetDescriptors["command-slider"],
1779
- implementation: { kind: "trusted-react", component: chunk2.component("CommandSlider") }
1174
+ implementation: { kind: "trusted-react", component: chunk3.component("CommandSlider") }
1780
1175
  });
1781
- var commandToggleWidget = defineWidget5({
1176
+ var commandToggleWidget = defineWidget3({
1782
1177
  descriptor: builtinWidgetDescriptors["command-toggle"],
1783
- implementation: { kind: "trusted-react", component: chunk2.component("CommandToggle") }
1178
+ implementation: { kind: "trusted-react", component: chunk3.component("CommandToggle") }
1179
+ });
1180
+ var commandButtonWidget = defineWidget3({
1181
+ descriptor: builtinWidgetDescriptors["command-button"],
1182
+ implementation: { kind: "trusted-react", component: chunk3.component("CommandButton") }
1784
1183
  });
1785
1184
 
1786
- // src/widgets/entity-selector.tsx
1787
- import { useEffect as useEffect3, useState as useState5 } from "react";
1788
- import {
1789
- css as css5,
1790
- fontVar as fontVar4,
1791
- defineWidget as defineWidget6,
1792
- optString as optString4,
1793
- useCandidates,
1794
- useWidgetSelect as useWidgetSelect2,
1795
- WidgetFrame as WidgetFrame4
1796
- } from "@devicechain/widget-sdk";
1797
- import { Fragment as Fragment4, jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
1798
- function tokenOf(b) {
1799
- return b.kind === "device" ? b.deviceToken : b.anchor.targetToken;
1800
- }
1801
- var control = {
1802
- width: "100%",
1803
- fontSize: fontVar4("md"),
1804
- padding: "8px 10px",
1805
- borderRadius: 6,
1806
- border: `1px solid ${css5("border")}`,
1807
- background: css5("background"),
1808
- color: css5("foreground")
1809
- };
1810
- var hint2 = {
1811
- fontSize: fontVar4("sm"),
1812
- color: css5("muted-foreground")
1813
- };
1814
- function EntitySelector({ widget }) {
1815
- const select = useWidgetSelect2();
1816
- const target = optString4(widget.options, "selectionTarget");
1817
- const { candidates, loading, error, wired } = useCandidates(target);
1818
- const title = optString4(widget.options, "title");
1819
- const [pending, setPending] = useState5(null);
1820
- const selected = candidates.find((c) => c.selected);
1821
- const selectedToken = selected ? tokenOf(selected.binding) : "";
1822
- useEffect3(() => {
1823
- if (pending !== null && (selectedToken === pending || !candidates.some((c) => tokenOf(c.binding) === pending))) {
1824
- setPending(null);
1825
- }
1826
- }, [candidates, selectedToken, pending]);
1827
- const inert = !select || !target || !wired;
1828
- const value = pending ?? selectedToken;
1829
- const onChange = (e) => {
1830
- const token = e.target.value;
1831
- if (!token) return;
1832
- const candidate = candidates.find((c) => tokenOf(c.binding) === token);
1833
- if (select && target && candidate) {
1834
- setPending(token);
1835
- select({ slot: target, binding: candidate.binding });
1836
- }
1837
- };
1838
- return /* @__PURE__ */ jsx5(WidgetFrame4, { title, children: /* @__PURE__ */ jsx5(
1839
- "div",
1840
- {
1841
- style: {
1842
- display: "flex",
1843
- flexDirection: "column",
1844
- gap: 8,
1845
- height: "100%",
1846
- boxSizing: "border-box",
1847
- overflow: "auto"
1848
- },
1849
- children: inert ? /* @__PURE__ */ jsx5("span", { style: hint2, children: select && target ? "Selection isn\u2019t available here." : select ? "No target slot configured." : "Selection is available on the live dashboard." }) : /* @__PURE__ */ jsxs4(Fragment4, { children: [
1850
- /* @__PURE__ */ jsxs4(
1851
- "select",
1852
- {
1853
- style: { ...control, opacity: loading ? 0.6 : 1 },
1854
- value,
1855
- disabled: candidates.length === 0,
1856
- onChange,
1857
- "aria-label": title || `Select ${target}`,
1858
- children: [
1859
- /* @__PURE__ */ jsx5("option", { value: "", disabled: true, children: loading ? "Loading\u2026" : candidates.length === 0 ? "No options" : "Select\u2026" }),
1860
- candidates.map((c) => /* @__PURE__ */ jsx5("option", { value: tokenOf(c.binding), children: c.label }, tokenOf(c.binding)))
1861
- ]
1862
- }
1863
- ),
1864
- error ? /* @__PURE__ */ jsx5("span", { style: hint2, children: "Couldn\u2019t load options." }) : null
1865
- ] })
1866
- }
1867
- ) });
1868
- }
1869
- var entitySelectorWidget = defineWidget6({
1185
+ // src/widgets/selection-lazy.tsx
1186
+ import { defineWidget as defineWidget4 } from "@devicechain/widget-sdk";
1187
+ var chunk4 = lazyChunk(() => import("./chunks/entity-selector-3JJFI4DT.js"));
1188
+ var loadSelectionWidgets = chunk4.load;
1189
+ var entitySelectorWidget = defineWidget4({
1870
1190
  descriptor: builtinWidgetDescriptors["entity-selector"],
1871
- implementation: { kind: "trusted-react", component: EntitySelector }
1191
+ implementation: { kind: "trusted-react", component: chunk4.component("EntitySelector") }
1872
1192
  });
1873
1193
 
1874
1194
  // src/widgets/gauge.tsx
1875
- import { useMemo as useMemo2 } from "react";
1195
+ import { useMemo } from "react";
1876
1196
  import {
1877
- defineWidget as defineWidget7,
1197
+ defineWidget as defineWidget5,
1878
1198
  flashBackgroundStyle,
1879
1199
  formatValue,
1880
- optBoolean as optBoolean2,
1881
- optNumber as optNumber2,
1882
- optString as optString5,
1200
+ optBoolean,
1201
+ optNumber,
1202
+ optString,
1883
1203
  optThresholds,
1884
1204
  pickSample,
1885
1205
  primaryMeasurementName,
1886
1206
  useFlashOnChange,
1887
- useWidgetScale as useWidgetScale2,
1888
- WidgetFrame as WidgetFrame5
1207
+ useWidgetScale,
1208
+ WidgetFrame
1889
1209
  } from "@devicechain/widget-sdk";
1890
- import { buildGaugeOption, EChart, gaugeReadoutBox, useChartTheme } from "@devicechain/widget-sdk/echarts";
1891
- import { jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
1210
+ import { buildGaugeOption, EChart, gaugeReadoutBox, loadChartEngine, useChartTheme } from "@devicechain/widget-sdk/echarts";
1211
+ import { jsx as jsx2, jsxs } from "react/jsx-runtime";
1892
1212
  function Gauge({ widget, data }) {
1893
1213
  const name = primaryMeasurementName(widget);
1894
1214
  const sample = pickSample(data.latest, name);
1895
- return /* @__PURE__ */ jsx6(WidgetFrame5, { title: optString5(widget.options, "title") ?? name, sampleTime: sample?.occurredTime ?? null, flush: true, children: /* @__PURE__ */ jsx6(GaugeBody, { widget, data }) });
1215
+ return /* @__PURE__ */ jsx2(WidgetFrame, { title: optString(widget.options, "title") ?? name, sampleTime: sample?.occurredTime ?? null, flush: true, children: /* @__PURE__ */ jsx2(GaugeBody, { widget, data }) });
1896
1216
  }
1897
1217
  function GaugeBody({ widget, data }) {
1898
1218
  const theme = useChartTheme();
1899
- const { size, scale } = useWidgetScale2();
1219
+ const { size, scale } = useWidgetScale();
1900
1220
  const name = primaryMeasurementName(widget);
1901
1221
  const sample = pickSample(data.latest, name);
1902
- const min = optNumber2(widget.options, "min");
1903
- const max = optNumber2(widget.options, "max");
1904
- const unit = optString5(widget.options, "unit");
1905
- const precision = optNumber2(widget.options, "precision");
1906
- const thresholds = useMemo2(() => optThresholds(widget.options, "thresholds"), [widget.options]);
1907
- const option = useMemo2(
1222
+ const min = optNumber(widget.options, "min");
1223
+ const max = optNumber(widget.options, "max");
1224
+ const unit = optString(widget.options, "unit");
1225
+ const precision = optNumber(widget.options, "precision");
1226
+ const thresholds = useMemo(() => optThresholds(widget.options, "thresholds"), [widget.options]);
1227
+ const option = useMemo(
1908
1228
  () => buildGaugeOption(sample?.value ?? null, theme, { min, max, thresholds, scale, readout: "none", emptyNeedle: "none" }, size),
1909
1229
  [sample?.value, theme, min, max, thresholds, scale, size]
1910
1230
  );
1911
1231
  const flashDirection = useFlashOnChange(
1912
1232
  sample?.value,
1913
- optBoolean2(widget.options, "flashOnChange"),
1233
+ optBoolean(widget.options, "flashOnChange"),
1914
1234
  sample && `${sample.deviceToken}:${sample.name}`
1915
1235
  );
1916
1236
  const box = gaugeReadoutBox(size);
@@ -1923,9 +1243,9 @@ function GaugeBody({ widget, data }) {
1923
1243
  "aria-valuenow": Math.min(range.range.max, Math.max(range.range.min, value)),
1924
1244
  "aria-valuetext": `${formatValue(value, precision)}${unit ? ` ${unit}` : ""}`
1925
1245
  } : {};
1926
- return /* @__PURE__ */ jsxs5("div", { style: { position: "relative", width: "100%", height: "100%", ...flashBackgroundStyle(flashDirection) }, ...meter, children: [
1927
- /* @__PURE__ */ jsx6(EChart, { option }),
1928
- /* @__PURE__ */ jsx6(
1246
+ return /* @__PURE__ */ jsxs("div", { style: { position: "relative", width: "100%", height: "100%", ...flashBackgroundStyle(flashDirection) }, ...meter, children: [
1247
+ /* @__PURE__ */ jsx2(EChart, { option }),
1248
+ /* @__PURE__ */ jsx2(
1929
1249
  "div",
1930
1250
  {
1931
1251
  style: {
@@ -1939,7 +1259,7 @@ function GaugeBody({ widget, data }) {
1939
1259
  justifyContent: "center",
1940
1260
  pointerEvents: "none"
1941
1261
  },
1942
- children: /* @__PURE__ */ jsx6(
1262
+ children: /* @__PURE__ */ jsx2(
1943
1263
  LevelReadout,
1944
1264
  {
1945
1265
  text: formatValue(value, precision),
@@ -1952,27 +1272,28 @@ function GaugeBody({ widget, data }) {
1952
1272
  )
1953
1273
  ] });
1954
1274
  }
1955
- var gaugeWidget = defineWidget7({
1275
+ Gauge.preload = loadChartEngine;
1276
+ var gaugeWidget = defineWidget5({
1956
1277
  descriptor: builtinWidgetDescriptors["gauge"],
1957
1278
  implementation: { kind: "trusted-react", component: Gauge }
1958
1279
  });
1959
1280
 
1960
1281
  // src/widgets/image.tsx
1961
1282
  import {
1962
- css as css6,
1963
- defineWidget as defineWidget8,
1964
- fontVar as fontVar5,
1965
- optString as optString6,
1966
- WidgetFrame as WidgetFrame6
1283
+ css,
1284
+ defineWidget as defineWidget6,
1285
+ fontVar,
1286
+ optString as optString2,
1287
+ WidgetFrame as WidgetFrame2
1967
1288
  } from "@devicechain/widget-sdk";
1968
- import { jsx as jsx7 } from "react/jsx-runtime";
1289
+ import { jsx as jsx3 } from "react/jsx-runtime";
1969
1290
  var FITS = /* @__PURE__ */ new Set(["contain", "cover", "fill"]);
1970
1291
  function Image({ widget }) {
1971
- const url = optString6(widget.options, "url");
1972
- const alt = optString6(widget.options, "alt") ?? "";
1973
- const fitOption = optString6(widget.options, "fit");
1292
+ const url = optString2(widget.options, "url");
1293
+ const alt = optString2(widget.options, "alt") ?? "";
1294
+ const fitOption = optString2(widget.options, "fit");
1974
1295
  const objectFit = fitOption && FITS.has(fitOption) ? fitOption : "contain";
1975
- return /* @__PURE__ */ jsx7(WidgetFrame6, { title: optString6(widget.options, "title"), flush: true, children: url ? /* @__PURE__ */ jsx7("img", { src: url, alt, style: { width: "100%", height: "100%", objectFit, display: "block" } }) : /* @__PURE__ */ jsx7(
1296
+ return /* @__PURE__ */ jsx3(WidgetFrame2, { title: optString2(widget.options, "title"), flush: true, children: url ? /* @__PURE__ */ jsx3("img", { src: url, alt, style: { width: "100%", height: "100%", objectFit, display: "block" } }) : /* @__PURE__ */ jsx3(
1976
1297
  "div",
1977
1298
  {
1978
1299
  style: {
@@ -1980,40 +1301,40 @@ function Image({ widget }) {
1980
1301
  alignItems: "center",
1981
1302
  justifyContent: "center",
1982
1303
  height: "100%",
1983
- color: css6("muted-foreground"),
1984
- fontSize: fontVar5("md")
1304
+ color: css("muted-foreground"),
1305
+ fontSize: fontVar("md")
1985
1306
  },
1986
1307
  children: "No image URL"
1987
1308
  }
1988
1309
  ) });
1989
1310
  }
1990
- var imageWidget = defineWidget8({
1311
+ var imageWidget = defineWidget6({
1991
1312
  descriptor: builtinWidgetDescriptors["image"],
1992
1313
  implementation: { kind: "trusted-react", component: Image }
1993
1314
  });
1994
1315
 
1995
1316
  // src/widgets/label.tsx
1996
1317
  import {
1997
- css as css7,
1998
- defineWidget as defineWidget9,
1999
- fontVar as fontVar6,
2000
- spaceVar as spaceVar2,
2001
- optNumber as optNumber3,
2002
- optString as optString7,
2003
- WidgetFrame as WidgetFrame7
1318
+ css as css2,
1319
+ defineWidget as defineWidget7,
1320
+ fontVar as fontVar2,
1321
+ spaceVar,
1322
+ optNumber as optNumber2,
1323
+ optString as optString3,
1324
+ WidgetFrame as WidgetFrame3
2004
1325
  } from "@devicechain/widget-sdk";
2005
- import { jsx as jsx8 } from "react/jsx-runtime";
1326
+ import { jsx as jsx4 } from "react/jsx-runtime";
2006
1327
  var justify = {
2007
1328
  left: "flex-start",
2008
1329
  center: "center",
2009
1330
  right: "flex-end"
2010
1331
  };
2011
1332
  function Label({ widget }) {
2012
- const text = optString7(widget.options, "text") ?? "";
2013
- const align = optString7(widget.options, "align") ?? "center";
2014
- const authored = optNumber3(widget.options, "fontSize");
2015
- const fontSize = authored !== void 0 ? `calc(${authored}px * var(--dc-scale, 1))` : fontVar6("lg");
2016
- return /* @__PURE__ */ jsx8(WidgetFrame7, { title: optString7(widget.options, "title"), flush: true, children: /* @__PURE__ */ jsx8(
1333
+ const text = optString3(widget.options, "text") ?? "";
1334
+ const align = optString3(widget.options, "align") ?? "center";
1335
+ const authored = optNumber2(widget.options, "fontSize");
1336
+ const fontSize = authored !== void 0 ? `calc(${authored}px * var(--dc-scale, 1))` : fontVar2("lg");
1337
+ return /* @__PURE__ */ jsx4(WidgetFrame3, { title: optString3(widget.options, "title"), flush: true, children: /* @__PURE__ */ jsx4(
2017
1338
  "div",
2018
1339
  {
2019
1340
  style: {
@@ -2025,14 +1346,14 @@ function Label({ widget }) {
2025
1346
  overflow: "hidden",
2026
1347
  // A label is often one row tall: the frame's uniform inset would leave it a line's
2027
1348
  // height or less, so it keeps a slim vertical inset and the usual side inset.
2028
- padding: `${spaceVar2(1)} ${spaceVar2(3)}`
1349
+ padding: `${spaceVar(1)} ${spaceVar(3)}`
2029
1350
  },
2030
- children: /* @__PURE__ */ jsx8(
1351
+ children: /* @__PURE__ */ jsx4(
2031
1352
  "span",
2032
1353
  {
2033
1354
  style: {
2034
1355
  fontSize,
2035
- color: css7("foreground"),
1356
+ color: css2("foreground"),
2036
1357
  textAlign: align,
2037
1358
  whiteSpace: "pre-wrap"
2038
1359
  },
@@ -2042,65 +1363,65 @@ function Label({ widget }) {
2042
1363
  }
2043
1364
  ) });
2044
1365
  }
2045
- var labelWidget = defineWidget9({
1366
+ var labelWidget = defineWidget7({
2046
1367
  descriptor: builtinWidgetDescriptors["label"],
2047
1368
  implementation: { kind: "trusted-react", component: Label }
2048
1369
  });
2049
1370
 
2050
1371
  // src/widgets/latest-card.tsx
2051
- import { useMemo as useMemo3 } from "react";
1372
+ import { useMemo as useMemo2 } from "react";
2052
1373
  import {
2053
1374
  bandAt,
2054
- css as css8,
2055
- defineWidget as defineWidget10,
2056
- fitValueFont as fitValueFont2,
2057
- fitValueFontCss as fitValueFontCss2,
2058
- FIT_MIN_FONT_PX as FIT_MIN_FONT_PX2,
1375
+ css as css3,
1376
+ defineWidget as defineWidget8,
1377
+ fitValueFont,
1378
+ fitValueFontCss,
1379
+ FIT_MIN_FONT_PX,
2059
1380
  flashTextStyle,
2060
- fontVar as fontVar7,
1381
+ fontVar as fontVar3,
2061
1382
  formatTimestamp,
2062
1383
  formatValue as formatValue2,
2063
1384
  levelColor,
2064
- optBoolean as optBoolean3,
2065
- optNumber as optNumber4,
2066
- optString as optString8,
1385
+ optBoolean as optBoolean2,
1386
+ optNumber as optNumber3,
1387
+ optString as optString4,
2067
1388
  optThresholds as optThresholds2,
2068
1389
  pickSample as pickSample2,
2069
1390
  primaryMeasurementName as primaryMeasurementName2,
2070
- spaceVar as spaceVar3,
2071
- useSeverityColors as useSeverityColors3,
2072
- useStickyChars as useStickyChars2,
1391
+ spaceVar as spaceVar2,
1392
+ useSeverityColors,
1393
+ useStickyChars,
2073
1394
  useFlashOnChange as useFlashOnChange2,
2074
- useWidgetTimeZone as useWidgetTimeZone3,
2075
- WidgetFrame as WidgetFrame8
1395
+ useWidgetTimeZone,
1396
+ WidgetFrame as WidgetFrame4
2076
1397
  } from "@devicechain/widget-sdk";
2077
- import { jsx as jsx9, jsxs as jsxs6 } from "react/jsx-runtime";
1398
+ import { jsx as jsx5, jsxs as jsxs2 } from "react/jsx-runtime";
2078
1399
  var TIMESTAMP_ROOM_PX = 18;
2079
1400
  function LatestCard({ widget, data }) {
2080
- const severity = useSeverityColors3();
2081
- const timeZone = useWidgetTimeZone3();
1401
+ const severity = useSeverityColors();
1402
+ const timeZone = useWidgetTimeZone();
2082
1403
  const name = primaryMeasurementName2(widget);
2083
1404
  const sample = pickSample2(data.latest, name);
2084
- const title = optString8(widget.options, "title") ?? name;
2085
- const unit = optString8(widget.options, "unit");
2086
- const precision = optNumber4(widget.options, "precision");
1405
+ const title = optString4(widget.options, "title") ?? name;
1406
+ const unit = optString4(widget.options, "unit");
1407
+ const precision = optNumber3(widget.options, "precision");
2087
1408
  const display = formatValue2(sample?.value, precision);
2088
- const thresholds = useMemo3(() => optThresholds2(widget.options, "thresholds"), [widget.options]);
1409
+ const thresholds = useMemo2(() => optThresholds2(widget.options, "thresholds"), [widget.options]);
2089
1410
  const band = bandAt(thresholds, sample?.value);
2090
- const valueColor = levelColor(severity, band?.level) ?? css8("foreground");
1411
+ const valueColor = levelColor(severity, band?.level) ?? css3("foreground");
2091
1412
  const flashDirection = useFlashOnChange2(
2092
1413
  sample?.value,
2093
- optBoolean3(widget.options, "flashOnChange"),
1414
+ optBoolean2(widget.options, "flashOnChange"),
2094
1415
  sample && `${sample.deviceToken}:${sample.name}`
2095
1416
  );
2096
- const chars = useStickyChars2(display.length + (sample?.value != null && unit ? Math.ceil(unit.length / 2) + 1 : 0));
2097
- return /* @__PURE__ */ jsx9(WidgetFrame8, { title, sampleTime: sample?.occurredTime ?? null, children: ({ size, scale }) => {
2098
- const floor = Math.round(FIT_MIN_FONT_PX2 * scale);
1417
+ const chars = useStickyChars(display.length + (sample?.value != null && unit ? Math.ceil(unit.length / 2) + 1 : 0));
1418
+ return /* @__PURE__ */ jsx5(WidgetFrame4, { title, sampleTime: sample?.occurredTime ?? null, children: ({ size, scale }) => {
1419
+ const floor = Math.round(FIT_MIN_FONT_PX * scale);
2099
1420
  const measured = size.width > 0 && size.height > 0;
2100
- const valuePx = measured ? fitValueFont2(size, chars, { floor }) : void 0;
2101
- const valueFont = valuePx ?? fitValueFontCss2(chars, { floor });
1421
+ const valuePx = measured ? fitValueFont(size, chars, { floor }) : void 0;
1422
+ const valueFont = valuePx ?? fitValueFontCss(chars, { floor });
2102
1423
  const showTimestamp = valuePx === void 0 || size.height - Math.ceil(valuePx * 1.1) >= TIMESTAMP_ROOM_PX * scale;
2103
- return /* @__PURE__ */ jsxs6(
1424
+ return /* @__PURE__ */ jsxs2(
2104
1425
  "div",
2105
1426
  {
2106
1427
  style: {
@@ -2112,7 +1433,7 @@ function LatestCard({ widget, data }) {
2112
1433
  overflow: "hidden"
2113
1434
  },
2114
1435
  children: [
2115
- /* @__PURE__ */ jsxs6(
1436
+ /* @__PURE__ */ jsxs2(
2116
1437
  "div",
2117
1438
  {
2118
1439
  "data-threshold-level": band?.level,
@@ -2130,13 +1451,13 @@ function LatestCard({ widget, data }) {
2130
1451
  },
2131
1452
  children: [
2132
1453
  display,
2133
- sample?.value != null && unit ? /* @__PURE__ */ jsx9(
1454
+ sample?.value != null && unit ? /* @__PURE__ */ jsx5(
2134
1455
  "span",
2135
1456
  {
2136
1457
  style: {
2137
1458
  fontSize: valuePx !== void 0 ? Math.round(valuePx / 2) : `calc(${valueFont} / 2)`,
2138
- color: css8("muted-foreground"),
2139
- marginLeft: spaceVar3(1)
1459
+ color: css3("muted-foreground"),
1460
+ marginLeft: spaceVar2(1)
2140
1461
  },
2141
1462
  children: unit
2142
1463
  }
@@ -2144,64 +1465,65 @@ function LatestCard({ widget, data }) {
2144
1465
  ]
2145
1466
  }
2146
1467
  ),
2147
- sample?.occurredTime && showTimestamp ? /* @__PURE__ */ jsx9("div", { style: { fontSize: fontVar7("xs"), color: css8("muted-foreground"), marginTop: spaceVar3(1) }, children: formatTimestamp(sample.occurredTime, timeZone) }) : null
1468
+ sample?.occurredTime && showTimestamp ? /* @__PURE__ */ jsx5("div", { style: { fontSize: fontVar3("xs"), color: css3("muted-foreground"), marginTop: spaceVar2(1) }, children: formatTimestamp(sample.occurredTime, timeZone) }) : null
2148
1469
  ]
2149
1470
  }
2150
1471
  );
2151
1472
  } });
2152
1473
  }
2153
- var latestCardWidget = defineWidget10({
1474
+ var latestCardWidget = defineWidget8({
2154
1475
  descriptor: builtinWidgetDescriptors["latest-card"],
2155
1476
  implementation: { kind: "trusted-react", component: LatestCard }
2156
1477
  });
2157
1478
 
2158
1479
  // src/widgets/level-lazy.tsx
2159
- import { defineWidget as defineWidget11 } from "@devicechain/widget-sdk";
2160
- var chunk3 = lazyChunk(() => import("./chunks/level-widgets-MJB7TOLU.js"));
2161
- var loadLevelWidgets = chunk3.load;
2162
- var lazyComponent = chunk3.component;
2163
- var linearGaugeWidget = defineWidget11({
1480
+ import { defineWidget as defineWidget9 } from "@devicechain/widget-sdk";
1481
+ import { loadChartEngine as loadChartEngine2 } from "@devicechain/widget-sdk/echarts";
1482
+ var chunk5 = lazyChunk(() => import("./chunks/level-widgets-MJB7TOLU.js"));
1483
+ var loadLevelWidgets = chunk5.load;
1484
+ var lazyComponent = chunk5.component;
1485
+ var linearGaugeWidget = defineWidget9({
2164
1486
  descriptor: builtinWidgetDescriptors["linear-gauge"],
2165
1487
  implementation: { kind: "trusted-react", component: lazyComponent("LinearGauge") }
2166
1488
  });
2167
- var levelGaugeWidget = defineWidget11({
1489
+ var levelGaugeWidget = defineWidget9({
2168
1490
  descriptor: builtinWidgetDescriptors["level-gauge"],
2169
1491
  implementation: { kind: "trusted-react", component: lazyComponent("LevelGauge") }
2170
1492
  });
2171
- var batteryWidget = defineWidget11({
1493
+ var batteryWidget = defineWidget9({
2172
1494
  descriptor: builtinWidgetDescriptors["battery"],
2173
1495
  implementation: { kind: "trusted-react", component: lazyComponent("Battery") }
2174
1496
  });
2175
- var statusLightWidget = defineWidget11({
1497
+ var statusLightWidget = defineWidget9({
2176
1498
  descriptor: builtinWidgetDescriptors["status-light"],
2177
1499
  implementation: { kind: "trusted-react", component: lazyComponent("StatusLight") }
2178
1500
  });
2179
- var signalBarsWidget = defineWidget11({
1501
+ var signalBarsWidget = defineWidget9({
2180
1502
  descriptor: builtinWidgetDescriptors["signal-bars"],
2181
1503
  implementation: { kind: "trusted-react", component: lazyComponent("SignalBars") }
2182
1504
  });
2183
- var compassWidget = defineWidget11({
1505
+ var compassWidget = defineWidget9({
2184
1506
  descriptor: builtinWidgetDescriptors["compass"],
2185
- implementation: { kind: "trusted-react", component: lazyComponent("Compass") }
1507
+ implementation: { kind: "trusted-react", component: lazyComponent("Compass", loadChartEngine2) }
2186
1508
  });
2187
- var progressRingWidget = defineWidget11({
1509
+ var progressRingWidget = defineWidget9({
2188
1510
  descriptor: builtinWidgetDescriptors["progress-ring"],
2189
1511
  implementation: { kind: "trusted-react", component: lazyComponent("ProgressRing") }
2190
1512
  });
2191
1513
 
2192
1514
  // src/widgets/map.tsx
2193
- import { useEffect as useEffect4, useRef as useRef2, useState as useState6 } from "react";
1515
+ import { useEffect as useEffect2, useRef, useState as useState3 } from "react";
2194
1516
  import { renderableBasemap, resolveBasemap } from "@devicechain/client";
2195
1517
 
2196
1518
  // src/basemap-context.tsx
2197
1519
  import { createContext, useContext } from "react";
2198
- import { jsx as jsx10 } from "react/jsx-runtime";
1520
+ import { jsx as jsx6 } from "react/jsx-runtime";
2199
1521
  var TenantBasemapContext = createContext(null);
2200
1522
  function TenantBasemapProvider({
2201
1523
  basemap,
2202
1524
  children
2203
1525
  }) {
2204
- return /* @__PURE__ */ jsx10(TenantBasemapContext.Provider, { value: basemap, children });
1526
+ return /* @__PURE__ */ jsx6(TenantBasemapContext.Provider, { value: basemap, children });
2205
1527
  }
2206
1528
  function useTenantBasemap() {
2207
1529
  return useContext(TenantBasemapContext);
@@ -2209,13 +1531,13 @@ function useTenantBasemap() {
2209
1531
 
2210
1532
  // src/map-runtime-context.tsx
2211
1533
  import { createContext as createContext2, useContext as useContext2 } from "react";
2212
- import { jsx as jsx11 } from "react/jsx-runtime";
1534
+ import { jsx as jsx7 } from "react/jsx-runtime";
2213
1535
  var MapRuntimeContext = createContext2(null);
2214
1536
  function MapRuntimeProvider({
2215
1537
  runtime,
2216
1538
  children
2217
1539
  }) {
2218
- return /* @__PURE__ */ jsx11(MapRuntimeContext.Provider, { value: runtime, children });
1540
+ return /* @__PURE__ */ jsx7(MapRuntimeContext.Provider, { value: runtime, children });
2219
1541
  }
2220
1542
  function useMapRuntime() {
2221
1543
  return useContext2(MapRuntimeContext);
@@ -2223,11 +1545,11 @@ function useMapRuntime() {
2223
1545
 
2224
1546
  // src/widgets/map.tsx
2225
1547
  import {
2226
- css as css9,
2227
- fontVar as fontVar8,
2228
- defineWidget as defineWidget12,
2229
- optString as optString9,
2230
- WidgetFrame as WidgetFrame9
1548
+ css as css4,
1549
+ fontVar as fontVar4,
1550
+ defineWidget as defineWidget10,
1551
+ optString as optString5,
1552
+ WidgetFrame as WidgetFrame5
2231
1553
  } from "@devicechain/widget-sdk";
2232
1554
 
2233
1555
  // src/widgets/map-geometry.ts
@@ -2323,7 +1645,7 @@ function loadLandStyle() {
2323
1645
  }
2324
1646
 
2325
1647
  // src/widgets/map.tsx
2326
- import { jsx as jsx12, jsxs as jsxs7 } from "react/jsx-runtime";
1648
+ import { jsx as jsx8, jsxs as jsxs3 } from "react/jsx-runtime";
2327
1649
  var mapLibrePromise;
2328
1650
  function loadMapLibre(runtime) {
2329
1651
  if (!mapLibrePromise) {
@@ -2339,20 +1661,20 @@ function loadMapLibre(runtime) {
2339
1661
  }
2340
1662
  var SINGLE_DEVICE_ZOOM = 14;
2341
1663
  function MapWidget({ widget, data }) {
2342
- const title = optString9(widget.options, "title");
1664
+ const title = optString5(widget.options, "title");
2343
1665
  const positions = placeable(data.locations);
2344
1666
  const runtime = useMapRuntime();
2345
1667
  const basemap = renderableBasemap(
2346
1668
  resolveBasemap(
2347
1669
  {
2348
- tileUrl: optString9(widget.options, "tileUrl"),
2349
- attribution: optString9(widget.options, "attribution")
1670
+ tileUrl: optString5(widget.options, "tileUrl"),
1671
+ attribution: optString5(widget.options, "attribution")
2350
1672
  },
2351
1673
  useTenantBasemap()
2352
1674
  )
2353
1675
  );
2354
1676
  if (data.forbidden) {
2355
- return /* @__PURE__ */ jsx12(WidgetFrame9, { title, children: /* @__PURE__ */ jsx12(
1677
+ return /* @__PURE__ */ jsx8(WidgetFrame5, { title, children: /* @__PURE__ */ jsx8(
2356
1678
  MapNotice,
2357
1679
  {
2358
1680
  glyph: "\u{1F512}",
@@ -2362,7 +1684,7 @@ function MapWidget({ widget, data }) {
2362
1684
  ) });
2363
1685
  }
2364
1686
  if (!runtime) {
2365
- return /* @__PURE__ */ jsx12(WidgetFrame9, { title, children: /* @__PURE__ */ jsx12(
1687
+ return /* @__PURE__ */ jsx8(WidgetFrame5, { title, children: /* @__PURE__ */ jsx8(
2366
1688
  MapNotice,
2367
1689
  {
2368
1690
  glyph: "\u{1F9E9}",
@@ -2372,10 +1694,10 @@ function MapWidget({ widget, data }) {
2372
1694
  ) });
2373
1695
  }
2374
1696
  if (data.loading && positions.length === 0) {
2375
- return /* @__PURE__ */ jsx12(WidgetFrame9, { title, children: /* @__PURE__ */ jsx12(MapNotice, { heading: "Loading\u2026" }) });
1697
+ return /* @__PURE__ */ jsx8(WidgetFrame5, { title, children: /* @__PURE__ */ jsx8(MapNotice, { heading: "Loading\u2026" }) });
2376
1698
  }
2377
1699
  if (positions.length === 0) {
2378
- return /* @__PURE__ */ jsx12(WidgetFrame9, { title, children: /* @__PURE__ */ jsx12(
1700
+ return /* @__PURE__ */ jsx8(WidgetFrame5, { title, children: /* @__PURE__ */ jsx8(
2379
1701
  MapNotice,
2380
1702
  {
2381
1703
  heading: data.deviceTokens.length === 0 ? "No devices selected" : "No positions reported",
@@ -2383,11 +1705,11 @@ function MapWidget({ widget, data }) {
2383
1705
  }
2384
1706
  ) });
2385
1707
  }
2386
- return /* @__PURE__ */ jsx12(WidgetFrame9, { title, flush: true, children: /* @__PURE__ */ jsx12(LiveMap, { basemap, positions, runtime }) });
1708
+ return /* @__PURE__ */ jsx8(WidgetFrame5, { title, flush: true, children: /* @__PURE__ */ jsx8(LiveMap, { basemap, positions, runtime }) });
2387
1709
  }
2388
1710
  function PlainPanel({ positions, note }) {
2389
1711
  const points = projectToPanel(positions);
2390
- return /* @__PURE__ */ jsxs7(
1712
+ return /* @__PURE__ */ jsxs3(
2391
1713
  "div",
2392
1714
  {
2393
1715
  "data-testid": "map-plain-panel",
@@ -2396,10 +1718,10 @@ function PlainPanel({ positions, note }) {
2396
1718
  width: "100%",
2397
1719
  height: "100%",
2398
1720
  overflow: "hidden",
2399
- background: css9("muted")
1721
+ background: css4("muted")
2400
1722
  },
2401
1723
  children: [
2402
- positions.map((position, i) => /* @__PURE__ */ jsx12(
1724
+ positions.map((position, i) => /* @__PURE__ */ jsx8(
2403
1725
  Marker,
2404
1726
  {
2405
1727
  position,
@@ -2412,7 +1734,7 @@ function PlainPanel({ positions, note }) {
2412
1734
  },
2413
1735
  position.deviceToken
2414
1736
  )),
2415
- /* @__PURE__ */ jsx12(
1737
+ /* @__PURE__ */ jsx8(
2416
1738
  "div",
2417
1739
  {
2418
1740
  "data-testid": "map-no-tiles-note",
@@ -2422,11 +1744,11 @@ function PlainPanel({ positions, note }) {
2422
1744
  right: 0,
2423
1745
  bottom: 0,
2424
1746
  padding: "4px 8px",
2425
- fontSize: fontVar8("sm"),
1747
+ fontSize: fontVar4("sm"),
2426
1748
  lineHeight: 1.3,
2427
1749
  textAlign: "center",
2428
- color: css9("muted-foreground"),
2429
- background: css9("card"),
1750
+ color: css4("muted-foreground"),
1751
+ background: css4("card"),
2430
1752
  opacity: 0.9
2431
1753
  },
2432
1754
  children: note
@@ -2441,13 +1763,13 @@ function LiveMap({
2441
1763
  positions,
2442
1764
  runtime
2443
1765
  }) {
2444
- const containerRef = useRef2(null);
2445
- const mapRef = useRef2(null);
2446
- const markersRef = useRef2([]);
2447
- const [status, setStatus] = useState6("loading");
1766
+ const containerRef = useRef(null);
1767
+ const mapRef = useRef(null);
1768
+ const markersRef = useRef([]);
1769
+ const [status, setStatus] = useState3("loading");
2448
1770
  const tileUrl = basemap?.tileUrl ?? null;
2449
1771
  const attribution = basemap?.attribution ?? null;
2450
- useEffect4(() => {
1772
+ useEffect2(() => {
2451
1773
  let cancelled = false;
2452
1774
  setStatus("loading");
2453
1775
  Promise.all([
@@ -2475,7 +1797,7 @@ function LiveMap({
2475
1797
  mapRef.current = null;
2476
1798
  };
2477
1799
  }, [tileUrl, attribution, runtime.workerUrl]);
2478
- useEffect4(() => {
1800
+ useEffect2(() => {
2479
1801
  const map = mapRef.current;
2480
1802
  if (status !== "ready" || !map) return;
2481
1803
  let live = true;
@@ -2504,7 +1826,7 @@ function LiveMap({
2504
1826
  };
2505
1827
  }, [status, positionsKey(positions)]);
2506
1828
  if (status === "unavailable") {
2507
- return /* @__PURE__ */ jsx12(
1829
+ return /* @__PURE__ */ jsx8(
2508
1830
  PlainPanel,
2509
1831
  {
2510
1832
  positions,
@@ -2512,7 +1834,7 @@ function LiveMap({
2512
1834
  }
2513
1835
  );
2514
1836
  }
2515
- return /* @__PURE__ */ jsx12("div", { ref: containerRef, "data-testid": "map-canvas", style: { width: "100%", height: "100%" } });
1837
+ return /* @__PURE__ */ jsx8("div", { ref: containerRef, "data-testid": "map-canvas", style: { width: "100%", height: "100%" } });
2516
1838
  }
2517
1839
  function positionsKey(positions) {
2518
1840
  return positions.map((p) => `${p.deviceToken}:${p.latitude}:${p.longitude}:${p.heading ?? ""}`).join("|");
@@ -2521,8 +1843,8 @@ var MARKER_DOT_STYLE = {
2521
1843
  width: "12px",
2522
1844
  height: "12px",
2523
1845
  borderRadius: "50%",
2524
- background: css9("primary"),
2525
- border: `2px solid ${css9("card")}`,
1846
+ background: css4("primary"),
1847
+ border: `2px solid ${css4("card")}`,
2526
1848
  boxShadow: "0 0 0 1px rgba(0,0,0,0.25)",
2527
1849
  cursor: "default"
2528
1850
  };
@@ -2531,7 +1853,7 @@ function Marker({
2531
1853
  style
2532
1854
  }) {
2533
1855
  const label = describePosition(position);
2534
- return /* @__PURE__ */ jsx12(
1856
+ return /* @__PURE__ */ jsx8(
2535
1857
  "div",
2536
1858
  {
2537
1859
  "data-testid": "map-marker",
@@ -2543,7 +1865,7 @@ function Marker({
2543
1865
  );
2544
1866
  }
2545
1867
  function MapNotice({ glyph, heading, detail }) {
2546
- return /* @__PURE__ */ jsxs7(
1868
+ return /* @__PURE__ */ jsxs3(
2547
1869
  "div",
2548
1870
  {
2549
1871
  style: {
@@ -2557,115 +1879,68 @@ function MapNotice({ glyph, heading, detail }) {
2557
1879
  height: "100%",
2558
1880
  boxSizing: "border-box",
2559
1881
  textAlign: "center",
2560
- color: css9("muted-foreground")
1882
+ color: css4("muted-foreground")
2561
1883
  },
2562
1884
  children: [
2563
- glyph ? /* @__PURE__ */ jsx12("div", { style: { fontSize: fontVar8("xl"), lineHeight: 1 }, "aria-hidden": "true", children: glyph }) : null,
2564
- /* @__PURE__ */ jsx12("div", { style: { fontSize: fontVar8("md"), fontWeight: 600 }, children: heading }),
2565
- detail ? /* @__PURE__ */ jsx12("div", { style: { fontSize: fontVar8("sm"), opacity: 0.8 }, children: detail }) : null
1885
+ glyph ? /* @__PURE__ */ jsx8("div", { style: { fontSize: fontVar4("xl"), lineHeight: 1 }, "aria-hidden": "true", children: glyph }) : null,
1886
+ /* @__PURE__ */ jsx8("div", { style: { fontSize: fontVar4("md"), fontWeight: 600 }, children: heading }),
1887
+ detail ? /* @__PURE__ */ jsx8("div", { style: { fontSize: fontVar4("sm"), opacity: 0.8 }, children: detail }) : null
2566
1888
  ]
2567
1889
  }
2568
1890
  );
2569
1891
  }
2570
- var mapWidget = defineWidget12({
1892
+ var mapWidget = defineWidget10({
2571
1893
  descriptor: builtinWidgetDescriptors["map"],
2572
1894
  implementation: { kind: "trusted-react", component: MapWidget }
2573
1895
  });
2574
1896
 
2575
- // src/widgets/table.tsx
2576
- import {
2577
- css as css10,
2578
- defineWidget as defineWidget13,
2579
- fontVar as fontVar9,
2580
- spaceVar as spaceVar4,
2581
- FlashValue as FlashValue2,
2582
- formatTimestamp as formatTimestamp2,
2583
- optBoolean as optBoolean4,
2584
- optNumber as optNumber5,
2585
- optString as optString10,
2586
- useWidgetTimeZone as useWidgetTimeZone4,
2587
- WidgetFrame as WidgetFrame10
2588
- } from "@devicechain/widget-sdk";
2589
- import { jsx as jsx13, jsxs as jsxs8 } from "react/jsx-runtime";
2590
- var cell2 = { padding: `${spaceVar4(1)} ${spaceVar4(3)}`, textAlign: "left" };
2591
- var headCell2 = {
2592
- ...cell2,
2593
- fontSize: fontVar9("xs"),
2594
- fontWeight: 600,
2595
- textTransform: "uppercase",
2596
- letterSpacing: "0.04em",
2597
- color: css10("muted-foreground"),
2598
- borderBottom: `1px solid ${css10("border")}`
2599
- };
2600
- function Table({ widget, data }) {
2601
- const timeZone = useWidgetTimeZone4();
2602
- const rows = Object.values(data.latest).sort((a, b) => a.name.localeCompare(b.name));
2603
- const precision = optNumber5(widget.options, "precision");
2604
- const flash = optBoolean4(widget.options, "flashOnChange");
2605
- return /* @__PURE__ */ jsx13(WidgetFrame10, { title: optString10(widget.options, "title"), flush: true, children: /* @__PURE__ */ jsx13("div", { style: { height: "100%", overflow: "auto" }, children: /* @__PURE__ */ jsxs8("table", { style: { width: "100%", borderCollapse: "collapse", fontSize: fontVar9("md"), color: css10("foreground") }, children: [
2606
- /* @__PURE__ */ jsx13("thead", { children: /* @__PURE__ */ jsxs8("tr", { children: [
2607
- /* @__PURE__ */ jsx13("th", { style: headCell2, children: "Measurement" }),
2608
- /* @__PURE__ */ jsx13("th", { style: headCell2, children: "Value" }),
2609
- /* @__PURE__ */ jsx13("th", { style: headCell2, children: "Time" })
2610
- ] }) }),
2611
- /* @__PURE__ */ jsx13("tbody", { children: rows.length === 0 ? /* @__PURE__ */ jsx13("tr", { children: /* @__PURE__ */ jsx13("td", { colSpan: 3, style: { ...cell2, textAlign: "center", color: css10("muted-foreground") }, children: "No data yet" }) }) : rows.map((row) => /* @__PURE__ */ jsxs8("tr", { children: [
2612
- /* @__PURE__ */ jsx13("td", { style: cell2, children: row.name }),
2613
- /* @__PURE__ */ jsx13("td", { style: { ...cell2, fontVariantNumeric: "tabular-nums" }, children: /* @__PURE__ */ jsx13(
2614
- FlashValue2,
2615
- {
2616
- value: row.value,
2617
- precision,
2618
- enabled: flash,
2619
- identity: `${row.deviceToken}:${row.name}`
2620
- }
2621
- ) }),
2622
- /* @__PURE__ */ jsx13("td", { style: { ...cell2, color: css10("muted-foreground") }, children: formatTimestamp2(row.occurredTime, timeZone) })
2623
- ] }, row.name)) })
2624
- ] }) }) });
2625
- }
2626
- var tableWidget = defineWidget13({
1897
+ // src/widgets/table-lazy.tsx
1898
+ import { defineWidget as defineWidget11 } from "@devicechain/widget-sdk";
1899
+ var chunk6 = lazyChunk(() => import("./chunks/table-6EVV7QZH.js"));
1900
+ var loadTableWidget = chunk6.load;
1901
+ var tableWidget = defineWidget11({
2627
1902
  descriptor: builtinWidgetDescriptors["table"],
2628
- implementation: { kind: "trusted-react", component: Table }
1903
+ implementation: { kind: "trusted-react", component: chunk6.component("Table") }
2629
1904
  });
2630
1905
 
2631
1906
  // src/widgets/time-series-chart.tsx
2632
- import { useMemo as useMemo4 } from "react";
1907
+ import { useMemo as useMemo3 } from "react";
2633
1908
  import { isValidSpanSeconds, spanLabel } from "@devicechain/dashboards";
2634
1909
  import {
2635
- css as css11,
2636
- defineWidget as defineWidget14,
2637
- fontVar as fontVar10,
2638
- formatDateTime as formatDateTime3,
2639
- formatTimestamp as formatTimestamp3,
2640
- optNumber as optNumber6,
2641
- optString as optString11,
1910
+ css as css5,
1911
+ defineWidget as defineWidget12,
1912
+ fontVar as fontVar5,
1913
+ formatDateTime,
1914
+ formatTimestamp as formatTimestamp2,
1915
+ optNumber as optNumber4,
1916
+ optString as optString6,
2642
1917
  optThresholds as optThresholds3,
2643
- spaceVar as spaceVar5,
2644
- useWidgetScale as useWidgetScale3,
1918
+ spaceVar as spaceVar3,
1919
+ useWidgetScale as useWidgetScale2,
2645
1920
  useWidgetTimeRange,
2646
- useWidgetTimeZone as useWidgetTimeZone5,
1921
+ useWidgetTimeZone as useWidgetTimeZone2,
2647
1922
  viewerLocale,
2648
- WidgetFrame as WidgetFrame11
1923
+ WidgetFrame as WidgetFrame6
2649
1924
  } from "@devicechain/widget-sdk";
2650
- import { buildLineOption, EChart as EChart2, useChartTheme as useChartTheme2 } from "@devicechain/widget-sdk/echarts";
2651
- import { jsx as jsx14, jsxs as jsxs9 } from "react/jsx-runtime";
1925
+ import { buildLineOption, EChart as EChart2, loadChartEngine as loadChartEngine3, useChartTheme as useChartTheme2 } from "@devicechain/widget-sdk/echarts";
1926
+ import { jsx as jsx9, jsxs as jsxs4 } from "react/jsx-runtime";
2652
1927
  function TimeSeriesChart({ widget, data }) {
2653
- return /* @__PURE__ */ jsx14(WidgetFrame11, { title: optString11(widget.options, "title"), flush: true, children: /* @__PURE__ */ jsx14(TimeSeriesBody, { widget, data }) });
1928
+ return /* @__PURE__ */ jsx9(WidgetFrame6, { title: optString6(widget.options, "title"), flush: true, children: /* @__PURE__ */ jsx9(TimeSeriesBody, { widget, data }) });
2654
1929
  }
2655
1930
  function TimeSeriesBody({ widget, data }) {
2656
1931
  const theme = useChartTheme2();
2657
- const { size, scale } = useWidgetScale3();
1932
+ const { size, scale } = useWidgetScale2();
2658
1933
  const measurements = widget.datasource?.measurements;
2659
- const unit = optString11(widget.options, "unit");
2660
- const precision = optNumber6(widget.options, "precision");
2661
- const thresholds = useMemo4(() => optThresholds3(widget.options, "thresholds"), [widget.options]);
2662
- const option = useMemo4(
2663
- () => buildLineOption(data.samples, theme, { measurements, unit, precision, thresholds, scale }, size),
2664
- [data.samples, theme, measurements, unit, precision, thresholds, scale, size]
1934
+ const unit = optString6(widget.options, "unit");
1935
+ const precision = optNumber4(widget.options, "precision");
1936
+ const thresholds = useMemo3(() => optThresholds3(widget.options, "thresholds"), [widget.options]);
1937
+ const option = useMemo3(
1938
+ () => buildLineOption(data.samples, theme, { measurements, unit, precision, thresholds, scale, gaps: data.gaps }, size),
1939
+ [data.samples, data.gaps, theme, measurements, unit, precision, thresholds, scale, size]
2665
1940
  );
2666
- return /* @__PURE__ */ jsxs9("div", { style: { position: "relative", width: "100%", height: "100%" }, children: [
2667
- /* @__PURE__ */ jsx14(EChart2, { option }),
2668
- /* @__PURE__ */ jsx14(SpanBadge, { widget, data })
1941
+ return /* @__PURE__ */ jsxs4("div", { style: { position: "relative", width: "100%", height: "100%" }, children: [
1942
+ /* @__PURE__ */ jsx9(EChart2, { option }),
1943
+ /* @__PURE__ */ jsx9(SpanBadge, { widget, data })
2669
1944
  ] });
2670
1945
  }
2671
1946
  var SPAN_STRINGS = {
@@ -2683,8 +1958,8 @@ var SPAN_STRINGS = {
2683
1958
  var DAY_MS = 864e5;
2684
1959
  function SpanBadge({ widget, data }) {
2685
1960
  const range = useWidgetTimeRange();
2686
- const timeZone = useWidgetTimeZone5();
2687
- const pinned = optNumber6(widget.options, "windowSeconds");
1961
+ const timeZone = useWidgetTimeZone2();
1962
+ const pinned = optNumber4(widget.options, "windowSeconds");
2688
1963
  const span = isValidSpanSeconds(pinned) ? pinned : range?.spanSeconds;
2689
1964
  const showSpan = range !== void 0 && span !== range.spanSeconds;
2690
1965
  const cutAt = data.truncatedBefore;
@@ -2692,10 +1967,10 @@ function SpanBadge({ widget, data }) {
2692
1967
  const words = viewerLocale()?.toLowerCase().startsWith("es") ? SPAN_STRINGS.es : SPAN_STRINGS.en;
2693
1968
  const label = span === void 0 ? "" : spanLabel(span);
2694
1969
  const end = range?.paused && range.pausedAt !== void 0 ? range.pausedAt : Date.now();
2695
- const time = cutAt ? end - Date.parse(cutAt) > DAY_MS ? formatDateTime3(cutAt, timeZone) : formatTimestamp3(cutAt, timeZone) : "";
1970
+ const time = cutAt ? end - Date.parse(cutAt) > DAY_MS ? formatDateTime(cutAt, timeZone) : formatTimestamp2(cutAt, timeZone) : "";
2696
1971
  const text = [showSpan ? label : "", cutAt ? words.from(time) : ""].filter(Boolean).join(" \xB7 ");
2697
1972
  const title = [showSpan ? words.pinned(label) : "", cutAt ? words.cut(time, label) : ""].filter(Boolean).join(" ");
2698
- return /* @__PURE__ */ jsx14(
1973
+ return /* @__PURE__ */ jsx9(
2699
1974
  "span",
2700
1975
  {
2701
1976
  "data-chart-span": showSpan ? label : "",
@@ -2703,13 +1978,13 @@ function SpanBadge({ widget, data }) {
2703
1978
  title,
2704
1979
  style: {
2705
1980
  position: "absolute",
2706
- top: spaceVar5(1),
2707
- right: spaceVar5(2),
2708
- padding: `0 ${spaceVar5(1)}`,
2709
- fontSize: fontVar10("xs"),
1981
+ top: spaceVar3(1),
1982
+ right: spaceVar3(2),
1983
+ padding: `0 ${spaceVar3(1)}`,
1984
+ fontSize: fontVar5("xs"),
2710
1985
  whiteSpace: "nowrap",
2711
- color: css11("muted-foreground"),
2712
- background: css11("muted"),
1986
+ color: css5("muted-foreground"),
1987
+ background: css5("muted"),
2713
1988
  borderRadius: 4,
2714
1989
  pointerEvents: "auto"
2715
1990
  },
@@ -2717,7 +1992,8 @@ function SpanBadge({ widget, data }) {
2717
1992
  }
2718
1993
  );
2719
1994
  }
2720
- var timeSeriesChartWidget = defineWidget14({
1995
+ TimeSeriesChart.preload = loadChartEngine3;
1996
+ var timeSeriesChartWidget = defineWidget12({
2721
1997
  descriptor: builtinWidgetDescriptors["timeseries-chart"],
2722
1998
  implementation: { kind: "trusted-react", component: TimeSeriesChart }
2723
1999
  });
@@ -2762,20 +2038,20 @@ function defaultWidgetRegistry() {
2762
2038
 
2763
2039
  // src/connected-widget.tsx
2764
2040
  import {
2765
- optString as optString12,
2041
+ optString as optString7,
2766
2042
  useAlarmStream,
2767
2043
  useCommandStream,
2768
2044
  useDatasourceAvailability,
2769
2045
  useLocationStream,
2770
2046
  useMeasurementStream,
2771
2047
  useWidgetCandidates,
2772
- useWidgetSelect as useWidgetSelect3,
2773
- WidgetFrame as WidgetFrame13
2048
+ useWidgetSelect,
2049
+ WidgetFrame as WidgetFrame8
2774
2050
  } from "@devicechain/widget-sdk";
2775
2051
 
2776
2052
  // src/widget-containment.tsx
2777
- import { Component, createContext as createContext3, useCallback, useContext as useContext3, useState as useState7 } from "react";
2778
- import { WidgetFrame as WidgetFrame12 } from "@devicechain/widget-sdk";
2053
+ import { Component, createContext as createContext3, useCallback, useContext as useContext3, useState as useState4 } from "react";
2054
+ import { WidgetFrame as WidgetFrame7 } from "@devicechain/widget-sdk";
2779
2055
 
2780
2056
  // src/widget-host.ts
2781
2057
  function describeError(error) {
@@ -2833,7 +2109,7 @@ function narrowCandidates(candidates, descriptor, report) {
2833
2109
  }
2834
2110
 
2835
2111
  // src/widget-containment.tsx
2836
- import { jsx as jsx15, jsxs as jsxs10 } from "react/jsx-runtime";
2112
+ import { jsx as jsx10, jsxs as jsxs5 } from "react/jsx-runtime";
2837
2113
  var MESSAGE_STYLE = {
2838
2114
  display: "flex",
2839
2115
  flexDirection: "column",
@@ -2877,23 +2153,23 @@ var WidgetErrorBoundary = class extends Component {
2877
2153
  render() {
2878
2154
  const { error } = this.state;
2879
2155
  if (!error) return this.props.children;
2880
- return /* @__PURE__ */ jsx15(WidgetFrame12, { title: this.props.title, children: /* @__PURE__ */ jsxs10("div", { style: MESSAGE_STYLE, role: "alert", children: [
2881
- /* @__PURE__ */ jsx15("div", { style: { fontSize: 20, lineHeight: 1 }, "aria-hidden": "true", children: "\u26A0" }),
2882
- /* @__PURE__ */ jsx15("div", { style: { fontSize: 13, fontWeight: 600 }, children: "This widget failed to render" }),
2883
- /* @__PURE__ */ jsx15("div", { style: { fontSize: 11, opacity: 0.8, wordBreak: "break-word" }, children: error.message }),
2884
- /* @__PURE__ */ jsx15("button", { type: "button", style: BUTTON_STYLE, onClick: this.reset, children: "Reset widget" })
2156
+ return /* @__PURE__ */ jsx10(WidgetFrame7, { title: this.props.title, children: /* @__PURE__ */ jsxs5("div", { style: MESSAGE_STYLE, role: "alert", children: [
2157
+ /* @__PURE__ */ jsx10("div", { style: { fontSize: 20, lineHeight: 1 }, "aria-hidden": "true", children: "\u26A0" }),
2158
+ /* @__PURE__ */ jsx10("div", { style: { fontSize: 13, fontWeight: 600 }, children: "This widget failed to render" }),
2159
+ /* @__PURE__ */ jsx10("div", { style: { fontSize: 11, opacity: 0.8, wordBreak: "break-word" }, children: error.message }),
2160
+ /* @__PURE__ */ jsx10("button", { type: "button", style: BUTTON_STYLE, onClick: this.reset, children: "Reset widget" })
2885
2161
  ] }) });
2886
2162
  }
2887
2163
  };
2888
2164
  function WidgetContainment({ title, resetKey, children }) {
2889
- const [messages, setMessages] = useState7([]);
2165
+ const [messages, setMessages] = useState4([]);
2890
2166
  const report = useCallback((message) => {
2891
2167
  setMessages((prev) => prev.includes(message) ? prev : [...prev, message].slice(-3));
2892
2168
  }, []);
2893
2169
  const clear = useCallback(() => setMessages([]), []);
2894
- return /* @__PURE__ */ jsxs10("div", { style: { position: "relative", width: "100%", height: "100%" }, children: [
2895
- /* @__PURE__ */ jsx15(ReportContext.Provider, { value: report, children: /* @__PURE__ */ jsx15(WidgetErrorBoundary, { title, resetKey, onReset: clear, children }) }),
2896
- messages.length > 0 && /* @__PURE__ */ jsxs10(
2170
+ return /* @__PURE__ */ jsxs5("div", { style: { position: "relative", width: "100%", height: "100%" }, children: [
2171
+ /* @__PURE__ */ jsx10(ReportContext.Provider, { value: report, children: /* @__PURE__ */ jsx10(WidgetErrorBoundary, { title, resetKey, onReset: clear, children }) }),
2172
+ messages.length > 0 && /* @__PURE__ */ jsxs5(
2897
2173
  "div",
2898
2174
  {
2899
2175
  role: "status",
@@ -2912,8 +2188,8 @@ function WidgetContainment({ title, resetKey, children }) {
2912
2188
  alignItems: "center"
2913
2189
  },
2914
2190
  children: [
2915
- /* @__PURE__ */ jsx15("span", { style: { flex: 1, wordBreak: "break-word" }, children: messages.join(" \xB7 ") }),
2916
- /* @__PURE__ */ jsx15("button", { type: "button", "aria-label": "Dismiss", onClick: clear, style: { cursor: "pointer" }, children: "\xD7" })
2191
+ /* @__PURE__ */ jsx10("span", { style: { flex: 1, wordBreak: "break-word" }, children: messages.join(" \xB7 ") }),
2192
+ /* @__PURE__ */ jsx10("button", { type: "button", "aria-label": "Dismiss", onClick: clear, style: { cursor: "pointer" }, children: "\xD7" })
2917
2193
  ]
2918
2194
  }
2919
2195
  )
@@ -2921,27 +2197,31 @@ function WidgetContainment({ title, resetKey, children }) {
2921
2197
  }
2922
2198
 
2923
2199
  // src/connected-widget.tsx
2924
- import { jsx as jsx16, jsxs as jsxs11 } from "react/jsx-runtime";
2200
+ import { jsx as jsx11, jsxs as jsxs6 } from "react/jsx-runtime";
2925
2201
  function ConnectedWidget(props) {
2926
2202
  const { widget } = props;
2927
2203
  const registry = props.registry ?? defaultWidgetRegistry();
2928
2204
  const resetKey = JSON.stringify([widget.type, widget.options ?? null, widget.datasource ?? null]);
2929
- return /* @__PURE__ */ jsx16(WidgetContainment, { title: optString12(widget.options, "title"), resetKey, children: /* @__PURE__ */ jsx16(ConnectedWidgetBody, { ...props, registry }) });
2205
+ return /* @__PURE__ */ jsx11(WidgetContainment, { title: optString7(widget.options, "title"), resetKey, children: /* @__PURE__ */ jsx11(ConnectedWidgetBody, { ...props, registry }) });
2930
2206
  }
2931
- function ConnectedWidgetBody({ widget, hub, registry, actions, initialSamples }) {
2207
+ function ConnectedWidgetBody({ widget, hub, registry, actions, initialSamples, initialSamplesAsOf, onReconnect }) {
2932
2208
  const unresolved = widget.type === UNKNOWN_WIDGET_TYPE;
2933
2209
  const descriptor = unresolved ? void 0 : registry.descriptor(widget.type);
2934
2210
  const implementation = unresolved ? void 0 : registry.implementation(widget.type);
2935
2211
  const readsDatasource = descriptor !== void 0 && descriptor.datasource.mode !== "none";
2936
2212
  const availability = useDatasourceAvailability(hub, readsDatasource ? widget.datasource : void 0);
2213
+ const supported = useDatasourceSupported(hub, readsDatasource ? widget.datasource : void 0);
2214
+ if (!supported) {
2215
+ return /* @__PURE__ */ jsx11(WidgetNotForCustomerUsersFrame, { widget });
2216
+ }
2937
2217
  if (availability === "unavailable") {
2938
- return /* @__PURE__ */ jsx16(WidgetUnavailableFrame, { widget });
2218
+ return /* @__PURE__ */ jsx11(WidgetUnavailableFrame, { widget });
2939
2219
  }
2940
2220
  if (widget.type === UNKNOWN_WIDGET_TYPE) {
2941
- return /* @__PURE__ */ jsx16(UnresolvedWidgetFrame, { storedType: widget.raw.type, reason: widget.reason });
2221
+ return /* @__PURE__ */ jsx11(UnresolvedWidgetFrame, { storedType: widget.raw.type, reason: widget.reason });
2942
2222
  }
2943
2223
  if (!descriptor || !implementation) {
2944
- return /* @__PURE__ */ jsx16(
2224
+ return /* @__PURE__ */ jsx11(
2945
2225
  UnresolvedWidgetFrame,
2946
2226
  {
2947
2227
  storedType: widget.type,
@@ -2949,7 +2229,7 @@ function ConnectedWidgetBody({ widget, hub, registry, actions, initialSamples })
2949
2229
  }
2950
2230
  );
2951
2231
  }
2952
- return /* @__PURE__ */ jsx16(HostScope, { descriptor, actions, children: (hostActions) => /* @__PURE__ */ jsx16(
2232
+ return /* @__PURE__ */ jsx11(HostScope, { descriptor, actions, children: (hostActions) => /* @__PURE__ */ jsx11(
2953
2233
  ChannelBody,
2954
2234
  {
2955
2235
  widget,
@@ -2957,183 +2237,205 @@ function ConnectedWidgetBody({ widget, hub, registry, actions, initialSamples })
2957
2237
  descriptor,
2958
2238
  Component: implementation.component,
2959
2239
  actions: hostActions,
2960
- initialSamples
2240
+ initialSamples,
2241
+ initialSamplesAsOf,
2242
+ onReconnect
2961
2243
  }
2962
2244
  ) });
2963
2245
  }
2246
+ function useDatasourceSupported(hub, datasource) {
2247
+ const key = datasource ? JSON.stringify(datasource) : null;
2248
+ const [refused, setRefused] = useState5(null);
2249
+ useEffect3(() => {
2250
+ if (!datasource || !hub.isDatasourceSupported) return;
2251
+ let cancelled = false;
2252
+ hub.isDatasourceSupported(datasource).then(
2253
+ (ok) => {
2254
+ if (!cancelled) setRefused(ok ? null : key);
2255
+ },
2256
+ () => {
2257
+ if (!cancelled) setRefused(null);
2258
+ }
2259
+ );
2260
+ return () => {
2261
+ cancelled = true;
2262
+ };
2263
+ }, [hub, key]);
2264
+ return refused === null || refused !== key;
2265
+ }
2964
2266
  function HostScope({
2965
2267
  descriptor,
2966
2268
  actions,
2967
2269
  children
2968
2270
  }) {
2969
2271
  const report = useReportRejection();
2970
- const select = useWidgetSelect3();
2272
+ const select = useWidgetSelect();
2971
2273
  const candidates = useWidgetCandidates();
2972
- const narrowed = useMemo5(() => narrowActions(actions, descriptor, report), [actions, descriptor, report]);
2973
- const narrowedSelect = useMemo5(() => narrowSelect(select, descriptor), [select, descriptor]);
2974
- const narrowedCandidates = useMemo5(
2274
+ const narrowed = useMemo4(() => narrowActions(actions, descriptor, report), [actions, descriptor, report]);
2275
+ const narrowedSelect = useMemo4(() => narrowSelect(select, descriptor), [select, descriptor]);
2276
+ const narrowedCandidates = useMemo4(
2975
2277
  () => narrowCandidates(candidates, descriptor, report),
2976
2278
  [candidates, descriptor, report]
2977
2279
  );
2978
- return /* @__PURE__ */ jsx16(WidgetSelectProvider, { select: narrowedSelect, children: /* @__PURE__ */ jsx16(WidgetCandidatesProvider, { candidates: narrowedCandidates, children: children(narrowed) }) });
2280
+ return /* @__PURE__ */ jsx11(WidgetSelectProvider, { select: narrowedSelect, children: /* @__PURE__ */ jsx11(WidgetCandidatesProvider, { candidates: narrowedCandidates, children: children(narrowed) }) });
2979
2281
  }
2980
2282
  function ChannelBody(props) {
2981
2283
  switch (props.descriptor.channel) {
2982
2284
  case "alarm":
2983
- return /* @__PURE__ */ jsx16(AlarmConnectedWidget, { ...props });
2285
+ return /* @__PURE__ */ jsx11(AlarmConnectedWidget, { ...props });
2984
2286
  case "control":
2985
- return /* @__PURE__ */ jsx16(ControlConnectedWidget, { ...props });
2287
+ return /* @__PURE__ */ jsx11(ControlConnectedWidget, { ...props });
2986
2288
  case "location":
2987
- return /* @__PURE__ */ jsx16(LocationConnectedWidget, { ...props });
2289
+ return /* @__PURE__ */ jsx11(LocationConnectedWidget, { ...props });
2988
2290
  case "aggregate":
2989
- return /* @__PURE__ */ jsx16(AggregateConnectedWidget, { ...props });
2291
+ return /* @__PURE__ */ jsx11(AggregateConnectedWidget, { ...props });
2990
2292
  case "selection":
2991
2293
  case "none":
2992
- return /* @__PURE__ */ jsx16(StaticConnectedWidget, { ...props });
2294
+ return /* @__PURE__ */ jsx11(StaticConnectedWidget, { ...props });
2993
2295
  case "measurement":
2994
- return /* @__PURE__ */ jsx16(MeasurementConnectedWidget, { ...props });
2296
+ return /* @__PURE__ */ jsx11(MeasurementConnectedWidget, { ...props });
2995
2297
  }
2996
2298
  }
2997
2299
  function StaticConnectedWidget({ widget, Component: Component2, actions }) {
2998
- return /* @__PURE__ */ jsx16(Component2, { widget, data: null, actions });
2300
+ return /* @__PURE__ */ jsx11(Component2, { widget, data: null, actions });
2999
2301
  }
3000
- var FleetFeed = lazyChunk(() => import("./chunks/fleet-feed-FK4ZMKIK.js")).component("default");
2302
+ var FleetFeed = lazyChunk(() => import("./chunks/fleet-feed-5QGDLOV5.js")).component("default");
3001
2303
  function MeasurementConnectedWidget(props) {
3002
2304
  const { widget, hub, descriptor, Component: Component2, actions } = props;
3003
2305
  const members = membersMode(descriptor, widget);
3004
2306
  if (members || widget.datasource?.kind === "anchor") {
3005
- return /* @__PURE__ */ jsx16(FleetFeed, { hub, widget, descriptor, Component: Component2, actions, ErrorFrame: WidgetErrorFrame, refuse: !members });
2307
+ return /* @__PURE__ */ jsx11(FleetFeed, { hub, widget, descriptor, Component: Component2, actions, ErrorFrame: WidgetErrorFrame, refuse: !members });
3006
2308
  }
3007
- return /* @__PURE__ */ jsx16(StreamConnectedWidget, { ...props });
2309
+ return /* @__PURE__ */ jsx11(StreamConnectedWidget, { ...props });
3008
2310
  }
3009
- function StreamConnectedWidget({ widget, hub, descriptor, Component: Component2, actions, initialSamples }) {
2311
+ function StreamConnectedWidget({ widget, hub, descriptor, Component: Component2, actions, initialSamples, initialSamplesAsOf, onReconnect }) {
3010
2312
  const range = useWidgetTimeRange2();
3011
- const now = useMemo5(() => hub.now ? () => hub.now() : Date.now, [hub]);
2313
+ const now = useMemo4(() => hub.now ? () => hub.now() : Date.now, [hub]);
3012
2314
  const data = useMeasurementStream(hub, widget.datasource, {
3013
2315
  window: measurementWindow(descriptor, widget),
3014
2316
  windowSeconds: measurementSpan(descriptor, widget, range?.spanSeconds),
3015
2317
  pausedAt: range?.paused ? range.pausedAt : void 0,
3016
2318
  now,
3017
- initialSamples
2319
+ initialSamples,
2320
+ initialSamplesAsOf,
2321
+ onReconnect
3018
2322
  });
3019
- const freshness = useMemo5(() => {
2323
+ const freshness = useMemo4(() => {
3020
2324
  if (descriptor.freshness !== true) return void 0;
3021
- const pinned = optString12(widget.options, "measurement");
2325
+ const pinned = optString7(widget.options, "measurement");
3022
2326
  const names = pinned ? [pinned] : widget.datasource?.measurements;
3023
2327
  return {
3024
2328
  at: newestSampleTime(data.latest, names),
3025
2329
  staleAfterSeconds: resolveStaleAfterSeconds(widget.options)
3026
2330
  };
3027
2331
  }, [descriptor, widget.options, widget.datasource, data.latest]);
3028
- if (data.error) return /* @__PURE__ */ jsx16(WidgetErrorFrame, { widget, error: data.error });
3029
- return /* @__PURE__ */ jsx16(WidgetFreshnessProvider, { freshness, children: /* @__PURE__ */ jsx16(Component2, { widget, data, actions }) });
2332
+ if (data.error) return /* @__PURE__ */ jsx11(WidgetErrorFrame, { widget, error: data.error });
2333
+ return /* @__PURE__ */ jsx11(WidgetFreshnessProvider, { freshness, children: /* @__PURE__ */ jsx11(Component2, { widget, data, actions }) });
3030
2334
  }
3031
- var AggregateFeed = lazyChunk(() => import("./chunks/aggregate-feed-6ZYKOQOB.js")).component("default");
2335
+ var AggregateFeed = lazyChunk(() => import("./chunks/aggregate-feed-BD3CHNFU.js")).component("default");
3032
2336
  function AggregateConnectedWidget({ widget, hub, descriptor, Component: Component2, actions }) {
3033
2337
  const props = { hub, widget, descriptor, Component: Component2, actions, ErrorFrame: WidgetErrorFrame };
3034
- return widget.datasource?.kind === "anchor" ? /* @__PURE__ */ jsx16(FleetFeed, { ...props, refuse: true }) : /* @__PURE__ */ jsx16(AggregateFeed, { ...props });
2338
+ return widget.datasource?.kind === "anchor" ? /* @__PURE__ */ jsx11(FleetFeed, { ...props, refuse: true }) : /* @__PURE__ */ jsx11(AggregateFeed, { ...props });
3035
2339
  }
3036
2340
  function AlarmConnectedWidget({ widget, hub, descriptor, Component: Component2, actions }) {
3037
2341
  const range = useWidgetTimeRange2();
3038
2342
  const live = useAlarmStream(hub, alarmSubscription(descriptor, widget));
3039
2343
  const data = useHeld(live, range?.paused === true, (s) => !s.loading);
3040
2344
  if (data.error && data.alarms.length === 0 && data.total === 0) {
3041
- return /* @__PURE__ */ jsx16(WidgetErrorFrame, { widget, error: data.error });
2345
+ return /* @__PURE__ */ jsx11(WidgetErrorFrame, { widget, error: data.error });
3042
2346
  }
3043
- return /* @__PURE__ */ jsx16(Component2, { widget, data, actions });
2347
+ return /* @__PURE__ */ jsx11(Component2, { widget, data, actions });
3044
2348
  }
3045
2349
  function ControlConnectedWidget({ widget, hub, descriptor, Component: Component2, actions }) {
3046
2350
  const data = useCommandStream(hub, commandSubscription(descriptor, widget));
3047
- return /* @__PURE__ */ jsx16(Component2, { widget, data, actions });
2351
+ return /* @__PURE__ */ jsx11(Component2, { widget, data, actions });
3048
2352
  }
3049
2353
  function LocationConnectedWidget({ widget, hub, Component: Component2, actions }) {
3050
2354
  const range = useWidgetTimeRange2();
3051
2355
  const live = useLocationStream(hub, { datasource: widget.datasource });
3052
2356
  const data = useHeld(live, range?.paused === true, (s) => !s.loading);
3053
2357
  if (data.error && data.locations.length === 0) {
3054
- return /* @__PURE__ */ jsx16(WidgetErrorFrame, { widget, error: data.error });
2358
+ return /* @__PURE__ */ jsx11(WidgetErrorFrame, { widget, error: data.error });
3055
2359
  }
3056
- return /* @__PURE__ */ jsx16(Component2, { widget, data, actions });
2360
+ return /* @__PURE__ */ jsx11(Component2, { widget, data, actions });
3057
2361
  }
2362
+ var STATE_STYLE = {
2363
+ display: "flex",
2364
+ flexDirection: "column",
2365
+ alignItems: "center",
2366
+ justifyContent: "center",
2367
+ gap: 4,
2368
+ width: "100%",
2369
+ height: "100%",
2370
+ padding: 12,
2371
+ boxSizing: "border-box",
2372
+ textAlign: "center",
2373
+ color: "hsl(var(--muted-foreground))"
2374
+ };
3058
2375
  function UnresolvedWidgetFrame({
3059
2376
  storedType: stored,
3060
2377
  reason
3061
2378
  }) {
3062
2379
  const storedType = typeof stored === "string" ? stored : "";
3063
2380
  const heading = (reason?.code ?? "unregistered") === "unregistered" ? "This widget needs a newer viewer" : "This widget cannot be shown here";
3064
- return /* @__PURE__ */ jsx16(WidgetFrame13, { children: /* @__PURE__ */ jsxs11(
2381
+ return /* @__PURE__ */ jsx11(WidgetFrame8, { children: /* @__PURE__ */ jsxs6(
3065
2382
  "div",
3066
2383
  {
3067
- style: {
3068
- display: "flex",
3069
- flexDirection: "column",
3070
- alignItems: "center",
3071
- justifyContent: "center",
3072
- gap: 4,
3073
- width: "100%",
3074
- height: "100%",
3075
- padding: 12,
3076
- boxSizing: "border-box",
3077
- textAlign: "center",
3078
- color: "hsl(var(--muted-foreground))"
3079
- },
2384
+ style: STATE_STYLE,
3080
2385
  children: [
3081
- /* @__PURE__ */ jsx16("div", { style: { fontSize: 13, fontWeight: 600 }, children: heading }),
3082
- storedType && !reason?.message.includes(storedType) && /* @__PURE__ */ jsxs11("div", { style: { fontSize: 11, opacity: 0.8 }, children: [
2386
+ /* @__PURE__ */ jsx11("div", { style: { fontSize: 13, fontWeight: 600 }, children: heading }),
2387
+ storedType && !reason?.message.includes(storedType) && /* @__PURE__ */ jsxs6("div", { style: { fontSize: 11, opacity: 0.8 }, children: [
3083
2388
  "Widget type: ",
3084
2389
  storedType
3085
2390
  ] }),
3086
- reason && /* @__PURE__ */ jsx16("div", { style: { fontSize: 11, opacity: 0.8, wordBreak: "break-word" }, children: reason.message })
2391
+ reason && /* @__PURE__ */ jsx11("div", { style: { fontSize: 11, opacity: 0.8, wordBreak: "break-word" }, children: reason.message })
3087
2392
  ]
3088
2393
  }
3089
2394
  ) });
3090
2395
  }
2396
+ function WidgetForbiddenFrame({ widget }) {
2397
+ return /* @__PURE__ */ jsx11(WidgetFrame8, { title: optString7(widget.options, "title"), children: /* @__PURE__ */ jsxs6("div", { role: "status", style: STATE_STYLE, children: [
2398
+ /* @__PURE__ */ jsx11("div", { style: { fontSize: 20, lineHeight: 1 }, "aria-hidden": "true", children: "\u2298" }),
2399
+ /* @__PURE__ */ jsx11("div", { style: { fontSize: 13, fontWeight: 600 }, children: accessStrings().forbidden })
2400
+ ] }) });
2401
+ }
3091
2402
  function WidgetUnavailableFrame({ widget }) {
3092
- return /* @__PURE__ */ jsx16(WidgetFrame13, { title: optString12(widget.options, "title"), children: /* @__PURE__ */ jsxs11(
2403
+ return /* @__PURE__ */ jsx11(WidgetFrame8, { title: optString7(widget.options, "title"), children: /* @__PURE__ */ jsxs6(
3093
2404
  "div",
3094
2405
  {
3095
- style: {
3096
- display: "flex",
3097
- flexDirection: "column",
3098
- alignItems: "center",
3099
- justifyContent: "center",
3100
- gap: 4,
3101
- width: "100%",
3102
- height: "100%",
3103
- padding: 12,
3104
- boxSizing: "border-box",
3105
- textAlign: "center",
3106
- color: "hsl(var(--muted-foreground))"
3107
- },
2406
+ style: STATE_STYLE,
3108
2407
  children: [
3109
- /* @__PURE__ */ jsx16("div", { style: { fontSize: 20, lineHeight: 1 }, "aria-hidden": "true", children: "\u2298" }),
3110
- /* @__PURE__ */ jsx16("div", { style: { fontSize: 13, fontWeight: 600 }, children: "Device unavailable" }),
3111
- /* @__PURE__ */ jsx16("div", { style: { fontSize: 11, opacity: 0.8 }, children: "The bound device no longer exists." })
2408
+ /* @__PURE__ */ jsx11("div", { style: { fontSize: 20, lineHeight: 1 }, "aria-hidden": "true", children: "\u2298" }),
2409
+ /* @__PURE__ */ jsx11("div", { style: { fontSize: 13, fontWeight: 600 }, children: "Device unavailable" }),
2410
+ /* @__PURE__ */ jsx11("div", { style: { fontSize: 11, opacity: 0.8 }, children: "The bound device no longer exists." })
2411
+ ]
2412
+ }
2413
+ ) });
2414
+ }
2415
+ function WidgetNotForCustomerUsersFrame({ widget }) {
2416
+ return /* @__PURE__ */ jsx11(WidgetFrame8, { title: optString7(widget.options, "title"), children: /* @__PURE__ */ jsxs6(
2417
+ "div",
2418
+ {
2419
+ role: "status",
2420
+ style: STATE_STYLE,
2421
+ children: [
2422
+ /* @__PURE__ */ jsx11("div", { style: { fontSize: 20, lineHeight: 1 }, "aria-hidden": "true", children: "\u2298" }),
2423
+ /* @__PURE__ */ jsx11("div", { style: { fontSize: 13, fontWeight: 600 }, children: "Not available for customer users" }),
2424
+ /* @__PURE__ */ jsx11("div", { style: { fontSize: 11, opacity: 0.8 }, children: "This widget is bound to an area or an asset, which customer users cannot view." })
3112
2425
  ]
3113
2426
  }
3114
2427
  ) });
3115
2428
  }
3116
2429
  function WidgetErrorFrame({ widget, error }) {
3117
- return /* @__PURE__ */ jsx16(WidgetFrame13, { title: optString12(widget.options, "title"), children: /* @__PURE__ */ jsxs11(
2430
+ if (isForbiddenError(error)) return /* @__PURE__ */ jsx11(WidgetForbiddenFrame, { widget });
2431
+ return /* @__PURE__ */ jsx11(WidgetFrame8, { title: optString7(widget.options, "title"), children: /* @__PURE__ */ jsxs6(
3118
2432
  "div",
3119
2433
  {
3120
- style: {
3121
- display: "flex",
3122
- flexDirection: "column",
3123
- alignItems: "center",
3124
- justifyContent: "center",
3125
- gap: 4,
3126
- width: "100%",
3127
- height: "100%",
3128
- padding: 12,
3129
- boxSizing: "border-box",
3130
- textAlign: "center",
3131
- color: "hsl(var(--muted-foreground))"
3132
- },
2434
+ style: STATE_STYLE,
3133
2435
  children: [
3134
- /* @__PURE__ */ jsx16("div", { style: { fontSize: 20, lineHeight: 1 }, children: "\u26A0" }),
3135
- /* @__PURE__ */ jsx16("div", { style: { fontSize: 13, fontWeight: 600 }, children: "Data unavailable" }),
3136
- /* @__PURE__ */ jsx16("div", { style: { fontSize: 11, opacity: 0.8, wordBreak: "break-word" }, children: String(error) })
2436
+ /* @__PURE__ */ jsx11("div", { style: { fontSize: 20, lineHeight: 1 }, children: "\u26A0" }),
2437
+ /* @__PURE__ */ jsx11("div", { style: { fontSize: 13, fontWeight: 600 }, children: "Data unavailable" }),
2438
+ /* @__PURE__ */ jsx11("div", { style: { fontSize: 11, opacity: 0.8, wordBreak: "break-word" }, children: String(error) })
3137
2439
  ]
3138
2440
  }
3139
2441
  ) });
@@ -3147,7 +2449,7 @@ import {
3147
2449
  WidgetThemeRootProvider,
3148
2450
  WidgetTimeZoneProvider
3149
2451
  } from "@devicechain/widget-sdk";
3150
- import { Fragment as Fragment6, jsx as jsx17, jsxs as jsxs12 } from "react/jsx-runtime";
2452
+ import { Fragment as Fragment2, jsx as jsx12, jsxs as jsxs7 } from "react/jsx-runtime";
3151
2453
  function DashboardRenderer({
3152
2454
  definition,
3153
2455
  hub,
@@ -3163,14 +2465,14 @@ function DashboardRenderer({
3163
2465
  density,
3164
2466
  timeRange
3165
2467
  }) {
3166
- const widgets = useMemo6(() => resolveWidgets(definition.widgets, bindings), [definition.widgets, bindings]);
2468
+ const widgets = useMemo5(() => resolveWidgets(definition.widgets, bindings), [definition.widgets, bindings]);
3167
2469
  const registry = registryProp ?? defaultWidgetRegistry();
3168
2470
  const defaultSeconds = definition.timeRange?.defaultSeconds;
3169
- const range = useMemo6(
2471
+ const range = useMemo5(
3170
2472
  () => timeRange ?? initialTimeRange(defaultSeconds),
3171
2473
  [timeRange, defaultSeconds]
3172
2474
  );
3173
- const histories = useWidgetHistories(widgets, seedHistory, registry, range);
2475
+ const { histories, reseed } = useWidgetHistories(widgets, seedHistory, registry, range);
3174
2476
  const { grid, background: bg, frame: canvasFrame } = definition.canvas;
3175
2477
  const effectiveSizing = sizing ?? definition.canvas.sizing;
3176
2478
  const effectiveDensity = density ?? definition.canvas.density ?? DEFAULT_CANVAS_DENSITY;
@@ -3178,7 +2480,7 @@ function DashboardRenderer({
3178
2480
  const { canvas } = definition;
3179
2481
  const shapeKey = useCallback2((width) => JSON.stringify(layoutShape(canvas, width, scale)), [canvas, scale]);
3180
2482
  const [boardRef, containerWidth] = useContainerWidth(shapeKey);
3181
- const layout = useMemo6(
2483
+ const layout = useMemo5(
3182
2484
  () => effectiveLayout(definition, containerWidth, {
3183
2485
  scale,
3184
2486
  limitsOf: (w) => w.type === UNKNOWN_WIDGET_TYPE2 ? void 0 : spanLimitsOfLayout(registry.descriptor(w.type)?.layout)
@@ -3187,7 +2489,7 @@ function DashboardRenderer({
3187
2489
  );
3188
2490
  const { breakpoint, columns } = layout;
3189
2491
  const lengths = gridCss(grid, columns);
3190
- return /* @__PURE__ */ jsxs12(
2492
+ return /* @__PURE__ */ jsxs7(
3191
2493
  "div",
3192
2494
  {
3193
2495
  ref: boardRef,
@@ -3196,8 +2498,8 @@ function DashboardRenderer({
3196
2498
  "data-time-paused": range.paused ? "" : void 0,
3197
2499
  style: { ...sizingStyle(effectiveSizing, bg), ...tokenStyle(scale) },
3198
2500
  children: [
3199
- /* @__PURE__ */ jsx17(WidgetTokenStyles, {}),
3200
- /* @__PURE__ */ jsx17(WidgetDensityProvider, { scale, children: /* @__PURE__ */ jsx17(WidgetThemeRootProvider, { root: themeRoot, children: /* @__PURE__ */ jsx17(WidgetTimeZoneProvider, { timeZone, children: /* @__PURE__ */ jsx17(WidgetTimeRangeProvider, { range, children: /* @__PURE__ */ jsx17(WidgetSelectProvider2, { select, children: /* @__PURE__ */ jsx17(WidgetCandidatesProvider2, { candidates, children: /* @__PURE__ */ jsx17("div", { style: { padding: lengths.padding }, children: /* @__PURE__ */ jsx17("div", { style: { containerType: "inline-size" }, children: /* @__PURE__ */ jsx17(
2501
+ /* @__PURE__ */ jsx12(WidgetTokenStyles, {}),
2502
+ /* @__PURE__ */ jsx12(WidgetDensityProvider, { scale, children: /* @__PURE__ */ jsx12(WidgetThemeRootProvider, { root: themeRoot, children: /* @__PURE__ */ jsx12(WidgetTimeZoneProvider, { timeZone, children: /* @__PURE__ */ jsx12(WidgetTimeRangeProvider, { range, children: /* @__PURE__ */ jsx12(WidgetSelectProvider2, { select, children: /* @__PURE__ */ jsx12(WidgetCandidatesProvider2, { candidates, children: /* @__PURE__ */ jsx12("div", { style: { padding: lengths.padding }, children: /* @__PURE__ */ jsx12("div", { style: { containerType: "inline-size" }, children: /* @__PURE__ */ jsx12(
3201
2503
  "div",
3202
2504
  {
3203
2505
  "data-grid": "",
@@ -3210,7 +2512,7 @@ function DashboardRenderer({
3210
2512
  width: "100%",
3211
2513
  ...{ "--dc-cell": lengths.cell }
3212
2514
  },
3213
- children: /* @__PURE__ */ jsx17(
2515
+ children: /* @__PURE__ */ jsx12(
3214
2516
  PlacedWidgets,
3215
2517
  {
3216
2518
  widgets,
@@ -3218,14 +2520,16 @@ function DashboardRenderer({
3218
2520
  columns,
3219
2521
  grid: layout.grid,
3220
2522
  lengths,
3221
- render: (widget) => /* @__PURE__ */ jsx17(WidgetFrameStyleProvider, { frame: resolveFrame(canvasFrame, widgetFrame(widget)), children: /* @__PURE__ */ jsx17(WidgetSubjectProvider, { label: widgetSubjectLabel(widget), children: /* @__PURE__ */ jsx17(
2523
+ render: (widget) => /* @__PURE__ */ jsx12(WidgetFrameStyleProvider, { frame: resolveFrame(canvasFrame, widgetFrame(widget)), children: /* @__PURE__ */ jsx12(WidgetSubjectProvider, { label: widgetSubjectLabel(widget), children: /* @__PURE__ */ jsx12(
3222
2524
  ConnectedWidget,
3223
2525
  {
3224
2526
  widget,
3225
2527
  hub,
3226
2528
  registry,
3227
2529
  actions,
3228
- initialSamples: histories[widget.id]
2530
+ initialSamples: histories[widget.id]?.samples,
2531
+ initialSamplesAsOf: histories[widget.id]?.asOf,
2532
+ onReconnect: () => reseed(widget.id)
3229
2533
  }
3230
2534
  ) }) })
3231
2535
  }
@@ -3299,20 +2603,20 @@ function PlacedWidgets({
3299
2603
  const relative = (host) => (dependents.get(host) ?? []).map(({ widget, placement }) => (
3300
2604
  // data-widget names the box a widget occupies, so a check over the rendered board (the
3301
2605
  // readability gate in apps/board-replay) can find it.
3302
- /* @__PURE__ */ jsxs12("div", { "data-widget": widget.id, "data-host": host, style: relativeBoxStyle(placement, lengths), children: [
2606
+ /* @__PURE__ */ jsxs7("div", { "data-widget": widget.id, "data-host": host, style: relativeBoxStyle(placement, lengths), children: [
3303
2607
  render(widget),
3304
2608
  relative(widget.id)
3305
2609
  ] }, widget.id)
3306
2610
  ));
3307
- return /* @__PURE__ */ jsx17(Fragment6, { children: placed.map(({ widget, placement }) => {
2611
+ return /* @__PURE__ */ jsx12(Fragment2, { children: placed.map(({ widget, placement }) => {
3308
2612
  if (placement.mode !== "grid") return null;
3309
2613
  const style = gridItemStyle(grid.get(widget.id) ?? placement, columns);
3310
- return /* @__PURE__ */ jsxs12(Fragment5, { children: [
3311
- /* @__PURE__ */ jsx17("div", { "data-widget": widget.id, style, children: render(widget) }),
2614
+ return /* @__PURE__ */ jsxs7(Fragment, { children: [
2615
+ /* @__PURE__ */ jsx12("div", { "data-widget": widget.id, style, children: render(widget) }),
3312
2616
  dependents.has(widget.id) ? (
3313
2617
  // The host's area again, as a layer for its relative widgets to be positioned in.
3314
2618
  // It takes no pointer events itself, so the host underneath stays usable.
3315
- /* @__PURE__ */ jsx17("div", { style: { ...style, position: "relative", pointerEvents: "none", zIndex: RELATIVE_Z }, children: relative(widget.id) })
2619
+ /* @__PURE__ */ jsx12("div", { style: { ...style, position: "relative", pointerEvents: "none", zIndex: RELATIVE_Z }, children: relative(widget.id) })
3316
2620
  ) : null
3317
2621
  ] }, widget.id);
3318
2622
  }) });
@@ -3342,9 +2646,9 @@ function widgetSubjectLabel(widget) {
3342
2646
  return void 0;
3343
2647
  }
3344
2648
  function useContainerWidth(keyOf) {
3345
- const ref = useRef3(null);
3346
- const [width, setWidth] = useState8(0);
3347
- const keyOfRef = useRef3(keyOf);
2649
+ const ref = useRef2(null);
2650
+ const [width, setWidth] = useState6(0);
2651
+ const keyOfRef = useRef2(keyOf);
3348
2652
  const measure = useCallback2(() => {
3349
2653
  const el = ref.current;
3350
2654
  if (!el) return;
@@ -3364,6 +2668,7 @@ function useContainerWidth(keyOf) {
3364
2668
  }, [measure]);
3365
2669
  return [ref, width];
3366
2670
  }
2671
+ var RESEED_RETRY_MS = 3e4;
3367
2672
  function seedKey(widget, registry) {
3368
2673
  if (widget.type === UNKNOWN_WIDGET_TYPE2 || registry.descriptor(widget.type)?.channel !== "measurement") {
3369
2674
  return void 0;
@@ -3371,15 +2676,21 @@ function seedKey(widget, registry) {
3371
2676
  return JSON.stringify(widget.datasource ?? null);
3372
2677
  }
3373
2678
  function useWidgetHistories(widgets, enabled, registry, range) {
3374
- const [seeds, setSeeds] = useState8({});
3375
- const requested = useRef3({});
3376
- const mounted = useRef3(true);
3377
- useEffect5(() => {
2679
+ const [seeds, setSeeds] = useState6({});
2680
+ const requested = useRef2({});
2681
+ const reseeds = useRef2({});
2682
+ const [reseedTick, bumpReseeds] = useState6(0);
2683
+ const mounted = useRef2(true);
2684
+ useEffect4(() => {
3378
2685
  mounted.current = true;
3379
2686
  return () => {
3380
2687
  mounted.current = false;
3381
2688
  };
3382
2689
  }, []);
2690
+ const reseed = useCallback2((id) => {
2691
+ reseeds.current[id] = (reseeds.current[id] ?? 0) + 1;
2692
+ bumpReseeds((n) => n + 1);
2693
+ }, []);
3383
2694
  const wanted = widgets.flatMap((w) => {
3384
2695
  const key = seedKey(w, registry);
3385
2696
  if (key === void 0) return [];
@@ -3388,7 +2699,7 @@ function useWidgetHistories(widgets, enabled, registry, range) {
3388
2699
  return [[w.id, key, span]];
3389
2700
  });
3390
2701
  const wantedKey = JSON.stringify(wanted);
3391
- useEffect5(() => {
2702
+ useEffect4(() => {
3392
2703
  if (!enabled) {
3393
2704
  requested.current = {};
3394
2705
  setSeeds({});
@@ -3398,28 +2709,42 @@ function useWidgetHistories(widgets, enabled, registry, range) {
3398
2709
  const byId = new Map(widgets.map((w) => [w.id, w]));
3399
2710
  const next = {};
3400
2711
  for (const [id, key, span] of wanted) {
3401
- const asked = `${key}|${span ?? ""}`;
2712
+ const base = `${key}|${span ?? ""}|`;
2713
+ const n = reseeds.current[id] ?? 0;
2714
+ const asked = `${base}${range.paused && n ? "p" : n}`;
2715
+ const previous = requested.current[id];
2716
+ if (previous === asked || range.paused && previous?.startsWith(base)) {
2717
+ next[id] = previous;
2718
+ continue;
2719
+ }
3402
2720
  next[id] = asked;
3403
- if (requested.current[id] === asked) continue;
3404
2721
  const widget = byId.get(id);
3405
- if (!widget) continue;
3406
- const historyWindow = span === null ? defaultHistoryWindow() : historyWindowFor(span, range.paused && range.pausedAt !== void 0 ? range.pausedAt : now);
3407
- void fetchWidgetHistory(widget, historyWindow).then((samples) => {
3408
- if (!mounted.current || requested.current[id] !== asked) return;
3409
- setSeeds((prev) => ({ ...prev, [id]: { key, samples } }));
3410
- });
2722
+ if (widget?.datasource?.kind !== "device") continue;
2723
+ const end = range.paused && range.pausedAt !== void 0 ? range.pausedAt : now;
2724
+ const historyWindow = span === null ? defaultHistoryWindow() : historyWindowFor(span, end);
2725
+ const current = () => mounted.current && requested.current[id] === asked;
2726
+ void fetchWidgetHistory(widget, historyWindow, { rethrow: n > 0 }).then(
2727
+ (samples) => {
2728
+ if (!current()) return;
2729
+ setSeeds((prev) => ({ ...prev, [id]: { key, samples, asOf: end } }));
2730
+ },
2731
+ () => {
2732
+ setTimeout(() => current() && reseed(id), RESEED_RETRY_MS);
2733
+ }
2734
+ );
3411
2735
  }
3412
2736
  requested.current = next;
3413
- }, [wantedKey, enabled]);
3414
- return useMemo6(() => {
2737
+ }, [wantedKey, enabled, reseedTick, range.paused]);
2738
+ const histories = useMemo5(() => {
3415
2739
  const out = {};
3416
2740
  if (!enabled) return out;
3417
2741
  for (const w of widgets) {
3418
2742
  const seed = seeds[w.id];
3419
- out[w.id] = seed && seed.key === seedKey(w, registry) ? seed.samples : void 0;
2743
+ out[w.id] = seed && seed.key === seedKey(w, registry) ? seed : void 0;
3420
2744
  }
3421
2745
  return out;
3422
2746
  }, [widgets, seeds, enabled, registry]);
2747
+ return { histories, reseed };
3423
2748
  }
3424
2749
 
3425
2750
  // src/time-range-bar.tsx
@@ -3434,17 +2759,17 @@ import {
3434
2759
  spanLabel as spanLabel2,
3435
2760
  withSpan
3436
2761
  } from "@devicechain/dashboards";
3437
- import { useCallback as useCallback3, useEffect as useEffect6, useMemo as useMemo7, useRef as useRef4, useState as useState9 } from "react";
3438
- import { jsx as jsx18, jsxs as jsxs13 } from "react/jsx-runtime";
2762
+ import { useCallback as useCallback3, useEffect as useEffect5, useMemo as useMemo6, useRef as useRef3, useState as useState7 } from "react";
2763
+ import { jsx as jsx13, jsxs as jsxs8 } from "react/jsx-runtime";
3439
2764
  function useBoardTimeRange(defaultSeconds, link = {}) {
3440
- const [state, setState] = useState9(() => initialTimeRange2(defaultSeconds, link));
3441
- const lastDefault = useRef4(defaultSeconds);
3442
- useEffect6(() => {
2765
+ const [state, setState] = useState7(() => initialTimeRange2(defaultSeconds, link));
2766
+ const lastDefault = useRef3(defaultSeconds);
2767
+ useEffect5(() => {
3443
2768
  if (lastDefault.current === defaultSeconds) return;
3444
2769
  lastDefault.current = defaultSeconds;
3445
2770
  setState((s) => withSpan(s, isValidSpanSeconds2(defaultSeconds) ? defaultSeconds : DEFAULT_TIME_RANGE_SECONDS));
3446
2771
  }, [defaultSeconds]);
3447
- const controls = useMemo7(
2772
+ const controls = useMemo6(
3448
2773
  () => ({
3449
2774
  setSpan: (spanSeconds) => setState((s) => withSpan(s, spanSeconds)),
3450
2775
  pause: () => setState((s) => pauseRange(s, Date.now())),
@@ -3477,7 +2802,7 @@ function PausedIndicator({
3477
2802
  labels = DEFAULT_TIME_RANGE_LABELS
3478
2803
  }) {
3479
2804
  const time = pausedAt === void 0 ? void 0 : new Date(pausedAt).toLocaleTimeString();
3480
- return /* @__PURE__ */ jsxs13(
2805
+ return /* @__PURE__ */ jsxs8(
3481
2806
  "span",
3482
2807
  {
3483
2808
  role: "status",
@@ -3498,10 +2823,10 @@ function PausedIndicator({
3498
2823
  borderRadius: 4
3499
2824
  },
3500
2825
  children: [
3501
- /* @__PURE__ */ jsx18("span", { "aria-hidden": "true", children: "\u23F8" }),
2826
+ /* @__PURE__ */ jsx13("span", { "aria-hidden": "true", children: "\u23F8" }),
3502
2827
  labels.paused,
3503
- time ? /* @__PURE__ */ jsx18("span", { style: { fontWeight: 400, textTransform: "none" }, children: ` ${time}` }) : null,
3504
- /* @__PURE__ */ jsx18("span", { "data-time-range-actions-live": "", style: { fontWeight: 400, textTransform: "none" }, children: `\xB7 ${labels.actionsLive}` })
2828
+ time ? /* @__PURE__ */ jsx13("span", { style: { fontWeight: 400, textTransform: "none" }, children: ` ${time}` }) : null,
2829
+ /* @__PURE__ */ jsx13("span", { "data-time-range-actions-live": "", style: { fontWeight: 400, textTransform: "none" }, children: `\xB7 ${labels.actionsLive}` })
3505
2830
  ]
3506
2831
  }
3507
2832
  );
@@ -3513,7 +2838,7 @@ function TimeRangeBar({
3513
2838
  }) {
3514
2839
  const preset = presetIdOf(state.spanSeconds);
3515
2840
  const onPause = useCallback3(() => state.paused ? controls.resume() : controls.pause(), [state.paused, controls]);
3516
- return /* @__PURE__ */ jsxs13(
2841
+ return /* @__PURE__ */ jsxs8(
3517
2842
  "div",
3518
2843
  {
3519
2844
  "data-time-range-bar": "",
@@ -3521,8 +2846,8 @@ function TimeRangeBar({
3521
2846
  "aria-label": labels.range,
3522
2847
  style: { display: "inline-flex", alignItems: "center", gap: 6, flexWrap: "wrap" },
3523
2848
  children: [
3524
- preset === void 0 ? /* @__PURE__ */ jsx18("button", { type: "button", "aria-pressed": "true", "data-range": spanLabel2(state.spanSeconds), style: button(true), children: spanLabel2(state.spanSeconds) }) : null,
3525
- TIME_RANGE_PRESETS.map((p) => /* @__PURE__ */ jsx18(
2849
+ preset === void 0 ? /* @__PURE__ */ jsx13("button", { type: "button", "aria-pressed": "true", "data-range": spanLabel2(state.spanSeconds), style: button(true), children: spanLabel2(state.spanSeconds) }) : null,
2850
+ TIME_RANGE_PRESETS.map((p) => /* @__PURE__ */ jsx13(
3526
2851
  "button",
3527
2852
  {
3528
2853
  type: "button",
@@ -3534,13 +2859,23 @@ function TimeRangeBar({
3534
2859
  },
3535
2860
  p.id
3536
2861
  )),
3537
- /* @__PURE__ */ jsx18("button", { type: "button", "aria-pressed": state.paused, "data-time-range-pause": "", onClick: onPause, style: button(state.paused), children: state.paused ? labels.resume : labels.pause }),
3538
- state.paused ? /* @__PURE__ */ jsx18(PausedIndicator, { pausedAt: state.pausedAt, labels }) : null
2862
+ /* @__PURE__ */ jsx13("button", { type: "button", "aria-pressed": state.paused, "data-time-range-pause": "", onClick: onPause, style: button(state.paused), children: state.paused ? labels.resume : labels.pause }),
2863
+ state.paused ? /* @__PURE__ */ jsx13(PausedIndicator, { pausedAt: state.pausedAt, labels }) : null
3539
2864
  ]
3540
2865
  }
3541
2866
  );
3542
2867
  }
3543
2868
 
2869
+ // src/preload.ts
2870
+ async function preloadWidgets(registry, types) {
2871
+ const loads = [];
2872
+ for (const type of new Set(types)) {
2873
+ const preload = registry.implementation(type)?.component?.preload;
2874
+ if (typeof preload === "function") loads.push(preload().catch(() => void 0));
2875
+ }
2876
+ await Promise.all(loads);
2877
+ }
2878
+
3544
2879
  // src/registry.ts
3545
2880
  var entries = Object.entries(builtinWidgetDescriptors);
3546
2881
  var WIDGET_CHANNEL = Object.freeze(
@@ -3551,7 +2886,7 @@ var WIDGET_BINDS_DATASOURCE = Object.freeze(
3551
2886
  );
3552
2887
 
3553
2888
  // src/index.ts
3554
- import { pickSample as pickSample3, optBoolean as optBoolean5 } from "@devicechain/widget-sdk";
2889
+ import { pickSample as pickSample3, optBoolean as optBoolean3 } from "@devicechain/widget-sdk";
3555
2890
 
3556
2891
  // src/options.ts
3557
2892
  import {
@@ -3625,12 +2960,12 @@ function stripUnknownWidgetOptions(widget, catalog) {
3625
2960
 
3626
2961
  // src/index.ts
3627
2962
  import {
3628
- WidgetFrame as WidgetFrame14,
2963
+ WidgetFrame as WidgetFrame9,
3629
2964
  WidgetSubjectProvider as WidgetSubjectProvider2,
3630
2965
  WidgetSelectProvider as WidgetSelectProvider3,
3631
- useWidgetSelect as useWidgetSelect4,
2966
+ useWidgetSelect as useWidgetSelect2,
3632
2967
  WidgetTimeZoneProvider as WidgetTimeZoneProvider2,
3633
- useWidgetTimeZone as useWidgetTimeZone6,
2968
+ useWidgetTimeZone as useWidgetTimeZone3,
3634
2969
  WidgetThemeRootProvider as WidgetThemeRootProvider2,
3635
2970
  useWidgetThemeRoot,
3636
2971
  WidgetCandidatesProvider as WidgetCandidatesProvider3,
@@ -3638,8 +2973,8 @@ import {
3638
2973
  useFlashOnChange as useFlashOnChange3,
3639
2974
  flashTextStyle as flashTextStyle2,
3640
2975
  flashBackgroundStyle as flashBackgroundStyle2,
3641
- FlashValue as FlashValue3,
3642
- fitValueFont as fitValueFont3,
2976
+ FlashValue,
2977
+ fitValueFont as fitValueFont2,
3643
2978
  useMeasurementStream as useMeasurementStream2,
3644
2979
  useAlarmStream as useAlarmStream2,
3645
2980
  useCommandStream as useCommandStream2,
@@ -3650,8 +2985,8 @@ import {
3650
2985
  HubConnectionBadge,
3651
2986
  useResolvedBindings,
3652
2987
  useSlotCandidates,
3653
- useCandidates as useCandidates2,
3654
- css as css12
2988
+ useCandidates,
2989
+ css as css6
3655
2990
  } from "@devicechain/widget-sdk";
3656
2991
  import {
3657
2992
  EChart as EChart3,
@@ -3670,7 +3005,7 @@ export {
3670
3005
  DashboardRenderer,
3671
3006
  EChart3 as EChart,
3672
3007
  EntitySelector,
3673
- FlashValue3 as FlashValue,
3008
+ FlashValue,
3674
3009
  Gauge,
3675
3010
  HubConnectionBadge,
3676
3011
  Image,
@@ -3687,7 +3022,7 @@ export {
3687
3022
  WIDGET_CHANNEL,
3688
3023
  WIDGET_OPTIONS,
3689
3024
  WidgetCandidatesProvider3 as WidgetCandidatesProvider,
3690
- WidgetFrame14 as WidgetFrame,
3025
+ WidgetFrame9 as WidgetFrame,
3691
3026
  WidgetSelectProvider3 as WidgetSelectProvider,
3692
3027
  WidgetSubjectProvider2 as WidgetSubjectProvider,
3693
3028
  WidgetThemeRootProvider2 as WidgetThemeRootProvider,
@@ -3702,11 +3037,11 @@ export {
3702
3037
  commandStatusColor,
3703
3038
  commandStatusLabel,
3704
3039
  createBuiltinWidgetRegistry,
3705
- css12 as css,
3040
+ css6 as css,
3706
3041
  defaultValues,
3707
3042
  describePosition,
3708
3043
  enumOptionValues,
3709
- fitValueFont3 as fitValueFont,
3044
+ fitValueFont2 as fitValueFont,
3710
3045
  flashBackgroundStyle2 as flashBackgroundStyle,
3711
3046
  flashTextStyle2 as flashTextStyle,
3712
3047
  formatDegrees,
@@ -3716,10 +3051,11 @@ export {
3716
3051
  landStyleFrom,
3717
3052
  loadLandStyle,
3718
3053
  numberOptionSpec,
3719
- optBoolean5 as optBoolean,
3054
+ optBoolean3 as optBoolean,
3720
3055
  parseParameterSchema,
3721
3056
  pickSample3 as pickSample,
3722
3057
  placeable,
3058
+ preloadWidgets,
3723
3059
  projectToPanel,
3724
3060
  rasterStyleFor,
3725
3061
  resolveChartTheme,
@@ -3730,7 +3066,7 @@ export {
3730
3066
  stripUnknownOptions,
3731
3067
  useAlarmStream2 as useAlarmStream,
3732
3068
  useBoardTimeRange,
3733
- useCandidates2 as useCandidates,
3069
+ useCandidates,
3734
3070
  useChartTheme3 as useChartTheme,
3735
3071
  useCommandStream2 as useCommandStream,
3736
3072
  useDashboardHub,
@@ -3744,9 +3080,9 @@ export {
3744
3080
  useSlotCandidates,
3745
3081
  useTenantBasemap,
3746
3082
  useWidgetCandidates2 as useWidgetCandidates,
3747
- useWidgetSelect4 as useWidgetSelect,
3083
+ useWidgetSelect2 as useWidgetSelect,
3748
3084
  useWidgetThemeRoot,
3749
- useWidgetTimeZone6 as useWidgetTimeZone,
3085
+ useWidgetTimeZone3 as useWidgetTimeZone,
3750
3086
  validateDefinitionOptions,
3751
3087
  validateParams,
3752
3088
  validateWidgetOptions,