@camstack/addon-post-analysis 1.2.612 → 1.2.614

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 (16) hide show
  1. package/dist/{clip-model-registry-C7WMvftu.js → clip-model-registry-CM-m6e1l.js} +16 -1
  2. package/dist/{clip-model-registry-JH4cTI06.mjs → clip-model-registry-D6tdLEFB.mjs} +16 -1
  3. package/dist/embedding-encoder/index.js +1 -1
  4. package/dist/embedding-encoder/index.mjs +1 -1
  5. package/dist/pipeline-analytics/_stub.js +559 -1180
  6. package/dist/pipeline-analytics/{_virtual_mf-localSharedImportMap___mfe_internal__addon_pipeline_analytics_widgets-DQE_Wu6_.mjs → _virtual_mf-localSharedImportMap___mfe_internal__addon_pipeline_analytics_widgets-PyXxg2Wg.mjs} +3 -3
  7. package/dist/pipeline-analytics/{_virtual_mf___mfe_internal__addon_pipeline_analytics_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-7dLQKt_H.mjs → _virtual_mf___mfe_internal__addon_pipeline_analytics_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-mydSlNUz.mjs} +1 -1
  8. package/dist/pipeline-analytics/_virtual_mf___mfe_internal__addon_pipeline_analytics_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.js-BB2kgLY1.mjs +26 -0
  9. package/dist/pipeline-analytics/{_virtual_mf___mfe_internal__addon_pipeline_analytics_widgets__loadShare__react__loadShare__.js-C0AuF9av.mjs → _virtual_mf___mfe_internal__addon_pipeline_analytics_widgets__loadShare__react__loadShare__.js-Cx9AsA5q.mjs} +1 -1
  10. package/dist/pipeline-analytics/{_virtual_mf___mfe_internal__addon_pipeline_analytics_widgets__loadShare__react_mf_1_jsx_mf_2_runtime__loadShare__.js-Bm-iyjmq.mjs → _virtual_mf___mfe_internal__addon_pipeline_analytics_widgets__loadShare__react_mf_1_jsx_mf_2_runtime__loadShare__.js-CkwmHEi0.mjs} +8 -8
  11. package/dist/pipeline-analytics/{hostInit-Bl6Zvb1p.mjs → hostInit-RCMuxWxC.mjs} +3 -3
  12. package/dist/pipeline-analytics/index.js +643 -75
  13. package/dist/pipeline-analytics/index.mjs +642 -75
  14. package/dist/pipeline-analytics/remoteEntry.js +1 -1
  15. package/package.json +1 -1
  16. package/dist/pipeline-analytics/_virtual_mf___mfe_internal__addon_pipeline_analytics_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.js-DbUPeg6m.mjs +0 -26
@@ -1,13 +1,13 @@
1
- import { a as e, i as t, n, o as r, r as i, t as a } from "./_virtual_mf___mfe_internal__addon_pipeline_analytics_widgets__loadShare__react__loadShare__.js-C0AuF9av.mjs";
1
+ import { a as e, i as t, n, o as r, r as i, t as a } from "./_virtual_mf___mfe_internal__addon_pipeline_analytics_widgets__loadShare__react__loadShare__.js-Cx9AsA5q.mjs";
2
2
  import { t as o } from "./_virtual_mf___mfe_internal__addon_pipeline_analytics_widgets__loadShare___mf_0_tanstack_mf_1_react_mf_2_query__loadShare__.js-B3Wx5J80.mjs";
3
- import { a as s, c, i as l, n as u, o as d, r as f, s as p, t as m } from "./_virtual_mf___mfe_internal__addon_pipeline_analytics_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.js-DbUPeg6m.mjs";
4
- import { n as h, r as g, t as _ } from "./_virtual_mf___mfe_internal__addon_pipeline_analytics_widgets__loadShare__react_mf_1_jsx_mf_2_runtime__loadShare__.js-Bm-iyjmq.mjs";
5
- import { t as v } from "./_virtual_mf___mfe_internal__addon_pipeline_analytics_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-7dLQKt_H.mjs";
3
+ import { a as s, c, d as l, f as u, i as d, l as f, m as p, n as m, o as h, p as g, r as _, s as v, t as y, u as b } from "./_virtual_mf___mfe_internal__addon_pipeline_analytics_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.js-BB2kgLY1.mjs";
4
+ import { n as x, t as S } from "./_virtual_mf___mfe_internal__addon_pipeline_analytics_widgets__loadShare__react_mf_1_jsx_mf_2_runtime__loadShare__.js-CkwmHEi0.mjs";
5
+ import { t as C } from "./_virtual_mf___mfe_internal__addon_pipeline_analytics_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-mydSlNUz.mjs";
6
6
  //#region ../../node_modules/lucide-react/dist/esm/shared/src/utils/mergeClasses.js
7
- var y = (...e) => e.filter((e, t, n) => !!e && e.trim() !== "" && n.indexOf(e) === t).join(" ").trim(), b = (e) => e.replace(/([a-z0-9])([A-Z])/g, "$1-$2").toLowerCase(), x = (e) => e.replace(/^([A-Z])|[\s-_]+(\w)/g, (e, t, n) => n ? n.toUpperCase() : t.toLowerCase()), S = (e) => {
8
- let t = x(e);
7
+ var w = (...e) => e.filter((e, t, n) => !!e && e.trim() !== "" && n.indexOf(e) === t).join(" ").trim(), T = (e) => e.replace(/([a-z0-9])([A-Z])/g, "$1-$2").toLowerCase(), E = (e) => e.replace(/^([A-Z])|[\s-_]+(\w)/g, (e, t, n) => n ? n.toUpperCase() : t.toLowerCase()), D = (e) => {
8
+ let t = E(e);
9
9
  return t.charAt(0).toUpperCase() + t.slice(1);
10
- }, C = {
10
+ }, O = {
11
11
  xmlns: "http://www.w3.org/2000/svg",
12
12
  width: 24,
13
13
  height: 24,
@@ -17,31 +17,31 @@ var y = (...e) => e.filter((e, t, n) => !!e && e.trim() !== "" && n.indexOf(e) =
17
17
  strokeWidth: 2,
18
18
  strokeLinecap: "round",
19
19
  strokeLinejoin: "round"
20
- }, w = (e) => {
20
+ }, k = (e) => {
21
21
  for (let t in e) if (t.startsWith("aria-") || t === "role" || t === "title") return !0;
22
22
  return !1;
23
- }, T = n(({ color: e = "currentColor", size: t = 24, strokeWidth: n = 2, absoluteStrokeWidth: r, className: i = "", children: o, iconNode: s, ...c }, l) => a("svg", {
23
+ }, A = n(({ color: e = "currentColor", size: t = 24, strokeWidth: n = 2, absoluteStrokeWidth: r, className: i = "", children: o, iconNode: s, ...c }, l) => a("svg", {
24
24
  ref: l,
25
- ...C,
25
+ ...O,
26
26
  width: t,
27
27
  height: t,
28
28
  stroke: e,
29
29
  strokeWidth: r ? Number(n) * 24 / Number(t) : n,
30
- className: y("lucide", i),
31
- ...!o && !w(c) && { "aria-hidden": "true" },
30
+ className: w("lucide", i),
31
+ ...!o && !k(c) && { "aria-hidden": "true" },
32
32
  ...c
33
- }, [...s.map(([e, t]) => a(e, t)), ...Array.isArray(o) ? o : [o]])), E = (e, t) => {
34
- let r = n(({ className: n, ...r }, i) => a(T, {
33
+ }, [...s.map(([e, t]) => a(e, t)), ...Array.isArray(o) ? o : [o]])), j = (e, t) => {
34
+ let r = n(({ className: n, ...r }, i) => a(A, {
35
35
  ref: i,
36
36
  iconNode: t,
37
- className: y(`lucide-${b(S(e))}`, `lucide-${e}`, n),
37
+ className: w(`lucide-${T(D(e))}`, `lucide-${e}`, n),
38
38
  ...r
39
39
  }));
40
- return r.displayName = S(e), r;
41
- }, D = E("activity", [["path", {
40
+ return r.displayName = D(e), r;
41
+ }, M = j("activity", [["path", {
42
42
  d: "M22 12h-2.48a2 2 0 0 0-1.93 1.46l-2.35 8.36a.25.25 0 0 1-.48 0L9.24 2.18a.25.25 0 0 0-.48 0l-2.35 8.36A2 2 0 0 1 4.49 12H2",
43
43
  key: "169zse"
44
- }]]), O = E("boxes", [
44
+ }]]), N = j("boxes", [
45
45
  ["path", {
46
46
  d: "M2.97 12.92A2 2 0 0 0 2 14.63v3.24a2 2 0 0 0 .97 1.71l3 1.8a2 2 0 0 0 2.06 0L12 19v-5.5l-5-3-4.03 2.42Z",
47
47
  key: "lc1i9w"
@@ -90,7 +90,7 @@ var y = (...e) => e.filter((e, t, n) => !!e && e.trim() !== "" && n.indexOf(e) =
90
90
  d: "M12 13.5V8",
91
91
  key: "1io7kd"
92
92
  }]
93
- ]), k = E("eye", [["path", {
93
+ ]), ee = j("eye", [["path", {
94
94
  d: "M2.062 12.348a1 1 0 0 1 0-.696 10.75 10.75 0 0 1 19.876 0 1 1 0 0 1 0 .696 10.75 10.75 0 0 1-19.876 0",
95
95
  key: "1nclc0"
96
96
  }], ["circle", {
@@ -98,7 +98,7 @@ var y = (...e) => e.filter((e, t, n) => !!e && e.trim() !== "" && n.indexOf(e) =
98
98
  cy: "12",
99
99
  r: "3",
100
100
  key: "1v7zrd"
101
- }]]), A = E("layers", [
101
+ }]]), P = j("layers", [
102
102
  ["path", {
103
103
  d: "M12.83 2.18a2 2 0 0 0-1.66 0L2.6 6.08a1 1 0 0 0 0 1.83l8.58 3.91a2 2 0 0 0 1.66 0l8.58-3.9a1 1 0 0 0 0-1.83z",
104
104
  key: "zw3jo"
@@ -111,7 +111,7 @@ var y = (...e) => e.filter((e, t, n) => !!e && e.trim() !== "" && n.indexOf(e) =
111
111
  d: "M2 17a1 1 0 0 0 .58.91l8.6 3.91a2 2 0 0 0 1.65 0l8.58-3.9A1 1 0 0 0 22 17",
112
112
  key: "kqbvx6"
113
113
  }]
114
- ]), j = E("map-pin-off", [
114
+ ]), te = j("map-pin-off", [
115
115
  ["path", {
116
116
  d: "M12.75 7.09a3 3 0 0 1 2.16 2.16",
117
117
  key: "1d4wjd"
@@ -132,7 +132,7 @@ var y = (...e) => e.filter((e, t, n) => !!e && e.trim() !== "" && n.indexOf(e) =
132
132
  d: "M9.13 9.13a3 3 0 0 0 3.74 3.74",
133
133
  key: "13wojd"
134
134
  }]
135
- ]), M = E("mic-off", [
135
+ ]), ne = j("mic-off", [
136
136
  ["path", {
137
137
  d: "M12 19v3",
138
138
  key: "npa21l"
@@ -157,7 +157,7 @@ var y = (...e) => e.filter((e, t, n) => !!e && e.trim() !== "" && n.indexOf(e) =
157
157
  d: "M9 9v3a3 3 0 0 0 5.12 2.12",
158
158
  key: "r2i35w"
159
159
  }]
160
- ]), N = E("mic", [
160
+ ]), re = j("mic", [
161
161
  ["path", {
162
162
  d: "M12 19v3",
163
163
  key: "npa21l"
@@ -174,14 +174,15 @@ var y = (...e) => e.filter((e, t, n) => !!e && e.trim() !== "" && n.indexOf(e) =
174
174
  rx: "3",
175
175
  key: "s6n7sd"
176
176
  }]
177
- ]), { useT: P } = c("pipeline-analytics", {
177
+ ]), { useT: F } = g("pipeline-analytics", {
178
178
  en: {
179
179
  missingDevice: "{{name}} requires a deviceId",
180
180
  common: {
181
181
  loading: "Loading…",
182
182
  resolving: "Resolving device…",
183
183
  justNow: "just now",
184
- secondsAgo: "{{seconds}}s ago"
184
+ secondsAgo: "{{seconds}}s ago",
185
+ timeWindow: "Time window"
185
186
  },
186
187
  audioMetrics: {
187
188
  title: "Audio Metrics",
@@ -210,51 +211,45 @@ var y = (...e) => e.filter((e, t, n) => !!e && e.trim() !== "" && n.indexOf(e) =
210
211
  audioHistory: {
211
212
  title: "Audio Level History",
212
213
  empty: "No audio history yet — analytics pipeline must be active.",
213
- ariaLabel: "Audio dBFS history",
214
214
  peakWindow: "peak (window)",
215
- avgWindow: "avg (window)",
216
215
  samples: "{{count}} samples · ~{{seconds}}s spacing",
217
- peak: "peak {{value}} dB"
216
+ peak: "peak {{value}} dB",
217
+ level: "Level",
218
+ lineTitle: "Level (dBFS)",
219
+ classHits: "Class hits: {{list}}"
218
220
  },
219
221
  occupancyHistory: {
220
222
  title: "Occupancy History",
221
223
  filterByClass: "Filter by detected class",
222
224
  allClasses: "All classes",
223
225
  empty: "No occupancy history yet — analytics pipeline must be active.",
224
- ariaLabel: "Frame occupancy history",
225
- objects_one: "{{count}} object",
226
- objects_other: "{{count}} objects",
227
- class: "Class",
228
- all: "all",
229
- bucket: "Bucket",
230
226
  buckets_one: "{{count}} bucket · 5 min resolution",
231
227
  buckets_other: "{{count}} buckets · 5 min resolution",
232
- peak: "peak {{value}} obj"
228
+ peak: "peak {{value}} obj",
229
+ lineTitle: "Objects in frame (bucket maximum)"
233
230
  },
234
231
  motionHistory: {
235
232
  title: "Motion History",
236
233
  empty: "No motion events in the selected window.",
237
- ariaLabel: "Motion event histogram",
238
234
  events_one: "{{count}} event",
239
235
  events_other: "{{count}} events",
240
- bucket: "Bucket",
241
- count: "Count",
242
236
  summary_one: "{{count}} event · {{bucket}} buckets",
243
237
  summary_other: "{{count}} events · {{bucket}} buckets",
244
- peak: "peak {{value}}/bucket"
238
+ peak: "peak {{value}}/bucket",
239
+ barsTitle: "Events per {{bucket}}"
245
240
  },
246
241
  detectionHistory: {
247
242
  title: "Detection History",
248
243
  filterByClass: "Filter by detected class",
249
244
  allClasses: "All classes",
250
245
  empty: "No detection events in the selected window.",
251
- ariaLabel: "Detection event histogram",
252
246
  detections_one: "{{count}} detection",
253
247
  detections_other: "{{count}} detections",
254
248
  other: "other",
255
249
  summary_one: "{{count}} detection · {{bucket}} buckets",
256
250
  summary_other: "{{count}} detections · {{bucket}} buckets",
257
- peak: "peak {{value}}/bucket"
251
+ peak: "peak {{value}}/bucket",
252
+ barsTitle: "Detections per {{bucket}}"
258
253
  }
259
254
  },
260
255
  it: {
@@ -263,7 +258,8 @@ var y = (...e) => e.filter((e, t, n) => !!e && e.trim() !== "" && n.indexOf(e) =
263
258
  loading: "Caricamento…",
264
259
  resolving: "Risoluzione del dispositivo…",
265
260
  justNow: "adesso",
266
- secondsAgo: "{{seconds}}s fa"
261
+ secondsAgo: "{{seconds}}s fa",
262
+ timeWindow: "Finestra temporale"
267
263
  },
268
264
  audioMetrics: {
269
265
  title: "Metriche audio",
@@ -292,170 +288,48 @@ var y = (...e) => e.filter((e, t, n) => !!e && e.trim() !== "" && n.indexOf(e) =
292
288
  audioHistory: {
293
289
  title: "Storico livello audio",
294
290
  empty: "Ancora nessuno storico audio: la pipeline di analisi deve essere attiva.",
295
- ariaLabel: "Storico dBFS audio",
296
291
  peakWindow: "picco (finestra)",
297
- avgWindow: "media (finestra)",
298
292
  samples: "{{count}} campioni · intervallo ~{{seconds}}s",
299
- peak: "picco {{value}} dB"
293
+ peak: "picco {{value}} dB",
294
+ level: "Livello",
295
+ lineTitle: "Livello (dBFS)",
296
+ classHits: "Classi rilevate: {{list}}"
300
297
  },
301
298
  occupancyHistory: {
302
299
  title: "Storico occupazione",
303
300
  filterByClass: "Filtra per classe rilevata",
304
301
  allClasses: "Tutte le classi",
305
302
  empty: "Ancora nessuno storico di occupazione: la pipeline di analisi deve essere attiva.",
306
- ariaLabel: "Storico occupazione del fotogramma",
307
- objects_one: "{{count}} oggetto",
308
- objects_other: "{{count}} oggetti",
309
- class: "Classe",
310
- all: "tutte",
311
- bucket: "Intervallo",
312
303
  buckets_one: "{{count}} intervallo · risoluzione 5 min",
313
304
  buckets_other: "{{count}} intervalli · risoluzione 5 min",
314
- peak: "picco {{value}} ogg."
305
+ peak: "picco {{value}} ogg.",
306
+ lineTitle: "Oggetti nell'inquadratura (massimo per intervallo)"
315
307
  },
316
308
  motionHistory: {
317
309
  title: "Storico movimento",
318
310
  empty: "Nessun evento di movimento nella finestra selezionata.",
319
- ariaLabel: "Istogramma degli eventi di movimento",
320
311
  events_one: "{{count}} evento",
321
312
  events_other: "{{count}} eventi",
322
- bucket: "Intervallo",
323
- count: "Conteggio",
324
313
  summary_one: "{{count}} evento · intervalli da {{bucket}}",
325
314
  summary_other: "{{count}} eventi · intervalli da {{bucket}}",
326
- peak: "picco {{value}}/intervallo"
315
+ peak: "picco {{value}}/intervallo",
316
+ barsTitle: "Eventi ogni {{bucket}}"
327
317
  },
328
318
  detectionHistory: {
329
319
  title: "Storico rilevamenti",
330
320
  filterByClass: "Filtra per classe rilevata",
331
321
  allClasses: "Tutte le classi",
332
322
  empty: "Nessun evento di rilevamento nella finestra selezionata.",
333
- ariaLabel: "Istogramma degli eventi di rilevamento",
334
323
  detections_one: "{{count}} rilevamento",
335
324
  detections_other: "{{count}} rilevamenti",
336
325
  other: "altro",
337
326
  summary_one: "{{count}} rilevamento · intervalli da {{bucket}}",
338
327
  summary_other: "{{count}} rilevamenti · intervalli da {{bucket}}",
339
- peak: "picco {{value}}/intervallo"
328
+ peak: "picco {{value}}/intervallo",
329
+ barsTitle: "Rilevamenti ogni {{bucket}}"
340
330
  }
341
331
  }
342
- });
343
- //#endregion
344
- //#region src/pipeline-analytics/widgets/chart-utils.tsx
345
- function F({ presets: e, value: t, onChange: n }) {
346
- return /* @__PURE__ */ h("div", {
347
- className: "flex items-center gap-1 border border-border rounded-md p-0.5 bg-background",
348
- children: e.map(({ id: e, label: r }) => /* @__PURE__ */ h("button", {
349
- type: "button",
350
- onClick: () => n(e),
351
- className: `px-2 py-0.5 rounded text-[10px] font-medium transition-colors ${t === e ? "bg-primary/10 text-primary" : "text-foreground-subtle hover:text-foreground"}`,
352
- children: r
353
- }, e))
354
- });
355
- }
356
- function I(t = 0) {
357
- let n = e(null), [a, o] = r(0);
358
- return i(() => {
359
- let e = n.current;
360
- if (!e) return;
361
- let r = (e) => o(Math.max(t, Math.floor(e)));
362
- r(e.clientWidth);
363
- let i = new ResizeObserver((e) => {
364
- let t = e[0];
365
- t && r(t.contentRect.width);
366
- });
367
- return i.observe(e), () => i.disconnect();
368
- }, [t]), [n, a];
369
- }
370
- function L(e, t) {
371
- let n = new Date(e), r = String(n.getHours()).padStart(2, "0"), i = String(n.getMinutes()).padStart(2, "0");
372
- return t <= 1440 * 60 * 1e3 ? `${r}:${i}` : `${String(n.getDate()).padStart(2, "0")}/${String(n.getMonth() + 1).padStart(2, "0")} ${r}:${i}`;
373
- }
374
- function ee(e, t, n, r, i) {
375
- if (t <= 1) return r;
376
- let a = n - r - i;
377
- return r + e / (t - 1) * a;
378
- }
379
- function te(e, t, n, r, i, a) {
380
- if (t <= e) return [];
381
- let o = t - e, s = [], c = n - r - i;
382
- for (let t = 0; t < a; t++) {
383
- let n = t / Math.max(1, a - 1), i = e + o * n;
384
- s.push({
385
- x: r + n * c,
386
- label: L(i, o)
387
- });
388
- }
389
- return s;
390
- }
391
- var ne = [
392
- "#3b82f6",
393
- "#a855f7",
394
- "#10b981",
395
- "#f59e0b",
396
- "#ec4899",
397
- "#14b8a6",
398
- "#6366f1",
399
- "#ef4444"
400
- ];
401
- function re(e) {
402
- return ne[e % ne.length] ?? "#64748b";
403
- }
404
- function ie() {
405
- let [e, t] = r(null);
406
- return {
407
- state: e,
408
- bindHover: t
409
- };
410
- }
411
- function R({ state: e, containerWidth: t }) {
412
- if (!e) return null;
413
- let n = Math.max(114, t - 110 - 4), r = Math.max(114, Math.min(n, e.anchorX)), i = e.anchorX - r;
414
- return /* @__PURE__ */ g("div", {
415
- role: "tooltip",
416
- style: {
417
- position: "absolute",
418
- left: r,
419
- top: e.anchorY,
420
- transform: "translate(-50%, calc(-100% - 8px))",
421
- pointerEvents: "none"
422
- },
423
- className: "z-10 rounded-md border border-border bg-surface shadow-lg px-2.5 py-1.5 text-[10px] text-foreground min-w-[140px] max-w-[240px]",
424
- children: [
425
- /* @__PURE__ */ h("div", {
426
- className: "font-semibold mb-1 truncate",
427
- children: e.title
428
- }),
429
- /* @__PURE__ */ h("div", {
430
- className: "space-y-0.5",
431
- children: e.rows.map((e, t) => /* @__PURE__ */ g("div", {
432
- className: "flex items-center justify-between gap-2",
433
- children: [/* @__PURE__ */ g("span", {
434
- className: "flex items-center gap-1 text-foreground-subtle truncate",
435
- children: [e.colour && /* @__PURE__ */ h("span", {
436
- className: "inline-block h-1.5 w-1.5 rounded-sm flex-shrink-0",
437
- style: { backgroundColor: e.colour }
438
- }), /* @__PURE__ */ h("span", {
439
- className: "truncate",
440
- children: e.label
441
- })]
442
- }), /* @__PURE__ */ h("span", {
443
- className: "tabular-nums",
444
- children: e.value
445
- })]
446
- }, t))
447
- }),
448
- /* @__PURE__ */ h("span", {
449
- "aria-hidden": !0,
450
- style: { left: `calc(50% + ${i}px)` },
451
- className: "absolute -bottom-1 -translate-x-1/2 h-2 w-2 rotate-45 bg-surface border-r border-b border-border"
452
- })
453
- ]
454
- });
455
- }
456
- //#endregion
457
- //#region src/pipeline-analytics/widgets/AudioHistoryChart.tsx
458
- var z = {
332
+ }), I = {
459
333
  "5m": {
460
334
  label: "5 min",
461
335
  windowSec: 300,
@@ -474,410 +348,253 @@ var z = {
474
348
  sampleEveryMs: 6e4,
475
349
  pollIntervalMs: 3e5
476
350
  }
477
- }, ae = [
351
+ }, ie = [
478
352
  {
479
353
  id: "5m",
480
- label: z["5m"].label
354
+ label: I["5m"].label
481
355
  },
482
356
  {
483
357
  id: "1h",
484
- label: z["1h"].label
358
+ label: I["1h"].label
485
359
  },
486
360
  {
487
361
  id: "24h",
488
- label: z["24h"].label
362
+ label: I["24h"].label
489
363
  }
490
- ], B = 140, V = {
491
- top: 16,
492
- right: 12,
493
- bottom: 24,
494
- left: 38
495
- }, oe = {
496
- speech: "#3b82f6",
497
- music: "#a855f7",
498
- dog_bark: "#ec4899",
499
- glass_break: "#f43f5e",
500
- alarm: "#f59e0b",
501
- baby_cry: "#10b981"
502
- };
503
- function se(e) {
504
- return e ? oe[e.toLowerCase()] ?? "#6366f1" : "#71717a";
505
- }
506
- function ce({ deviceId: n }) {
507
- let { t: i } = P(), a = m(l().trpcClient, n), [s, c] = r("5m"), u = z[s], [d, f] = I(), p = ie(), v = e(null), y = (e) => {
508
- let t = v.current;
509
- if (!t) return e;
510
- let n = t.getBoundingClientRect();
511
- return n.width === 0 ? e : e / f * n.width;
512
- }, b = o({
364
+ ], ae = (e) => e in I, oe = 120, L = "dBFS";
365
+ function se({ deviceId: n }) {
366
+ let { t: i } = F(), a = t(), c = y(s().trpcClient, n), [u, d] = r("5m"), m = I[u], h = o({
513
367
  queryKey: [
514
368
  "audio-metrics",
515
369
  n,
516
370
  "history",
517
- s
371
+ u
518
372
  ],
519
- queryFn: async () => a ? await a.audioMetrics?.getHistory({
520
- windowSec: u.windowSec,
521
- sampleEveryMs: u.sampleEveryMs
373
+ queryFn: async () => c ? await c.audioMetrics?.getHistory({
374
+ windowSec: m.windowSec,
375
+ sampleEveryMs: m.sampleEveryMs
522
376
  }) ?? null : null,
523
- enabled: !!a,
524
- refetchInterval: u.pollIntervalMs,
525
- staleTime: Math.max(1e3, u.pollIntervalMs / 2)
526
- }), x = b.data, S = x?.points ?? [], C = t(() => pe(S), [S]), w = t(() => de(S, f, C), [
527
- S,
528
- f,
529
- C
530
- ]), T = t(() => fe(S, f, C), [
531
- S,
532
- f,
533
- C
534
- ]), E = t(() => me(C), [C]), O = t(() => he(S, f), [S, f]);
535
- return /* @__PURE__ */ g("div", {
536
- className: "rounded-lg border border-border bg-surface overflow-hidden",
537
- children: [/* @__PURE__ */ g("div", {
538
- className: "border-b border-border px-4 py-2 flex items-center justify-between gap-3",
539
- children: [/* @__PURE__ */ g("div", {
540
- className: "flex items-center gap-1.5",
541
- children: [/* @__PURE__ */ h(D, { className: "h-3.5 w-3.5 text-foreground-subtle" }), /* @__PURE__ */ h("h2", {
542
- className: "text-xs font-semibold text-foreground uppercase tracking-wider",
543
- children: i("audioHistory.title")
544
- })]
545
- }), /* @__PURE__ */ h(F, {
546
- presets: ae,
547
- value: s,
548
- onChange: c
549
- })]
550
- }), /* @__PURE__ */ g("div", {
551
- ref: d,
552
- className: "p-3 min-w-0 relative",
553
- children: [S.length === 0 ? /* @__PURE__ */ h("div", {
554
- className: "flex items-center justify-center h-32 text-[11px] text-foreground-subtle italic",
555
- children: b.isLoading ? i("common.loading") : i("audioHistory.empty")
556
- }) : f === 0 ? /* @__PURE__ */ h("div", { className: "h-32" }) : /* @__PURE__ */ g(_, { children: [/* @__PURE__ */ g("svg", {
557
- ref: v,
558
- role: "img",
559
- "aria-label": i("audioHistory.ariaLabel"),
560
- width: "100%",
561
- height: B,
562
- viewBox: `0 0 ${f} ${B}`,
563
- preserveAspectRatio: "none",
564
- className: "block",
565
- onMouseLeave: () => p.bindHover(null),
566
- children: [
567
- E.map(({ y: e, label: t }, n) => /* @__PURE__ */ g("g", { children: [/* @__PURE__ */ h("line", {
568
- x1: V.left,
569
- x2: f - V.right,
570
- y1: e,
571
- y2: e,
572
- stroke: "currentColor",
573
- strokeOpacity: .08,
574
- strokeWidth: .5
575
- }), /* @__PURE__ */ h("text", {
576
- x: V.left - 6,
577
- y: e + 3,
578
- textAnchor: "end",
579
- className: "text-[9px] fill-foreground-subtle",
580
- children: t
581
- })] }, `y-${n}`)),
582
- O.map(({ x: e, label: t }, n) => /* @__PURE__ */ h("text", {
583
- x: e,
584
- y: B - V.bottom + 12,
585
- textAnchor: "middle",
586
- className: "text-[9px] fill-foreground-subtle",
587
- children: t
588
- }, `x-${n}`)),
589
- T && /* @__PURE__ */ h("path", {
590
- d: T,
591
- fill: "none",
592
- stroke: "currentColor",
593
- strokeOpacity: .25,
594
- strokeWidth: 1,
595
- strokeDasharray: "3 2"
596
- }),
597
- w && /* @__PURE__ */ h("path", {
598
- d: w,
599
- fill: "none",
600
- stroke: "currentColor",
601
- className: "text-primary",
602
- strokeWidth: 1.5
603
- }),
604
- S.map((e, t) => e.topClass === null ? null : /* @__PURE__ */ h("circle", {
605
- cx: H(t, S.length, f),
606
- cy: le(e.dbfs, C),
607
- r: 3,
608
- fill: se(e.topClass),
609
- stroke: "#000",
610
- strokeOpacity: .3,
611
- strokeWidth: .5
612
- }, `dot-${t}`)),
613
- S.map((e, t) => {
614
- let n = H(t, S.length, f), r = le(e.dbfs, C), a = B - V.top - V.bottom, o = S.length > 1 ? (f - V.left - V.right) / (S.length - 1) : 24;
615
- return /* @__PURE__ */ h("rect", {
616
- x: n - o / 2,
617
- y: V.top,
618
- width: Math.max(2, o),
619
- height: a,
620
- fill: "transparent",
621
- onMouseEnter: () => {
622
- p.bindHover({
623
- anchorX: y(n),
624
- anchorY: r,
625
- title: `${ge(e.ts)} · ${e.dbfs?.toFixed(1) ?? "—"} dB`,
626
- rows: [
627
- {
628
- label: i("audioHistory.peakWindow"),
629
- value: `${e.peakDbfs.toFixed(1)} dB`
630
- },
631
- {
632
- label: i("audioHistory.avgWindow"),
633
- value: `${e.avgDbfs.toFixed(1)} dB`
634
- },
635
- ...e.topClass === null ? [] : [{
636
- label: e.topClass,
637
- value: e.topScore == null ? "—" : `${(e.topScore * 100).toFixed(0)}%`,
638
- colour: se(e.topClass)
639
- }]
640
- ]
641
- });
642
- }
643
- }, `hit-${t}`);
644
- })
645
- ]
646
- }), /* @__PURE__ */ h(R, {
647
- state: p.state,
648
- containerWidth: f
649
- })] }), S.length > 0 && /* @__PURE__ */ g("div", {
650
- className: "flex items-center justify-between text-[10px] text-foreground-subtle mt-1",
651
- children: [/* @__PURE__ */ h("span", { children: i("audioHistory.samples", {
652
- count: S.length,
653
- seconds: Math.round((x?.effectiveSampleEveryMs ?? u.sampleEveryMs) / 1e3)
654
- }) }), /* @__PURE__ */ h("span", { children: i("audioHistory.peak", { value: S.reduce((e, t) => Math.max(e, t.peakDbfs), -Infinity).toFixed(1) }) })]
655
- })]
656
- })]
377
+ enabled: !!c,
378
+ refetchInterval: m.pollIntervalMs,
379
+ staleTime: Math.max(1e3, m.pollIntervalMs / 2)
380
+ }), g = h.data, _ = e(() => g?.points ?? [], [g]), v = g?.effectiveSampleEveryMs ?? m.sampleEveryMs, b = h.dataUpdatedAt > 0 ? h.dataUpdatedAt : Date.now(), C = b - m.windowSec * 1e3, w = e(() => {
381
+ let e = p(v);
382
+ return [{
383
+ id: "level",
384
+ label: i("audioHistory.level"),
385
+ unit: L,
386
+ colorIndex: 0,
387
+ gapMs: e,
388
+ points: _.map((e) => ({
389
+ t: e.ts,
390
+ v: e.dbfs
391
+ }))
392
+ }, {
393
+ id: "peak",
394
+ label: i("audioHistory.peakWindow"),
395
+ unit: L,
396
+ colorIndex: 1,
397
+ gapMs: e,
398
+ points: _.map((e) => ({
399
+ t: e.ts,
400
+ v: e.peakDbfs
401
+ }))
402
+ }];
403
+ }, [
404
+ _,
405
+ v,
406
+ i
407
+ ]), T = e(() => {
408
+ let e = /* @__PURE__ */ new Map();
409
+ for (let t of _) t.topClass !== null && e.set(t.topClass, (e.get(t.topClass) ?? 0) + 1);
410
+ return [...e.entries()].toSorted(([, e], [, t]) => t - e);
411
+ }, [_]), E = _.reduce((e, t) => Math.max(e, t.peakDbfs), -Infinity);
412
+ return /* @__PURE__ */ S(f, {
413
+ headingId: a,
414
+ title: i("audioHistory.title"),
415
+ icon: M,
416
+ children: /* @__PURE__ */ S("div", {
417
+ className: "p-3 min-w-0",
418
+ children: /* @__PURE__ */ S(l, {
419
+ title: i("audioHistory.lineTitle"),
420
+ series: _.length === 0 ? [] : w,
421
+ range: {
422
+ from: C,
423
+ to: b
424
+ },
425
+ height: oe,
426
+ pending: h.isLoading,
427
+ emptyMessage: i("audioHistory.empty"),
428
+ windowToggle: {
429
+ options: ie,
430
+ value: u,
431
+ onChange: (e) => {
432
+ ae(e) && d(e);
433
+ },
434
+ ariaLabel: i("common.timeWindow")
435
+ },
436
+ footer: _.length > 0 ? /* @__PURE__ */ x("div", {
437
+ className: "space-y-0.5",
438
+ children: [/* @__PURE__ */ x("div", {
439
+ className: "flex items-center justify-between",
440
+ children: [/* @__PURE__ */ S("span", { children: i("audioHistory.samples", {
441
+ count: _.length,
442
+ seconds: Math.round(v / 1e3)
443
+ }) }), /* @__PURE__ */ S("span", { children: i("audioHistory.peak", { value: E.toFixed(1) }) })]
444
+ }), T.length > 0 && /* @__PURE__ */ S("div", { children: i("audioHistory.classHits", { list: T.map(([e, t]) => `${e} ×${String(t)}`).join(", ") }) })]
445
+ }) : void 0
446
+ })
447
+ })
657
448
  });
658
449
  }
659
- function H(e, t, n) {
660
- if (t <= 1) return V.left;
661
- let r = n - V.left - V.right;
662
- return V.left + e / (t - 1) * r;
663
- }
664
- function le(e, t) {
665
- return ue(e === null || !Number.isFinite(e) ? t.min : Math.max(t.min, Math.min(t.max, e)), t);
666
- }
667
- function ue(e, t) {
668
- let n = B - V.top - V.bottom, r = Math.max(1, t.max - t.min), i = (e - t.min) / r;
669
- return V.top + (1 - i) * n;
670
- }
671
- function de(e, t, n) {
672
- if (e.length === 0) return null;
673
- let r = [];
674
- for (let i = 0; i < e.length; i++) {
675
- let a = H(i, e.length, t), o = le(e[i].dbfs, n);
676
- r.push(`${i === 0 ? "M" : "L"} ${a.toFixed(1)} ${o.toFixed(1)}`);
677
- }
678
- return r.join(" ");
679
- }
680
- function fe(e, t, n) {
681
- if (e.length === 0) return null;
682
- let r = [];
683
- for (let i = 0; i < e.length; i++) {
684
- let a = H(i, e.length, t), o = ue(Math.max(n.min, Math.min(n.max, e[i].peakDbfs)), n);
685
- r.push(`${i === 0 ? "M" : "L"} ${a.toFixed(1)} ${o.toFixed(1)}`);
686
- }
687
- return r.join(" ");
688
- }
689
- function pe(e) {
690
- if (e.length === 0) return {
691
- min: -80,
692
- max: -40
693
- };
694
- let t = Infinity, n = -Infinity;
695
- for (let r of e) r.dbfs !== null && Number.isFinite(r.dbfs) && (t = Math.min(t, r.dbfs), n = Math.max(n, r.dbfs)), Number.isFinite(r.peakDbfs) && (t = Math.min(t, r.peakDbfs), n = Math.max(n, r.peakDbfs));
696
- if (!Number.isFinite(t) || !Number.isFinite(n)) return {
697
- min: -80,
698
- max: -40
699
- };
700
- let r = Math.max(-100, Math.floor(t - 1)), i = Math.min(0, Math.ceil(n));
701
- return i - r < 5 && (r = Math.max(-100, i - 5)), {
702
- min: r,
703
- max: i
704
- };
705
- }
706
- function me(e) {
707
- let t = [];
708
- for (let n = 0; n < 4; n++) {
709
- let r = n / 3, i = e.min + (e.max - e.min) * r;
710
- t.push({
711
- y: ue(i, e),
712
- label: `${Math.round(i)}`
713
- });
714
- }
715
- return t;
716
- }
717
- function he(e, t) {
718
- if (e.length === 0) return [];
719
- let n = e[0], r = e[e.length - 1], i = [], a = Math.min(5, e.length);
720
- for (let e = 0; e < a; e++) {
721
- let o = e / Math.max(1, a - 1), s = n.ts + (r.ts - n.ts) * o;
722
- i.push({
723
- x: V.left + o * (t - V.left - V.right),
724
- label: ge(s)
725
- });
726
- }
727
- return i;
728
- }
729
- function ge(e) {
730
- let t = new Date(e);
731
- return `${String(t.getHours()).padStart(2, "0")}:${String(t.getMinutes()).padStart(2, "0")}`;
732
- }
733
450
  //#endregion
734
451
  //#region src/pipeline-analytics/widgets/AudioMetricsPanel.tsx
735
- function _e(e) {
452
+ function R(e) {
736
453
  return !Number.isFinite(e) || e <= 0 ? 60 : Math.round(e > 600 ? e / 1e3 : e);
737
454
  }
738
- function ve({ dev: e, deviceId: t, title: n, variant: r = "full" }) {
739
- let { t: i } = P(), a = n ?? i("audioMetrics.title"), o = u(l().trpcClient, e === void 0 && t !== void 0 ? t : null, (e) => e.audioMetrics), s = f(e ? e.state.audioMetrics : void 0), c = e === void 0 ? o : s;
740
- return c ? /* @__PURE__ */ h(ye, {
455
+ function ce({ dev: e, deviceId: t, title: n, variant: r = "full" }) {
456
+ let { t: i } = F(), a = n ?? i("audioMetrics.title"), o = m(s().trpcClient, e === void 0 && t !== void 0 ? t : null, (e) => e.audioMetrics), c = _(e ? e.state.audioMetrics : void 0), l = e === void 0 ? o : c;
457
+ return l ? /* @__PURE__ */ S(z, {
741
458
  title: a,
742
459
  variant: r,
743
- ts: c.ts,
744
- children: /* @__PURE__ */ g("div", {
460
+ ts: l.ts,
461
+ children: /* @__PURE__ */ x("div", {
745
462
  className: r === "compact" ? "space-y-2" : "grid grid-cols-1 2xl:grid-cols-3 gap-3",
746
463
  children: [
747
- /* @__PURE__ */ h(xe, { snapshot: c }),
748
- /* @__PURE__ */ h(Se, { snapshot: c }),
749
- /* @__PURE__ */ h(Ce, { snapshot: c })
464
+ /* @__PURE__ */ S(ue, { snapshot: l }),
465
+ /* @__PURE__ */ S(de, { snapshot: l }),
466
+ /* @__PURE__ */ S(fe, { snapshot: l })
750
467
  ]
751
468
  })
752
- }) : /* @__PURE__ */ h(ye, {
469
+ }) : /* @__PURE__ */ S(z, {
753
470
  title: a,
754
471
  variant: r,
755
- children: /* @__PURE__ */ h(be, {
756
- icon: /* @__PURE__ */ h(M, { className: "h-5 w-5 mb-2 opacity-30" }),
472
+ children: /* @__PURE__ */ S(le, {
473
+ icon: /* @__PURE__ */ S(ne, { className: "h-5 w-5 mb-2 opacity-30" }),
757
474
  message: i(e || t !== void 0 ? "audioMetrics.noData" : "common.resolving")
758
475
  })
759
476
  });
760
477
  }
761
- function ye({ title: e, variant: t, ts: n, children: r }) {
762
- let { t: i } = P(), a = n ? Math.max(0, Math.floor((Date.now() - n) / 1e3)) : null;
763
- return /* @__PURE__ */ g("div", {
478
+ function z({ title: e, variant: t, ts: n, children: r }) {
479
+ let { t: i } = F(), a = n ? Math.max(0, Math.floor((Date.now() - n) / 1e3)) : null;
480
+ return /* @__PURE__ */ x("div", {
764
481
  className: t === "compact" ? "rounded-md border border-border/60 bg-surface/60 p-3" : "rounded-lg border border-border bg-surface overflow-hidden",
765
- children: [/* @__PURE__ */ g("div", {
482
+ children: [/* @__PURE__ */ x("div", {
766
483
  className: t === "compact" ? "flex items-center justify-between mb-2" : "border-b border-border px-4 py-2 flex items-center justify-between",
767
- children: [/* @__PURE__ */ h("h2", {
484
+ children: [/* @__PURE__ */ S("h2", {
768
485
  className: "text-xs font-semibold text-foreground uppercase tracking-wider",
769
486
  children: e
770
- }), a !== null && /* @__PURE__ */ h("span", {
487
+ }), a !== null && /* @__PURE__ */ S("span", {
771
488
  className: "text-[10px] text-foreground-subtle",
772
489
  children: a === 0 ? i("common.justNow") : i("common.secondsAgo", { seconds: a })
773
490
  })]
774
- }), /* @__PURE__ */ h("div", {
491
+ }), /* @__PURE__ */ S("div", {
775
492
  className: t === "compact" ? "" : "p-3",
776
493
  children: r
777
494
  })]
778
495
  });
779
496
  }
780
- function be({ icon: e, message: t }) {
781
- return /* @__PURE__ */ g("div", {
497
+ function le({ icon: e, message: t }) {
498
+ return /* @__PURE__ */ x("div", {
782
499
  className: "px-4 py-6 flex flex-col items-center text-center text-foreground-subtle",
783
- children: [e, /* @__PURE__ */ h("p", {
500
+ children: [e, /* @__PURE__ */ S("p", {
784
501
  className: "text-[11px]",
785
502
  children: t
786
503
  })]
787
504
  });
788
505
  }
789
- function xe({ snapshot: e }) {
790
- let { t } = P(), { dbfs: n } = e.level, r = Math.max(-80, Math.min(0, Number.isFinite(n) ? n : -80)), i = (r + 80) / 80 * 100, a = r > -10 ? "bg-danger" : r > -25 ? "bg-warning" : "bg-primary";
791
- return /* @__PURE__ */ g("div", {
506
+ function ue({ snapshot: e }) {
507
+ let { t } = F(), { dbfs: n } = e.level, r = Math.max(-80, Math.min(0, Number.isFinite(n) ? n : -80)), i = (r + 80) / 80 * 100, a = r > -10 ? "bg-danger" : r > -25 ? "bg-warning" : "bg-primary";
508
+ return /* @__PURE__ */ x("div", {
792
509
  className: "rounded-md border border-border/60 bg-background/40 px-3 py-2",
793
510
  children: [
794
- /* @__PURE__ */ g("div", {
511
+ /* @__PURE__ */ x("div", {
795
512
  className: "flex items-center gap-1.5 mb-1.5 text-[11px] uppercase tracking-wider text-foreground-subtle",
796
513
  children: [
797
- /* @__PURE__ */ h(D, { className: "h-3.5 w-3.5" }),
798
- /* @__PURE__ */ h("span", { children: t("audioMetrics.level") }),
799
- /* @__PURE__ */ h("span", {
514
+ /* @__PURE__ */ S(M, { className: "h-3.5 w-3.5" }),
515
+ /* @__PURE__ */ S("span", { children: t("audioMetrics.level") }),
516
+ /* @__PURE__ */ S("span", {
800
517
  className: "ml-auto text-base font-semibold text-foreground tabular-nums normal-case tracking-normal",
801
518
  children: Number.isFinite(n) ? `${n.toFixed(1)} dB` : t("audioMetrics.silent")
802
519
  })
803
520
  ]
804
521
  }),
805
- /* @__PURE__ */ h("div", {
522
+ /* @__PURE__ */ S("div", {
806
523
  className: "h-1.5 rounded-full bg-foreground-subtle/15 overflow-hidden",
807
- children: /* @__PURE__ */ h("div", {
524
+ children: /* @__PURE__ */ S("div", {
808
525
  className: `h-full ${a} transition-all`,
809
526
  style: { width: `${i}%` }
810
527
  })
811
528
  }),
812
- /* @__PURE__ */ g("div", {
529
+ /* @__PURE__ */ x("div", {
813
530
  className: "flex justify-between text-[9px] text-foreground-subtle mt-1 tabular-nums",
814
531
  children: [
815
- /* @__PURE__ */ h("span", { children: t("audioMetrics.peak", { value: Number.isFinite(e.peakDbfs) ? e.peakDbfs.toFixed(1) : "—" }) }),
816
- /* @__PURE__ */ h("span", { children: t("audioMetrics.avg", { value: e.avgDbfs.toFixed(1) }) }),
817
- /* @__PURE__ */ h("span", { children: t("audioMetrics.window", { seconds: _e(e.windowSec) }) })
532
+ /* @__PURE__ */ S("span", { children: t("audioMetrics.peak", { value: Number.isFinite(e.peakDbfs) ? e.peakDbfs.toFixed(1) : "—" }) }),
533
+ /* @__PURE__ */ S("span", { children: t("audioMetrics.avg", { value: e.avgDbfs.toFixed(1) }) }),
534
+ /* @__PURE__ */ S("span", { children: t("audioMetrics.window", { seconds: R(e.windowSec) }) })
818
535
  ]
819
536
  })
820
537
  ]
821
538
  });
822
539
  }
823
- function Se({ snapshot: e }) {
824
- let { t } = P(), { current: n } = e;
825
- return /* @__PURE__ */ g("div", {
540
+ function de({ snapshot: e }) {
541
+ let { t } = F(), { current: n } = e;
542
+ return /* @__PURE__ */ x("div", {
826
543
  className: "rounded-md border border-border/60 bg-background/40 px-3 py-2",
827
- children: [/* @__PURE__ */ g("div", {
544
+ children: [/* @__PURE__ */ x("div", {
828
545
  className: "flex items-center gap-1.5 mb-1.5 text-[11px] uppercase tracking-wider text-foreground-subtle",
829
- children: [/* @__PURE__ */ h(N, { className: "h-3.5 w-3.5" }), /* @__PURE__ */ h("span", { children: t("audioMetrics.now") })]
830
- }), n ? /* @__PURE__ */ g("div", {
546
+ children: [/* @__PURE__ */ S(re, { className: "h-3.5 w-3.5" }), /* @__PURE__ */ S("span", { children: t("audioMetrics.now") })]
547
+ }), n ? /* @__PURE__ */ x("div", {
831
548
  className: "flex flex-col gap-1",
832
- children: [/* @__PURE__ */ h("span", {
549
+ children: [/* @__PURE__ */ S("span", {
833
550
  className: "text-sm font-semibold text-foreground",
834
551
  children: n.className
835
- }), /* @__PURE__ */ h("span", {
552
+ }), /* @__PURE__ */ S("span", {
836
553
  className: "text-[10px] text-foreground-subtle tabular-nums",
837
554
  children: t("audioMetrics.scoreAgo", {
838
555
  score: (n.score * 100).toFixed(0),
839
556
  seconds: Math.max(0, Math.floor((Date.now() - n.timestamp) / 1e3))
840
557
  })
841
558
  })]
842
- }) : /* @__PURE__ */ h("span", {
559
+ }) : /* @__PURE__ */ S("span", {
843
560
  className: "text-[10px] text-foreground-subtle italic",
844
561
  children: t("audioMetrics.unclassified")
845
562
  })]
846
563
  });
847
564
  }
848
- function Ce({ snapshot: e }) {
849
- let { t } = P();
850
- return e.byClass.length === 0 ? /* @__PURE__ */ g("div", {
565
+ function fe({ snapshot: e }) {
566
+ let { t } = F();
567
+ return e.byClass.length === 0 ? /* @__PURE__ */ x("div", {
851
568
  className: "rounded-md border border-border/40 bg-background/20 px-3 py-2",
852
- children: [/* @__PURE__ */ g("div", {
569
+ children: [/* @__PURE__ */ x("div", {
853
570
  className: "flex items-center gap-1.5 mb-1.5 text-[11px] uppercase tracking-wider text-foreground-subtle",
854
- children: [/* @__PURE__ */ h(D, { className: "h-3.5 w-3.5" }), /* @__PURE__ */ h("span", { children: t("audioMetrics.last", { seconds: _e(e.windowSec) }) })]
855
- }), /* @__PURE__ */ h("span", {
571
+ children: [/* @__PURE__ */ S(M, { className: "h-3.5 w-3.5" }), /* @__PURE__ */ S("span", { children: t("audioMetrics.last", { seconds: R(e.windowSec) }) })]
572
+ }), /* @__PURE__ */ S("span", {
856
573
  className: "text-[10px] text-foreground-subtle italic",
857
574
  children: t("audioMetrics.noClassified")
858
575
  })]
859
- }) : /* @__PURE__ */ g("div", {
576
+ }) : /* @__PURE__ */ x("div", {
860
577
  className: "rounded-md border border-border/60 bg-background/40",
861
- children: [/* @__PURE__ */ g("div", {
578
+ children: [/* @__PURE__ */ x("div", {
862
579
  className: "px-3 py-1.5 border-b border-border/40 flex items-center gap-1.5 text-[11px] uppercase tracking-wider text-foreground-subtle",
863
580
  children: [
864
- /* @__PURE__ */ h(D, { className: "h-3.5 w-3.5" }),
865
- /* @__PURE__ */ h("span", { children: t("audioMetrics.last", { seconds: _e(e.windowSec) }) }),
866
- /* @__PURE__ */ h("span", {
581
+ /* @__PURE__ */ S(M, { className: "h-3.5 w-3.5" }),
582
+ /* @__PURE__ */ S("span", { children: t("audioMetrics.last", { seconds: R(e.windowSec) }) }),
583
+ /* @__PURE__ */ S("span", {
867
584
  className: "ml-auto text-[10px] normal-case tracking-normal",
868
585
  children: e.byClass.length
869
586
  })
870
587
  ]
871
- }), /* @__PURE__ */ h("div", {
588
+ }), /* @__PURE__ */ S("div", {
872
589
  className: "divide-y divide-border/30",
873
- children: e.byClass.slice(0, 8).map((e) => /* @__PURE__ */ g("div", {
590
+ children: e.byClass.slice(0, 8).map((e) => /* @__PURE__ */ x("div", {
874
591
  className: "px-3 py-1.5 flex items-center justify-between text-xs",
875
- children: [/* @__PURE__ */ h("span", {
592
+ children: [/* @__PURE__ */ S("span", {
876
593
  className: "font-medium text-foreground truncate",
877
594
  children: e.className
878
- }), /* @__PURE__ */ g("span", {
595
+ }), /* @__PURE__ */ x("span", {
879
596
  className: "flex items-center gap-2 tabular-nums text-foreground-subtle",
880
- children: [/* @__PURE__ */ h("span", { children: t("audioMetrics.hits", { count: e.hits }) }), /* @__PURE__ */ g("span", {
597
+ children: [/* @__PURE__ */ S("span", { children: t("audioMetrics.hits", { count: e.hits }) }), /* @__PURE__ */ x("span", {
881
598
  className: "rounded-full px-1.5 py-0.5 text-[10px] bg-primary/10 text-primary border border-primary/20",
882
599
  children: [(e.peakScore * 100).toFixed(0), "%"]
883
600
  })]
@@ -888,7 +605,7 @@ function Ce({ snapshot: e }) {
888
605
  }
889
606
  //#endregion
890
607
  //#region src/pipeline-analytics/widgets/OccupancyHistoryChart.tsx
891
- var we = 5 * 6e4, U = {
608
+ var B = 5 * 6e4, V = {
892
609
  "1h": {
893
610
  label: "1 h",
894
611
  windowMs: 60 * 6e4,
@@ -909,58 +626,48 @@ var we = 5 * 6e4, U = {
909
626
  windowMs: 10080 * 6e4,
910
627
  pollIntervalMs: 3e5
911
628
  }
912
- }, Te = [
629
+ }, pe = [
913
630
  {
914
631
  id: "1h",
915
- label: U["1h"].label
632
+ label: V["1h"].label
916
633
  },
917
634
  {
918
635
  id: "6h",
919
- label: U["6h"].label
636
+ label: V["6h"].label
920
637
  },
921
638
  {
922
639
  id: "24h",
923
- label: U["24h"].label
640
+ label: V["24h"].label
924
641
  },
925
642
  {
926
643
  id: "7d",
927
- label: U["7d"].label
644
+ label: V["7d"].label
928
645
  }
929
- ], W = 140, G = {
930
- top: 14,
931
- right: 12,
932
- bottom: 24,
933
- left: 32
934
- }, K = "__all__";
935
- function Ee({ deviceId: n }) {
936
- let { t: a } = P(), s = m(l().trpcClient, n), [c, u] = r("24h"), [d, p] = r(K), y = U[c], [b, x] = I(), S = ie(), C = e(null), w = (e) => {
937
- let t = C.current;
938
- if (!t) return e;
939
- let n = t.getBoundingClientRect();
940
- return n.width === 0 ? e : e / x * n.width;
941
- }, T = f(s?.state.zoneAnalytics), E = t(() => {
646
+ ], me = (e) => e in V, he = 120, H = "__all__";
647
+ function ge({ deviceId: n }) {
648
+ let { t: a } = F(), c = y(s().trpcClient, n), [u, d] = r("24h"), [m, h] = r(H), g = V[u], v = t(), w = _(c?.state.zoneAnalytics), T = e(() => {
942
649
  let e = /* @__PURE__ */ new Set();
943
- if (T?.frame.byClass) for (let t of Object.keys(T.frame.byClass)) e.add(t);
944
- if (T?.zones) for (let t of T.zones) for (let n of Object.keys(t.byClass)) e.add(n);
650
+ if (w?.frame.byClass) for (let t of Object.keys(w.frame.byClass)) e.add(t);
651
+ if (w?.zones) for (let t of w.zones) for (let n of Object.keys(t.byClass)) e.add(n);
945
652
  return [...e].toSorted();
946
- }, [T]);
653
+ }, [w]);
947
654
  i(() => {
948
- d !== K && !E.includes(d) && p(K);
949
- }, [d, E]);
950
- let D = o({
655
+ m !== H && !T.includes(m) && h(H);
656
+ }, [m, T]);
657
+ let E = o({
951
658
  queryKey: [
952
659
  "pipeline-analytics",
953
660
  n,
954
661
  "occupancyLts",
955
- c,
956
- d
662
+ u,
663
+ m
957
664
  ],
958
665
  queryFn: async () => {
959
- if (!s) return [];
960
- let e = Date.now(), t = Math.floor((e - y.windowMs) / we) * we;
961
- return (await s.pipelineAnalytics?.readLongTermSeries({
666
+ if (!c) return [];
667
+ let e = Date.now(), t = Math.floor((e - g.windowMs) / B) * B;
668
+ return (await c.pipelineAnalytics?.readLongTermSeries({
962
669
  series: "occupancy",
963
- scope: d === K ? v() : v(void 0, d),
670
+ scope: m === H ? C() : C(void 0, m),
964
671
  from: t,
965
672
  to: e
966
673
  }) ?? []).map((e) => ({
@@ -968,170 +675,102 @@ function Ee({ deviceId: n }) {
968
675
  count: e.max
969
676
  }));
970
677
  },
971
- enabled: !!s,
972
- refetchInterval: y.pollIntervalMs,
973
- staleTime: Math.max(1e3, y.pollIntervalMs / 2)
974
- }), O = D.data ?? [], k = D.dataUpdatedAt > 0 ? D.dataUpdatedAt : Date.now(), j = k - y.windowMs, M = t(() => {
975
- if (O.length === 0) return 1;
976
- let e = O.reduce((e, t) => Math.max(e, t.count), 0);
977
- return Math.max(1, Math.ceil(e * 1.15));
978
- }, [O]), N = t(() => Oe(O, x, M), [
979
- O,
980
- x,
981
- M
982
- ]), L = t(() => te(j, k, x, G.left, G.right, 5), [
983
- j,
984
- k,
985
- x
986
- ]), ne = t(() => ke(M), [M]);
987
- return /* @__PURE__ */ g("div", {
988
- className: "rounded-lg border border-border bg-surface overflow-hidden",
989
- children: [/* @__PURE__ */ g("div", {
990
- className: "border-b border-border px-4 py-2 flex items-center justify-between gap-3",
991
- children: [/* @__PURE__ */ g("div", {
992
- className: "flex items-center gap-1.5",
993
- children: [/* @__PURE__ */ h(A, { className: "h-3.5 w-3.5 text-foreground-subtle" }), /* @__PURE__ */ h("h2", {
994
- className: "text-xs font-semibold text-foreground uppercase tracking-wider",
995
- children: a("occupancyHistory.title")
996
- })]
997
- }), /* @__PURE__ */ g("div", {
998
- className: "flex items-center gap-2",
999
- children: [E.length > 0 && /* @__PURE__ */ g("select", {
1000
- value: d,
1001
- onChange: (e) => p(e.target.value),
1002
- className: "text-[10px] px-1.5 py-0.5 rounded border border-border bg-background text-foreground focus:outline-none focus:ring-1 focus:ring-primary/40",
1003
- title: a("occupancyHistory.filterByClass"),
1004
- children: [/* @__PURE__ */ h("option", {
1005
- value: K,
1006
- children: a("occupancyHistory.allClasses")
1007
- }), E.map((e) => /* @__PURE__ */ h("option", {
1008
- value: e,
1009
- children: e
1010
- }, e))]
1011
- }), /* @__PURE__ */ h(F, {
1012
- presets: Te,
1013
- value: c,
1014
- onChange: u
1015
- })]
1016
- })]
1017
- }), /* @__PURE__ */ g("div", {
1018
- ref: b,
1019
- className: "p-3 min-w-0 relative",
1020
- children: [O.length === 0 ? /* @__PURE__ */ h("div", {
1021
- className: "flex items-center justify-center h-32 text-[11px] text-foreground-subtle italic",
1022
- children: D.isLoading ? a("common.loading") : a("occupancyHistory.empty")
1023
- }) : x === 0 ? /* @__PURE__ */ h("div", { className: "h-32" }) : /* @__PURE__ */ g(_, { children: [/* @__PURE__ */ g("svg", {
1024
- ref: C,
1025
- role: "img",
1026
- "aria-label": a("occupancyHistory.ariaLabel"),
1027
- width: "100%",
1028
- height: W,
1029
- viewBox: `0 0 ${x} ${W}`,
1030
- preserveAspectRatio: "none",
1031
- className: "block",
1032
- onMouseLeave: () => S.bindHover(null),
1033
- children: [
1034
- ne.map(({ y: e, label: t }, n) => /* @__PURE__ */ g("g", { children: [/* @__PURE__ */ h("line", {
1035
- x1: G.left,
1036
- x2: x - G.right,
1037
- y1: e,
1038
- y2: e,
1039
- stroke: "currentColor",
1040
- strokeOpacity: .08,
1041
- strokeWidth: .5
1042
- }), /* @__PURE__ */ h("text", {
1043
- x: G.left - 6,
1044
- y: e + 3,
1045
- textAnchor: "end",
1046
- className: "text-[9px] fill-foreground-subtle",
1047
- children: t
1048
- })] }, `y-${n}`)),
1049
- L.map(({ x: e, label: t }, n) => /* @__PURE__ */ h("text", {
1050
- x: e,
1051
- y: W - G.bottom + 12,
1052
- textAnchor: "middle",
1053
- className: "text-[9px] fill-foreground-subtle",
1054
- children: t
1055
- }, `x-${n}`)),
1056
- N && /* @__PURE__ */ h("path", {
1057
- d: N,
1058
- fill: "none",
1059
- stroke: "currentColor",
1060
- className: "text-primary",
1061
- strokeWidth: 1.5
1062
- }),
1063
- O.map((e, t) => {
1064
- let n = ee(t, O.length, x, G.left, G.right), r = De(e.count, M), i = W - G.top - G.bottom, o = O.length > 1 ? (x - G.left - G.right) / (O.length - 1) : 24;
1065
- return /* @__PURE__ */ g("g", { children: [/* @__PURE__ */ h("circle", {
1066
- cx: n,
1067
- cy: r,
1068
- r: 2,
1069
- fill: "currentColor",
1070
- className: "text-primary"
1071
- }), /* @__PURE__ */ h("rect", {
1072
- x: n - o / 2,
1073
- y: G.top,
1074
- width: Math.max(2, o),
1075
- height: i,
1076
- fill: "transparent",
1077
- onMouseEnter: () => {
1078
- S.bindHover({
1079
- anchorX: w(n),
1080
- anchorY: r,
1081
- title: `${Ae(e.ts)} · ${a("occupancyHistory.objects", { count: e.count })}`,
1082
- rows: [{
1083
- label: a("occupancyHistory.class"),
1084
- value: d === K ? a("occupancyHistory.all") : d
1085
- }, {
1086
- label: a("occupancyHistory.bucket"),
1087
- value: "5 min"
1088
- }]
1089
- });
1090
- }
1091
- })] }, `${e.ts}-${t}`);
1092
- })
1093
- ]
1094
- }), /* @__PURE__ */ h(R, {
1095
- state: S.state,
1096
- containerWidth: x
1097
- })] }), O.length > 0 && /* @__PURE__ */ g("div", {
1098
- className: "flex items-center justify-between text-[10px] text-foreground-subtle mt-1",
1099
- children: [/* @__PURE__ */ h("span", { children: a("occupancyHistory.buckets", { count: O.length }) }), /* @__PURE__ */ h("span", { children: a("occupancyHistory.peak", { value: O.reduce((e, t) => Math.max(e, t.count), 0) }) })]
1100
- })]
1101
- })]
678
+ enabled: !!c,
679
+ refetchInterval: g.pollIntervalMs,
680
+ staleTime: Math.max(1e3, g.pollIntervalMs / 2)
681
+ }), D = E.data ?? [], O = E.dataUpdatedAt > 0 ? E.dataUpdatedAt : Date.now(), k = O - g.windowMs, A = e(() => [{
682
+ id: m,
683
+ label: m === H ? a("occupancyHistory.allClasses") : m,
684
+ unit: null,
685
+ colorIndex: 0,
686
+ interpolation: "step",
687
+ gapMs: p(B),
688
+ points: D.map((e) => ({
689
+ t: e.ts,
690
+ v: e.count
691
+ }))
692
+ }], [
693
+ D,
694
+ m,
695
+ a
696
+ ]), j = e(() => [{
697
+ value: H,
698
+ label: a("occupancyHistory.allClasses")
699
+ }, ...T.map((e) => ({
700
+ value: e,
701
+ label: e
702
+ }))], [T, a]);
703
+ return /* @__PURE__ */ S(f, {
704
+ headingId: v,
705
+ title: a("occupancyHistory.title"),
706
+ icon: P,
707
+ actions: T.length > 0 ? /* @__PURE__ */ S("div", {
708
+ className: "w-32",
709
+ children: /* @__PURE__ */ S(b, {
710
+ value: m,
711
+ onChange: (e) => h(e.target.value),
712
+ options: j,
713
+ "aria-label": a("occupancyHistory.filterByClass")
714
+ })
715
+ }) : void 0,
716
+ children: /* @__PURE__ */ S("div", {
717
+ className: "p-3 min-w-0",
718
+ children: /* @__PURE__ */ S(l, {
719
+ title: a("occupancyHistory.lineTitle"),
720
+ series: D.length === 0 ? [] : A,
721
+ range: {
722
+ from: k,
723
+ to: O
724
+ },
725
+ height: he,
726
+ pending: E.isLoading,
727
+ emptyMessage: a("occupancyHistory.empty"),
728
+ formatValue: (e) => String(Math.round(e)),
729
+ windowToggle: {
730
+ options: pe,
731
+ value: u,
732
+ onChange: (e) => {
733
+ me(e) && d(e);
734
+ },
735
+ ariaLabel: a("common.timeWindow")
736
+ },
737
+ footer: D.length > 0 ? /* @__PURE__ */ x("div", {
738
+ className: "flex items-center justify-between",
739
+ children: [/* @__PURE__ */ S("span", { children: a("occupancyHistory.buckets", { count: D.length }) }), /* @__PURE__ */ S("span", { children: a("occupancyHistory.peak", { value: D.reduce((e, t) => Math.max(e, t.count), 0) }) })]
740
+ }) : void 0
741
+ })
742
+ })
1102
743
  });
1103
744
  }
1104
- function De(e, t) {
1105
- let n = W - G.top - G.bottom, r = Math.min(1, e / t);
1106
- return G.top + (1 - r) * n;
1107
- }
1108
- function Oe(e, t, n) {
1109
- if (e.length === 0) return null;
1110
- let r = [];
1111
- for (let i = 0; i < e.length; i++) {
1112
- let a = ee(i, e.length, t, G.left, G.right), o = De(e[i].count, n);
1113
- r.push(`${i === 0 ? "M" : "L"} ${a.toFixed(1)} ${o.toFixed(1)}`);
745
+ //#endregion
746
+ //#region src/pipeline-analytics/widgets/chart-utils.tsx
747
+ function _e(e, t, n, r) {
748
+ if (n <= t || !(r > 0)) return [];
749
+ let i = Math.floor(t / r) * r, a = Math.floor(n / r) * r, o = /* @__PURE__ */ new Map();
750
+ for (let e = i; e <= a; e += r) o.set(e, 0);
751
+ for (let i of e) {
752
+ if (i < t || i > n) continue;
753
+ let e = Math.floor(i / r) * r;
754
+ o.set(e, (o.get(e) ?? 0) + 1);
1114
755
  }
1115
- return r.join(" ");
756
+ return [...o.entries()].toSorted(([e], [t]) => e - t).map(([e, t]) => ({
757
+ bucketStart: e,
758
+ count: t
759
+ }));
1116
760
  }
1117
- function ke(e) {
1118
- let t = [];
1119
- for (let n = 0; n < 4; n++) {
1120
- let r = n / 3, i = Math.round(e * r), a = W - G.top - G.bottom;
1121
- t.push({
1122
- y: G.top + (1 - r) * a,
1123
- label: `${i}`
1124
- });
1125
- }
1126
- return t;
761
+ function U(e, t) {
762
+ let n = (e) => {
763
+ let t = new Date(e);
764
+ return `${String(t.getHours()).padStart(2, "0")}:${String(t.getMinutes()).padStart(2, "0")}`;
765
+ };
766
+ return `${n(e)}–${n(t)}`;
1127
767
  }
1128
- function Ae(e) {
1129
- let t = new Date(e);
1130
- return `${String(t.getHours()).padStart(2, "0")}:${String(t.getMinutes()).padStart(2, "0")}`;
768
+ function W(e) {
769
+ return e >= 60 * 6e4 ? `${String(Math.round(e / 6e4 / 60))}h` : e >= 6e4 ? `${String(Math.round(e / 6e4))}m` : `${String(Math.round(e / 1e3))}s`;
1131
770
  }
1132
771
  //#endregion
1133
772
  //#region src/pipeline-analytics/widgets/MotionHistoryChart.tsx
1134
- var je = {
773
+ var G = {
1135
774
  "1h": {
1136
775
  label: "1 h",
1137
776
  windowMs: 60 * 6e4,
@@ -1150,208 +789,93 @@ var je = {
1150
789
  bucketMs: 15 * 6e4,
1151
790
  pollIntervalMs: 3e5
1152
791
  }
1153
- }, Me = [
792
+ }, ve = [
1154
793
  {
1155
794
  id: "1h",
1156
- label: je["1h"].label
795
+ label: G["1h"].label
1157
796
  },
1158
797
  {
1159
798
  id: "6h",
1160
- label: je["6h"].label
799
+ label: G["6h"].label
1161
800
  },
1162
801
  {
1163
802
  id: "24h",
1164
- label: je["24h"].label
803
+ label: G["24h"].label
1165
804
  }
1166
- ], Ne = 5e3, q = 140, J = {
1167
- top: 14,
1168
- right: 12,
1169
- bottom: 24,
1170
- left: 32
1171
- };
1172
- function Pe({ deviceId: n }) {
1173
- let { t: i } = P(), a = m(l().trpcClient, n), [s, c] = r("1h"), u = je[s], [d, f] = I(), p = ie(), v = e(null), y = (e) => {
1174
- let t = v.current;
1175
- if (!t) return e;
1176
- let n = t.getBoundingClientRect();
1177
- return n.width === 0 ? e : e / f * n.width;
1178
- }, b = o({
805
+ ], ye = (e) => e in G, be = 5e3, xe = 120;
806
+ function Se({ deviceId: n }) {
807
+ let { t: i } = F(), a = t(), c = y(s().trpcClient, n), [l, u] = r("1h"), d = G[l], p = o({
1179
808
  queryKey: [
1180
809
  "pipeline-analytics",
1181
810
  n,
1182
811
  "motionEvents",
1183
- s
812
+ l
1184
813
  ],
1185
814
  queryFn: async () => {
1186
- if (!a) return [];
1187
- let e = Date.now() - u.windowMs;
1188
- return await a.pipelineAnalytics?.getMotionEvents({
815
+ if (!c) return [];
816
+ let e = Date.now() - d.windowMs;
817
+ return await c.pipelineAnalytics?.getMotionEvents({
1189
818
  since: e,
1190
- limit: Ne
819
+ limit: be
1191
820
  }) ?? [];
1192
821
  },
1193
- enabled: !!a,
1194
- refetchInterval: u.pollIntervalMs,
1195
- staleTime: Math.max(1e3, u.pollIntervalMs / 2)
1196
- }), x = b.data ?? [], S = b.dataUpdatedAt > 0 ? b.dataUpdatedAt : Date.now(), C = S - u.windowMs, w = t(() => Fe(x, C, S, u.bucketMs), [
1197
- x,
1198
- C,
1199
- S,
1200
- u.bucketMs
1201
- ]), T = t(() => {
1202
- if (w.length === 0) return 1;
1203
- let e = w.reduce((e, t) => Math.max(e, t.count), 0);
1204
- return Math.max(1, Math.ceil(e * 1.15));
1205
- }, [w]), E = t(() => te(C, S, f, J.left, J.right, 5), [
1206
- C,
1207
- S,
1208
- f
1209
- ]), O = t(() => Le(T), [T]), k = x.length;
1210
- return /* @__PURE__ */ g("div", {
1211
- className: "rounded-lg border border-border bg-surface overflow-hidden",
1212
- children: [/* @__PURE__ */ g("div", {
1213
- className: "border-b border-border px-4 py-2 flex items-center justify-between gap-3",
1214
- children: [/* @__PURE__ */ g("div", {
1215
- className: "flex items-center gap-1.5",
1216
- children: [/* @__PURE__ */ h(D, { className: "h-3.5 w-3.5 text-foreground-subtle" }), /* @__PURE__ */ h("h2", {
1217
- className: "text-xs font-semibold text-foreground uppercase tracking-wider",
1218
- children: i("motionHistory.title")
1219
- })]
1220
- }), /* @__PURE__ */ h(F, {
1221
- presets: Me,
1222
- value: s,
1223
- onChange: c
1224
- })]
1225
- }), /* @__PURE__ */ g("div", {
1226
- ref: d,
1227
- className: "p-3 min-w-0 relative",
1228
- children: [k === 0 ? /* @__PURE__ */ h("div", {
1229
- className: "flex items-center justify-center h-32 text-[11px] text-foreground-subtle italic",
1230
- children: b.isLoading ? i("common.loading") : i("motionHistory.empty")
1231
- }) : f === 0 ? /* @__PURE__ */ h("div", { className: "h-32" }) : /* @__PURE__ */ g(_, { children: [/* @__PURE__ */ g("svg", {
1232
- ref: v,
1233
- role: "img",
1234
- "aria-label": i("motionHistory.ariaLabel"),
1235
- width: "100%",
1236
- height: q,
1237
- viewBox: `0 0 ${f} ${q}`,
1238
- preserveAspectRatio: "none",
1239
- className: "block",
1240
- onMouseLeave: () => p.bindHover(null),
1241
- children: [
1242
- O.map(({ y: e, label: t }, n) => /* @__PURE__ */ g("g", { children: [/* @__PURE__ */ h("line", {
1243
- x1: J.left,
1244
- x2: f - J.right,
1245
- y1: e,
1246
- y2: e,
1247
- stroke: "currentColor",
1248
- strokeOpacity: .08,
1249
- strokeWidth: .5
1250
- }), /* @__PURE__ */ h("text", {
1251
- x: J.left - 6,
1252
- y: e + 3,
1253
- textAnchor: "end",
1254
- className: "text-[9px] fill-foreground-subtle",
1255
- children: t
1256
- })] }, `y-${n}`)),
1257
- E.map(({ x: e, label: t }, n) => /* @__PURE__ */ h("text", {
1258
- x: e,
1259
- y: q - J.bottom + 12,
1260
- textAnchor: "middle",
1261
- className: "text-[9px] fill-foreground-subtle",
1262
- children: t
1263
- }, `x-${n}`)),
1264
- w.map((e, t) => {
1265
- let { x: n, w: r } = Ie(e.bucketStart, u.bucketMs, C, S, f), a = q - J.top - J.bottom, o = e.count / T * a, s = J.top + (a - o), c = e.bucketStart + u.bucketMs;
1266
- return /* @__PURE__ */ g("g", { children: [e.count > 0 && /* @__PURE__ */ h("rect", {
1267
- x: n,
1268
- y: s,
1269
- width: Math.max(1, r - 1),
1270
- height: Math.max(1, o),
1271
- fill: "currentColor",
1272
- className: "text-primary",
1273
- opacity: .85
1274
- }), /* @__PURE__ */ h("rect", {
1275
- x: n,
1276
- y: J.top,
1277
- width: Math.max(2, r),
1278
- height: a,
1279
- fill: "transparent",
1280
- onMouseEnter: () => {
1281
- p.bindHover({
1282
- anchorX: y(n + r / 2),
1283
- anchorY: s,
1284
- title: `${Re(e.bucketStart, c)} · ${i("motionHistory.events", { count: e.count })}`,
1285
- rows: [{
1286
- label: i("motionHistory.bucket"),
1287
- value: ze(u.bucketMs)
1288
- }, {
1289
- label: i("motionHistory.count"),
1290
- value: `${e.count}`
1291
- }]
1292
- });
1293
- }
1294
- })] }, `${e.bucketStart}-${t}`);
1295
- })
1296
- ]
1297
- }), /* @__PURE__ */ h(R, {
1298
- state: p.state,
1299
- containerWidth: f
1300
- })] }), k > 0 && /* @__PURE__ */ g("div", {
1301
- className: "flex items-center justify-between text-[10px] text-foreground-subtle mt-1",
1302
- children: [/* @__PURE__ */ h("span", { children: i("motionHistory.summary", {
1303
- count: k,
1304
- bucket: ze(u.bucketMs)
1305
- }) }), /* @__PURE__ */ h("span", { children: i("motionHistory.peak", { value: w.reduce((e, t) => Math.max(e, t.count), 0) }) })]
1306
- })]
1307
- })]
822
+ enabled: !!c,
823
+ refetchInterval: d.pollIntervalMs,
824
+ staleTime: Math.max(1e3, d.pollIntervalMs / 2)
825
+ }), m = p.data ?? [], h = p.dataUpdatedAt > 0 ? p.dataUpdatedAt : Date.now(), g = h - d.windowMs, _ = e(() => _e(m.map((e) => e.timestamp), g, h, d.bucketMs).map((e) => ({
826
+ t: e.bucketStart,
827
+ values: [e.count]
828
+ })), [
829
+ m,
830
+ g,
831
+ h,
832
+ d.bucketMs
833
+ ]), b = e(() => [{
834
+ id: "motion",
835
+ label: i("motionHistory.title"),
836
+ colorIndex: 0
837
+ }], [i]), C = _.reduce((e, t) => Math.max(e, t.values[0] ?? 0), 0), w = m.length, T = W(d.bucketMs);
838
+ return /* @__PURE__ */ S(f, {
839
+ headingId: a,
840
+ title: i("motionHistory.title"),
841
+ icon: M,
842
+ children: /* @__PURE__ */ S("div", {
843
+ className: "p-3 min-w-0",
844
+ children: /* @__PURE__ */ S(v, {
845
+ title: i("motionHistory.barsTitle", { bucket: T }),
846
+ layers: b,
847
+ buckets: w === 0 ? [] : _,
848
+ bucketMs: d.bucketMs,
849
+ range: {
850
+ from: g,
851
+ to: h
852
+ },
853
+ height: xe,
854
+ pending: p.isLoading,
855
+ emptyMessage: i("motionHistory.empty"),
856
+ windowToggle: {
857
+ options: ve,
858
+ value: l,
859
+ onChange: (e) => {
860
+ ye(e) && u(e);
861
+ },
862
+ ariaLabel: i("common.timeWindow")
863
+ },
864
+ bucketLabel: (e) => `${U(e.t, e.t + d.bucketMs)} · ${i("motionHistory.events", { count: e.values[0] ?? 0 })}`,
865
+ footer: w > 0 ? /* @__PURE__ */ x("div", {
866
+ className: "flex items-center justify-between",
867
+ children: [/* @__PURE__ */ S("span", { children: i("motionHistory.summary", {
868
+ count: w,
869
+ bucket: T
870
+ }) }), /* @__PURE__ */ S("span", { children: i("motionHistory.peak", { value: C }) })]
871
+ }) : void 0
872
+ })
873
+ })
1308
874
  });
1309
875
  }
1310
- function Fe(e, t, n, r) {
1311
- if (n <= t) return [];
1312
- let i = Math.floor(t / r) * r, a = Math.floor(n / r) * r, o = /* @__PURE__ */ new Map();
1313
- for (let e = i; e <= a; e += r) o.set(e, 0);
1314
- for (let i of e) {
1315
- if (i.timestamp < t || i.timestamp > n) continue;
1316
- let e = Math.floor(i.timestamp / r) * r;
1317
- o.set(e, (o.get(e) ?? 0) + 1);
1318
- }
1319
- return [...o.entries()].toSorted(([e], [t]) => e - t).map(([e, t]) => ({
1320
- bucketStart: e,
1321
- count: t
1322
- }));
1323
- }
1324
- function Ie(e, t, n, r, i) {
1325
- let a = Math.max(1, r - n), o = i - J.left - J.right;
1326
- return {
1327
- x: J.left + (e - n) / a * o,
1328
- w: t / a * o
1329
- };
1330
- }
1331
- function Le(e) {
1332
- let t = [];
1333
- for (let n = 0; n < 4; n++) {
1334
- let r = n / 3, i = Math.round(e * r), a = q - J.top - J.bottom;
1335
- t.push({
1336
- y: J.top + (1 - r) * a,
1337
- label: `${i}`
1338
- });
1339
- }
1340
- return t;
1341
- }
1342
- function Re(e, t) {
1343
- let n = (e) => {
1344
- let t = new Date(e);
1345
- return `${String(t.getHours()).padStart(2, "0")}:${String(t.getMinutes()).padStart(2, "0")}`;
1346
- };
1347
- return `${n(e)}–${n(t)}`;
1348
- }
1349
- function ze(e) {
1350
- return e >= 60 * 6e4 ? `${Math.round(e / 6e4 / 60)}h` : e >= 6e4 ? `${Math.round(e / 6e4)}m` : `${Math.round(e / 1e3)}s`;
1351
- }
1352
876
  //#endregion
1353
877
  //#region src/pipeline-analytics/widgets/DetectionHistoryChart.tsx
1354
- var Be = {
878
+ var K = {
1355
879
  "1h": {
1356
880
  label: "1 h",
1357
881
  windowMs: 60 * 6e4,
@@ -1370,415 +894,281 @@ var Be = {
1370
894
  bucketMs: 15 * 6e4,
1371
895
  pollIntervalMs: 3e5
1372
896
  }
1373
- }, Ve = [
897
+ }, Ce = [
1374
898
  {
1375
899
  id: "1h",
1376
- label: Be["1h"].label
900
+ label: K["1h"].label
1377
901
  },
1378
902
  {
1379
903
  id: "6h",
1380
- label: Be["6h"].label
904
+ label: K["6h"].label
1381
905
  },
1382
906
  {
1383
907
  id: "24h",
1384
- label: Be["24h"].label
908
+ label: K["24h"].label
1385
909
  }
1386
- ], He = 5e3, Ue = 4, Y = "__other__", X = "__all__", Z = 160, Q = {
1387
- top: 14,
1388
- right: 12,
1389
- bottom: 24,
1390
- left: 32
1391
- };
1392
- function We({ deviceId: n }) {
1393
- let { t: a } = P(), s = m(l().trpcClient, n), [c, u] = r("1h"), [d, f] = r(X), p = Be[c], [v, y] = I(), b = ie(), x = e(null), S = o({
910
+ ], we = (e) => e in K, Te = 5e3, Ee = 4, q = "__other__", J = "__all__", De = 140;
911
+ function Oe({ deviceId: n }) {
912
+ let { t: a } = F(), c = t(), l = y(s().trpcClient, n), [u, d] = r("1h"), [p, m] = r(J), h = K[u], g = o({
1394
913
  queryKey: [
1395
914
  "pipeline-analytics",
1396
915
  n,
1397
916
  "objectEvents",
1398
- c
917
+ u
1399
918
  ],
1400
919
  queryFn: async () => {
1401
- if (!s) return [];
1402
- let e = Date.now() - p.windowMs;
1403
- return await s.pipelineAnalytics?.getObjectEvents({
920
+ if (!l) return [];
921
+ let e = Date.now() - h.windowMs;
922
+ return await l.pipelineAnalytics?.getObjectEvents({
1404
923
  since: e,
1405
- limit: He
924
+ limit: Te
1406
925
  }) ?? [];
1407
926
  },
1408
- enabled: !!s,
1409
- refetchInterval: p.pollIntervalMs,
1410
- staleTime: Math.max(1e3, p.pollIntervalMs / 2)
1411
- }), C = S.data ?? [], w = t(() => d === X ? C : C.filter((e) => e.className === d), [C, d]), T = S.dataUpdatedAt > 0 ? S.dataUpdatedAt : Date.now(), E = T - p.windowMs, D = t(() => {
927
+ enabled: !!l,
928
+ refetchInterval: h.pollIntervalMs,
929
+ staleTime: Math.max(1e3, h.pollIntervalMs / 2)
930
+ }), _ = g.data ?? [], C = e(() => p === J ? _ : _.filter((e) => e.className === p), [_, p]), w = g.dataUpdatedAt > 0 ? g.dataUpdatedAt : Date.now(), T = w - h.windowMs, E = e(() => {
1412
931
  let e = /* @__PURE__ */ new Set();
1413
- for (let t of C) e.add(t.className);
1414
- return d !== X && e.add(d), [...e].toSorted();
1415
- }, [C, d]);
932
+ for (let t of _) e.add(t.className);
933
+ return p !== J && e.add(p), [...e].toSorted();
934
+ }, [_, p]);
1416
935
  i(() => {
1417
- d !== X && C.length > 0 && !D.includes(d) && f(X);
936
+ p !== J && _.length > 0 && !E.includes(p) && m(J);
1418
937
  }, [
1419
- d,
1420
- C,
1421
- D
938
+ p,
939
+ _,
940
+ E
1422
941
  ]);
1423
- let O = t(() => Ge(w, Ue), [w]), A = t(() => Ke(w, E, T, p.bucketMs, O), [
1424
- w,
1425
- E,
1426
- T,
1427
- p.bucketMs,
1428
- O
1429
- ]), j = t(() => {
1430
- if (A.length === 0) return 1;
1431
- let e = A.reduce((e, t) => Math.max(e, t.total), 0);
1432
- return Math.max(1, Math.ceil(e * 1.15));
1433
- }, [A]), M = t(() => te(E, T, y, Q.left, Q.right, 5), [
942
+ let D = e(() => {
943
+ let e = ke(C, Ee), t = e.toSorted();
944
+ return C.some((t) => !e.includes(t.className)) && t.push(q), t;
945
+ }, [C]), O = e(() => D.map((e) => ({
946
+ id: e,
947
+ label: e === q ? a("detectionHistory.other") : e,
948
+ colorIndex: e === q ? E.length : E.indexOf(e)
949
+ })), [
950
+ D,
1434
951
  E,
952
+ a
953
+ ]), k = e(() => Ae(C, T, w, h.bucketMs, D), [
954
+ C,
1435
955
  T,
1436
- y
1437
- ]), N = t(() => Je(j), [j]), L = t(() => {
1438
- let e = O.map((e) => e.className);
1439
- return w.some((e) => !O.some((t) => t.className === e.className)) && e.push(Y), e;
1440
- }, [w, O]), ee = (e) => {
1441
- let t = x.current;
1442
- if (!t) return e;
1443
- let n = t.getBoundingClientRect();
1444
- return n.width === 0 ? e : e / y * n.width;
1445
- };
1446
- return /* @__PURE__ */ g("div", {
1447
- className: "rounded-lg border border-border bg-surface overflow-hidden",
1448
- children: [/* @__PURE__ */ g("div", {
1449
- className: "border-b border-border px-4 py-2 flex items-center justify-between gap-3",
1450
- children: [/* @__PURE__ */ g("div", {
1451
- className: "flex items-center gap-1.5",
1452
- children: [/* @__PURE__ */ h(k, { className: "h-3.5 w-3.5 text-foreground-subtle" }), /* @__PURE__ */ h("h2", {
1453
- className: "text-xs font-semibold text-foreground uppercase tracking-wider",
1454
- children: a("detectionHistory.title")
1455
- })]
1456
- }), /* @__PURE__ */ g("div", {
1457
- className: "flex items-center gap-2",
1458
- children: [D.length > 0 && /* @__PURE__ */ g("select", {
1459
- value: d,
1460
- onChange: (e) => f(e.target.value),
1461
- className: "text-[10px] px-1.5 py-0.5 rounded border border-border bg-background text-foreground focus:outline-none focus:ring-1 focus:ring-primary/40",
1462
- title: a("detectionHistory.filterByClass"),
1463
- children: [/* @__PURE__ */ h("option", {
1464
- value: X,
1465
- children: a("detectionHistory.allClasses")
1466
- }), D.map((e) => /* @__PURE__ */ h("option", {
1467
- value: e,
1468
- children: e
1469
- }, e))]
1470
- }), /* @__PURE__ */ h(F, {
1471
- presets: Ve,
1472
- value: c,
1473
- onChange: u
1474
- })]
1475
- })]
1476
- }), /* @__PURE__ */ g("div", {
1477
- ref: v,
1478
- className: "p-3 min-w-0 relative",
1479
- children: [w.length === 0 ? /* @__PURE__ */ h("div", {
1480
- className: "flex items-center justify-center h-32 text-[11px] text-foreground-subtle italic",
1481
- children: S.isLoading ? a("common.loading") : a("detectionHistory.empty")
1482
- }) : y === 0 ? /* @__PURE__ */ h("div", { className: "h-32" }) : /* @__PURE__ */ g(_, { children: [
1483
- /* @__PURE__ */ g("svg", {
1484
- ref: x,
1485
- role: "img",
1486
- "aria-label": a("detectionHistory.ariaLabel"),
1487
- width: "100%",
1488
- height: Z,
1489
- viewBox: `0 0 ${y} ${Z}`,
1490
- preserveAspectRatio: "none",
1491
- className: "block",
1492
- onMouseLeave: () => b.bindHover(null),
1493
- children: [
1494
- N.map(({ y: e, label: t }, n) => /* @__PURE__ */ g("g", { children: [/* @__PURE__ */ h("line", {
1495
- x1: Q.left,
1496
- x2: y - Q.right,
1497
- y1: e,
1498
- y2: e,
1499
- stroke: "currentColor",
1500
- strokeOpacity: .08,
1501
- strokeWidth: .5
1502
- }), /* @__PURE__ */ h("text", {
1503
- x: Q.left - 6,
1504
- y: e + 3,
1505
- textAnchor: "end",
1506
- className: "text-[9px] fill-foreground-subtle",
1507
- children: t
1508
- })] }, `y-${n}`)),
1509
- M.map(({ x: e, label: t }, n) => /* @__PURE__ */ h("text", {
1510
- x: e,
1511
- y: Z - Q.bottom + 12,
1512
- textAnchor: "middle",
1513
- className: "text-[9px] fill-foreground-subtle",
1514
- children: t
1515
- }, `x-${n}`)),
1516
- A.map((e, t) => {
1517
- if (e.total === 0) return null;
1518
- let { x: n, w: r } = qe(e.bucketStart, p.bucketMs, E, T, y), i = Z - Q.top - Q.bottom, o = e.total / j * i, s = Q.top + (i - o), c = 0, l = L.map((t, a) => {
1519
- let o = e.byClass[t] ?? 0;
1520
- if (o === 0) return null;
1521
- let s = o / j * i, l = Q.top + (i - c - s);
1522
- c += s;
1523
- let u = t === Y ? "#94a3b8" : re(a);
1524
- return /* @__PURE__ */ h("rect", {
1525
- x: n,
1526
- y: l,
1527
- width: Math.max(1, r - 1),
1528
- height: Math.max(1, s),
1529
- fill: u,
1530
- opacity: .9
1531
- }, `${e.bucketStart}-${t}`);
1532
- }).filter((e) => e !== null), u = e.bucketStart + p.bucketMs;
1533
- return /* @__PURE__ */ g("g", { children: [l, /* @__PURE__ */ h("rect", {
1534
- x: n,
1535
- y: Q.top,
1536
- width: Math.max(2, r),
1537
- height: i,
1538
- fill: "transparent",
1539
- onMouseEnter: () => {
1540
- b.bindHover({
1541
- anchorX: ee(n + r / 2),
1542
- anchorY: s,
1543
- title: `${Ye(e.bucketStart, u, p.bucketMs)} · ${a("detectionHistory.detections", { count: e.total })}`,
1544
- rows: L.map((t, n) => {
1545
- let r = e.byClass[t] ?? 0;
1546
- return r === 0 ? null : {
1547
- label: t === Y ? a("detectionHistory.other") : t,
1548
- value: `${r}`,
1549
- colour: t === Y ? "#94a3b8" : re(n)
1550
- };
1551
- }).filter((e) => e !== null)
1552
- });
1553
- }
1554
- })] }, `g-${e.bucketStart}-${t}`);
1555
- })
1556
- ]
1557
- }),
1558
- /* @__PURE__ */ h(R, {
1559
- state: b.state,
1560
- containerWidth: y
1561
- }),
1562
- /* @__PURE__ */ h(Ze, { stackOrder: L })
1563
- ] }), w.length > 0 && /* @__PURE__ */ g("div", {
1564
- className: "flex items-center justify-between text-[10px] text-foreground-subtle mt-1",
1565
- children: [/* @__PURE__ */ h("span", { children: a("detectionHistory.summary", {
1566
- count: w.length,
1567
- bucket: Xe(p.bucketMs)
1568
- }) }), /* @__PURE__ */ h("span", { children: a("detectionHistory.peak", { value: A.reduce((e, t) => Math.max(e, t.total), 0) }) })]
1569
- })]
1570
- })]
956
+ w,
957
+ h.bucketMs,
958
+ D
959
+ ]), A = k.reduce((e, t) => Math.max(e, t.values.reduce((e, t) => e + (t ?? 0), 0)), 0), j = W(h.bucketMs), M = e(() => [{
960
+ value: J,
961
+ label: a("detectionHistory.allClasses")
962
+ }, ...E.map((e) => ({
963
+ value: e,
964
+ label: e
965
+ }))], [E, a]);
966
+ return /* @__PURE__ */ S(f, {
967
+ headingId: c,
968
+ title: a("detectionHistory.title"),
969
+ icon: ee,
970
+ actions: E.length > 0 ? /* @__PURE__ */ S("div", {
971
+ className: "w-32",
972
+ children: /* @__PURE__ */ S(b, {
973
+ value: p,
974
+ onChange: (e) => m(e.target.value),
975
+ options: M,
976
+ "aria-label": a("detectionHistory.filterByClass")
977
+ })
978
+ }) : void 0,
979
+ children: /* @__PURE__ */ S("div", {
980
+ className: "p-3 min-w-0",
981
+ children: /* @__PURE__ */ S(v, {
982
+ title: a("detectionHistory.barsTitle", { bucket: j }),
983
+ layers: O,
984
+ buckets: C.length === 0 ? [] : k,
985
+ bucketMs: h.bucketMs,
986
+ range: {
987
+ from: T,
988
+ to: w
989
+ },
990
+ height: De,
991
+ stacked: !0,
992
+ pending: g.isLoading,
993
+ emptyMessage: a("detectionHistory.empty"),
994
+ windowToggle: {
995
+ options: Ce,
996
+ value: u,
997
+ onChange: (e) => {
998
+ we(e) && d(e);
999
+ },
1000
+ ariaLabel: a("common.timeWindow")
1001
+ },
1002
+ bucketLabel: (e) => `${U(e.t, e.t + h.bucketMs)} · ${a("detectionHistory.detections", { count: e.values.reduce((e, t) => e + (t ?? 0), 0) })}`,
1003
+ footer: C.length > 0 ? /* @__PURE__ */ x("div", {
1004
+ className: "flex items-center justify-between",
1005
+ children: [/* @__PURE__ */ S("span", { children: a("detectionHistory.summary", {
1006
+ count: C.length,
1007
+ bucket: j
1008
+ }) }), /* @__PURE__ */ S("span", { children: a("detectionHistory.peak", { value: A }) })]
1009
+ }) : void 0
1010
+ })
1011
+ })
1571
1012
  });
1572
1013
  }
1573
- function Ge(e, t) {
1014
+ function ke(e, t) {
1574
1015
  let n = /* @__PURE__ */ new Map();
1575
1016
  for (let t of e) n.set(t.className, (n.get(t.className) ?? 0) + 1);
1576
- return [...n.entries()].toSorted(([, e], [, t]) => t - e).slice(0, t).map(([e, t]) => ({
1577
- className: e,
1578
- count: t
1579
- }));
1017
+ return [...n.entries()].toSorted(([, e], [, t]) => t - e).slice(0, t).map(([e]) => e);
1580
1018
  }
1581
- function Ke(e, t, n, r, i) {
1019
+ function Ae(e, t, n, r, i) {
1582
1020
  if (n <= t) return [];
1583
- let a = new Set(i.map((e) => e.className)), o = Math.floor(t / r) * r, s = Math.floor(n / r) * r, c = /* @__PURE__ */ new Map();
1584
- for (let e = o; e <= s; e += r) c.set(e, {
1585
- total: 0,
1586
- byClass: {}
1587
- });
1021
+ let a = Math.floor(t / r) * r, o = Math.floor(n / r) * r, s = new Map(i.map((e, t) => [e, t])), c = s.get(q), l = /* @__PURE__ */ new Map();
1022
+ for (let e = a; e <= o; e += r) l.set(e, i.map(() => 0));
1588
1023
  for (let i of e) {
1589
1024
  if (i.timestamp < t || i.timestamp > n) continue;
1590
- let e = Math.floor(i.timestamp / r) * r, o = c.get(e);
1591
- if (!o) continue;
1592
- o.total += 1;
1593
- let s = a.has(i.className) ? i.className : Y;
1594
- o.byClass[s] = (o.byClass[s] ?? 0) + 1;
1025
+ let e = l.get(Math.floor(i.timestamp / r) * r), a = s.get(i.className) ?? c;
1026
+ !e || a === void 0 || (e[a] = (e[a] ?? 0) + 1);
1595
1027
  }
1596
- return [...c.entries()].toSorted(([e], [t]) => e - t).map(([e, t]) => ({
1597
- bucketStart: e,
1598
- total: t.total,
1599
- byClass: t.byClass
1028
+ return [...l.entries()].toSorted(([e], [t]) => e - t).map(([e, t]) => ({
1029
+ t: e,
1030
+ values: t
1600
1031
  }));
1601
1032
  }
1602
- function qe(e, t, n, r, i) {
1603
- let a = Math.max(1, r - n), o = i - Q.left - Q.right;
1604
- return {
1605
- x: Q.left + (e - n) / a * o,
1606
- w: t / a * o
1607
- };
1608
- }
1609
- function Je(e) {
1610
- let t = [];
1611
- for (let n = 0; n < 4; n++) {
1612
- let r = n / 3, i = Math.round(e * r), a = Z - Q.top - Q.bottom;
1613
- t.push({
1614
- y: Q.top + (1 - r) * a,
1615
- label: `${i}`
1616
- });
1617
- }
1618
- return t;
1619
- }
1620
- function Ye(e, t, n) {
1621
- let r = (e) => `${String(e.getHours()).padStart(2, "0")}:${String(e.getMinutes()).padStart(2, "0")}`;
1622
- return `${r(new Date(e))}–${r(new Date(t))}`;
1623
- }
1624
- function Xe(e) {
1625
- return e >= 60 * 6e4 ? `${Math.round(e / 6e4 / 60)}h` : e >= 6e4 ? `${Math.round(e / 6e4)}m` : `${Math.round(e / 1e3)}s`;
1626
- }
1627
- function Ze({ stackOrder: e }) {
1628
- let { t } = P();
1629
- return e.length === 0 ? null : /* @__PURE__ */ h("div", {
1630
- className: "flex flex-wrap gap-2 mt-2 px-1",
1631
- children: e.map((e, n) => {
1632
- let r = e === Y ? "#94a3b8" : re(n), i = e === Y ? t("detectionHistory.other") : e;
1633
- return /* @__PURE__ */ g("span", {
1634
- className: "inline-flex items-center gap-1 text-[10px] text-foreground-subtle",
1635
- children: [/* @__PURE__ */ h("span", {
1636
- className: "inline-block h-2 w-2 rounded-sm",
1637
- style: { backgroundColor: r }
1638
- }), /* @__PURE__ */ h("span", { children: i })]
1639
- }, e);
1640
- })
1641
- });
1642
- }
1643
1033
  //#endregion
1644
1034
  //#region src/pipeline-analytics/widgets/OccupancyPanel.tsx
1645
- function Qe({ dev: e, deviceId: t, title: n, variant: r = "full" }) {
1646
- let { t: i } = P(), a = n ?? i("occupancy.title"), o = m(l().trpcClient, e === void 0 && t !== void 0 ? t : null), s = e ?? o, c = f(s?.state.zoneAnalytics);
1647
- return c ? /* @__PURE__ */ h($e, {
1035
+ function je({ dev: e, deviceId: t, title: n, variant: r = "full" }) {
1036
+ let { t: i } = F(), a = n ?? i("occupancy.title"), o = y(s().trpcClient, e === void 0 && t !== void 0 ? t : null), c = e ?? o, l = _(c?.state.zoneAnalytics);
1037
+ return l ? /* @__PURE__ */ S(Y, {
1648
1038
  title: a,
1649
1039
  variant: r,
1650
- ts: c.ts,
1651
- children: /* @__PURE__ */ g("div", {
1040
+ ts: l.ts,
1041
+ children: /* @__PURE__ */ x("div", {
1652
1042
  className: r === "compact" ? "space-y-2" : "grid grid-cols-1 2xl:grid-cols-3 gap-3",
1653
1043
  children: [
1654
- /* @__PURE__ */ h(tt, { frame: c.frame }),
1655
- /* @__PURE__ */ h(rt, { snapshot: c }),
1656
- /* @__PURE__ */ h(nt, { unzoned: c.unzoned })
1044
+ /* @__PURE__ */ S(Ne, { frame: l.frame }),
1045
+ /* @__PURE__ */ S(Fe, { snapshot: l }),
1046
+ /* @__PURE__ */ S(Pe, { unzoned: l.unzoned })
1657
1047
  ]
1658
1048
  })
1659
- }) : /* @__PURE__ */ h($e, {
1049
+ }) : /* @__PURE__ */ S(Y, {
1660
1050
  title: a,
1661
1051
  variant: r,
1662
- children: /* @__PURE__ */ h(et, { message: i(s ? "occupancy.noData" : "common.resolving") })
1052
+ children: /* @__PURE__ */ S(Me, { message: i(c ? "occupancy.noData" : "common.resolving") })
1663
1053
  });
1664
1054
  }
1665
- function $e({ title: e, variant: t, ts: n, children: r }) {
1666
- let { t: i } = P(), a = n ? Math.max(0, Math.floor((Date.now() - n) / 1e3)) : null;
1667
- return /* @__PURE__ */ g("div", {
1055
+ function Y({ title: e, variant: t, ts: n, children: r }) {
1056
+ let { t: i } = F(), a = n ? Math.max(0, Math.floor((Date.now() - n) / 1e3)) : null;
1057
+ return /* @__PURE__ */ x("div", {
1668
1058
  className: t === "compact" ? "rounded-md border border-border/60 bg-surface/60 p-3" : "rounded-lg border border-border bg-surface overflow-hidden",
1669
- children: [/* @__PURE__ */ g("div", {
1059
+ children: [/* @__PURE__ */ x("div", {
1670
1060
  className: t === "compact" ? "flex items-center justify-between mb-2" : "border-b border-border px-4 py-2 flex items-center justify-between",
1671
- children: [/* @__PURE__ */ h("h2", {
1061
+ children: [/* @__PURE__ */ S("h2", {
1672
1062
  className: "text-xs font-semibold text-foreground uppercase tracking-wider",
1673
1063
  children: e
1674
- }), a !== null && /* @__PURE__ */ h("span", {
1064
+ }), a !== null && /* @__PURE__ */ S("span", {
1675
1065
  className: "text-[10px] text-foreground-subtle",
1676
1066
  children: a === 0 ? i("common.justNow") : i("common.secondsAgo", { seconds: a })
1677
1067
  })]
1678
- }), /* @__PURE__ */ h("div", {
1068
+ }), /* @__PURE__ */ S("div", {
1679
1069
  className: t === "compact" ? "" : "p-3",
1680
1070
  children: r
1681
1071
  })]
1682
1072
  });
1683
1073
  }
1684
- function et({ message: e }) {
1685
- return /* @__PURE__ */ g("div", {
1074
+ function Me({ message: e }) {
1075
+ return /* @__PURE__ */ x("div", {
1686
1076
  className: "px-4 py-6 flex flex-col items-center text-center text-foreground-subtle",
1687
- children: [/* @__PURE__ */ h(A, { className: "h-5 w-5 mb-2 opacity-30" }), /* @__PURE__ */ h("p", {
1077
+ children: [/* @__PURE__ */ S(P, { className: "h-5 w-5 mb-2 opacity-30" }), /* @__PURE__ */ S("p", {
1688
1078
  className: "text-[11px]",
1689
1079
  children: e
1690
1080
  })]
1691
1081
  });
1692
1082
  }
1693
- function tt({ frame: e }) {
1694
- let { t } = P();
1695
- return /* @__PURE__ */ h(it, {
1696
- icon: /* @__PURE__ */ h(O, { className: "h-3.5 w-3.5" }),
1083
+ function Ne({ frame: e }) {
1084
+ let { t } = F();
1085
+ return /* @__PURE__ */ S(X, {
1086
+ icon: /* @__PURE__ */ S(N, { className: "h-3.5 w-3.5" }),
1697
1087
  label: t("occupancy.frameTotal"),
1698
1088
  total: e.totalObjects,
1699
1089
  byClass: e.byClass,
1700
1090
  tone: "default"
1701
1091
  });
1702
1092
  }
1703
- function nt({ unzoned: e }) {
1704
- let { t } = P();
1705
- return /* @__PURE__ */ h(it, {
1706
- icon: /* @__PURE__ */ h(j, { className: "h-3.5 w-3.5" }),
1093
+ function Pe({ unzoned: e }) {
1094
+ let { t } = F();
1095
+ return /* @__PURE__ */ S(X, {
1096
+ icon: /* @__PURE__ */ S(te, { className: "h-3.5 w-3.5" }),
1707
1097
  label: t("occupancy.outsideZone"),
1708
1098
  total: e.totalObjects,
1709
1099
  byClass: e.byClass,
1710
1100
  tone: "muted"
1711
1101
  });
1712
1102
  }
1713
- function rt({ snapshot: e }) {
1714
- let { t } = P();
1715
- return e.zones.length === 0 ? /* @__PURE__ */ h(it, {
1716
- icon: /* @__PURE__ */ h(A, { className: "h-3.5 w-3.5" }),
1103
+ function Fe({ snapshot: e }) {
1104
+ let { t } = F();
1105
+ return e.zones.length === 0 ? /* @__PURE__ */ S(X, {
1106
+ icon: /* @__PURE__ */ S(P, { className: "h-3.5 w-3.5" }),
1717
1107
  label: t("occupancy.perZone"),
1718
1108
  total: 0,
1719
1109
  byClass: {},
1720
1110
  tone: "muted",
1721
1111
  emptyMessage: t("occupancy.noZones")
1722
- }) : /* @__PURE__ */ g("div", {
1112
+ }) : /* @__PURE__ */ x("div", {
1723
1113
  className: "rounded-md border border-border/60 bg-background/40",
1724
- children: [/* @__PURE__ */ g("div", {
1114
+ children: [/* @__PURE__ */ x("div", {
1725
1115
  className: "px-3 py-1.5 border-b border-border/40 flex items-center gap-1.5 text-[11px] uppercase tracking-wider text-foreground-subtle",
1726
1116
  children: [
1727
- /* @__PURE__ */ h(A, { className: "h-3.5 w-3.5" }),
1728
- /* @__PURE__ */ h("span", { children: t("occupancy.perZone") }),
1729
- /* @__PURE__ */ h("span", {
1117
+ /* @__PURE__ */ S(P, { className: "h-3.5 w-3.5" }),
1118
+ /* @__PURE__ */ S("span", { children: t("occupancy.perZone") }),
1119
+ /* @__PURE__ */ S("span", {
1730
1120
  className: "ml-auto text-[10px] normal-case tracking-normal",
1731
1121
  children: e.zones.length
1732
1122
  })
1733
1123
  ]
1734
- }), /* @__PURE__ */ h("div", {
1124
+ }), /* @__PURE__ */ S("div", {
1735
1125
  className: "divide-y divide-border/30",
1736
- children: e.zones.map((e) => /* @__PURE__ */ g("div", {
1126
+ children: e.zones.map((e) => /* @__PURE__ */ x("div", {
1737
1127
  className: "px-3 py-2",
1738
- children: [/* @__PURE__ */ g("div", {
1128
+ children: [/* @__PURE__ */ x("div", {
1739
1129
  className: "flex items-center justify-between mb-1",
1740
- children: [/* @__PURE__ */ h("span", {
1130
+ children: [/* @__PURE__ */ S("span", {
1741
1131
  className: "text-xs font-medium text-foreground truncate",
1742
1132
  children: e.zoneName
1743
- }), /* @__PURE__ */ h("span", {
1133
+ }), /* @__PURE__ */ S("span", {
1744
1134
  className: "rounded-full px-2 py-0.5 text-[10px] font-medium bg-foreground-subtle/10 text-foreground-subtle border border-border",
1745
1135
  children: e.totalObjects
1746
1136
  })]
1747
- }), /* @__PURE__ */ h(at, { byClass: e.byClass })]
1137
+ }), /* @__PURE__ */ S(Z, { byClass: e.byClass })]
1748
1138
  }, e.zoneId))
1749
1139
  })]
1750
1140
  });
1751
1141
  }
1752
- function it({ icon: e, label: t, total: n, byClass: r, tone: i, emptyMessage: a }) {
1753
- let { t: o } = P(), s = Object.keys(r).length;
1754
- return /* @__PURE__ */ g("div", {
1142
+ function X({ icon: e, label: t, total: n, byClass: r, tone: i, emptyMessage: a }) {
1143
+ let { t: o } = F(), s = Object.keys(r).length;
1144
+ return /* @__PURE__ */ x("div", {
1755
1145
  className: i === "muted" ? "rounded-md border border-border/40 bg-background/20 px-3 py-2" : "rounded-md border border-border/60 bg-background/40 px-3 py-2",
1756
- children: [/* @__PURE__ */ g("div", {
1146
+ children: [/* @__PURE__ */ x("div", {
1757
1147
  className: "flex items-center gap-1.5 mb-1.5 text-[11px] uppercase tracking-wider text-foreground-subtle",
1758
1148
  children: [
1759
1149
  e,
1760
- /* @__PURE__ */ h("span", { children: t }),
1761
- /* @__PURE__ */ h("span", {
1150
+ /* @__PURE__ */ S("span", { children: t }),
1151
+ /* @__PURE__ */ S("span", {
1762
1152
  className: "ml-auto text-base font-semibold text-foreground tabular-nums normal-case tracking-normal",
1763
1153
  children: n
1764
1154
  })
1765
1155
  ]
1766
- }), s === 0 ? /* @__PURE__ */ h("span", {
1156
+ }), s === 0 ? /* @__PURE__ */ S("span", {
1767
1157
  className: "text-[10px] text-foreground-subtle italic",
1768
1158
  children: a ?? o("occupancy.noObjects")
1769
- }) : /* @__PURE__ */ h(at, { byClass: r })]
1159
+ }) : /* @__PURE__ */ S(Z, { byClass: r })]
1770
1160
  });
1771
1161
  }
1772
- function at({ byClass: e }) {
1773
- let { t: n } = P(), r = t(() => Object.entries(e).sort(([, e], [, t]) => t - e), [e]);
1774
- return r.length === 0 ? /* @__PURE__ */ h("span", {
1162
+ function Z({ byClass: t }) {
1163
+ let { t: n } = F(), r = e(() => Object.entries(t).sort(([, e], [, t]) => t - e), [t]);
1164
+ return r.length === 0 ? /* @__PURE__ */ S("span", {
1775
1165
  className: "text-[10px] text-foreground-subtle italic",
1776
1166
  children: n("occupancy.noObjects")
1777
- }) : /* @__PURE__ */ h("div", {
1167
+ }) : /* @__PURE__ */ S("div", {
1778
1168
  className: "flex flex-wrap gap-1",
1779
- children: r.map(([e, t]) => /* @__PURE__ */ g("span", {
1169
+ children: r.map(([e, t]) => /* @__PURE__ */ x("span", {
1780
1170
  className: "inline-flex items-center gap-1 rounded-full px-2 py-0.5 text-[10px] font-medium bg-primary/10 text-primary border border-primary/20",
1781
- children: [/* @__PURE__ */ h("span", { children: e }), /* @__PURE__ */ h("span", {
1171
+ children: [/* @__PURE__ */ S("span", { children: e }), /* @__PURE__ */ S("span", {
1782
1172
  className: "tabular-nums opacity-80",
1783
1173
  children: t
1784
1174
  })]
@@ -1787,39 +1177,28 @@ function at({ byClass: e }) {
1787
1177
  }
1788
1178
  //#endregion
1789
1179
  //#region src/pipeline-analytics/widgets/LiveStatsTab.tsx
1790
- function ot({ deviceId: e }) {
1791
- return /* @__PURE__ */ g("div", {
1792
- className: d,
1180
+ function Q({ deviceId: e }) {
1181
+ return /* @__PURE__ */ x("div", {
1182
+ className: c,
1793
1183
  children: [
1794
- /* @__PURE__ */ g("div", {
1795
- className: `grid ${s}`,
1184
+ /* @__PURE__ */ x("div", {
1185
+ className: `grid ${h}`,
1796
1186
  style: { gridTemplateColumns: "repeat(auto-fit, minmax(min(100%, 340px), 1fr))" },
1797
- children: [/* @__PURE__ */ h(p, {
1187
+ children: [/* @__PURE__ */ S(u, {
1798
1188
  widgetId: "pipeline-analytics/live-occupancy-panel",
1799
1189
  host: "device-tab",
1800
1190
  deviceId: e
1801
- }), /* @__PURE__ */ h(p, {
1191
+ }), /* @__PURE__ */ S(u, {
1802
1192
  widgetId: "pipeline-analytics/audio-metrics-panel",
1803
1193
  host: "device-tab",
1804
1194
  deviceId: e
1805
1195
  })]
1806
1196
  }),
1807
- /* @__PURE__ */ h(p, {
1808
- widgetId: "pipeline-analytics/audio-history-chart",
1809
- host: "device-tab",
1810
- deviceId: e
1811
- }),
1812
- /* @__PURE__ */ h(p, {
1813
- widgetId: "pipeline-analytics/occupancy-history-chart",
1814
- host: "device-tab",
1815
- deviceId: e
1197
+ /* @__PURE__ */ S(d, {
1198
+ deviceId: e,
1199
+ fixedWindow: "24h"
1816
1200
  }),
1817
- /* @__PURE__ */ h(p, {
1818
- widgetId: "pipeline-analytics/motion-history-chart",
1819
- host: "device-tab",
1820
- deviceId: e
1821
- }),
1822
- /* @__PURE__ */ h(p, {
1201
+ /* @__PURE__ */ S(u, {
1823
1202
  widgetId: "pipeline-analytics/detection-history-chart",
1824
1203
  host: "device-tab",
1825
1204
  deviceId: e
@@ -1830,41 +1209,41 @@ function ot({ deviceId: e }) {
1830
1209
  //#endregion
1831
1210
  //#region src/pipeline-analytics/widgets/index.tsx
1832
1211
  function $({ name: e }) {
1833
- let { t } = P();
1834
- return /* @__PURE__ */ h("div", {
1212
+ let { t } = F();
1213
+ return /* @__PURE__ */ S("div", {
1835
1214
  className: "rounded-lg border border-warning/30 bg-warning/10 px-3 py-2 text-xs text-warning",
1836
1215
  children: t("missingDevice", { name: e })
1837
1216
  });
1838
1217
  }
1839
- function st(e) {
1840
- return e.deviceId === void 0 ? /* @__PURE__ */ h($, { name: "AudioHistoryChart" }) : /* @__PURE__ */ h(ce, { deviceId: e.deviceId });
1218
+ function Ie(e) {
1219
+ return e.deviceId === void 0 ? /* @__PURE__ */ S($, { name: "AudioHistoryChart" }) : /* @__PURE__ */ S(se, { deviceId: e.deviceId });
1841
1220
  }
1842
- function ct(e) {
1843
- return e.deviceId === void 0 ? /* @__PURE__ */ h($, { name: "AudioMetricsPanel" }) : /* @__PURE__ */ h(ve, { deviceId: e.deviceId });
1221
+ function Le(e) {
1222
+ return e.deviceId === void 0 ? /* @__PURE__ */ S($, { name: "AudioMetricsPanel" }) : /* @__PURE__ */ S(ce, { deviceId: e.deviceId });
1844
1223
  }
1845
- function lt(e) {
1846
- return e.deviceId === void 0 ? /* @__PURE__ */ h($, { name: "OccupancyHistoryChart" }) : /* @__PURE__ */ h(Ee, { deviceId: e.deviceId });
1224
+ function Re(e) {
1225
+ return e.deviceId === void 0 ? /* @__PURE__ */ S($, { name: "OccupancyHistoryChart" }) : /* @__PURE__ */ S(ge, { deviceId: e.deviceId });
1847
1226
  }
1848
- function ut(e) {
1849
- return e.deviceId === void 0 ? /* @__PURE__ */ h($, { name: "MotionHistoryChart" }) : /* @__PURE__ */ h(Pe, { deviceId: e.deviceId });
1227
+ function ze(e) {
1228
+ return e.deviceId === void 0 ? /* @__PURE__ */ S($, { name: "MotionHistoryChart" }) : /* @__PURE__ */ S(Se, { deviceId: e.deviceId });
1850
1229
  }
1851
- function dt(e) {
1852
- return e.deviceId === void 0 ? /* @__PURE__ */ h($, { name: "DetectionHistoryChart" }) : /* @__PURE__ */ h(We, { deviceId: e.deviceId });
1230
+ function Be(e) {
1231
+ return e.deviceId === void 0 ? /* @__PURE__ */ S($, { name: "DetectionHistoryChart" }) : /* @__PURE__ */ S(Oe, { deviceId: e.deviceId });
1853
1232
  }
1854
- function ft(e) {
1855
- return e.deviceId === void 0 ? /* @__PURE__ */ h($, { name: "LiveOccupancyPanel" }) : /* @__PURE__ */ h(Qe, { deviceId: e.deviceId });
1233
+ function Ve(e) {
1234
+ return e.deviceId === void 0 ? /* @__PURE__ */ S($, { name: "LiveOccupancyPanel" }) : /* @__PURE__ */ S(je, { deviceId: e.deviceId });
1856
1235
  }
1857
- function pt(e) {
1858
- return e.deviceId === void 0 ? /* @__PURE__ */ h($, { name: "LiveStats" }) : /* @__PURE__ */ h(ot, { deviceId: e.deviceId });
1236
+ function He(e) {
1237
+ return e.deviceId === void 0 ? /* @__PURE__ */ S($, { name: "LiveStats" }) : /* @__PURE__ */ S(Q, { deviceId: e.deviceId });
1859
1238
  }
1860
- var mt = {
1861
- "audio-history-chart": st,
1862
- "audio-metrics-panel": ct,
1863
- "occupancy-history-chart": lt,
1864
- "motion-history-chart": ut,
1865
- "detection-history-chart": dt,
1866
- "live-occupancy-panel": ft,
1867
- "live-stats": pt
1239
+ var Ue = {
1240
+ "audio-history-chart": Ie,
1241
+ "audio-metrics-panel": Le,
1242
+ "occupancy-history-chart": Re,
1243
+ "motion-history-chart": ze,
1244
+ "detection-history-chart": Be,
1245
+ "live-occupancy-panel": Ve,
1246
+ "live-stats": He
1868
1247
  };
1869
1248
  //#endregion
1870
- export { mt as default };
1249
+ export { Ue as default };