@camstack/addon-post-analysis 0.1.20 → 0.2.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 (73) hide show
  1. package/dist/dist-4mTLJ7BJ.mjs +20750 -0
  2. package/dist/dist-CS2K80so.js +20933 -0
  3. package/dist/embedding-encoder/index.js +977 -902
  4. package/dist/embedding-encoder/index.mjs +967 -860
  5. package/dist/enrichment-engine/index.js +834 -833
  6. package/dist/enrichment-engine/index.mjs +828 -832
  7. package/dist/pipeline-analytics/_stub.js +1680 -1396
  8. package/dist/pipeline-analytics/_virtual_mf-localSharedImportMap___mfe_internal__addon_pipeline_analytics_widgets-DOSUJ-U0.mjs +156 -0
  9. package/dist/pipeline-analytics/_virtual_mf___mfe_internal__addon_pipeline_analytics_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.js-DJvmVCso.mjs +26 -0
  10. package/dist/pipeline-analytics/_virtual_mf___mfe_internal__addon_pipeline_analytics_widgets__loadShare___mf_0_tanstack_mf_1_react_mf_2_query__loadShare__.js-B3Wx5J80.mjs +26 -0
  11. package/dist/pipeline-analytics/_virtual_mf___mfe_internal__addon_pipeline_analytics_widgets__loadShare__react__loadShare__.js-C0AuF9av.mjs +26 -0
  12. 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 +26 -0
  13. package/dist/pipeline-analytics/dist-CYZr2fwk.mjs +2726 -0
  14. package/dist/pipeline-analytics/hostInit-BazRS2O7.mjs +129 -0
  15. package/dist/pipeline-analytics/index.js +7112 -3100
  16. package/dist/pipeline-analytics/index.mjs +7105 -3100
  17. package/dist/pipeline-analytics/remoteEntry.js +134 -2973
  18. package/dist/pipeline-analytics/remoteEntry.ssr.js +33 -0
  19. package/dist/pipeline-analytics/virtualExposes-BgYzpJZG.mjs +27 -0
  20. package/dist/pipeline-analytics/virtual_mf-exposes-ssr___mfe_internal__addon_pipeline_analytics_widgets__remoteEntry_js-D7qgWCKX.mjs +10 -0
  21. package/dist/resolve-frame-5lMxmeI1.js +57 -0
  22. package/dist/resolve-frame-CT1T1tWy.mjs +44 -0
  23. package/package.json +15 -6
  24. package/dist/embedding-encoder/index.js.map +0 -1
  25. package/dist/embedding-encoder/index.mjs.map +0 -1
  26. package/dist/enrichment-engine/index.js.map +0 -1
  27. package/dist/enrichment-engine/index.mjs.map +0 -1
  28. package/dist/index-B0RhVv1c.js +0 -17107
  29. package/dist/index-B0RhVv1c.js.map +0 -1
  30. package/dist/index-ot5PeFg_.mjs +0 -17108
  31. package/dist/index-ot5PeFg_.mjs.map +0 -1
  32. package/dist/pipeline-analytics/@mf-types/compiled-types/pipeline-analytics/widgets/AudioHistoryChart.d.ts +0 -4
  33. package/dist/pipeline-analytics/@mf-types/compiled-types/pipeline-analytics/widgets/AudioMetricsPanel.d.ts +0 -10
  34. package/dist/pipeline-analytics/@mf-types/compiled-types/pipeline-analytics/widgets/DetectionHistoryChart.d.ts +0 -4
  35. package/dist/pipeline-analytics/@mf-types/compiled-types/pipeline-analytics/widgets/LiveStatsTab.d.ts +0 -5
  36. package/dist/pipeline-analytics/@mf-types/compiled-types/pipeline-analytics/widgets/MotionHistoryChart.d.ts +0 -4
  37. package/dist/pipeline-analytics/@mf-types/compiled-types/pipeline-analytics/widgets/OccupancyHistoryChart.d.ts +0 -4
  38. package/dist/pipeline-analytics/@mf-types/compiled-types/pipeline-analytics/widgets/OccupancyPanel.d.ts +0 -10
  39. package/dist/pipeline-analytics/@mf-types/compiled-types/pipeline-analytics/widgets/chart-utils.d.ts +0 -97
  40. package/dist/pipeline-analytics/@mf-types/compiled-types/pipeline-analytics/widgets/index.d.ts +0 -29
  41. package/dist/pipeline-analytics/@mf-types/widgets.d.ts +0 -2
  42. package/dist/pipeline-analytics/@mf-types.d.ts +0 -3
  43. package/dist/pipeline-analytics/@mf-types.zip +0 -0
  44. package/dist/pipeline-analytics/__mfe_internal__addon_pipeline_analytics_widgets__loadShare___mf_0_camstack_mf_1_sdk__loadShare__.mjs-lantnv8e.mjs +0 -12
  45. package/dist/pipeline-analytics/__mfe_internal__addon_pipeline_analytics_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.mjs-BD3oMNGB.mjs +0 -29
  46. package/dist/pipeline-analytics/__mfe_internal__addon_pipeline_analytics_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.mjs-BgOHCakr.mjs +0 -18
  47. package/dist/pipeline-analytics/__mfe_internal__addon_pipeline_analytics_widgets__loadShare___mf_0_tanstack_mf_1_react_mf_2_query__loadShare__.mjs-DoWbefqS.mjs +0 -104
  48. package/dist/pipeline-analytics/__mfe_internal__addon_pipeline_analytics_widgets__loadShare___mf_0_trpc_mf_1_client__loadShare__.mjs-52bfkwC8.mjs +0 -85
  49. package/dist/pipeline-analytics/__mfe_internal__addon_pipeline_analytics_widgets__loadShare___mf_0_trpc_mf_1_react_mf_2_query__loadShare__.mjs-CVrnrGED.mjs +0 -62
  50. package/dist/pipeline-analytics/__mfe_internal__addon_pipeline_analytics_widgets__loadShare__react__loadShare__.mjs-D1qPKjvR.mjs +0 -89
  51. package/dist/pipeline-analytics/__mfe_internal__addon_pipeline_analytics_widgets__loadShare__react__loadShare__.mjs_commonjs-proxy-B5X50Xa4.mjs +0 -29
  52. package/dist/pipeline-analytics/__mfe_internal__addon_pipeline_analytics_widgets__loadShare__react_mf_1_jsx_mf_2_runtime__loadShare__.mjs-BsyrX6NO.mjs +0 -36
  53. package/dist/pipeline-analytics/__mfe_internal__addon_pipeline_analytics_widgets__loadShare__react_mf_2_dom__loadShare__.mjs-Dp8hqYOB.mjs +0 -45
  54. package/dist/pipeline-analytics/__mfe_internal__addon_pipeline_analytics_widgets__loadShare__react_mf_2_dom__loadShare__.mjs_commonjs-proxy-B10b5k5J.mjs +0 -6
  55. package/dist/pipeline-analytics/__mfe_internal__addon_pipeline_analytics_widgets__loadShare__react_mf_2_dom_mf_1_client__loadShare__.mjs-BZjEt71l.mjs +0 -34
  56. package/dist/pipeline-analytics/_virtual_mf-localSharedImportMap___mfe_internal__addon_pipeline_analytics_widgets-DWB3apaJ.mjs +0 -156
  57. package/dist/pipeline-analytics/client-C6xdgLZU.mjs +0 -9836
  58. package/dist/pipeline-analytics/getErrorShape-BPSzUA7W-TlK8ipWe.mjs +0 -211
  59. package/dist/pipeline-analytics/hostInit-3cyL9eyG.mjs +0 -168
  60. package/dist/pipeline-analytics/index-BCTHeI2m.mjs +0 -1641
  61. package/dist/pipeline-analytics/index-BuWLz0GG.mjs +0 -2603
  62. package/dist/pipeline-analytics/index-CIwq-tQL.mjs +0 -725
  63. package/dist/pipeline-analytics/index-CWBMDbou.mjs +0 -435
  64. package/dist/pipeline-analytics/index-CWkKuNLr.mjs +0 -232
  65. package/dist/pipeline-analytics/index-CZhagnlH.mjs +0 -67784
  66. package/dist/pipeline-analytics/index-D883Q5B8.mjs +0 -185
  67. package/dist/pipeline-analytics/index-DtOI1aTU.mjs +0 -18504
  68. package/dist/pipeline-analytics/index-xncRG7-x.mjs +0 -2713
  69. package/dist/pipeline-analytics/index.js.map +0 -1
  70. package/dist/pipeline-analytics/index.mjs.map +0 -1
  71. package/dist/pipeline-analytics/jsx-runtime-DdLhuHmJ.mjs +0 -55
  72. package/dist/pipeline-analytics/schemas-B7L0qZtq.mjs +0 -3599
  73. package/dist/pipeline-analytics/virtualExposes-8FzWTdq3.mjs +0 -42
@@ -1,1462 +1,1746 @@
1
- import { _ as n, a as i, b as ie } from "./__mfe_internal__addon_pipeline_analytics_widgets__loadShare__react_mf_1_jsx_mf_2_runtime__loadShare__.mjs-BsyrX6NO.mjs";
2
- import { a as Ae, b as pe, c as Q, d as H, e as ye, f as k } from "./__mfe_internal__addon_pipeline_analytics_widgets__loadShare__react__loadShare__.mjs-D1qPKjvR.mjs";
3
- import { _ as le } from "./__mfe_internal__addon_pipeline_analytics_widgets__loadShare___mf_0_tanstack_mf_1_react_mf_2_query__loadShare__.mjs-DoWbefqS.mjs";
4
- import { _ as Y, a as J, b as Pe, c as ve, d as ze, e as Xe, f as B } from "./__mfe_internal__addon_pipeline_analytics_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.mjs-BgOHCakr.mjs";
5
- /**
6
- * @license lucide-react v0.511.0 - ISC
7
- *
8
- * This source code is licensed under the ISC license.
9
- * See the LICENSE file in the root directory of this source tree.
10
- */
11
- const Ye = (e) => e.replace(/([a-z0-9])([A-Z])/g, "$1-$2").toLowerCase(), qe = (e) => e.replace(
12
- /^([A-Z])|[\s-_]+(\w)/g,
13
- (t, o, r) => r ? r.toUpperCase() : o.toLowerCase()
14
- ), Me = (e) => {
15
- const t = qe(e);
16
- return t.charAt(0).toUpperCase() + t.slice(1);
17
- }, Fe = (...e) => e.filter((t, o, r) => !!t && t.trim() !== "" && r.indexOf(t) === o).join(" ").trim(), Ge = (e) => {
18
- for (const t in e)
19
- if (t.startsWith("aria-") || t === "role" || t === "title")
20
- return !0;
21
- };
22
- /**
23
- * @license lucide-react v0.511.0 - ISC
24
- *
25
- * This source code is licensed under the ISC license.
26
- * See the LICENSE file in the root directory of this source tree.
27
- */
28
- var Ue = {
29
- xmlns: "http://www.w3.org/2000/svg",
30
- width: 24,
31
- height: 24,
32
- viewBox: "0 0 24 24",
33
- fill: "none",
34
- stroke: "currentColor",
35
- strokeWidth: 2,
36
- strokeLinecap: "round",
37
- strokeLinejoin: "round"
38
- };
39
- /**
40
- * @license lucide-react v0.511.0 - ISC
41
- *
42
- * This source code is licensed under the ISC license.
43
- * See the LICENSE file in the root directory of this source tree.
44
- */
45
- const Ve = Ae(
46
- ({
47
- color: e = "currentColor",
48
- size: t = 24,
49
- strokeWidth: o = 2,
50
- absoluteStrokeWidth: r,
51
- className: a = "",
52
- children: s,
53
- iconNode: d,
54
- ...l
55
- }, f) => pe(
56
- "svg",
57
- {
58
- ref: f,
59
- ...Ue,
60
- width: t,
61
- height: t,
62
- stroke: e,
63
- strokeWidth: r ? Number(o) * 24 / Number(t) : o,
64
- className: Fe("lucide", a),
65
- ...!s && !Ge(l) && { "aria-hidden": "true" },
66
- ...l
67
- },
68
- [
69
- ...d.map(([u, N]) => pe(u, N)),
70
- ...Array.isArray(s) ? s : [s]
71
- ]
72
- )
73
- );
74
- /**
75
- * @license lucide-react v0.511.0 - ISC
76
- *
77
- * This source code is licensed under the ISC license.
78
- * See the LICENSE file in the root directory of this source tree.
79
- */
80
- const j = (e, t) => {
81
- const o = Ae(
82
- ({ className: r, ...a }, s) => pe(Ve, {
83
- ref: s,
84
- iconNode: t,
85
- className: Fe(
86
- `lucide-${Ye(Me(e))}`,
87
- `lucide-${e}`,
88
- r
89
- ),
90
- ...a
91
- })
92
- );
93
- return o.displayName = Me(e), o;
94
- };
95
- /**
96
- * @license lucide-react v0.511.0 - ISC
97
- *
98
- * This source code is licensed under the ISC license.
99
- * See the LICENSE file in the root directory of this source tree.
100
- */
101
- const Ze = [
102
- [
103
- "path",
104
- {
105
- 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",
106
- key: "169zse"
107
- }
108
- ]
109
- ], K = j("activity", Ze);
110
- /**
111
- * @license lucide-react v0.511.0 - ISC
112
- *
113
- * This source code is licensed under the ISC license.
114
- * See the LICENSE file in the root directory of this source tree.
115
- */
116
- const Ke = [
117
- [
118
- "path",
119
- {
120
- 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",
121
- key: "lc1i9w"
122
- }
123
- ],
124
- ["path", { d: "m7 16.5-4.74-2.85", key: "1o9zyk" }],
125
- ["path", { d: "m7 16.5 5-3", key: "va8pkn" }],
126
- ["path", { d: "M7 16.5v5.17", key: "jnp8gn" }],
127
- [
128
- "path",
129
- {
130
- d: "M12 13.5V19l3.97 2.38a2 2 0 0 0 2.06 0l3-1.8a2 2 0 0 0 .97-1.71v-3.24a2 2 0 0 0-.97-1.71L17 10.5l-5 3Z",
131
- key: "8zsnat"
132
- }
133
- ],
134
- ["path", { d: "m17 16.5-5-3", key: "8arw3v" }],
135
- ["path", { d: "m17 16.5 4.74-2.85", key: "8rfmw" }],
136
- ["path", { d: "M17 16.5v5.17", key: "k6z78m" }],
137
- [
138
- "path",
139
- {
140
- d: "M7.97 4.42A2 2 0 0 0 7 6.13v4.37l5 3 5-3V6.13a2 2 0 0 0-.97-1.71l-3-1.8a2 2 0 0 0-2.06 0l-3 1.8Z",
141
- key: "1xygjf"
142
- }
143
- ],
144
- ["path", { d: "M12 8 7.26 5.15", key: "1vbdud" }],
145
- ["path", { d: "m12 8 4.74-2.85", key: "3rx089" }],
146
- ["path", { d: "M12 13.5V8", key: "1io7kd" }]
147
- ], Qe = j("boxes", Ke);
148
- /**
149
- * @license lucide-react v0.511.0 - ISC
150
- *
151
- * This source code is licensed under the ISC license.
152
- * See the LICENSE file in the root directory of this source tree.
153
- */
154
- const Je = [
155
- [
156
- "path",
157
- {
158
- 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",
159
- key: "1nclc0"
160
- }
161
- ],
162
- ["circle", { cx: "12", cy: "12", r: "3", key: "1v7zrd" }]
163
- ], et = j("eye", Je);
164
- /**
165
- * @license lucide-react v0.511.0 - ISC
166
- *
167
- * This source code is licensed under the ISC license.
168
- * See the LICENSE file in the root directory of this source tree.
169
- */
170
- const tt = [
171
- [
172
- "path",
173
- {
174
- 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",
175
- key: "zw3jo"
176
- }
177
- ],
178
- [
179
- "path",
180
- {
181
- d: "M2 12a1 1 0 0 0 .58.91l8.6 3.91a2 2 0 0 0 1.65 0l8.58-3.9A1 1 0 0 0 22 12",
182
- key: "1wduqc"
183
- }
184
- ],
185
- [
186
- "path",
187
- {
188
- 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",
189
- key: "kqbvx6"
190
- }
191
- ]
192
- ], oe = j("layers", tt);
193
- /**
194
- * @license lucide-react v0.511.0 - ISC
195
- *
196
- * This source code is licensed under the ISC license.
197
- * See the LICENSE file in the root directory of this source tree.
198
- */
199
- const nt = [
200
- ["path", { d: "M12.75 7.09a3 3 0 0 1 2.16 2.16", key: "1d4wjd" }],
201
- [
202
- "path",
203
- {
204
- d: "M17.072 17.072c-1.634 2.17-3.527 3.912-4.471 4.727a1 1 0 0 1-1.202 0C9.539 20.193 4 14.993 4 10a8 8 0 0 1 1.432-4.568",
205
- key: "12yil7"
206
- }
207
- ],
208
- ["path", { d: "m2 2 20 20", key: "1ooewy" }],
209
- ["path", { d: "M8.475 2.818A8 8 0 0 1 20 10c0 1.183-.31 2.377-.81 3.533", key: "lhrkcz" }],
210
- ["path", { d: "M9.13 9.13a3 3 0 0 0 3.74 3.74", key: "13wojd" }]
211
- ], rt = j("map-pin-off", nt);
212
- /**
213
- * @license lucide-react v0.511.0 - ISC
214
- *
215
- * This source code is licensed under the ISC license.
216
- * See the LICENSE file in the root directory of this source tree.
217
- */
218
- const ot = [
219
- ["line", { x1: "2", x2: "22", y1: "2", y2: "22", key: "a6p6uj" }],
220
- ["path", { d: "M18.89 13.23A7.12 7.12 0 0 0 19 12v-2", key: "80xlxr" }],
221
- ["path", { d: "M5 10v2a7 7 0 0 0 12 5", key: "p2k8kg" }],
222
- ["path", { d: "M15 9.34V5a3 3 0 0 0-5.68-1.33", key: "1gzdoj" }],
223
- ["path", { d: "M9 9v3a3 3 0 0 0 5.12 2.12", key: "r2i35w" }],
224
- ["line", { x1: "12", x2: "12", y1: "19", y2: "22", key: "x3vr5v" }]
225
- ], st = j("mic-off", ot);
226
- /**
227
- * @license lucide-react v0.511.0 - ISC
228
- *
229
- * This source code is licensed under the ISC license.
230
- * See the LICENSE file in the root directory of this source tree.
231
- */
232
- const at = [
233
- ["path", { d: "M12 2a3 3 0 0 0-3 3v7a3 3 0 0 0 6 0V5a3 3 0 0 0-3-3Z", key: "131961" }],
234
- ["path", { d: "M19 10v2a7 7 0 0 1-14 0v-2", key: "1vc78b" }],
235
- ["line", { x1: "12", x2: "12", y1: "19", y2: "22", key: "x3vr5v" }]
236
- ], it = j("mic", at);
237
- function ce({
238
- presets: e,
239
- value: t,
240
- onChange: o
241
- }) {
242
- return /* @__PURE__ */ n("div", { className: "flex items-center gap-1 border border-border rounded-md p-0.5 bg-background", children: e.map(({ id: r, label: a }) => /* @__PURE__ */ n(
243
- "button",
244
- {
245
- type: "button",
246
- onClick: () => o(r),
247
- className: `px-2 py-0.5 rounded text-[10px] font-medium transition-colors ${t === r ? "bg-primary/10 text-primary" : "text-foreground-subtle hover:text-foreground"}`,
248
- children: a
249
- },
250
- r
251
- )) });
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";
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, i as c, n as l, o as u, r as d, s as f, t as p } from "./_virtual_mf___mfe_internal__addon_pipeline_analytics_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.js-DJvmVCso.mjs";
4
+ import { n as m, r as h, t as g } from "./_virtual_mf___mfe_internal__addon_pipeline_analytics_widgets__loadShare__react_mf_1_jsx_mf_2_runtime__loadShare__.js-Bm-iyjmq.mjs";
5
+ //#region ../../node_modules/lucide-react/dist/esm/shared/src/utils.js
6
+ var _ = (e) => e.replace(/([a-z0-9])([A-Z])/g, "$1-$2").toLowerCase(), v = (e) => e.replace(/^([A-Z])|[\s-_]+(\w)/g, (e, t, n) => n ? n.toUpperCase() : t.toLowerCase()), y = (e) => {
7
+ let t = v(e);
8
+ return t.charAt(0).toUpperCase() + t.slice(1);
9
+ }, b = (...e) => e.filter((e, t, n) => !!e && e.trim() !== "" && n.indexOf(e) === t).join(" ").trim(), x = (e) => {
10
+ for (let t in e) if (t.startsWith("aria-") || t === "role" || t === "title") return !0;
11
+ }, S = {
12
+ xmlns: "http://www.w3.org/2000/svg",
13
+ width: 24,
14
+ height: 24,
15
+ viewBox: "0 0 24 24",
16
+ fill: "none",
17
+ stroke: "currentColor",
18
+ strokeWidth: 2,
19
+ strokeLinecap: "round",
20
+ strokeLinejoin: "round"
21
+ }, C = n(({ color: e = "currentColor", size: t = 24, strokeWidth: n = 2, absoluteStrokeWidth: r, className: i = "", children: o, iconNode: s, ...c }, l) => a("svg", {
22
+ ref: l,
23
+ ...S,
24
+ width: t,
25
+ height: t,
26
+ stroke: e,
27
+ strokeWidth: r ? Number(n) * 24 / Number(t) : n,
28
+ className: b("lucide", i),
29
+ ...!o && !x(c) && { "aria-hidden": "true" },
30
+ ...c
31
+ }, [...s.map(([e, t]) => a(e, t)), ...Array.isArray(o) ? o : [o]])), w = (e, t) => {
32
+ let r = n(({ className: n, ...r }, i) => a(C, {
33
+ ref: i,
34
+ iconNode: t,
35
+ className: b(`lucide-${_(y(e))}`, `lucide-${e}`, n),
36
+ ...r
37
+ }));
38
+ return r.displayName = y(e), r;
39
+ }, T = w("activity", [["path", {
40
+ 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",
41
+ key: "169zse"
42
+ }]]), E = w("boxes", [
43
+ ["path", {
44
+ 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",
45
+ key: "lc1i9w"
46
+ }],
47
+ ["path", {
48
+ d: "m7 16.5-4.74-2.85",
49
+ key: "1o9zyk"
50
+ }],
51
+ ["path", {
52
+ d: "m7 16.5 5-3",
53
+ key: "va8pkn"
54
+ }],
55
+ ["path", {
56
+ d: "M7 16.5v5.17",
57
+ key: "jnp8gn"
58
+ }],
59
+ ["path", {
60
+ d: "M12 13.5V19l3.97 2.38a2 2 0 0 0 2.06 0l3-1.8a2 2 0 0 0 .97-1.71v-3.24a2 2 0 0 0-.97-1.71L17 10.5l-5 3Z",
61
+ key: "8zsnat"
62
+ }],
63
+ ["path", {
64
+ d: "m17 16.5-5-3",
65
+ key: "8arw3v"
66
+ }],
67
+ ["path", {
68
+ d: "m17 16.5 4.74-2.85",
69
+ key: "8rfmw"
70
+ }],
71
+ ["path", {
72
+ d: "M17 16.5v5.17",
73
+ key: "k6z78m"
74
+ }],
75
+ ["path", {
76
+ d: "M7.97 4.42A2 2 0 0 0 7 6.13v4.37l5 3 5-3V6.13a2 2 0 0 0-.97-1.71l-3-1.8a2 2 0 0 0-2.06 0l-3 1.8Z",
77
+ key: "1xygjf"
78
+ }],
79
+ ["path", {
80
+ d: "M12 8 7.26 5.15",
81
+ key: "1vbdud"
82
+ }],
83
+ ["path", {
84
+ d: "m12 8 4.74-2.85",
85
+ key: "3rx089"
86
+ }],
87
+ ["path", {
88
+ d: "M12 13.5V8",
89
+ key: "1io7kd"
90
+ }]
91
+ ]), D = w("eye", [["path", {
92
+ 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",
93
+ key: "1nclc0"
94
+ }], ["circle", {
95
+ cx: "12",
96
+ cy: "12",
97
+ r: "3",
98
+ key: "1v7zrd"
99
+ }]]), O = w("layers", [
100
+ ["path", {
101
+ 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",
102
+ key: "zw3jo"
103
+ }],
104
+ ["path", {
105
+ d: "M2 12a1 1 0 0 0 .58.91l8.6 3.91a2 2 0 0 0 1.65 0l8.58-3.9A1 1 0 0 0 22 12",
106
+ key: "1wduqc"
107
+ }],
108
+ ["path", {
109
+ 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",
110
+ key: "kqbvx6"
111
+ }]
112
+ ]), k = w("map-pin-off", [
113
+ ["path", {
114
+ d: "M12.75 7.09a3 3 0 0 1 2.16 2.16",
115
+ key: "1d4wjd"
116
+ }],
117
+ ["path", {
118
+ d: "M17.072 17.072c-1.634 2.17-3.527 3.912-4.471 4.727a1 1 0 0 1-1.202 0C9.539 20.193 4 14.993 4 10a8 8 0 0 1 1.432-4.568",
119
+ key: "12yil7"
120
+ }],
121
+ ["path", {
122
+ d: "m2 2 20 20",
123
+ key: "1ooewy"
124
+ }],
125
+ ["path", {
126
+ d: "M8.475 2.818A8 8 0 0 1 20 10c0 1.183-.31 2.377-.81 3.533",
127
+ key: "lhrkcz"
128
+ }],
129
+ ["path", {
130
+ d: "M9.13 9.13a3 3 0 0 0 3.74 3.74",
131
+ key: "13wojd"
132
+ }]
133
+ ]), A = w("mic-off", [
134
+ ["line", {
135
+ x1: "2",
136
+ x2: "22",
137
+ y1: "2",
138
+ y2: "22",
139
+ key: "a6p6uj"
140
+ }],
141
+ ["path", {
142
+ d: "M18.89 13.23A7.12 7.12 0 0 0 19 12v-2",
143
+ key: "80xlxr"
144
+ }],
145
+ ["path", {
146
+ d: "M5 10v2a7 7 0 0 0 12 5",
147
+ key: "p2k8kg"
148
+ }],
149
+ ["path", {
150
+ d: "M15 9.34V5a3 3 0 0 0-5.68-1.33",
151
+ key: "1gzdoj"
152
+ }],
153
+ ["path", {
154
+ d: "M9 9v3a3 3 0 0 0 5.12 2.12",
155
+ key: "r2i35w"
156
+ }],
157
+ ["line", {
158
+ x1: "12",
159
+ x2: "12",
160
+ y1: "19",
161
+ y2: "22",
162
+ key: "x3vr5v"
163
+ }]
164
+ ]), j = w("mic", [
165
+ ["path", {
166
+ d: "M12 2a3 3 0 0 0-3 3v7a3 3 0 0 0 6 0V5a3 3 0 0 0-3-3Z",
167
+ key: "131961"
168
+ }],
169
+ ["path", {
170
+ d: "M19 10v2a7 7 0 0 1-14 0v-2",
171
+ key: "1vc78b"
172
+ }],
173
+ ["line", {
174
+ x1: "12",
175
+ x2: "12",
176
+ y1: "19",
177
+ y2: "22",
178
+ key: "x3vr5v"
179
+ }]
180
+ ]);
181
+ //#endregion
182
+ //#region src/pipeline-analytics/widgets/chart-utils.tsx
183
+ function M({ presets: e, value: t, onChange: n }) {
184
+ return /* @__PURE__ */ m("div", {
185
+ className: "flex items-center gap-1 border border-border rounded-md p-0.5 bg-background",
186
+ children: e.map(({ id: e, label: r }) => /* @__PURE__ */ m("button", {
187
+ type: "button",
188
+ onClick: () => n(e),
189
+ 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"}`,
190
+ children: r
191
+ }, e))
192
+ });
252
193
  }
253
- function de(e = 0) {
254
- const t = Q(null), [o, r] = H(0);
255
- return ye(() => {
256
- const a = t.current;
257
- if (!a) return;
258
- const s = (l) => r(Math.max(e, Math.floor(l)));
259
- s(a.clientWidth);
260
- const d = new ResizeObserver((l) => {
261
- const f = l[0];
262
- f && s(f.contentRect.width);
263
- });
264
- return d.observe(a), () => d.disconnect();
265
- }, [e]), [t, o];
194
+ function ee(t = 0) {
195
+ let n = e(null), [a, o] = r(0);
196
+ return i(() => {
197
+ let e = n.current;
198
+ if (!e) return;
199
+ let r = (e) => o(Math.max(t, Math.floor(e)));
200
+ r(e.clientWidth);
201
+ let i = new ResizeObserver((e) => {
202
+ let t = e[0];
203
+ t && r(t.contentRect.width);
204
+ });
205
+ return i.observe(e), () => i.disconnect();
206
+ }, [t]), [n, a];
266
207
  }
267
- function lt(e, t) {
268
- const o = new Date(e), r = String(o.getHours()).padStart(2, "0"), a = String(o.getMinutes()).padStart(2, "0");
269
- if (t <= 1440 * 60 * 1e3) return `${r}:${a}`;
270
- const s = String(o.getDate()).padStart(2, "0"), d = String(o.getMonth() + 1).padStart(2, "0");
271
- return `${s}/${d} ${r}:${a}`;
208
+ function te(e, t) {
209
+ let n = new Date(e), r = String(n.getHours()).padStart(2, "0"), i = String(n.getMinutes()).padStart(2, "0");
210
+ return t <= 1440 * 60 * 1e3 ? `${r}:${i}` : `${String(n.getDate()).padStart(2, "0")}/${String(n.getMonth() + 1).padStart(2, "0")} ${r}:${i}`;
272
211
  }
273
- function Te(e, t, o, r, a) {
274
- if (t <= 1) return r;
275
- const s = o - r - a;
276
- return r + e / (t - 1) * s;
212
+ function N(e, t, n, r, i) {
213
+ if (t <= 1) return r;
214
+ let a = n - r - i;
215
+ return r + e / (t - 1) * a;
277
216
  }
278
- function we(e, t, o, r, a, s) {
279
- if (t <= e) return [];
280
- const d = t - e, l = [], f = o - r - a;
281
- for (let u = 0; u < s; u++) {
282
- const N = u / Math.max(1, s - 1), $ = e + d * N;
283
- l.push({
284
- x: r + N * f,
285
- label: lt($, d)
286
- });
287
- }
288
- return l;
217
+ function ne(e, t, n, r, i, a) {
218
+ if (t <= e) return [];
219
+ let o = t - e, s = [], c = n - r - i;
220
+ for (let t = 0; t < a; t++) {
221
+ let n = t / Math.max(1, a - 1), i = e + o * n;
222
+ s.push({
223
+ x: r + n * c,
224
+ label: te(i, o)
225
+ });
226
+ }
227
+ return s;
289
228
  }
290
- const $e = [
291
- "#3b82f6",
292
- // blue-500
293
- "#a855f7",
294
- // purple-500
295
- "#10b981",
296
- // emerald-500
297
- "#f59e0b",
298
- // amber-500
299
- "#ec4899",
300
- // pink-500
301
- "#14b8a6",
302
- // teal-500
303
- "#6366f1",
304
- // indigo-500
305
- "#ef4444"
306
- // red-500
229
+ var P = [
230
+ "#3b82f6",
231
+ "#a855f7",
232
+ "#10b981",
233
+ "#f59e0b",
234
+ "#ec4899",
235
+ "#14b8a6",
236
+ "#6366f1",
237
+ "#ef4444"
307
238
  ];
308
- function be(e) {
309
- return $e[e % $e.length] ?? "#64748b";
239
+ function re(e) {
240
+ return P[e % P.length] ?? "#64748b";
310
241
  }
311
- function ue() {
312
- const [e, t] = H(null);
313
- return { state: e, bindHover: t };
242
+ function F() {
243
+ let [e, t] = r(null);
244
+ return {
245
+ state: e,
246
+ bindHover: t
247
+ };
314
248
  }
315
- function he({ state: e, containerWidth: t }) {
316
- if (!e) return null;
317
- const r = 220 / 2, a = r + 4, s = Math.max(a, t - r - 4), d = Math.max(a, Math.min(s, e.anchorX)), l = e.anchorX - d;
318
- return /* @__PURE__ */ i(
319
- "div",
320
- {
321
- role: "tooltip",
322
- style: {
323
- position: "absolute",
324
- left: d,
325
- top: e.anchorY,
326
- transform: "translate(-50%, calc(-100% - 8px))",
327
- pointerEvents: "none"
328
- },
329
- 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]",
330
- children: [
331
- /* @__PURE__ */ n("div", { className: "font-semibold mb-1 truncate", children: e.title }),
332
- /* @__PURE__ */ n("div", { className: "space-y-0.5", children: e.rows.map((f, u) => /* @__PURE__ */ i("div", { className: "flex items-center justify-between gap-2", children: [
333
- /* @__PURE__ */ i("span", { className: "flex items-center gap-1 text-foreground-subtle truncate", children: [
334
- f.colour && /* @__PURE__ */ n("span", { className: "inline-block h-1.5 w-1.5 rounded-sm flex-shrink-0", style: { backgroundColor: f.colour } }),
335
- /* @__PURE__ */ n("span", { className: "truncate", children: f.label })
336
- ] }),
337
- /* @__PURE__ */ n("span", { className: "tabular-nums", children: f.value })
338
- ] }, u)) }),
339
- /* @__PURE__ */ n(
340
- "span",
341
- {
342
- "aria-hidden": !0,
343
- style: { left: `calc(50% + ${l}px)` },
344
- className: "absolute -bottom-1 -translate-x-1/2 h-2 w-2 rotate-45 bg-surface border-r border-b border-border"
345
- }
346
- )
347
- ]
348
- }
349
- );
249
+ function I({ state: e, containerWidth: t }) {
250
+ if (!e) return null;
251
+ let n = Math.max(114, t - 110 - 4), r = Math.max(114, Math.min(n, e.anchorX)), i = e.anchorX - r;
252
+ return /* @__PURE__ */ h("div", {
253
+ role: "tooltip",
254
+ style: {
255
+ position: "absolute",
256
+ left: r,
257
+ top: e.anchorY,
258
+ transform: "translate(-50%, calc(-100% - 8px))",
259
+ pointerEvents: "none"
260
+ },
261
+ 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]",
262
+ children: [
263
+ /* @__PURE__ */ m("div", {
264
+ className: "font-semibold mb-1 truncate",
265
+ children: e.title
266
+ }),
267
+ /* @__PURE__ */ m("div", {
268
+ className: "space-y-0.5",
269
+ children: e.rows.map((e, t) => /* @__PURE__ */ h("div", {
270
+ className: "flex items-center justify-between gap-2",
271
+ children: [/* @__PURE__ */ h("span", {
272
+ className: "flex items-center gap-1 text-foreground-subtle truncate",
273
+ children: [e.colour && /* @__PURE__ */ m("span", {
274
+ className: "inline-block h-1.5 w-1.5 rounded-sm flex-shrink-0",
275
+ style: { backgroundColor: e.colour }
276
+ }), /* @__PURE__ */ m("span", {
277
+ className: "truncate",
278
+ children: e.label
279
+ })]
280
+ }), /* @__PURE__ */ m("span", {
281
+ className: "tabular-nums",
282
+ children: e.value
283
+ })]
284
+ }, t))
285
+ }),
286
+ /* @__PURE__ */ m("span", {
287
+ "aria-hidden": !0,
288
+ style: { left: `calc(50% + ${i}px)` },
289
+ className: "absolute -bottom-1 -translate-x-1/2 h-2 w-2 rotate-45 bg-surface border-r border-b border-border"
290
+ })
291
+ ]
292
+ });
350
293
  }
351
- const ee = {
352
- "5m": { label: "5 min", windowSec: 300, sampleEveryMs: 1e3, pollIntervalMs: 5e3 },
353
- "1h": { label: "1 h", windowSec: 3600, sampleEveryMs: 5e3, pollIntervalMs: 3e4 },
354
- "24h": { label: "24 h", windowSec: 1440 * 60, sampleEveryMs: 6e4, pollIntervalMs: 3e5 }
355
- }, ct = [
356
- { id: "5m", label: ee["5m"].label },
357
- { id: "1h", label: ee["1h"].label },
358
- { id: "24h", label: ee["24h"].label }
359
- ], U = 140, S = { top: 16, right: 12, bottom: 24, left: 38 }, dt = {
360
- speech: "#3b82f6",
361
- music: "#a855f7",
362
- dog_bark: "#ec4899",
363
- glass_break: "#f43f5e",
364
- alarm: "#f59e0b",
365
- baby_cry: "#10b981"
294
+ //#endregion
295
+ //#region src/pipeline-analytics/widgets/AudioHistoryChart.tsx
296
+ var L = {
297
+ "5m": {
298
+ label: "5 min",
299
+ windowSec: 300,
300
+ sampleEveryMs: 1e3,
301
+ pollIntervalMs: 5e3
302
+ },
303
+ "1h": {
304
+ label: "1 h",
305
+ windowSec: 3600,
306
+ sampleEveryMs: 5e3,
307
+ pollIntervalMs: 3e4
308
+ },
309
+ "24h": {
310
+ label: "24 h",
311
+ windowSec: 1440 * 60,
312
+ sampleEveryMs: 6e4,
313
+ pollIntervalMs: 3e5
314
+ }
315
+ }, ie = [
316
+ {
317
+ id: "5m",
318
+ label: L["5m"].label
319
+ },
320
+ {
321
+ id: "1h",
322
+ label: L["1h"].label
323
+ },
324
+ {
325
+ id: "24h",
326
+ label: L["24h"].label
327
+ }
328
+ ], R = 140, z = {
329
+ top: 16,
330
+ right: 12,
331
+ bottom: 24,
332
+ left: 38
333
+ }, ae = {
334
+ speech: "#3b82f6",
335
+ music: "#a855f7",
336
+ dog_bark: "#ec4899",
337
+ glass_break: "#f43f5e",
338
+ alarm: "#f59e0b",
339
+ baby_cry: "#10b981"
366
340
  };
367
- function Ce(e) {
368
- return e ? dt[e.toLowerCase()] ?? "#6366f1" : "#71717a";
341
+ function oe(e) {
342
+ return e ? ae[e.toLowerCase()] ?? "#6366f1" : "#71717a";
369
343
  }
370
- function ut({ deviceId: e }) {
371
- const t = Y(), o = J(t.trpcClient, e), [r, a] = H("5m"), s = ee[r], [d, l] = de(), f = ue(), u = Q(null), N = (m) => {
372
- const h = u.current;
373
- if (!h) return m;
374
- const g = h.getBoundingClientRect();
375
- return g.width === 0 ? m : m / l * g.width;
376
- }, $ = le({
377
- queryKey: ["audio-metrics", e, "history", r],
378
- queryFn: async () => o ? await o.audioMetrics?.getHistory({
379
- windowSec: s.windowSec,
380
- sampleEveryMs: s.sampleEveryMs
381
- }) ?? null : null,
382
- enabled: !!o,
383
- refetchInterval: s.pollIntervalMs,
384
- staleTime: Math.max(1e3, s.pollIntervalMs / 2)
385
- }), F = $.data, b = F?.points ?? [], x = k(() => ft(b), [b]), C = k(() => ht(b, l, x), [b, l, x]), y = k(() => mt(b, l, x), [b, l, x]), L = k(() => pt(x), [x]), D = k(() => bt(b, l), [b, l]);
386
- return /* @__PURE__ */ i("div", { className: "rounded-lg border border-border bg-surface overflow-hidden", children: [
387
- /* @__PURE__ */ i("div", { className: "border-b border-border px-4 py-2 flex items-center justify-between gap-3", children: [
388
- /* @__PURE__ */ i("div", { className: "flex items-center gap-1.5", children: [
389
- /* @__PURE__ */ n(K, { className: "h-3.5 w-3.5 text-foreground-subtle" }),
390
- /* @__PURE__ */ n("h2", { className: "text-xs font-semibold text-foreground uppercase tracking-wider", children: "Audio Level History" })
391
- ] }),
392
- /* @__PURE__ */ n(ce, { presets: ct, value: r, onChange: a })
393
- ] }),
394
- /* @__PURE__ */ i("div", { ref: d, className: "p-3 min-w-0 relative", children: [
395
- b.length === 0 ? /* @__PURE__ */ n("div", { className: "flex items-center justify-center h-32 text-[11px] text-foreground-subtle italic", children: $.isLoading ? "Loading…" : "No audio history yet — analytics pipeline must be active." }) : l === 0 ? /* @__PURE__ */ n("div", { className: "h-32" }) : /* @__PURE__ */ i(ie, { children: [
396
- /* @__PURE__ */ i(
397
- "svg",
398
- {
399
- ref: u,
400
- role: "img",
401
- "aria-label": "Audio dBFS history",
402
- width: "100%",
403
- height: U,
404
- viewBox: `0 0 ${l} ${U}`,
405
- preserveAspectRatio: "none",
406
- className: "block",
407
- onMouseLeave: () => f.bindHover(null),
408
- children: [
409
- L.map(({ y: m, label: h }, g) => /* @__PURE__ */ i("g", { children: [
410
- /* @__PURE__ */ n("line", { x1: S.left, x2: l - S.right, y1: m, y2: m, stroke: "currentColor", strokeOpacity: 0.08, strokeWidth: 0.5 }),
411
- /* @__PURE__ */ n("text", { x: S.left - 6, y: m + 3, textAnchor: "end", className: "text-[9px] fill-foreground-subtle", children: h })
412
- ] }, `y-${g}`)),
413
- D.map(({ x: m, label: h }, g) => /* @__PURE__ */ n("text", { x: m, y: U - S.bottom + 12, textAnchor: "middle", className: "text-[9px] fill-foreground-subtle", children: h }, `x-${g}`)),
414
- y && /* @__PURE__ */ n("path", { d: y, fill: "none", stroke: "currentColor", strokeOpacity: 0.25, strokeWidth: 1, strokeDasharray: "3 2" }),
415
- C && /* @__PURE__ */ n("path", { d: C, fill: "none", stroke: "currentColor", className: "text-primary", strokeWidth: 1.5 }),
416
- b.map((m, h) => {
417
- if (m.topClass === null) return null;
418
- const g = se(h, b.length, l), _ = xe(m.dbfs, x);
419
- return /* @__PURE__ */ n(
420
- "circle",
421
- {
422
- cx: g,
423
- cy: _,
424
- r: 3,
425
- fill: Ce(m.topClass),
426
- stroke: "#000",
427
- strokeOpacity: 0.3,
428
- strokeWidth: 0.5
429
- },
430
- `dot-${h}`
431
- );
432
- }),
433
- b.map((m, h) => {
434
- const g = se(h, b.length, l), _ = xe(m.dbfs, x), p = U - S.top - S.bottom, v = b.length > 1 ? (l - S.left - S.right) / (b.length - 1) : 24;
435
- return /* @__PURE__ */ n(
436
- "rect",
437
- {
438
- x: g - v / 2,
439
- y: S.top,
440
- width: Math.max(2, v),
441
- height: p,
442
- fill: "transparent",
443
- onMouseEnter: () => {
444
- f.bindHover({
445
- anchorX: N(g),
446
- anchorY: _,
447
- title: `${Le(m.ts)} · ${m.dbfs?.toFixed(1) ?? "—"} dB`,
448
- rows: [
449
- { label: "peak (window)", value: `${m.peakDbfs.toFixed(1)} dB` },
450
- { label: "avg (window)", value: `${m.avgDbfs.toFixed(1)} dB` },
451
- ...m.topClass !== null ? [{
452
- label: m.topClass,
453
- value: m.topScore != null ? `${(m.topScore * 100).toFixed(0)}%` : "",
454
- colour: Ce(m.topClass)
455
- }] : []
456
- ]
457
- });
458
- }
459
- },
460
- `hit-${h}`
461
- );
462
- })
463
- ]
464
- }
465
- ),
466
- /* @__PURE__ */ n(he, { state: f.state, containerWidth: l })
467
- ] }),
468
- b.length > 0 && /* @__PURE__ */ i("div", { className: "flex items-center justify-between text-[10px] text-foreground-subtle mt-1", children: [
469
- /* @__PURE__ */ i("span", { children: [
470
- b.length,
471
- " samples · ~",
472
- Math.round((F?.effectiveSampleEveryMs ?? s.sampleEveryMs) / 1e3),
473
- "s spacing"
474
- ] }),
475
- /* @__PURE__ */ i("span", { children: [
476
- "peak ",
477
- b.reduce((m, h) => Math.max(m, h.peakDbfs), -1 / 0).toFixed(1),
478
- " dB"
479
- ] })
480
- ] })
481
- ] })
482
- ] });
344
+ function se({ deviceId: n }) {
345
+ let i = c(f().trpcClient, n), [a, s] = r("5m"), l = L[a], [u, d] = ee(), p = F(), _ = e(null), v = (e) => {
346
+ let t = _.current;
347
+ if (!t) return e;
348
+ let n = t.getBoundingClientRect();
349
+ return n.width === 0 ? e : e / d * n.width;
350
+ }, y = o({
351
+ queryKey: [
352
+ "audio-metrics",
353
+ n,
354
+ "history",
355
+ a
356
+ ],
357
+ queryFn: async () => i ? await i.audioMetrics?.getHistory({
358
+ windowSec: l.windowSec,
359
+ sampleEveryMs: l.sampleEveryMs
360
+ }) ?? null : null,
361
+ enabled: !!i,
362
+ refetchInterval: l.pollIntervalMs,
363
+ staleTime: Math.max(1e3, l.pollIntervalMs / 2)
364
+ }), b = y.data, x = b?.points ?? [], S = t(() => fe(x), [x]), C = t(() => ue(x, d, S), [
365
+ x,
366
+ d,
367
+ S
368
+ ]), w = t(() => de(x, d, S), [
369
+ x,
370
+ d,
371
+ S
372
+ ]), E = t(() => pe(S), [S]), D = t(() => me(x, d), [x, d]);
373
+ return /* @__PURE__ */ h("div", {
374
+ className: "rounded-lg border border-border bg-surface overflow-hidden",
375
+ children: [/* @__PURE__ */ h("div", {
376
+ className: "border-b border-border px-4 py-2 flex items-center justify-between gap-3",
377
+ children: [/* @__PURE__ */ h("div", {
378
+ className: "flex items-center gap-1.5",
379
+ children: [/* @__PURE__ */ m(T, { className: "h-3.5 w-3.5 text-foreground-subtle" }), /* @__PURE__ */ m("h2", {
380
+ className: "text-xs font-semibold text-foreground uppercase tracking-wider",
381
+ children: "Audio Level History"
382
+ })]
383
+ }), /* @__PURE__ */ m(M, {
384
+ presets: ie,
385
+ value: a,
386
+ onChange: s
387
+ })]
388
+ }), /* @__PURE__ */ h("div", {
389
+ ref: u,
390
+ className: "p-3 min-w-0 relative",
391
+ children: [x.length === 0 ? /* @__PURE__ */ m("div", {
392
+ className: "flex items-center justify-center h-32 text-[11px] text-foreground-subtle italic",
393
+ children: y.isLoading ? "Loading…" : "No audio history yet — analytics pipeline must be active."
394
+ }) : d === 0 ? /* @__PURE__ */ m("div", { className: "h-32" }) : /* @__PURE__ */ h(g, { children: [/* @__PURE__ */ h("svg", {
395
+ ref: _,
396
+ role: "img",
397
+ "aria-label": "Audio dBFS history",
398
+ width: "100%",
399
+ height: R,
400
+ viewBox: `0 0 ${d} ${R}`,
401
+ preserveAspectRatio: "none",
402
+ className: "block",
403
+ onMouseLeave: () => p.bindHover(null),
404
+ children: [
405
+ E.map(({ y: e, label: t }, n) => /* @__PURE__ */ h("g", { children: [/* @__PURE__ */ m("line", {
406
+ x1: z.left,
407
+ x2: d - z.right,
408
+ y1: e,
409
+ y2: e,
410
+ stroke: "currentColor",
411
+ strokeOpacity: .08,
412
+ strokeWidth: .5
413
+ }), /* @__PURE__ */ m("text", {
414
+ x: z.left - 6,
415
+ y: e + 3,
416
+ textAnchor: "end",
417
+ className: "text-[9px] fill-foreground-subtle",
418
+ children: t
419
+ })] }, `y-${n}`)),
420
+ D.map(({ x: e, label: t }, n) => /* @__PURE__ */ m("text", {
421
+ x: e,
422
+ y: R - z.bottom + 12,
423
+ textAnchor: "middle",
424
+ className: "text-[9px] fill-foreground-subtle",
425
+ children: t
426
+ }, `x-${n}`)),
427
+ w && /* @__PURE__ */ m("path", {
428
+ d: w,
429
+ fill: "none",
430
+ stroke: "currentColor",
431
+ strokeOpacity: .25,
432
+ strokeWidth: 1,
433
+ strokeDasharray: "3 2"
434
+ }),
435
+ C && /* @__PURE__ */ m("path", {
436
+ d: C,
437
+ fill: "none",
438
+ stroke: "currentColor",
439
+ className: "text-primary",
440
+ strokeWidth: 1.5
441
+ }),
442
+ x.map((e, t) => e.topClass === null ? null : /* @__PURE__ */ m("circle", {
443
+ cx: B(t, x.length, d),
444
+ cy: ce(e.dbfs, S),
445
+ r: 3,
446
+ fill: oe(e.topClass),
447
+ stroke: "#000",
448
+ strokeOpacity: .3,
449
+ strokeWidth: .5
450
+ }, `dot-${t}`)),
451
+ x.map((e, t) => {
452
+ let n = B(t, x.length, d), r = ce(e.dbfs, S), i = R - z.top - z.bottom, a = x.length > 1 ? (d - z.left - z.right) / (x.length - 1) : 24;
453
+ return /* @__PURE__ */ m("rect", {
454
+ x: n - a / 2,
455
+ y: z.top,
456
+ width: Math.max(2, a),
457
+ height: i,
458
+ fill: "transparent",
459
+ onMouseEnter: () => {
460
+ p.bindHover({
461
+ anchorX: v(n),
462
+ anchorY: r,
463
+ title: `${he(e.ts)} · ${e.dbfs?.toFixed(1) ?? "—"} dB`,
464
+ rows: [
465
+ {
466
+ label: "peak (window)",
467
+ value: `${e.peakDbfs.toFixed(1)} dB`
468
+ },
469
+ {
470
+ label: "avg (window)",
471
+ value: `${e.avgDbfs.toFixed(1)} dB`
472
+ },
473
+ ...e.topClass === null ? [] : [{
474
+ label: e.topClass,
475
+ value: e.topScore == null ? "—" : `${(e.topScore * 100).toFixed(0)}%`,
476
+ colour: oe(e.topClass)
477
+ }]
478
+ ]
479
+ });
480
+ }
481
+ }, `hit-${t}`);
482
+ })
483
+ ]
484
+ }), /* @__PURE__ */ m(I, {
485
+ state: p.state,
486
+ containerWidth: d
487
+ })] }), x.length > 0 && /* @__PURE__ */ h("div", {
488
+ className: "flex items-center justify-between text-[10px] text-foreground-subtle mt-1",
489
+ children: [/* @__PURE__ */ h("span", { children: [
490
+ x.length,
491
+ " samples · ~",
492
+ Math.round((b?.effectiveSampleEveryMs ?? l.sampleEveryMs) / 1e3),
493
+ "s spacing"
494
+ ] }), /* @__PURE__ */ h("span", { children: [
495
+ "peak ",
496
+ x.reduce((e, t) => Math.max(e, t.peakDbfs), -Infinity).toFixed(1),
497
+ " dB"
498
+ ] })]
499
+ })]
500
+ })]
501
+ });
483
502
  }
484
- function se(e, t, o) {
485
- if (t <= 1) return S.left;
486
- const r = o - S.left - S.right;
487
- return S.left + e / (t - 1) * r;
503
+ function B(e, t, n) {
504
+ if (t <= 1) return z.left;
505
+ let r = n - z.left - z.right;
506
+ return z.left + e / (t - 1) * r;
488
507
  }
489
- function xe(e, t) {
490
- return e === null || !Number.isFinite(e) ? ae(t.min, t) : ae(Math.max(t.min, Math.min(t.max, e)), t);
508
+ function ce(e, t) {
509
+ return le(e === null || !Number.isFinite(e) ? t.min : Math.max(t.min, Math.min(t.max, e)), t);
491
510
  }
492
- function ae(e, t) {
493
- const o = U - S.top - S.bottom, r = Math.max(1, t.max - t.min), a = (e - t.min) / r;
494
- return S.top + (1 - a) * o;
511
+ function le(e, t) {
512
+ let n = R - z.top - z.bottom, r = Math.max(1, t.max - t.min), i = (e - t.min) / r;
513
+ return z.top + (1 - i) * n;
495
514
  }
496
- function ht(e, t, o) {
497
- if (e.length === 0) return null;
498
- const r = [];
499
- for (let a = 0; a < e.length; a++) {
500
- const s = se(a, e.length, t), d = xe(e[a].dbfs, o);
501
- r.push(`${a === 0 ? "M" : "L"} ${s.toFixed(1)} ${d.toFixed(1)}`);
502
- }
503
- return r.join(" ");
515
+ function ue(e, t, n) {
516
+ if (e.length === 0) return null;
517
+ let r = [];
518
+ for (let i = 0; i < e.length; i++) {
519
+ let a = B(i, e.length, t), o = ce(e[i].dbfs, n);
520
+ r.push(`${i === 0 ? "M" : "L"} ${a.toFixed(1)} ${o.toFixed(1)}`);
521
+ }
522
+ return r.join(" ");
504
523
  }
505
- function mt(e, t, o) {
506
- if (e.length === 0) return null;
507
- const r = [];
508
- for (let a = 0; a < e.length; a++) {
509
- const s = se(a, e.length, t), d = ae(Math.max(o.min, Math.min(o.max, e[a].peakDbfs)), o);
510
- r.push(`${a === 0 ? "M" : "L"} ${s.toFixed(1)} ${d.toFixed(1)}`);
511
- }
512
- return r.join(" ");
524
+ function de(e, t, n) {
525
+ if (e.length === 0) return null;
526
+ let r = [];
527
+ for (let i = 0; i < e.length; i++) {
528
+ let a = B(i, e.length, t), o = le(Math.max(n.min, Math.min(n.max, e[i].peakDbfs)), n);
529
+ r.push(`${i === 0 ? "M" : "L"} ${a.toFixed(1)} ${o.toFixed(1)}`);
530
+ }
531
+ return r.join(" ");
513
532
  }
514
- function ft(e) {
515
- if (e.length === 0) return { min: -80, max: -40 };
516
- let t = Number.POSITIVE_INFINITY, o = Number.NEGATIVE_INFINITY;
517
- for (const s of e)
518
- s.dbfs !== null && Number.isFinite(s.dbfs) && (t = Math.min(t, s.dbfs), o = Math.max(o, s.dbfs)), Number.isFinite(s.peakDbfs) && (t = Math.min(t, s.peakDbfs), o = Math.max(o, s.peakDbfs));
519
- if (!Number.isFinite(t) || !Number.isFinite(o)) return { min: -80, max: -40 };
520
- let r = Math.max(-100, Math.floor(t - 1)), a = Math.min(0, Math.ceil(o));
521
- return a - r < 5 && (r = Math.max(-100, a - 5)), { min: r, max: a };
533
+ function fe(e) {
534
+ if (e.length === 0) return {
535
+ min: -80,
536
+ max: -40
537
+ };
538
+ let t = Infinity, n = -Infinity;
539
+ 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));
540
+ if (!Number.isFinite(t) || !Number.isFinite(n)) return {
541
+ min: -80,
542
+ max: -40
543
+ };
544
+ let r = Math.max(-100, Math.floor(t - 1)), i = Math.min(0, Math.ceil(n));
545
+ return i - r < 5 && (r = Math.max(-100, i - 5)), {
546
+ min: r,
547
+ max: i
548
+ };
522
549
  }
523
- function pt(e) {
524
- const t = [];
525
- for (let o = 0; o < 4; o++) {
526
- const r = o / 3, a = e.min + (e.max - e.min) * r;
527
- t.push({
528
- y: ae(a, e),
529
- label: `${Math.round(a)}`
530
- });
531
- }
532
- return t;
550
+ function pe(e) {
551
+ let t = [];
552
+ for (let n = 0; n < 4; n++) {
553
+ let r = n / 3, i = e.min + (e.max - e.min) * r;
554
+ t.push({
555
+ y: le(i, e),
556
+ label: `${Math.round(i)}`
557
+ });
558
+ }
559
+ return t;
533
560
  }
534
- function bt(e, t) {
535
- if (e.length === 0) return [];
536
- const o = e[0], r = e[e.length - 1], a = [], s = Math.min(5, e.length);
537
- for (let d = 0; d < s; d++) {
538
- const l = d / Math.max(1, s - 1), f = o.ts + (r.ts - o.ts) * l;
539
- a.push({
540
- x: S.left + l * (t - S.left - S.right),
541
- label: Le(f)
542
- });
543
- }
544
- return a;
561
+ function me(e, t) {
562
+ if (e.length === 0) return [];
563
+ let n = e[0], r = e[e.length - 1], i = [], a = Math.min(5, e.length);
564
+ for (let e = 0; e < a; e++) {
565
+ let o = e / Math.max(1, a - 1), s = n.ts + (r.ts - n.ts) * o;
566
+ i.push({
567
+ x: z.left + o * (t - z.left - z.right),
568
+ label: he(s)
569
+ });
570
+ }
571
+ return i;
545
572
  }
546
- function Le(e) {
547
- const t = new Date(e), o = String(t.getHours()).padStart(2, "0"), r = String(t.getMinutes()).padStart(2, "0");
548
- return `${o}:${r}`;
573
+ function he(e) {
574
+ let t = new Date(e);
575
+ return `${String(t.getHours()).padStart(2, "0")}:${String(t.getMinutes()).padStart(2, "0")}`;
549
576
  }
577
+ //#endregion
578
+ //#region src/pipeline-analytics/widgets/AudioMetricsPanel.tsx
550
579
  function ge(e) {
551
- return !Number.isFinite(e) || e <= 0 ? 60 : e > 600 ? Math.round(e / 1e3) : Math.round(e);
580
+ return !Number.isFinite(e) || e <= 0 ? 60 : Math.round(e > 600 ? e / 1e3 : e);
552
581
  }
553
- function xt({
554
- dev: e,
555
- deviceId: t,
556
- title: o = "Audio Metrics",
557
- variant: r = "full"
558
- }) {
559
- const a = Y(), s = Pe(
560
- a.trpcClient,
561
- e === void 0 && t !== void 0 ? t : null,
562
- (f) => f.audioMetrics
563
- ), d = ve(
564
- e ? e.state.audioMetrics : void 0
565
- ), l = e !== void 0 ? d : s;
566
- return l ? /* @__PURE__ */ n(_e, { title: o, variant: r, ts: l.ts, children: /* @__PURE__ */ i("div", { className: r === "compact" ? "space-y-2" : "grid grid-cols-1 2xl:grid-cols-3 gap-3", children: [
567
- /* @__PURE__ */ n(yt, { snapshot: l }),
568
- /* @__PURE__ */ n(vt, { snapshot: l }),
569
- /* @__PURE__ */ n(wt, { snapshot: l })
570
- ] }) }) : /* @__PURE__ */ n(_e, { title: o, variant: r, children: /* @__PURE__ */ n(
571
- gt,
572
- {
573
- icon: /* @__PURE__ */ n(st, { className: "h-5 w-5 mb-2 opacity-30" }),
574
- message: e || t !== void 0 ? "No audio data yet — analytics pipeline must be active and audio enabled for this device." : "Resolving device…"
575
- }
576
- ) });
582
+ function _e({ dev: e, deviceId: t, title: n = "Audio Metrics", variant: r = "full" }) {
583
+ let i = s(f().trpcClient, e === void 0 && t !== void 0 ? t : null, (e) => e.audioMetrics), a = u(e ? e.state.audioMetrics : void 0), o = e === void 0 ? i : a;
584
+ return o ? /* @__PURE__ */ m(ve, {
585
+ title: n,
586
+ variant: r,
587
+ ts: o.ts,
588
+ children: /* @__PURE__ */ h("div", {
589
+ className: r === "compact" ? "space-y-2" : "grid grid-cols-1 2xl:grid-cols-3 gap-3",
590
+ children: [
591
+ /* @__PURE__ */ m(be, { snapshot: o }),
592
+ /* @__PURE__ */ m(xe, { snapshot: o }),
593
+ /* @__PURE__ */ m(Se, { snapshot: o })
594
+ ]
595
+ })
596
+ }) : /* @__PURE__ */ m(ve, {
597
+ title: n,
598
+ variant: r,
599
+ children: /* @__PURE__ */ m(ye, {
600
+ icon: /* @__PURE__ */ m(A, { className: "h-5 w-5 mb-2 opacity-30" }),
601
+ message: e || t !== void 0 ? "No audio data yet — analytics pipeline must be active and audio enabled for this device." : "Resolving device…"
602
+ })
603
+ });
577
604
  }
578
- function _e({ title: e, variant: t, ts: o, children: r }) {
579
- const a = o ? Math.max(0, Math.floor((Date.now() - o) / 1e3)) : null;
580
- return /* @__PURE__ */ i("div", { className: t === "compact" ? "rounded-md border border-border/60 bg-surface/60 p-3" : "rounded-lg border border-border bg-surface overflow-hidden", children: [
581
- /* @__PURE__ */ i("div", { className: t === "compact" ? "flex items-center justify-between mb-2" : "border-b border-border px-4 py-2 flex items-center justify-between", children: [
582
- /* @__PURE__ */ n("h2", { className: "text-xs font-semibold text-foreground uppercase tracking-wider", children: e }),
583
- a !== null && /* @__PURE__ */ n("span", { className: "text-[10px] text-foreground-subtle", children: a === 0 ? "just now" : `${a}s ago` })
584
- ] }),
585
- /* @__PURE__ */ n("div", { className: t === "compact" ? "" : "p-3", children: r })
586
- ] });
605
+ function ve({ title: e, variant: t, ts: n, children: r }) {
606
+ let i = n ? Math.max(0, Math.floor((Date.now() - n) / 1e3)) : null;
607
+ return /* @__PURE__ */ h("div", {
608
+ className: t === "compact" ? "rounded-md border border-border/60 bg-surface/60 p-3" : "rounded-lg border border-border bg-surface overflow-hidden",
609
+ children: [/* @__PURE__ */ h("div", {
610
+ className: t === "compact" ? "flex items-center justify-between mb-2" : "border-b border-border px-4 py-2 flex items-center justify-between",
611
+ children: [/* @__PURE__ */ m("h2", {
612
+ className: "text-xs font-semibold text-foreground uppercase tracking-wider",
613
+ children: e
614
+ }), i !== null && /* @__PURE__ */ m("span", {
615
+ className: "text-[10px] text-foreground-subtle",
616
+ children: i === 0 ? "just now" : `${i}s ago`
617
+ })]
618
+ }), /* @__PURE__ */ m("div", {
619
+ className: t === "compact" ? "" : "p-3",
620
+ children: r
621
+ })]
622
+ });
587
623
  }
588
- function gt({ icon: e, message: t }) {
589
- return /* @__PURE__ */ i("div", { className: "px-4 py-6 flex flex-col items-center text-center text-foreground-subtle", children: [
590
- e,
591
- /* @__PURE__ */ n("p", { className: "text-[11px]", children: t })
592
- ] });
624
+ function ye({ icon: e, message: t }) {
625
+ return /* @__PURE__ */ h("div", {
626
+ className: "px-4 py-6 flex flex-col items-center text-center text-foreground-subtle",
627
+ children: [e, /* @__PURE__ */ m("p", {
628
+ className: "text-[11px]",
629
+ children: t
630
+ })]
631
+ });
593
632
  }
594
- function yt({ snapshot: e }) {
595
- const { dbfs: t } = e.level, o = Number.isFinite(t) ? t : -80, r = Math.max(-80, Math.min(0, o)), a = (r + 80) / 80 * 100, s = r > -10 ? "bg-danger" : r > -25 ? "bg-warning" : "bg-primary";
596
- return /* @__PURE__ */ i("div", { className: "rounded-md border border-border/60 bg-background/40 px-3 py-2", children: [
597
- /* @__PURE__ */ i("div", { className: "flex items-center gap-1.5 mb-1.5 text-[11px] uppercase tracking-wider text-foreground-subtle", children: [
598
- /* @__PURE__ */ n(K, { className: "h-3.5 w-3.5" }),
599
- /* @__PURE__ */ n("span", { children: "Level" }),
600
- /* @__PURE__ */ n("span", { className: "ml-auto text-base font-semibold text-foreground tabular-nums normal-case tracking-normal", children: Number.isFinite(t) ? `${t.toFixed(1)} dB` : "silent" })
601
- ] }),
602
- /* @__PURE__ */ n("div", { className: "h-1.5 rounded-full bg-foreground-subtle/15 overflow-hidden", children: /* @__PURE__ */ n(
603
- "div",
604
- {
605
- className: `h-full ${s} transition-all`,
606
- style: { width: `${a}%` }
607
- }
608
- ) }),
609
- /* @__PURE__ */ i("div", { className: "flex justify-between text-[9px] text-foreground-subtle mt-1 tabular-nums", children: [
610
- /* @__PURE__ */ i("span", { children: [
611
- "peak ",
612
- Number.isFinite(e.peakDbfs) ? e.peakDbfs.toFixed(1) : "",
613
- " dB"
614
- ] }),
615
- /* @__PURE__ */ i("span", { children: [
616
- "avg ",
617
- e.avgDbfs.toFixed(1),
618
- " dB"
619
- ] }),
620
- /* @__PURE__ */ i("span", { children: [
621
- ge(e.windowSec),
622
- "s window"
623
- ] })
624
- ] })
625
- ] });
633
+ function be({ snapshot: e }) {
634
+ let { dbfs: t } = e.level, n = Math.max(-80, Math.min(0, Number.isFinite(t) ? t : -80)), r = (n + 80) / 80 * 100, i = n > -10 ? "bg-danger" : n > -25 ? "bg-warning" : "bg-primary";
635
+ return /* @__PURE__ */ h("div", {
636
+ className: "rounded-md border border-border/60 bg-background/40 px-3 py-2",
637
+ children: [
638
+ /* @__PURE__ */ h("div", {
639
+ className: "flex items-center gap-1.5 mb-1.5 text-[11px] uppercase tracking-wider text-foreground-subtle",
640
+ children: [
641
+ /* @__PURE__ */ m(T, { className: "h-3.5 w-3.5" }),
642
+ /* @__PURE__ */ m("span", { children: "Level" }),
643
+ /* @__PURE__ */ m("span", {
644
+ className: "ml-auto text-base font-semibold text-foreground tabular-nums normal-case tracking-normal",
645
+ children: Number.isFinite(t) ? `${t.toFixed(1)} dB` : "silent"
646
+ })
647
+ ]
648
+ }),
649
+ /* @__PURE__ */ m("div", {
650
+ className: "h-1.5 rounded-full bg-foreground-subtle/15 overflow-hidden",
651
+ children: /* @__PURE__ */ m("div", {
652
+ className: `h-full ${i} transition-all`,
653
+ style: { width: `${r}%` }
654
+ })
655
+ }),
656
+ /* @__PURE__ */ h("div", {
657
+ className: "flex justify-between text-[9px] text-foreground-subtle mt-1 tabular-nums",
658
+ children: [
659
+ /* @__PURE__ */ h("span", { children: [
660
+ "peak ",
661
+ Number.isFinite(e.peakDbfs) ? e.peakDbfs.toFixed(1) : "—",
662
+ " dB"
663
+ ] }),
664
+ /* @__PURE__ */ h("span", { children: [
665
+ "avg ",
666
+ e.avgDbfs.toFixed(1),
667
+ " dB"
668
+ ] }),
669
+ /* @__PURE__ */ h("span", { children: [ge(e.windowSec), "s window"] })
670
+ ]
671
+ })
672
+ ]
673
+ });
626
674
  }
627
- function vt({ snapshot: e }) {
628
- const { current: t } = e;
629
- return /* @__PURE__ */ i("div", { className: "rounded-md border border-border/60 bg-background/40 px-3 py-2", children: [
630
- /* @__PURE__ */ i("div", { className: "flex items-center gap-1.5 mb-1.5 text-[11px] uppercase tracking-wider text-foreground-subtle", children: [
631
- /* @__PURE__ */ n(it, { className: "h-3.5 w-3.5" }),
632
- /* @__PURE__ */ n("span", { children: "Now" })
633
- ] }),
634
- t ? /* @__PURE__ */ i("div", { className: "flex flex-col gap-1", children: [
635
- /* @__PURE__ */ n("span", { className: "text-sm font-semibold text-foreground", children: t.className }),
636
- /* @__PURE__ */ i("span", { className: "text-[10px] text-foreground-subtle tabular-nums", children: [
637
- "score ",
638
- (t.score * 100).toFixed(0),
639
- "% ",
640
- Math.max(0, Math.floor((Date.now() - t.timestamp) / 1e3)),
641
- "s ago"
642
- ] })
643
- ] }) : /* @__PURE__ */ n("span", { className: "text-[10px] text-foreground-subtle italic", children: "silence / unclassified" })
644
- ] });
675
+ function xe({ snapshot: e }) {
676
+ let { current: t } = e;
677
+ return /* @__PURE__ */ h("div", {
678
+ className: "rounded-md border border-border/60 bg-background/40 px-3 py-2",
679
+ children: [/* @__PURE__ */ h("div", {
680
+ className: "flex items-center gap-1.5 mb-1.5 text-[11px] uppercase tracking-wider text-foreground-subtle",
681
+ children: [/* @__PURE__ */ m(j, { className: "h-3.5 w-3.5" }), /* @__PURE__ */ m("span", { children: "Now" })]
682
+ }), t ? /* @__PURE__ */ h("div", {
683
+ className: "flex flex-col gap-1",
684
+ children: [/* @__PURE__ */ m("span", {
685
+ className: "text-sm font-semibold text-foreground",
686
+ children: t.className
687
+ }), /* @__PURE__ */ h("span", {
688
+ className: "text-[10px] text-foreground-subtle tabular-nums",
689
+ children: [
690
+ "score ",
691
+ (t.score * 100).toFixed(0),
692
+ "% —",
693
+ " ",
694
+ Math.max(0, Math.floor((Date.now() - t.timestamp) / 1e3)),
695
+ "s ago"
696
+ ]
697
+ })]
698
+ }) : /* @__PURE__ */ m("span", {
699
+ className: "text-[10px] text-foreground-subtle italic",
700
+ children: "silence / unclassified"
701
+ })]
702
+ });
645
703
  }
646
- function wt({ snapshot: e }) {
647
- return e.byClass.length === 0 ? /* @__PURE__ */ i("div", { className: "rounded-md border border-border/40 bg-background/20 px-3 py-2", children: [
648
- /* @__PURE__ */ i("div", { className: "flex items-center gap-1.5 mb-1.5 text-[11px] uppercase tracking-wider text-foreground-subtle", children: [
649
- /* @__PURE__ */ n(K, { className: "h-3.5 w-3.5" }),
650
- /* @__PURE__ */ i("span", { children: [
651
- "Last ",
652
- ge(e.windowSec),
653
- "s"
654
- ] })
655
- ] }),
656
- /* @__PURE__ */ n("span", { className: "text-[10px] text-foreground-subtle italic", children: "no classified audio" })
657
- ] }) : /* @__PURE__ */ i("div", { className: "rounded-md border border-border/60 bg-background/40", children: [
658
- /* @__PURE__ */ i("div", { 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", children: [
659
- /* @__PURE__ */ n(K, { className: "h-3.5 w-3.5" }),
660
- /* @__PURE__ */ i("span", { children: [
661
- "Last ",
662
- ge(e.windowSec),
663
- "s"
664
- ] }),
665
- /* @__PURE__ */ n("span", { className: "ml-auto text-[10px] normal-case tracking-normal", children: e.byClass.length })
666
- ] }),
667
- /* @__PURE__ */ n("div", { className: "divide-y divide-border/30", children: e.byClass.slice(0, 8).map((t) => /* @__PURE__ */ i("div", { className: "px-3 py-1.5 flex items-center justify-between text-xs", children: [
668
- /* @__PURE__ */ n("span", { className: "font-medium text-foreground truncate", children: t.className }),
669
- /* @__PURE__ */ i("span", { className: "flex items-center gap-2 tabular-nums text-foreground-subtle", children: [
670
- /* @__PURE__ */ i("span", { children: [
671
- t.hits,
672
- "× hits"
673
- ] }),
674
- /* @__PURE__ */ i("span", { className: "rounded-full px-1.5 py-0.5 text-[10px] bg-primary/10 text-primary border border-primary/20", children: [
675
- (t.peakScore * 100).toFixed(0),
676
- "%"
677
- ] })
678
- ] })
679
- ] }, t.className)) })
680
- ] });
704
+ function Se({ snapshot: e }) {
705
+ return e.byClass.length === 0 ? /* @__PURE__ */ h("div", {
706
+ className: "rounded-md border border-border/40 bg-background/20 px-3 py-2",
707
+ children: [/* @__PURE__ */ h("div", {
708
+ className: "flex items-center gap-1.5 mb-1.5 text-[11px] uppercase tracking-wider text-foreground-subtle",
709
+ children: [/* @__PURE__ */ m(T, { className: "h-3.5 w-3.5" }), /* @__PURE__ */ h("span", { children: [
710
+ "Last ",
711
+ ge(e.windowSec),
712
+ "s"
713
+ ] })]
714
+ }), /* @__PURE__ */ m("span", {
715
+ className: "text-[10px] text-foreground-subtle italic",
716
+ children: "no classified audio"
717
+ })]
718
+ }) : /* @__PURE__ */ h("div", {
719
+ className: "rounded-md border border-border/60 bg-background/40",
720
+ children: [/* @__PURE__ */ h("div", {
721
+ 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",
722
+ children: [
723
+ /* @__PURE__ */ m(T, { className: "h-3.5 w-3.5" }),
724
+ /* @__PURE__ */ h("span", { children: [
725
+ "Last ",
726
+ ge(e.windowSec),
727
+ "s"
728
+ ] }),
729
+ /* @__PURE__ */ m("span", {
730
+ className: "ml-auto text-[10px] normal-case tracking-normal",
731
+ children: e.byClass.length
732
+ })
733
+ ]
734
+ }), /* @__PURE__ */ m("div", {
735
+ className: "divide-y divide-border/30",
736
+ children: e.byClass.slice(0, 8).map((e) => /* @__PURE__ */ h("div", {
737
+ className: "px-3 py-1.5 flex items-center justify-between text-xs",
738
+ children: [/* @__PURE__ */ m("span", {
739
+ className: "font-medium text-foreground truncate",
740
+ children: e.className
741
+ }), /* @__PURE__ */ h("span", {
742
+ className: "flex items-center gap-2 tabular-nums text-foreground-subtle",
743
+ children: [/* @__PURE__ */ h("span", { children: [e.hits, "× hits"] }), /* @__PURE__ */ h("span", {
744
+ className: "rounded-full px-1.5 py-0.5 text-[10px] bg-primary/10 text-primary border border-primary/20",
745
+ children: [(e.peakScore * 100).toFixed(0), "%"]
746
+ })]
747
+ })]
748
+ }, e.className))
749
+ })]
750
+ });
681
751
  }
682
- const te = {
683
- "5m": { label: "5 min", windowMs: 5 * 6e4, resolution: "minute", pollIntervalMs: 5e3 },
684
- "30m": { label: "30 min", windowMs: 30 * 6e4, resolution: "minute", pollIntervalMs: 15e3 },
685
- "1h": { label: "1 h", windowMs: 60 * 6e4, resolution: "5min", pollIntervalMs: 3e4 }
686
- }, Nt = [
687
- { id: "5m", label: te["5m"].label },
688
- { id: "30m", label: te["30m"].label },
689
- { id: "1h", label: te["1h"].label }
690
- ], X = 140, M = { top: 14, right: 12, bottom: 24, left: 32 }, P = "__all__";
691
- function kt({ deviceId: e }) {
692
- const t = Y(), o = J(t.trpcClient, e), [r, a] = H("5m"), [s, d] = H(P), l = te[r], [f, u] = de(), N = ue(), $ = Q(null), F = (p) => {
693
- const v = $.current;
694
- if (!v) return p;
695
- const c = v.getBoundingClientRect();
696
- return c.width === 0 ? p : p / u * c.width;
697
- }, b = ve(o?.state.zoneAnalytics), x = k(() => {
698
- const p = /* @__PURE__ */ new Set();
699
- if (b?.frame.byClass)
700
- for (const v of Object.keys(b.frame.byClass)) p.add(v);
701
- if (b?.zones)
702
- for (const v of b.zones)
703
- for (const c of Object.keys(v.byClass)) p.add(c);
704
- return [...p].sort();
705
- }, [b]);
706
- ye(() => {
707
- s !== P && !x.includes(s) && d(P);
708
- }, [s, x]);
709
- const C = le({
710
- queryKey: ["zone-analytics", e, "cameraHistory", r, s],
711
- queryFn: async () => {
712
- if (!o) return [];
713
- const p = Date.now();
714
- return await o.zoneAnalytics?.getCameraHistory({
715
- from: p - l.windowMs,
716
- to: p,
717
- resolution: l.resolution,
718
- ...s === P ? {} : { className: s }
719
- }) ?? [];
720
- },
721
- enabled: !!o,
722
- refetchInterval: l.pollIntervalMs,
723
- staleTime: Math.max(1e3, l.pollIntervalMs / 2)
724
- }), y = C.data ?? [], L = C.dataUpdatedAt > 0 ? C.dataUpdatedAt : Date.now(), D = L - l.windowMs, m = k(() => {
725
- if (y.length === 0) return 1;
726
- const p = y.reduce((v, c) => Math.max(v, c.count), 0);
727
- return Math.max(1, Math.ceil(p * 1.15));
728
- }, [y]), h = k(
729
- () => Mt(y, u, m),
730
- [y, u, m]
731
- ), g = k(
732
- () => we(D, L, u, M.left, M.right, 5),
733
- [D, L, u]
734
- ), _ = k(() => $t(m), [m]);
735
- return /* @__PURE__ */ i("div", { className: "rounded-lg border border-border bg-surface overflow-hidden", children: [
736
- /* @__PURE__ */ i("div", { className: "border-b border-border px-4 py-2 flex items-center justify-between gap-3", children: [
737
- /* @__PURE__ */ i("div", { className: "flex items-center gap-1.5", children: [
738
- /* @__PURE__ */ n(oe, { className: "h-3.5 w-3.5 text-foreground-subtle" }),
739
- /* @__PURE__ */ n("h2", { className: "text-xs font-semibold text-foreground uppercase tracking-wider", children: "Occupancy History" })
740
- ] }),
741
- /* @__PURE__ */ i("div", { className: "flex items-center gap-2", children: [
742
- x.length > 0 && /* @__PURE__ */ i(
743
- "select",
744
- {
745
- value: s,
746
- onChange: (p) => d(p.target.value),
747
- 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",
748
- title: "Filter by detected class",
749
- children: [
750
- /* @__PURE__ */ n("option", { value: P, children: "All classes" }),
751
- x.map((p) => /* @__PURE__ */ n("option", { value: p, children: p }, p))
752
- ]
753
- }
754
- ),
755
- /* @__PURE__ */ n(ce, { presets: Nt, value: r, onChange: a })
756
- ] })
757
- ] }),
758
- /* @__PURE__ */ i("div", { ref: f, className: "p-3 min-w-0 relative", children: [
759
- y.length === 0 ? /* @__PURE__ */ n("div", { className: "flex items-center justify-center h-32 text-[11px] text-foreground-subtle italic", children: C.isLoading ? "Loading…" : "No occupancy history yet — analytics pipeline must be active." }) : u === 0 ? /* @__PURE__ */ n("div", { className: "h-32" }) : /* @__PURE__ */ i(ie, { children: [
760
- /* @__PURE__ */ i(
761
- "svg",
762
- {
763
- ref: $,
764
- role: "img",
765
- "aria-label": "Frame occupancy history",
766
- width: "100%",
767
- height: X,
768
- viewBox: `0 0 ${u} ${X}`,
769
- preserveAspectRatio: "none",
770
- className: "block",
771
- onMouseLeave: () => N.bindHover(null),
772
- children: [
773
- _.map(({ y: p, label: v }, c) => /* @__PURE__ */ i("g", { children: [
774
- /* @__PURE__ */ n("line", { x1: M.left, x2: u - M.right, y1: p, y2: p, stroke: "currentColor", strokeOpacity: 0.08, strokeWidth: 0.5 }),
775
- /* @__PURE__ */ n("text", { x: M.left - 6, y: p + 3, textAnchor: "end", className: "text-[9px] fill-foreground-subtle", children: v })
776
- ] }, `y-${c}`)),
777
- g.map(({ x: p, label: v }, c) => /* @__PURE__ */ n("text", { x: p, y: X - M.bottom + 12, textAnchor: "middle", className: "text-[9px] fill-foreground-subtle", children: v }, `x-${c}`)),
778
- h && /* @__PURE__ */ n("path", { d: h, fill: "none", stroke: "currentColor", className: "text-primary", strokeWidth: 1.5 }),
779
- y.map((p, v) => {
780
- const c = Te(v, y.length, u, M.left, M.right), w = De(p.count, m), I = X - M.top - M.bottom, R = y.length > 1 ? (u - M.left - M.right) / (y.length - 1) : 24;
781
- return /* @__PURE__ */ i("g", { children: [
782
- /* @__PURE__ */ n("circle", { cx: c, cy: w, r: 2, fill: "currentColor", className: "text-primary" }),
783
- /* @__PURE__ */ n(
784
- "rect",
785
- {
786
- x: c - R / 2,
787
- y: M.top,
788
- width: Math.max(2, R),
789
- height: I,
790
- fill: "transparent",
791
- onMouseEnter: () => {
792
- N.bindHover({
793
- anchorX: F(c),
794
- anchorY: w,
795
- title: `${Ct(p.ts)} · ${p.count} object${p.count === 1 ? "" : "s"}`,
796
- rows: [
797
- { label: "Class", value: s === P ? "all" : s },
798
- { label: "Bucket", value: l.resolution }
799
- ]
800
- });
801
- }
802
- }
803
- )
804
- ] }, `${p.ts}-${v}`);
805
- })
806
- ]
807
- }
808
- ),
809
- /* @__PURE__ */ n(he, { state: N.state, containerWidth: u })
810
- ] }),
811
- y.length > 0 && /* @__PURE__ */ i("div", { className: "flex items-center justify-between text-[10px] text-foreground-subtle mt-1", children: [
812
- /* @__PURE__ */ i("span", { children: [
813
- y.length,
814
- " bucket",
815
- y.length === 1 ? "" : "s",
816
- " · ",
817
- l.resolution,
818
- " resolution"
819
- ] }),
820
- /* @__PURE__ */ i("span", { children: [
821
- "peak ",
822
- y.reduce((p, v) => Math.max(p, v.count), 0),
823
- " obj"
824
- ] })
825
- ] })
826
- ] })
827
- ] });
752
+ //#endregion
753
+ //#region src/pipeline-analytics/widgets/OccupancyHistoryChart.tsx
754
+ var V = {
755
+ "5m": {
756
+ label: "5 min",
757
+ windowMs: 5 * 6e4,
758
+ resolution: "minute",
759
+ pollIntervalMs: 5e3
760
+ },
761
+ "30m": {
762
+ label: "30 min",
763
+ windowMs: 30 * 6e4,
764
+ resolution: "minute",
765
+ pollIntervalMs: 15e3
766
+ },
767
+ "1h": {
768
+ label: "1 h",
769
+ windowMs: 60 * 6e4,
770
+ resolution: "5min",
771
+ pollIntervalMs: 3e4
772
+ }
773
+ }, Ce = [
774
+ {
775
+ id: "5m",
776
+ label: V["5m"].label
777
+ },
778
+ {
779
+ id: "30m",
780
+ label: V["30m"].label
781
+ },
782
+ {
783
+ id: "1h",
784
+ label: V["1h"].label
785
+ }
786
+ ], H = 140, U = {
787
+ top: 14,
788
+ right: 12,
789
+ bottom: 24,
790
+ left: 32
791
+ }, W = "__all__";
792
+ function we({ deviceId: n }) {
793
+ let a = c(f().trpcClient, n), [s, l] = r("5m"), [d, p] = r(W), _ = V[s], [v, y] = ee(), b = F(), x = e(null), S = (e) => {
794
+ let t = x.current;
795
+ if (!t) return e;
796
+ let n = t.getBoundingClientRect();
797
+ return n.width === 0 ? e : e / y * n.width;
798
+ }, C = u(a?.state.zoneAnalytics), w = t(() => {
799
+ let e = /* @__PURE__ */ new Set();
800
+ if (C?.frame.byClass) for (let t of Object.keys(C.frame.byClass)) e.add(t);
801
+ if (C?.zones) for (let t of C.zones) for (let n of Object.keys(t.byClass)) e.add(n);
802
+ return [...e].toSorted();
803
+ }, [C]);
804
+ i(() => {
805
+ d !== W && !w.includes(d) && p(W);
806
+ }, [d, w]);
807
+ let T = o({
808
+ queryKey: [
809
+ "zone-analytics",
810
+ n,
811
+ "cameraHistory",
812
+ s,
813
+ d
814
+ ],
815
+ queryFn: async () => {
816
+ if (!a) return [];
817
+ let e = Date.now();
818
+ return await a.zoneAnalytics?.getCameraHistory({
819
+ from: e - _.windowMs,
820
+ to: e,
821
+ resolution: _.resolution,
822
+ ...d === W ? {} : { className: d }
823
+ }) ?? [];
824
+ },
825
+ enabled: !!a,
826
+ refetchInterval: _.pollIntervalMs,
827
+ staleTime: Math.max(1e3, _.pollIntervalMs / 2)
828
+ }), E = T.data ?? [], D = T.dataUpdatedAt > 0 ? T.dataUpdatedAt : Date.now(), k = D - _.windowMs, A = t(() => {
829
+ if (E.length === 0) return 1;
830
+ let e = E.reduce((e, t) => Math.max(e, t.count), 0);
831
+ return Math.max(1, Math.ceil(e * 1.15));
832
+ }, [E]), j = t(() => Ee(E, y, A), [
833
+ E,
834
+ y,
835
+ A
836
+ ]), te = t(() => ne(k, D, y, U.left, U.right, 5), [
837
+ k,
838
+ D,
839
+ y
840
+ ]), P = t(() => De(A), [A]);
841
+ return /* @__PURE__ */ h("div", {
842
+ className: "rounded-lg border border-border bg-surface overflow-hidden",
843
+ children: [/* @__PURE__ */ h("div", {
844
+ className: "border-b border-border px-4 py-2 flex items-center justify-between gap-3",
845
+ children: [/* @__PURE__ */ h("div", {
846
+ className: "flex items-center gap-1.5",
847
+ children: [/* @__PURE__ */ m(O, { className: "h-3.5 w-3.5 text-foreground-subtle" }), /* @__PURE__ */ m("h2", {
848
+ className: "text-xs font-semibold text-foreground uppercase tracking-wider",
849
+ children: "Occupancy History"
850
+ })]
851
+ }), /* @__PURE__ */ h("div", {
852
+ className: "flex items-center gap-2",
853
+ children: [w.length > 0 && /* @__PURE__ */ h("select", {
854
+ value: d,
855
+ onChange: (e) => p(e.target.value),
856
+ 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",
857
+ title: "Filter by detected class",
858
+ children: [/* @__PURE__ */ m("option", {
859
+ value: W,
860
+ children: "All classes"
861
+ }), w.map((e) => /* @__PURE__ */ m("option", {
862
+ value: e,
863
+ children: e
864
+ }, e))]
865
+ }), /* @__PURE__ */ m(M, {
866
+ presets: Ce,
867
+ value: s,
868
+ onChange: l
869
+ })]
870
+ })]
871
+ }), /* @__PURE__ */ h("div", {
872
+ ref: v,
873
+ className: "p-3 min-w-0 relative",
874
+ children: [E.length === 0 ? /* @__PURE__ */ m("div", {
875
+ className: "flex items-center justify-center h-32 text-[11px] text-foreground-subtle italic",
876
+ children: T.isLoading ? "Loading…" : "No occupancy history yet — analytics pipeline must be active."
877
+ }) : y === 0 ? /* @__PURE__ */ m("div", { className: "h-32" }) : /* @__PURE__ */ h(g, { children: [/* @__PURE__ */ h("svg", {
878
+ ref: x,
879
+ role: "img",
880
+ "aria-label": "Frame occupancy history",
881
+ width: "100%",
882
+ height: H,
883
+ viewBox: `0 0 ${y} ${H}`,
884
+ preserveAspectRatio: "none",
885
+ className: "block",
886
+ onMouseLeave: () => b.bindHover(null),
887
+ children: [
888
+ P.map(({ y: e, label: t }, n) => /* @__PURE__ */ h("g", { children: [/* @__PURE__ */ m("line", {
889
+ x1: U.left,
890
+ x2: y - U.right,
891
+ y1: e,
892
+ y2: e,
893
+ stroke: "currentColor",
894
+ strokeOpacity: .08,
895
+ strokeWidth: .5
896
+ }), /* @__PURE__ */ m("text", {
897
+ x: U.left - 6,
898
+ y: e + 3,
899
+ textAnchor: "end",
900
+ className: "text-[9px] fill-foreground-subtle",
901
+ children: t
902
+ })] }, `y-${n}`)),
903
+ te.map(({ x: e, label: t }, n) => /* @__PURE__ */ m("text", {
904
+ x: e,
905
+ y: H - U.bottom + 12,
906
+ textAnchor: "middle",
907
+ className: "text-[9px] fill-foreground-subtle",
908
+ children: t
909
+ }, `x-${n}`)),
910
+ j && /* @__PURE__ */ m("path", {
911
+ d: j,
912
+ fill: "none",
913
+ stroke: "currentColor",
914
+ className: "text-primary",
915
+ strokeWidth: 1.5
916
+ }),
917
+ E.map((e, t) => {
918
+ let n = N(t, E.length, y, U.left, U.right), r = Te(e.count, A), i = H - U.top - U.bottom, a = E.length > 1 ? (y - U.left - U.right) / (E.length - 1) : 24;
919
+ return /* @__PURE__ */ h("g", { children: [/* @__PURE__ */ m("circle", {
920
+ cx: n,
921
+ cy: r,
922
+ r: 2,
923
+ fill: "currentColor",
924
+ className: "text-primary"
925
+ }), /* @__PURE__ */ m("rect", {
926
+ x: n - a / 2,
927
+ y: U.top,
928
+ width: Math.max(2, a),
929
+ height: i,
930
+ fill: "transparent",
931
+ onMouseEnter: () => {
932
+ b.bindHover({
933
+ anchorX: S(n),
934
+ anchorY: r,
935
+ title: `${Oe(e.ts)} · ${e.count} object${e.count === 1 ? "" : "s"}`,
936
+ rows: [{
937
+ label: "Class",
938
+ value: d === W ? "all" : d
939
+ }, {
940
+ label: "Bucket",
941
+ value: _.resolution
942
+ }]
943
+ });
944
+ }
945
+ })] }, `${e.ts}-${t}`);
946
+ })
947
+ ]
948
+ }), /* @__PURE__ */ m(I, {
949
+ state: b.state,
950
+ containerWidth: y
951
+ })] }), E.length > 0 && /* @__PURE__ */ h("div", {
952
+ className: "flex items-center justify-between text-[10px] text-foreground-subtle mt-1",
953
+ children: [/* @__PURE__ */ h("span", { children: [
954
+ E.length,
955
+ " bucket",
956
+ E.length === 1 ? "" : "s",
957
+ " · ",
958
+ _.resolution,
959
+ " ",
960
+ "resolution"
961
+ ] }), /* @__PURE__ */ h("span", { children: [
962
+ "peak ",
963
+ E.reduce((e, t) => Math.max(e, t.count), 0),
964
+ " obj"
965
+ ] })]
966
+ })]
967
+ })]
968
+ });
828
969
  }
829
- function De(e, t) {
830
- const o = X - M.top - M.bottom, r = Math.min(1, e / t);
831
- return M.top + (1 - r) * o;
970
+ function Te(e, t) {
971
+ let n = H - U.top - U.bottom, r = Math.min(1, e / t);
972
+ return U.top + (1 - r) * n;
832
973
  }
833
- function Mt(e, t, o) {
834
- if (e.length === 0) return null;
835
- const r = [];
836
- for (let a = 0; a < e.length; a++) {
837
- const s = Te(a, e.length, t, M.left, M.right), d = De(e[a].count, o);
838
- r.push(`${a === 0 ? "M" : "L"} ${s.toFixed(1)} ${d.toFixed(1)}`);
839
- }
840
- return r.join(" ");
974
+ function Ee(e, t, n) {
975
+ if (e.length === 0) return null;
976
+ let r = [];
977
+ for (let i = 0; i < e.length; i++) {
978
+ let a = N(i, e.length, t, U.left, U.right), o = Te(e[i].count, n);
979
+ r.push(`${i === 0 ? "M" : "L"} ${a.toFixed(1)} ${o.toFixed(1)}`);
980
+ }
981
+ return r.join(" ");
841
982
  }
842
- function $t(e) {
843
- const t = [];
844
- for (let o = 0; o < 4; o++) {
845
- const r = o / 3, a = Math.round(e * r), s = X - M.top - M.bottom;
846
- t.push({
847
- y: M.top + (1 - r) * s,
848
- label: `${a}`
849
- });
850
- }
851
- return t;
983
+ function De(e) {
984
+ let t = [];
985
+ for (let n = 0; n < 4; n++) {
986
+ let r = n / 3, i = Math.round(e * r), a = H - U.top - U.bottom;
987
+ t.push({
988
+ y: U.top + (1 - r) * a,
989
+ label: `${i}`
990
+ });
991
+ }
992
+ return t;
852
993
  }
853
- function Ct(e) {
854
- const t = new Date(e), o = String(t.getHours()).padStart(2, "0"), r = String(t.getMinutes()).padStart(2, "0");
855
- return `${o}:${r}`;
994
+ function Oe(e) {
995
+ let t = new Date(e);
996
+ return `${String(t.getHours()).padStart(2, "0")}:${String(t.getMinutes()).padStart(2, "0")}`;
856
997
  }
857
- const ne = {
858
- "1h": { label: "1 h", windowMs: 60 * 6e4, bucketMs: 6e4, pollIntervalMs: 15e3 },
859
- "6h": { label: "6 h", windowMs: 360 * 6e4, bucketMs: 5 * 6e4, pollIntervalMs: 6e4 },
860
- "24h": { label: "24 h", windowMs: 1440 * 6e4, bucketMs: 15 * 6e4, pollIntervalMs: 3e5 }
861
- }, _t = [
862
- { id: "1h", label: ne["1h"].label },
863
- { id: "6h", label: ne["6h"].label },
864
- { id: "24h", label: ne["24h"].label }
865
- ], St = 5e3, V = 140, T = { top: 14, right: 12, bottom: 24, left: 32 };
866
- function It({ deviceId: e }) {
867
- const t = Y(), o = J(t.trpcClient, e), [r, a] = H("1h"), s = ne[r], [d, l] = de(), f = ue(), u = Q(null), N = (h) => {
868
- const g = u.current;
869
- if (!g) return h;
870
- const _ = g.getBoundingClientRect();
871
- return _.width === 0 ? h : h / l * _.width;
872
- }, $ = le({
873
- queryKey: ["pipeline-analytics", e, "motionEvents", r],
874
- queryFn: async () => {
875
- if (!o) return [];
876
- const h = Date.now() - s.windowMs;
877
- return await o.pipelineAnalytics?.getMotionEvents({
878
- since: h,
879
- limit: St
880
- }) ?? [];
881
- },
882
- enabled: !!o,
883
- refetchInterval: s.pollIntervalMs,
884
- staleTime: Math.max(1e3, s.pollIntervalMs / 2)
885
- }), F = $.data ?? [], b = $.dataUpdatedAt > 0 ? $.dataUpdatedAt : Date.now(), x = b - s.windowMs, C = k(
886
- () => At(F, x, b, s.bucketMs),
887
- [F, x, b, s.bucketMs]
888
- ), y = k(() => {
889
- if (C.length === 0) return 1;
890
- const h = C.reduce((g, _) => Math.max(g, _.count), 0);
891
- return Math.max(1, Math.ceil(h * 1.15));
892
- }, [C]), L = k(
893
- () => we(x, b, l, T.left, T.right, 5),
894
- [x, b, l]
895
- ), D = k(() => Tt(y), [y]), m = F.length;
896
- return /* @__PURE__ */ i("div", { className: "rounded-lg border border-border bg-surface overflow-hidden", children: [
897
- /* @__PURE__ */ i("div", { className: "border-b border-border px-4 py-2 flex items-center justify-between gap-3", children: [
898
- /* @__PURE__ */ i("div", { className: "flex items-center gap-1.5", children: [
899
- /* @__PURE__ */ n(K, { className: "h-3.5 w-3.5 text-foreground-subtle" }),
900
- /* @__PURE__ */ n("h2", { className: "text-xs font-semibold text-foreground uppercase tracking-wider", children: "Motion History" })
901
- ] }),
902
- /* @__PURE__ */ n(ce, { presets: _t, value: r, onChange: a })
903
- ] }),
904
- /* @__PURE__ */ i("div", { ref: d, className: "p-3 min-w-0 relative", children: [
905
- m === 0 ? /* @__PURE__ */ n("div", { className: "flex items-center justify-center h-32 text-[11px] text-foreground-subtle italic", children: $.isLoading ? "Loading…" : "No motion events in the selected window." }) : l === 0 ? /* @__PURE__ */ n("div", { className: "h-32" }) : /* @__PURE__ */ i(ie, { children: [
906
- /* @__PURE__ */ i(
907
- "svg",
908
- {
909
- ref: u,
910
- role: "img",
911
- "aria-label": "Motion event histogram",
912
- width: "100%",
913
- height: V,
914
- viewBox: `0 0 ${l} ${V}`,
915
- preserveAspectRatio: "none",
916
- className: "block",
917
- onMouseLeave: () => f.bindHover(null),
918
- children: [
919
- D.map(({ y: h, label: g }, _) => /* @__PURE__ */ i("g", { children: [
920
- /* @__PURE__ */ n("line", { x1: T.left, x2: l - T.right, y1: h, y2: h, stroke: "currentColor", strokeOpacity: 0.08, strokeWidth: 0.5 }),
921
- /* @__PURE__ */ n("text", { x: T.left - 6, y: h + 3, textAnchor: "end", className: "text-[9px] fill-foreground-subtle", children: g })
922
- ] }, `y-${_}`)),
923
- L.map(({ x: h, label: g }, _) => /* @__PURE__ */ n("text", { x: h, y: V - T.bottom + 12, textAnchor: "middle", className: "text-[9px] fill-foreground-subtle", children: g }, `x-${_}`)),
924
- C.map((h, g) => {
925
- const { x: _, w: p } = Ft(h.bucketStart, s.bucketMs, x, b, l), v = V - T.top - T.bottom, c = h.count / y * v, w = T.top + (v - c), I = h.bucketStart + s.bucketMs;
926
- return /* @__PURE__ */ i("g", { children: [
927
- h.count > 0 && /* @__PURE__ */ n(
928
- "rect",
929
- {
930
- x: _,
931
- y: w,
932
- width: Math.max(1, p - 1),
933
- height: Math.max(1, c),
934
- fill: "currentColor",
935
- className: "text-primary",
936
- opacity: 0.85
937
- }
938
- ),
939
- /* @__PURE__ */ n(
940
- "rect",
941
- {
942
- x: _,
943
- y: T.top,
944
- width: Math.max(2, p),
945
- height: v,
946
- fill: "transparent",
947
- onMouseEnter: () => {
948
- f.bindHover({
949
- anchorX: N(_ + p / 2),
950
- anchorY: w,
951
- title: `${Lt(h.bucketStart, I)} · ${h.count} event${h.count === 1 ? "" : "s"}`,
952
- rows: [
953
- { label: "Bucket", value: Se(s.bucketMs) },
954
- { label: "Count", value: `${h.count}` }
955
- ]
956
- });
957
- }
958
- }
959
- )
960
- ] }, `${h.bucketStart}-${g}`);
961
- })
962
- ]
963
- }
964
- ),
965
- /* @__PURE__ */ n(he, { state: f.state, containerWidth: l })
966
- ] }),
967
- m > 0 && /* @__PURE__ */ i("div", { className: "flex items-center justify-between text-[10px] text-foreground-subtle mt-1", children: [
968
- /* @__PURE__ */ i("span", { children: [
969
- m,
970
- " event",
971
- m === 1 ? "" : "s",
972
- " · ",
973
- Se(s.bucketMs),
974
- " buckets"
975
- ] }),
976
- /* @__PURE__ */ i("span", { children: [
977
- "peak ",
978
- C.reduce((h, g) => Math.max(h, g.count), 0),
979
- "/bucket"
980
- ] })
981
- ] })
982
- ] })
983
- ] });
998
+ //#endregion
999
+ //#region src/pipeline-analytics/widgets/MotionHistoryChart.tsx
1000
+ var G = {
1001
+ "1h": {
1002
+ label: "1 h",
1003
+ windowMs: 60 * 6e4,
1004
+ bucketMs: 6e4,
1005
+ pollIntervalMs: 15e3
1006
+ },
1007
+ "6h": {
1008
+ label: "6 h",
1009
+ windowMs: 360 * 6e4,
1010
+ bucketMs: 5 * 6e4,
1011
+ pollIntervalMs: 6e4
1012
+ },
1013
+ "24h": {
1014
+ label: "24 h",
1015
+ windowMs: 1440 * 6e4,
1016
+ bucketMs: 15 * 6e4,
1017
+ pollIntervalMs: 3e5
1018
+ }
1019
+ }, ke = [
1020
+ {
1021
+ id: "1h",
1022
+ label: G["1h"].label
1023
+ },
1024
+ {
1025
+ id: "6h",
1026
+ label: G["6h"].label
1027
+ },
1028
+ {
1029
+ id: "24h",
1030
+ label: G["24h"].label
1031
+ }
1032
+ ], Ae = 5e3, K = 140, q = {
1033
+ top: 14,
1034
+ right: 12,
1035
+ bottom: 24,
1036
+ left: 32
1037
+ };
1038
+ function je({ deviceId: n }) {
1039
+ let i = c(f().trpcClient, n), [a, s] = r("1h"), l = G[a], [u, d] = ee(), p = F(), _ = e(null), v = (e) => {
1040
+ let t = _.current;
1041
+ if (!t) return e;
1042
+ let n = t.getBoundingClientRect();
1043
+ return n.width === 0 ? e : e / d * n.width;
1044
+ }, y = o({
1045
+ queryKey: [
1046
+ "pipeline-analytics",
1047
+ n,
1048
+ "motionEvents",
1049
+ a
1050
+ ],
1051
+ queryFn: async () => {
1052
+ if (!i) return [];
1053
+ let e = Date.now() - l.windowMs;
1054
+ return await i.pipelineAnalytics?.getMotionEvents({
1055
+ since: e,
1056
+ limit: Ae
1057
+ }) ?? [];
1058
+ },
1059
+ enabled: !!i,
1060
+ refetchInterval: l.pollIntervalMs,
1061
+ staleTime: Math.max(1e3, l.pollIntervalMs / 2)
1062
+ }), b = y.data ?? [], x = y.dataUpdatedAt > 0 ? y.dataUpdatedAt : Date.now(), S = x - l.windowMs, C = t(() => Me(b, S, x, l.bucketMs), [
1063
+ b,
1064
+ S,
1065
+ x,
1066
+ l.bucketMs
1067
+ ]), w = t(() => {
1068
+ if (C.length === 0) return 1;
1069
+ let e = C.reduce((e, t) => Math.max(e, t.count), 0);
1070
+ return Math.max(1, Math.ceil(e * 1.15));
1071
+ }, [C]), E = t(() => ne(S, x, d, q.left, q.right, 5), [
1072
+ S,
1073
+ x,
1074
+ d
1075
+ ]), D = t(() => Pe(w), [w]), O = b.length;
1076
+ return /* @__PURE__ */ h("div", {
1077
+ className: "rounded-lg border border-border bg-surface overflow-hidden",
1078
+ children: [/* @__PURE__ */ h("div", {
1079
+ className: "border-b border-border px-4 py-2 flex items-center justify-between gap-3",
1080
+ children: [/* @__PURE__ */ h("div", {
1081
+ className: "flex items-center gap-1.5",
1082
+ children: [/* @__PURE__ */ m(T, { className: "h-3.5 w-3.5 text-foreground-subtle" }), /* @__PURE__ */ m("h2", {
1083
+ className: "text-xs font-semibold text-foreground uppercase tracking-wider",
1084
+ children: "Motion History"
1085
+ })]
1086
+ }), /* @__PURE__ */ m(M, {
1087
+ presets: ke,
1088
+ value: a,
1089
+ onChange: s
1090
+ })]
1091
+ }), /* @__PURE__ */ h("div", {
1092
+ ref: u,
1093
+ className: "p-3 min-w-0 relative",
1094
+ children: [O === 0 ? /* @__PURE__ */ m("div", {
1095
+ className: "flex items-center justify-center h-32 text-[11px] text-foreground-subtle italic",
1096
+ children: y.isLoading ? "Loading…" : "No motion events in the selected window."
1097
+ }) : d === 0 ? /* @__PURE__ */ m("div", { className: "h-32" }) : /* @__PURE__ */ h(g, { children: [/* @__PURE__ */ h("svg", {
1098
+ ref: _,
1099
+ role: "img",
1100
+ "aria-label": "Motion event histogram",
1101
+ width: "100%",
1102
+ height: K,
1103
+ viewBox: `0 0 ${d} ${K}`,
1104
+ preserveAspectRatio: "none",
1105
+ className: "block",
1106
+ onMouseLeave: () => p.bindHover(null),
1107
+ children: [
1108
+ D.map(({ y: e, label: t }, n) => /* @__PURE__ */ h("g", { children: [/* @__PURE__ */ m("line", {
1109
+ x1: q.left,
1110
+ x2: d - q.right,
1111
+ y1: e,
1112
+ y2: e,
1113
+ stroke: "currentColor",
1114
+ strokeOpacity: .08,
1115
+ strokeWidth: .5
1116
+ }), /* @__PURE__ */ m("text", {
1117
+ x: q.left - 6,
1118
+ y: e + 3,
1119
+ textAnchor: "end",
1120
+ className: "text-[9px] fill-foreground-subtle",
1121
+ children: t
1122
+ })] }, `y-${n}`)),
1123
+ E.map(({ x: e, label: t }, n) => /* @__PURE__ */ m("text", {
1124
+ x: e,
1125
+ y: K - q.bottom + 12,
1126
+ textAnchor: "middle",
1127
+ className: "text-[9px] fill-foreground-subtle",
1128
+ children: t
1129
+ }, `x-${n}`)),
1130
+ C.map((e, t) => {
1131
+ let { x: n, w: r } = Ne(e.bucketStart, l.bucketMs, S, x, d), i = K - q.top - q.bottom, a = e.count / w * i, o = q.top + (i - a), s = e.bucketStart + l.bucketMs;
1132
+ return /* @__PURE__ */ h("g", { children: [e.count > 0 && /* @__PURE__ */ m("rect", {
1133
+ x: n,
1134
+ y: o,
1135
+ width: Math.max(1, r - 1),
1136
+ height: Math.max(1, a),
1137
+ fill: "currentColor",
1138
+ className: "text-primary",
1139
+ opacity: .85
1140
+ }), /* @__PURE__ */ m("rect", {
1141
+ x: n,
1142
+ y: q.top,
1143
+ width: Math.max(2, r),
1144
+ height: i,
1145
+ fill: "transparent",
1146
+ onMouseEnter: () => {
1147
+ p.bindHover({
1148
+ anchorX: v(n + r / 2),
1149
+ anchorY: o,
1150
+ title: `${Fe(e.bucketStart, s)} · ${e.count} event${e.count === 1 ? "" : "s"}`,
1151
+ rows: [{
1152
+ label: "Bucket",
1153
+ value: Ie(l.bucketMs)
1154
+ }, {
1155
+ label: "Count",
1156
+ value: `${e.count}`
1157
+ }]
1158
+ });
1159
+ }
1160
+ })] }, `${e.bucketStart}-${t}`);
1161
+ })
1162
+ ]
1163
+ }), /* @__PURE__ */ m(I, {
1164
+ state: p.state,
1165
+ containerWidth: d
1166
+ })] }), O > 0 && /* @__PURE__ */ h("div", {
1167
+ className: "flex items-center justify-between text-[10px] text-foreground-subtle mt-1",
1168
+ children: [/* @__PURE__ */ h("span", { children: [
1169
+ O,
1170
+ " event",
1171
+ O === 1 ? "" : "s",
1172
+ " · ",
1173
+ Ie(l.bucketMs),
1174
+ " ",
1175
+ "buckets"
1176
+ ] }), /* @__PURE__ */ h("span", { children: [
1177
+ "peak ",
1178
+ C.reduce((e, t) => Math.max(e, t.count), 0),
1179
+ "/bucket"
1180
+ ] })]
1181
+ })]
1182
+ })]
1183
+ });
984
1184
  }
985
- function At(e, t, o, r) {
986
- if (o <= t) return [];
987
- const a = Math.floor(t / r) * r, s = Math.floor(o / r) * r, d = /* @__PURE__ */ new Map();
988
- for (let l = a; l <= s; l += r)
989
- d.set(l, 0);
990
- for (const l of e) {
991
- if (l.timestamp < t || l.timestamp > o) continue;
992
- const f = Math.floor(l.timestamp / r) * r;
993
- d.set(f, (d.get(f) ?? 0) + 1);
994
- }
995
- return [...d.entries()].sort(([l], [f]) => l - f).map(([l, f]) => ({ bucketStart: l, count: f }));
1185
+ function Me(e, t, n, r) {
1186
+ if (n <= t) return [];
1187
+ let i = Math.floor(t / r) * r, a = Math.floor(n / r) * r, o = /* @__PURE__ */ new Map();
1188
+ for (let e = i; e <= a; e += r) o.set(e, 0);
1189
+ for (let i of e) {
1190
+ if (i.timestamp < t || i.timestamp > n) continue;
1191
+ let e = Math.floor(i.timestamp / r) * r;
1192
+ o.set(e, (o.get(e) ?? 0) + 1);
1193
+ }
1194
+ return [...o.entries()].toSorted(([e], [t]) => e - t).map(([e, t]) => ({
1195
+ bucketStart: e,
1196
+ count: t
1197
+ }));
996
1198
  }
997
- function Ft(e, t, o, r, a) {
998
- const s = Math.max(1, r - o), d = a - T.left - T.right, l = T.left + (e - o) / s * d, f = t / s * d;
999
- return { x: l, w: f };
1199
+ function Ne(e, t, n, r, i) {
1200
+ let a = Math.max(1, r - n), o = i - q.left - q.right;
1201
+ return {
1202
+ x: q.left + (e - n) / a * o,
1203
+ w: t / a * o
1204
+ };
1000
1205
  }
1001
- function Tt(e) {
1002
- const t = [];
1003
- for (let o = 0; o < 4; o++) {
1004
- const r = o / 3, a = Math.round(e * r), s = V - T.top - T.bottom;
1005
- t.push({
1006
- y: T.top + (1 - r) * s,
1007
- label: `${a}`
1008
- });
1009
- }
1010
- return t;
1206
+ function Pe(e) {
1207
+ let t = [];
1208
+ for (let n = 0; n < 4; n++) {
1209
+ let r = n / 3, i = Math.round(e * r), a = K - q.top - q.bottom;
1210
+ t.push({
1211
+ y: q.top + (1 - r) * a,
1212
+ label: `${i}`
1213
+ });
1214
+ }
1215
+ return t;
1011
1216
  }
1012
- function Lt(e, t) {
1013
- const o = (r) => {
1014
- const a = new Date(r), s = String(a.getHours()).padStart(2, "0"), d = String(a.getMinutes()).padStart(2, "0");
1015
- return `${s}:${d}`;
1016
- };
1017
- return `${o(e)}–${o(t)}`;
1217
+ function Fe(e, t) {
1218
+ let n = (e) => {
1219
+ let t = new Date(e);
1220
+ return `${String(t.getHours()).padStart(2, "0")}:${String(t.getMinutes()).padStart(2, "0")}`;
1221
+ };
1222
+ return `${n(e)}–${n(t)}`;
1018
1223
  }
1019
- function Se(e) {
1020
- return e >= 60 * 6e4 ? `${Math.round(e / 6e4 / 60)}h` : e >= 6e4 ? `${Math.round(e / 6e4)}m` : `${Math.round(e / 1e3)}s`;
1224
+ function Ie(e) {
1225
+ return e >= 60 * 6e4 ? `${Math.round(e / 6e4 / 60)}h` : e >= 6e4 ? `${Math.round(e / 6e4)}m` : `${Math.round(e / 1e3)}s`;
1021
1226
  }
1022
- const re = {
1023
- "1h": { label: "1 h", windowMs: 60 * 6e4, bucketMs: 6e4, pollIntervalMs: 15e3 },
1024
- "6h": { label: "6 h", windowMs: 360 * 6e4, bucketMs: 5 * 6e4, pollIntervalMs: 6e4 },
1025
- "24h": { label: "24 h", windowMs: 1440 * 6e4, bucketMs: 15 * 6e4, pollIntervalMs: 3e5 }
1026
- }, Dt = [
1027
- { id: "1h", label: re["1h"].label },
1028
- { id: "6h", label: re["6h"].label },
1029
- { id: "24h", label: re["24h"].label }
1030
- ], Et = 5e3, Ht = 4, W = "__other__", z = "__all__", Z = 160, A = { top: 14, right: 12, bottom: 24, left: 32 };
1031
- function Wt({ deviceId: e }) {
1032
- const t = Y(), o = J(t.trpcClient, e), [r, a] = H("1h"), [s, d] = H(z), l = re[r], [f, u] = de(), N = ue(), $ = Q(null), F = le({
1033
- queryKey: ["pipeline-analytics", e, "objectEvents", r],
1034
- queryFn: async () => {
1035
- if (!o) return [];
1036
- const c = Date.now() - l.windowMs;
1037
- return await o.pipelineAnalytics?.getObjectEvents({
1038
- since: c,
1039
- limit: Et
1040
- }) ?? [];
1041
- },
1042
- enabled: !!o,
1043
- refetchInterval: l.pollIntervalMs,
1044
- staleTime: Math.max(1e3, l.pollIntervalMs / 2)
1045
- }), b = F.data ?? [], x = k(
1046
- () => s === z ? b : b.filter((c) => c.className === s),
1047
- [b, s]
1048
- ), C = F.dataUpdatedAt > 0 ? F.dataUpdatedAt : Date.now(), y = C - l.windowMs, L = k(() => {
1049
- const c = /* @__PURE__ */ new Set();
1050
- for (const w of b) c.add(w.className);
1051
- return s !== z && c.add(s), [...c].sort();
1052
- }, [b, s]);
1053
- ye(() => {
1054
- s !== z && b.length > 0 && !L.includes(s) && d(z);
1055
- }, [s, b, L]);
1056
- const D = k(() => jt(x, Ht), [x]), m = k(
1057
- () => Ot(x, y, C, l.bucketMs, D),
1058
- [x, y, C, l.bucketMs, D]
1059
- ), h = k(() => {
1060
- if (m.length === 0) return 1;
1061
- const c = m.reduce((w, I) => Math.max(w, I.total), 0);
1062
- return Math.max(1, Math.ceil(c * 1.15));
1063
- }, [m]), g = k(
1064
- () => we(y, C, u, A.left, A.right, 5),
1065
- [y, C, u]
1066
- ), _ = k(() => Bt(h), [h]), p = k(() => {
1067
- const c = D.map((w) => w.className);
1068
- return x.some((w) => !D.some((I) => I.className === w.className)) && c.push(W), c;
1069
- }, [x, D]), v = (c) => {
1070
- const w = $.current;
1071
- if (!w) return c;
1072
- const I = w.getBoundingClientRect();
1073
- return I.width === 0 ? c : c / u * I.width;
1074
- };
1075
- return /* @__PURE__ */ i("div", { className: "rounded-lg border border-border bg-surface overflow-hidden", children: [
1076
- /* @__PURE__ */ i("div", { className: "border-b border-border px-4 py-2 flex items-center justify-between gap-3", children: [
1077
- /* @__PURE__ */ i("div", { className: "flex items-center gap-1.5", children: [
1078
- /* @__PURE__ */ n(et, { className: "h-3.5 w-3.5 text-foreground-subtle" }),
1079
- /* @__PURE__ */ n("h2", { className: "text-xs font-semibold text-foreground uppercase tracking-wider", children: "Detection History" })
1080
- ] }),
1081
- /* @__PURE__ */ i("div", { className: "flex items-center gap-2", children: [
1082
- L.length > 0 && /* @__PURE__ */ i(
1083
- "select",
1084
- {
1085
- value: s,
1086
- onChange: (c) => d(c.target.value),
1087
- 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",
1088
- title: "Filter by detected class",
1089
- children: [
1090
- /* @__PURE__ */ n("option", { value: z, children: "All classes" }),
1091
- L.map((c) => /* @__PURE__ */ n("option", { value: c, children: c }, c))
1092
- ]
1093
- }
1094
- ),
1095
- /* @__PURE__ */ n(ce, { presets: Dt, value: r, onChange: a })
1096
- ] })
1097
- ] }),
1098
- /* @__PURE__ */ i("div", { ref: f, className: "p-3 min-w-0 relative", children: [
1099
- x.length === 0 ? /* @__PURE__ */ n("div", { className: "flex items-center justify-center h-32 text-[11px] text-foreground-subtle italic", children: F.isLoading ? "Loading…" : "No detection events in the selected window." }) : u === 0 ? /* @__PURE__ */ n("div", { className: "h-32" }) : /* @__PURE__ */ i(ie, { children: [
1100
- /* @__PURE__ */ i(
1101
- "svg",
1102
- {
1103
- ref: $,
1104
- role: "img",
1105
- "aria-label": "Detection event histogram",
1106
- width: "100%",
1107
- height: Z,
1108
- viewBox: `0 0 ${u} ${Z}`,
1109
- preserveAspectRatio: "none",
1110
- className: "block",
1111
- onMouseLeave: () => N.bindHover(null),
1112
- children: [
1113
- _.map(({ y: c, label: w }, I) => /* @__PURE__ */ i("g", { children: [
1114
- /* @__PURE__ */ n("line", { x1: A.left, x2: u - A.right, y1: c, y2: c, stroke: "currentColor", strokeOpacity: 0.08, strokeWidth: 0.5 }),
1115
- /* @__PURE__ */ n("text", { x: A.left - 6, y: c + 3, textAnchor: "end", className: "text-[9px] fill-foreground-subtle", children: w })
1116
- ] }, `y-${I}`)),
1117
- g.map(({ x: c, label: w }, I) => /* @__PURE__ */ n("text", { x: c, y: Z - A.bottom + 12, textAnchor: "middle", className: "text-[9px] fill-foreground-subtle", children: w }, `x-${I}`)),
1118
- m.map((c, w) => {
1119
- if (c.total === 0) return null;
1120
- const { x: I, w: R } = Rt(c.bucketStart, l.bucketMs, y, C, u), q = Z - A.top - A.bottom, He = c.total / h * q, We = A.top + (q - He);
1121
- let ke = 0;
1122
- const je = p.map((E, me) => {
1123
- const G = c.byClass[E] ?? 0;
1124
- if (G === 0) return null;
1125
- const fe = G / h * q, Re = A.top + (q - ke - fe);
1126
- ke += fe;
1127
- const Be = E === W ? "#94a3b8" : be(me);
1128
- return /* @__PURE__ */ n(
1129
- "rect",
1130
- {
1131
- x: I,
1132
- y: Re,
1133
- width: Math.max(1, R - 1),
1134
- height: Math.max(1, fe),
1135
- fill: Be,
1136
- opacity: 0.9
1137
- },
1138
- `${c.bucketStart}-${E}`
1139
- );
1140
- }).filter((E) => E !== null), Oe = c.bucketStart + l.bucketMs;
1141
- return /* @__PURE__ */ i("g", { children: [
1142
- je,
1143
- /* @__PURE__ */ n(
1144
- "rect",
1145
- {
1146
- x: I,
1147
- y: A.top,
1148
- width: Math.max(2, R),
1149
- height: q,
1150
- fill: "transparent",
1151
- onMouseEnter: () => {
1152
- N.bindHover({
1153
- anchorX: v(I + R / 2),
1154
- anchorY: We,
1155
- title: `${Pt(c.bucketStart, Oe, l.bucketMs)} · ${c.total} detection${c.total === 1 ? "" : "s"}`,
1156
- rows: p.map((E, me) => {
1157
- const G = c.byClass[E] ?? 0;
1158
- return G === 0 ? null : {
1159
- label: E === W ? "other" : E,
1160
- value: `${G}`,
1161
- colour: E === W ? "#94a3b8" : be(me)
1162
- };
1163
- }).filter((E) => E !== null)
1164
- });
1165
- }
1166
- }
1167
- )
1168
- ] }, `g-${c.bucketStart}-${w}`);
1169
- })
1170
- ]
1171
- }
1172
- ),
1173
- /* @__PURE__ */ n(he, { state: N.state, containerWidth: u }),
1174
- /* @__PURE__ */ n(Xt, { stackOrder: p })
1175
- ] }),
1176
- x.length > 0 && /* @__PURE__ */ i("div", { className: "flex items-center justify-between text-[10px] text-foreground-subtle mt-1", children: [
1177
- /* @__PURE__ */ i("span", { children: [
1178
- x.length,
1179
- " detection",
1180
- x.length === 1 ? "" : "s",
1181
- " · ",
1182
- zt(l.bucketMs),
1183
- " buckets"
1184
- ] }),
1185
- /* @__PURE__ */ i("span", { children: [
1186
- "peak ",
1187
- m.reduce((c, w) => Math.max(c, w.total), 0),
1188
- "/bucket"
1189
- ] })
1190
- ] })
1191
- ] })
1192
- ] });
1227
+ //#endregion
1228
+ //#region src/pipeline-analytics/widgets/DetectionHistoryChart.tsx
1229
+ var J = {
1230
+ "1h": {
1231
+ label: "1 h",
1232
+ windowMs: 60 * 6e4,
1233
+ bucketMs: 6e4,
1234
+ pollIntervalMs: 15e3
1235
+ },
1236
+ "6h": {
1237
+ label: "6 h",
1238
+ windowMs: 360 * 6e4,
1239
+ bucketMs: 5 * 6e4,
1240
+ pollIntervalMs: 6e4
1241
+ },
1242
+ "24h": {
1243
+ label: "24 h",
1244
+ windowMs: 1440 * 6e4,
1245
+ bucketMs: 15 * 6e4,
1246
+ pollIntervalMs: 3e5
1247
+ }
1248
+ }, Le = [
1249
+ {
1250
+ id: "1h",
1251
+ label: J["1h"].label
1252
+ },
1253
+ {
1254
+ id: "6h",
1255
+ label: J["6h"].label
1256
+ },
1257
+ {
1258
+ id: "24h",
1259
+ label: J["24h"].label
1260
+ }
1261
+ ], Re = 5e3, ze = 4, Y = "__other__", X = "__all__", Z = 160, Q = {
1262
+ top: 14,
1263
+ right: 12,
1264
+ bottom: 24,
1265
+ left: 32
1266
+ };
1267
+ function Be({ deviceId: n }) {
1268
+ let a = c(f().trpcClient, n), [s, l] = r("1h"), [u, d] = r(X), p = J[s], [_, v] = ee(), y = F(), b = e(null), x = o({
1269
+ queryKey: [
1270
+ "pipeline-analytics",
1271
+ n,
1272
+ "objectEvents",
1273
+ s
1274
+ ],
1275
+ queryFn: async () => {
1276
+ if (!a) return [];
1277
+ let e = Date.now() - p.windowMs;
1278
+ return await a.pipelineAnalytics?.getObjectEvents({
1279
+ since: e,
1280
+ limit: Re
1281
+ }) ?? [];
1282
+ },
1283
+ enabled: !!a,
1284
+ refetchInterval: p.pollIntervalMs,
1285
+ staleTime: Math.max(1e3, p.pollIntervalMs / 2)
1286
+ }), S = x.data ?? [], C = t(() => u === X ? S : S.filter((e) => e.className === u), [S, u]), w = x.dataUpdatedAt > 0 ? x.dataUpdatedAt : Date.now(), T = w - p.windowMs, E = t(() => {
1287
+ let e = /* @__PURE__ */ new Set();
1288
+ for (let t of S) e.add(t.className);
1289
+ return u !== X && e.add(u), [...e].toSorted();
1290
+ }, [S, u]);
1291
+ i(() => {
1292
+ u !== X && S.length > 0 && !E.includes(u) && d(X);
1293
+ }, [
1294
+ u,
1295
+ S,
1296
+ E
1297
+ ]);
1298
+ let O = t(() => Ve(C, ze), [C]), k = t(() => He(C, T, w, p.bucketMs, O), [
1299
+ C,
1300
+ T,
1301
+ w,
1302
+ p.bucketMs,
1303
+ O
1304
+ ]), A = t(() => {
1305
+ if (k.length === 0) return 1;
1306
+ let e = k.reduce((e, t) => Math.max(e, t.total), 0);
1307
+ return Math.max(1, Math.ceil(e * 1.15));
1308
+ }, [k]), j = t(() => ne(T, w, v, Q.left, Q.right, 5), [
1309
+ T,
1310
+ w,
1311
+ v
1312
+ ]), te = t(() => We(A), [A]), N = t(() => {
1313
+ let e = O.map((e) => e.className);
1314
+ return C.some((e) => !O.some((t) => t.className === e.className)) && e.push(Y), e;
1315
+ }, [C, O]), P = (e) => {
1316
+ let t = b.current;
1317
+ if (!t) return e;
1318
+ let n = t.getBoundingClientRect();
1319
+ return n.width === 0 ? e : e / v * n.width;
1320
+ };
1321
+ return /* @__PURE__ */ h("div", {
1322
+ className: "rounded-lg border border-border bg-surface overflow-hidden",
1323
+ children: [/* @__PURE__ */ h("div", {
1324
+ className: "border-b border-border px-4 py-2 flex items-center justify-between gap-3",
1325
+ children: [/* @__PURE__ */ h("div", {
1326
+ className: "flex items-center gap-1.5",
1327
+ children: [/* @__PURE__ */ m(D, { className: "h-3.5 w-3.5 text-foreground-subtle" }), /* @__PURE__ */ m("h2", {
1328
+ className: "text-xs font-semibold text-foreground uppercase tracking-wider",
1329
+ children: "Detection History"
1330
+ })]
1331
+ }), /* @__PURE__ */ h("div", {
1332
+ className: "flex items-center gap-2",
1333
+ children: [E.length > 0 && /* @__PURE__ */ h("select", {
1334
+ value: u,
1335
+ onChange: (e) => d(e.target.value),
1336
+ 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",
1337
+ title: "Filter by detected class",
1338
+ children: [/* @__PURE__ */ m("option", {
1339
+ value: X,
1340
+ children: "All classes"
1341
+ }), E.map((e) => /* @__PURE__ */ m("option", {
1342
+ value: e,
1343
+ children: e
1344
+ }, e))]
1345
+ }), /* @__PURE__ */ m(M, {
1346
+ presets: Le,
1347
+ value: s,
1348
+ onChange: l
1349
+ })]
1350
+ })]
1351
+ }), /* @__PURE__ */ h("div", {
1352
+ ref: _,
1353
+ className: "p-3 min-w-0 relative",
1354
+ children: [C.length === 0 ? /* @__PURE__ */ m("div", {
1355
+ className: "flex items-center justify-center h-32 text-[11px] text-foreground-subtle italic",
1356
+ children: x.isLoading ? "Loading…" : "No detection events in the selected window."
1357
+ }) : v === 0 ? /* @__PURE__ */ m("div", { className: "h-32" }) : /* @__PURE__ */ h(g, { children: [
1358
+ /* @__PURE__ */ h("svg", {
1359
+ ref: b,
1360
+ role: "img",
1361
+ "aria-label": "Detection event histogram",
1362
+ width: "100%",
1363
+ height: Z,
1364
+ viewBox: `0 0 ${v} ${Z}`,
1365
+ preserveAspectRatio: "none",
1366
+ className: "block",
1367
+ onMouseLeave: () => y.bindHover(null),
1368
+ children: [
1369
+ te.map(({ y: e, label: t }, n) => /* @__PURE__ */ h("g", { children: [/* @__PURE__ */ m("line", {
1370
+ x1: Q.left,
1371
+ x2: v - Q.right,
1372
+ y1: e,
1373
+ y2: e,
1374
+ stroke: "currentColor",
1375
+ strokeOpacity: .08,
1376
+ strokeWidth: .5
1377
+ }), /* @__PURE__ */ m("text", {
1378
+ x: Q.left - 6,
1379
+ y: e + 3,
1380
+ textAnchor: "end",
1381
+ className: "text-[9px] fill-foreground-subtle",
1382
+ children: t
1383
+ })] }, `y-${n}`)),
1384
+ j.map(({ x: e, label: t }, n) => /* @__PURE__ */ m("text", {
1385
+ x: e,
1386
+ y: Z - Q.bottom + 12,
1387
+ textAnchor: "middle",
1388
+ className: "text-[9px] fill-foreground-subtle",
1389
+ children: t
1390
+ }, `x-${n}`)),
1391
+ k.map((e, t) => {
1392
+ if (e.total === 0) return null;
1393
+ let { x: n, w: r } = Ue(e.bucketStart, p.bucketMs, T, w, v), i = Z - Q.top - Q.bottom, a = e.total / A * i, o = Q.top + (i - a), s = 0, c = N.map((t, a) => {
1394
+ let o = e.byClass[t] ?? 0;
1395
+ if (o === 0) return null;
1396
+ let c = o / A * i, l = Q.top + (i - s - c);
1397
+ s += c;
1398
+ let u = t === Y ? "#94a3b8" : re(a);
1399
+ return /* @__PURE__ */ m("rect", {
1400
+ x: n,
1401
+ y: l,
1402
+ width: Math.max(1, r - 1),
1403
+ height: Math.max(1, c),
1404
+ fill: u,
1405
+ opacity: .9
1406
+ }, `${e.bucketStart}-${t}`);
1407
+ }).filter((e) => e !== null), l = e.bucketStart + p.bucketMs;
1408
+ return /* @__PURE__ */ h("g", { children: [c, /* @__PURE__ */ m("rect", {
1409
+ x: n,
1410
+ y: Q.top,
1411
+ width: Math.max(2, r),
1412
+ height: i,
1413
+ fill: "transparent",
1414
+ onMouseEnter: () => {
1415
+ y.bindHover({
1416
+ anchorX: P(n + r / 2),
1417
+ anchorY: o,
1418
+ title: `${Ge(e.bucketStart, l, p.bucketMs)} · ${e.total} detection${e.total === 1 ? "" : "s"}`,
1419
+ rows: N.map((t, n) => {
1420
+ let r = e.byClass[t] ?? 0;
1421
+ return r === 0 ? null : {
1422
+ label: t === Y ? "other" : t,
1423
+ value: `${r}`,
1424
+ colour: t === Y ? "#94a3b8" : re(n)
1425
+ };
1426
+ }).filter((e) => e !== null)
1427
+ });
1428
+ }
1429
+ })] }, `g-${e.bucketStart}-${t}`);
1430
+ })
1431
+ ]
1432
+ }),
1433
+ /* @__PURE__ */ m(I, {
1434
+ state: y.state,
1435
+ containerWidth: v
1436
+ }),
1437
+ /* @__PURE__ */ m(qe, { stackOrder: N })
1438
+ ] }), C.length > 0 && /* @__PURE__ */ h("div", {
1439
+ className: "flex items-center justify-between text-[10px] text-foreground-subtle mt-1",
1440
+ children: [/* @__PURE__ */ h("span", { children: [
1441
+ C.length,
1442
+ " detection",
1443
+ C.length === 1 ? "" : "s",
1444
+ " ·",
1445
+ " ",
1446
+ Ke(p.bucketMs),
1447
+ " buckets"
1448
+ ] }), /* @__PURE__ */ h("span", { children: [
1449
+ "peak ",
1450
+ k.reduce((e, t) => Math.max(e, t.total), 0),
1451
+ "/bucket"
1452
+ ] })]
1453
+ })]
1454
+ })]
1455
+ });
1193
1456
  }
1194
- function jt(e, t) {
1195
- const o = /* @__PURE__ */ new Map();
1196
- for (const r of e)
1197
- o.set(r.className, (o.get(r.className) ?? 0) + 1);
1198
- return [...o.entries()].sort(([, r], [, a]) => a - r).slice(0, t).map(([r, a]) => ({ className: r, count: a }));
1457
+ function Ve(e, t) {
1458
+ let n = /* @__PURE__ */ new Map();
1459
+ for (let t of e) n.set(t.className, (n.get(t.className) ?? 0) + 1);
1460
+ return [...n.entries()].toSorted(([, e], [, t]) => t - e).slice(0, t).map(([e, t]) => ({
1461
+ className: e,
1462
+ count: t
1463
+ }));
1199
1464
  }
1200
- function Ot(e, t, o, r, a) {
1201
- if (o <= t) return [];
1202
- const s = new Set(a.map((u) => u.className)), d = Math.floor(t / r) * r, l = Math.floor(o / r) * r, f = /* @__PURE__ */ new Map();
1203
- for (let u = d; u <= l; u += r)
1204
- f.set(u, { total: 0, byClass: {} });
1205
- for (const u of e) {
1206
- if (u.timestamp < t || u.timestamp > o) continue;
1207
- const N = Math.floor(u.timestamp / r) * r, $ = f.get(N);
1208
- if (!$) continue;
1209
- $.total += 1;
1210
- const F = s.has(u.className) ? u.className : W;
1211
- $.byClass[F] = ($.byClass[F] ?? 0) + 1;
1212
- }
1213
- return [...f.entries()].sort(([u], [N]) => u - N).map(([u, N]) => ({
1214
- bucketStart: u,
1215
- total: N.total,
1216
- byClass: N.byClass
1217
- }));
1465
+ function He(e, t, n, r, i) {
1466
+ if (n <= t) return [];
1467
+ 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();
1468
+ for (let e = o; e <= s; e += r) c.set(e, {
1469
+ total: 0,
1470
+ byClass: {}
1471
+ });
1472
+ for (let i of e) {
1473
+ if (i.timestamp < t || i.timestamp > n) continue;
1474
+ let e = Math.floor(i.timestamp / r) * r, o = c.get(e);
1475
+ if (!o) continue;
1476
+ o.total += 1;
1477
+ let s = a.has(i.className) ? i.className : Y;
1478
+ o.byClass[s] = (o.byClass[s] ?? 0) + 1;
1479
+ }
1480
+ return [...c.entries()].toSorted(([e], [t]) => e - t).map(([e, t]) => ({
1481
+ bucketStart: e,
1482
+ total: t.total,
1483
+ byClass: t.byClass
1484
+ }));
1218
1485
  }
1219
- function Rt(e, t, o, r, a) {
1220
- const s = Math.max(1, r - o), d = a - A.left - A.right, l = A.left + (e - o) / s * d, f = t / s * d;
1221
- return { x: l, w: f };
1486
+ function Ue(e, t, n, r, i) {
1487
+ let a = Math.max(1, r - n), o = i - Q.left - Q.right;
1488
+ return {
1489
+ x: Q.left + (e - n) / a * o,
1490
+ w: t / a * o
1491
+ };
1222
1492
  }
1223
- function Bt(e) {
1224
- const t = [];
1225
- for (let o = 0; o < 4; o++) {
1226
- const r = o / 3, a = Math.round(e * r), s = Z - A.top - A.bottom;
1227
- t.push({
1228
- y: A.top + (1 - r) * s,
1229
- label: `${a}`
1230
- });
1231
- }
1232
- return t;
1493
+ function We(e) {
1494
+ let t = [];
1495
+ for (let n = 0; n < 4; n++) {
1496
+ let r = n / 3, i = Math.round(e * r), a = Z - Q.top - Q.bottom;
1497
+ t.push({
1498
+ y: Q.top + (1 - r) * a,
1499
+ label: `${i}`
1500
+ });
1501
+ }
1502
+ return t;
1233
1503
  }
1234
- function Pt(e, t, o) {
1235
- const r = (a) => {
1236
- const s = String(a.getHours()).padStart(2, "0"), d = String(a.getMinutes()).padStart(2, "0");
1237
- return `${s}:${d}`;
1238
- };
1239
- return o >= 60 * 6e4 ? `${r(new Date(e))}–${r(new Date(t))}` : `${r(new Date(e))}–${r(new Date(t))}`;
1504
+ function Ge(e, t, n) {
1505
+ let r = (e) => `${String(e.getHours()).padStart(2, "0")}:${String(e.getMinutes()).padStart(2, "0")}`;
1506
+ return `${r(new Date(e))}–${r(new Date(t))}`;
1240
1507
  }
1241
- function zt(e) {
1242
- return e >= 60 * 6e4 ? `${Math.round(e / 6e4 / 60)}h` : e >= 6e4 ? `${Math.round(e / 6e4)}m` : `${Math.round(e / 1e3)}s`;
1508
+ function Ke(e) {
1509
+ return e >= 60 * 6e4 ? `${Math.round(e / 6e4 / 60)}h` : e >= 6e4 ? `${Math.round(e / 6e4)}m` : `${Math.round(e / 1e3)}s`;
1243
1510
  }
1244
- function Xt({ stackOrder: e }) {
1245
- return e.length === 0 ? null : /* @__PURE__ */ n("div", { className: "flex flex-wrap gap-2 mt-2 px-1", children: e.map((t, o) => {
1246
- const r = t === W ? "#94a3b8" : be(o);
1247
- return /* @__PURE__ */ i("span", { className: "inline-flex items-center gap-1 text-[10px] text-foreground-subtle", children: [
1248
- /* @__PURE__ */ n("span", { className: "inline-block h-2 w-2 rounded-sm", style: { backgroundColor: r } }),
1249
- /* @__PURE__ */ n("span", { children: t === W ? "other" : t })
1250
- ] }, t);
1251
- }) });
1511
+ function qe({ stackOrder: e }) {
1512
+ return e.length === 0 ? null : /* @__PURE__ */ m("div", {
1513
+ className: "flex flex-wrap gap-2 mt-2 px-1",
1514
+ children: e.map((e, t) => /* @__PURE__ */ h("span", {
1515
+ className: "inline-flex items-center gap-1 text-[10px] text-foreground-subtle",
1516
+ children: [/* @__PURE__ */ m("span", {
1517
+ className: "inline-block h-2 w-2 rounded-sm",
1518
+ style: { backgroundColor: e === Y ? "#94a3b8" : re(t) }
1519
+ }), /* @__PURE__ */ m("span", { children: e === Y ? "other" : e })]
1520
+ }, e))
1521
+ });
1252
1522
  }
1253
- function Yt({
1254
- dev: e,
1255
- deviceId: t,
1256
- title: o = "Live Occupancy",
1257
- variant: r = "full"
1258
- }) {
1259
- const a = Y(), s = J(
1260
- a.trpcClient,
1261
- e === void 0 && t !== void 0 ? t : null
1262
- ), d = e ?? s, l = ve(d?.state.zoneAnalytics);
1263
- return l ? /* @__PURE__ */ n(Ie, { title: o, variant: r, ts: l.ts, children: /* @__PURE__ */ i("div", { className: r === "compact" ? "space-y-2" : "grid grid-cols-1 2xl:grid-cols-3 gap-3", children: [
1264
- /* @__PURE__ */ n(Gt, { frame: l.frame }),
1265
- /* @__PURE__ */ n(Vt, { snapshot: l }),
1266
- /* @__PURE__ */ n(Ut, { unzoned: l.unzoned })
1267
- ] }) }) : /* @__PURE__ */ n(Ie, { title: o, variant: r, children: /* @__PURE__ */ n(qt, { message: d ? "No occupancy data yet — analytics pipeline must be active for this device." : "Resolving device…" }) });
1523
+ //#endregion
1524
+ //#region src/pipeline-analytics/widgets/OccupancyPanel.tsx
1525
+ function Je({ dev: e, deviceId: t, title: n = "Live Occupancy", variant: r = "full" }) {
1526
+ let i = c(f().trpcClient, e === void 0 && t !== void 0 ? t : null), a = e ?? i, o = u(a?.state.zoneAnalytics);
1527
+ return o ? /* @__PURE__ */ m(Ye, {
1528
+ title: n,
1529
+ variant: r,
1530
+ ts: o.ts,
1531
+ children: /* @__PURE__ */ h("div", {
1532
+ className: r === "compact" ? "space-y-2" : "grid grid-cols-1 2xl:grid-cols-3 gap-3",
1533
+ children: [
1534
+ /* @__PURE__ */ m(Ze, { frame: o.frame }),
1535
+ /* @__PURE__ */ m($e, { snapshot: o }),
1536
+ /* @__PURE__ */ m(Qe, { unzoned: o.unzoned })
1537
+ ]
1538
+ })
1539
+ }) : /* @__PURE__ */ m(Ye, {
1540
+ title: n,
1541
+ variant: r,
1542
+ children: /* @__PURE__ */ m(Xe, { message: a ? "No occupancy data yet — analytics pipeline must be active for this device." : "Resolving device…" })
1543
+ });
1268
1544
  }
1269
- function Ie({ title: e, variant: t, ts: o, children: r }) {
1270
- const a = o ? Math.max(0, Math.floor((Date.now() - o) / 1e3)) : null;
1271
- return /* @__PURE__ */ i("div", { className: t === "compact" ? "rounded-md border border-border/60 bg-surface/60 p-3" : "rounded-lg border border-border bg-surface overflow-hidden", children: [
1272
- /* @__PURE__ */ i("div", { className: t === "compact" ? "flex items-center justify-between mb-2" : "border-b border-border px-4 py-2 flex items-center justify-between", children: [
1273
- /* @__PURE__ */ n("h2", { className: "text-xs font-semibold text-foreground uppercase tracking-wider", children: e }),
1274
- a !== null && /* @__PURE__ */ n("span", { className: "text-[10px] text-foreground-subtle", children: a === 0 ? "just now" : `${a}s ago` })
1275
- ] }),
1276
- /* @__PURE__ */ n("div", { className: t === "compact" ? "" : "p-3", children: r })
1277
- ] });
1545
+ function Ye({ title: e, variant: t, ts: n, children: r }) {
1546
+ let i = n ? Math.max(0, Math.floor((Date.now() - n) / 1e3)) : null;
1547
+ return /* @__PURE__ */ h("div", {
1548
+ className: t === "compact" ? "rounded-md border border-border/60 bg-surface/60 p-3" : "rounded-lg border border-border bg-surface overflow-hidden",
1549
+ children: [/* @__PURE__ */ h("div", {
1550
+ className: t === "compact" ? "flex items-center justify-between mb-2" : "border-b border-border px-4 py-2 flex items-center justify-between",
1551
+ children: [/* @__PURE__ */ m("h2", {
1552
+ className: "text-xs font-semibold text-foreground uppercase tracking-wider",
1553
+ children: e
1554
+ }), i !== null && /* @__PURE__ */ m("span", {
1555
+ className: "text-[10px] text-foreground-subtle",
1556
+ children: i === 0 ? "just now" : `${i}s ago`
1557
+ })]
1558
+ }), /* @__PURE__ */ m("div", {
1559
+ className: t === "compact" ? "" : "p-3",
1560
+ children: r
1561
+ })]
1562
+ });
1278
1563
  }
1279
- function qt({ message: e }) {
1280
- return /* @__PURE__ */ i("div", { className: "px-4 py-6 flex flex-col items-center text-center text-foreground-subtle", children: [
1281
- /* @__PURE__ */ n(oe, { className: "h-5 w-5 mb-2 opacity-30" }),
1282
- /* @__PURE__ */ n("p", { className: "text-[11px]", children: e })
1283
- ] });
1564
+ function Xe({ message: e }) {
1565
+ return /* @__PURE__ */ h("div", {
1566
+ className: "px-4 py-6 flex flex-col items-center text-center text-foreground-subtle",
1567
+ children: [/* @__PURE__ */ m(O, { className: "h-5 w-5 mb-2 opacity-30" }), /* @__PURE__ */ m("p", {
1568
+ className: "text-[11px]",
1569
+ children: e
1570
+ })]
1571
+ });
1284
1572
  }
1285
- function Gt({ frame: e }) {
1286
- return /* @__PURE__ */ n(
1287
- Ne,
1288
- {
1289
- icon: /* @__PURE__ */ n(Qe, { className: "h-3.5 w-3.5" }),
1290
- label: "Frame total",
1291
- total: e.totalObjects,
1292
- byClass: e.byClass,
1293
- tone: "default"
1294
- }
1295
- );
1573
+ function Ze({ frame: e }) {
1574
+ return /* @__PURE__ */ m(et, {
1575
+ icon: /* @__PURE__ */ m(E, { className: "h-3.5 w-3.5" }),
1576
+ label: "Frame total",
1577
+ total: e.totalObjects,
1578
+ byClass: e.byClass,
1579
+ tone: "default"
1580
+ });
1296
1581
  }
1297
- function Ut({ unzoned: e }) {
1298
- return /* @__PURE__ */ n(
1299
- Ne,
1300
- {
1301
- icon: /* @__PURE__ */ n(rt, { className: "h-3.5 w-3.5" }),
1302
- label: "Outside any zone",
1303
- total: e.totalObjects,
1304
- byClass: e.byClass,
1305
- tone: "muted"
1306
- }
1307
- );
1582
+ function Qe({ unzoned: e }) {
1583
+ return /* @__PURE__ */ m(et, {
1584
+ icon: /* @__PURE__ */ m(k, { className: "h-3.5 w-3.5" }),
1585
+ label: "Outside any zone",
1586
+ total: e.totalObjects,
1587
+ byClass: e.byClass,
1588
+ tone: "muted"
1589
+ });
1308
1590
  }
1309
- function Vt({ snapshot: e }) {
1310
- return e.zones.length === 0 ? /* @__PURE__ */ n(
1311
- Ne,
1312
- {
1313
- icon: /* @__PURE__ */ n(oe, { className: "h-3.5 w-3.5" }),
1314
- label: "Per-zone",
1315
- total: 0,
1316
- byClass: {},
1317
- tone: "muted",
1318
- emptyMessage: "No zones defined for this camera."
1319
- }
1320
- ) : /* @__PURE__ */ i("div", { className: "rounded-md border border-border/60 bg-background/40", children: [
1321
- /* @__PURE__ */ i("div", { 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", children: [
1322
- /* @__PURE__ */ n(oe, { className: "h-3.5 w-3.5" }),
1323
- /* @__PURE__ */ n("span", { children: "Per-zone" }),
1324
- /* @__PURE__ */ n("span", { className: "ml-auto text-[10px] normal-case tracking-normal", children: e.zones.length })
1325
- ] }),
1326
- /* @__PURE__ */ n("div", { className: "divide-y divide-border/30", children: e.zones.map((t) => /* @__PURE__ */ i("div", { className: "px-3 py-2", children: [
1327
- /* @__PURE__ */ i("div", { className: "flex items-center justify-between mb-1", children: [
1328
- /* @__PURE__ */ n("span", { className: "text-xs font-medium text-foreground truncate", children: t.zoneName }),
1329
- /* @__PURE__ */ n("span", { className: "rounded-full px-2 py-0.5 text-[10px] font-medium bg-foreground-subtle/10 text-foreground-subtle border border-border", children: t.totalObjects })
1330
- ] }),
1331
- /* @__PURE__ */ n(Ee, { byClass: t.byClass })
1332
- ] }, t.zoneId)) })
1333
- ] });
1591
+ function $e({ snapshot: e }) {
1592
+ return e.zones.length === 0 ? /* @__PURE__ */ m(et, {
1593
+ icon: /* @__PURE__ */ m(O, { className: "h-3.5 w-3.5" }),
1594
+ label: "Per-zone",
1595
+ total: 0,
1596
+ byClass: {},
1597
+ tone: "muted",
1598
+ emptyMessage: "No zones defined for this camera."
1599
+ }) : /* @__PURE__ */ h("div", {
1600
+ className: "rounded-md border border-border/60 bg-background/40",
1601
+ children: [/* @__PURE__ */ h("div", {
1602
+ 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",
1603
+ children: [
1604
+ /* @__PURE__ */ m(O, { className: "h-3.5 w-3.5" }),
1605
+ /* @__PURE__ */ m("span", { children: "Per-zone" }),
1606
+ /* @__PURE__ */ m("span", {
1607
+ className: "ml-auto text-[10px] normal-case tracking-normal",
1608
+ children: e.zones.length
1609
+ })
1610
+ ]
1611
+ }), /* @__PURE__ */ m("div", {
1612
+ className: "divide-y divide-border/30",
1613
+ children: e.zones.map((e) => /* @__PURE__ */ h("div", {
1614
+ className: "px-3 py-2",
1615
+ children: [/* @__PURE__ */ h("div", {
1616
+ className: "flex items-center justify-between mb-1",
1617
+ children: [/* @__PURE__ */ m("span", {
1618
+ className: "text-xs font-medium text-foreground truncate",
1619
+ children: e.zoneName
1620
+ }), /* @__PURE__ */ m("span", {
1621
+ className: "rounded-full px-2 py-0.5 text-[10px] font-medium bg-foreground-subtle/10 text-foreground-subtle border border-border",
1622
+ children: e.totalObjects
1623
+ })]
1624
+ }), /* @__PURE__ */ m(tt, { byClass: e.byClass })]
1625
+ }, e.zoneId))
1626
+ })]
1627
+ });
1334
1628
  }
1335
- function Ne({ icon: e, label: t, total: o, byClass: r, tone: a, emptyMessage: s }) {
1336
- const d = Object.keys(r).length;
1337
- return /* @__PURE__ */ i("div", { className: a === "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", children: [
1338
- /* @__PURE__ */ i("div", { className: "flex items-center gap-1.5 mb-1.5 text-[11px] uppercase tracking-wider text-foreground-subtle", children: [
1339
- e,
1340
- /* @__PURE__ */ n("span", { children: t }),
1341
- /* @__PURE__ */ n("span", { className: "ml-auto text-base font-semibold text-foreground tabular-nums normal-case tracking-normal", children: o })
1342
- ] }),
1343
- d === 0 ? /* @__PURE__ */ n("span", { className: "text-[10px] text-foreground-subtle italic", children: s ?? "no objects" }) : /* @__PURE__ */ n(Ee, { byClass: r })
1344
- ] });
1629
+ function et({ icon: e, label: t, total: n, byClass: r, tone: i, emptyMessage: a }) {
1630
+ let o = Object.keys(r).length;
1631
+ return /* @__PURE__ */ h("div", {
1632
+ 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",
1633
+ children: [/* @__PURE__ */ h("div", {
1634
+ className: "flex items-center gap-1.5 mb-1.5 text-[11px] uppercase tracking-wider text-foreground-subtle",
1635
+ children: [
1636
+ e,
1637
+ /* @__PURE__ */ m("span", { children: t }),
1638
+ /* @__PURE__ */ m("span", {
1639
+ className: "ml-auto text-base font-semibold text-foreground tabular-nums normal-case tracking-normal",
1640
+ children: n
1641
+ })
1642
+ ]
1643
+ }), o === 0 ? /* @__PURE__ */ m("span", {
1644
+ className: "text-[10px] text-foreground-subtle italic",
1645
+ children: a ?? "no objects"
1646
+ }) : /* @__PURE__ */ m(tt, { byClass: r })]
1647
+ });
1345
1648
  }
1346
- function Ee({ byClass: e }) {
1347
- const t = k(
1348
- () => Object.entries(e).sort(([, o], [, r]) => r - o),
1349
- [e]
1350
- );
1351
- return t.length === 0 ? /* @__PURE__ */ n("span", { className: "text-[10px] text-foreground-subtle italic", children: "no objects" }) : /* @__PURE__ */ n("div", { className: "flex flex-wrap gap-1", children: t.map(([o, r]) => /* @__PURE__ */ i(
1352
- "span",
1353
- {
1354
- 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",
1355
- children: [
1356
- /* @__PURE__ */ n("span", { children: o }),
1357
- /* @__PURE__ */ n("span", { className: "tabular-nums opacity-80", children: r })
1358
- ]
1359
- },
1360
- o
1361
- )) });
1649
+ function tt({ byClass: e }) {
1650
+ let n = t(() => Object.entries(e).sort(([, e], [, t]) => t - e), [e]);
1651
+ return n.length === 0 ? /* @__PURE__ */ m("span", {
1652
+ className: "text-[10px] text-foreground-subtle italic",
1653
+ children: "no objects"
1654
+ }) : /* @__PURE__ */ m("div", {
1655
+ className: "flex flex-wrap gap-1",
1656
+ children: n.map(([e, t]) => /* @__PURE__ */ h("span", {
1657
+ 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",
1658
+ children: [/* @__PURE__ */ m("span", { children: e }), /* @__PURE__ */ m("span", {
1659
+ className: "tabular-nums opacity-80",
1660
+ children: t
1661
+ })]
1662
+ }, e))
1663
+ });
1362
1664
  }
1363
- function Zt({ deviceId: e }) {
1364
- return /* @__PURE__ */ i("div", { className: ze, children: [
1365
- /* @__PURE__ */ i(
1366
- "div",
1367
- {
1368
- className: `grid ${Xe}`,
1369
- style: { gridTemplateColumns: "repeat(auto-fit, minmax(min(100%, 340px), 1fr))" },
1370
- children: [
1371
- /* @__PURE__ */ n(
1372
- B,
1373
- {
1374
- widgetId: "pipeline-analytics/live-occupancy-panel",
1375
- host: "device-tab",
1376
- deviceId: e
1377
- }
1378
- ),
1379
- /* @__PURE__ */ n(
1380
- B,
1381
- {
1382
- widgetId: "pipeline-analytics/audio-metrics-panel",
1383
- host: "device-tab",
1384
- deviceId: e
1385
- }
1386
- )
1387
- ]
1388
- }
1389
- ),
1390
- /* @__PURE__ */ n(
1391
- B,
1392
- {
1393
- widgetId: "pipeline-analytics/audio-history-chart",
1394
- host: "device-tab",
1395
- deviceId: e
1396
- }
1397
- ),
1398
- /* @__PURE__ */ n(
1399
- B,
1400
- {
1401
- widgetId: "pipeline-analytics/occupancy-history-chart",
1402
- host: "device-tab",
1403
- deviceId: e
1404
- }
1405
- ),
1406
- /* @__PURE__ */ n(
1407
- B,
1408
- {
1409
- widgetId: "pipeline-analytics/motion-history-chart",
1410
- host: "device-tab",
1411
- deviceId: e
1412
- }
1413
- ),
1414
- /* @__PURE__ */ n(
1415
- B,
1416
- {
1417
- widgetId: "pipeline-analytics/detection-history-chart",
1418
- host: "device-tab",
1419
- deviceId: e
1420
- }
1421
- )
1422
- ] });
1665
+ //#endregion
1666
+ //#region src/pipeline-analytics/widgets/LiveStatsTab.tsx
1667
+ function nt({ deviceId: e }) {
1668
+ return /* @__PURE__ */ h("div", {
1669
+ className: l,
1670
+ children: [
1671
+ /* @__PURE__ */ h("div", {
1672
+ className: `grid ${p}`,
1673
+ style: { gridTemplateColumns: "repeat(auto-fit, minmax(min(100%, 340px), 1fr))" },
1674
+ children: [/* @__PURE__ */ m(d, {
1675
+ widgetId: "pipeline-analytics/live-occupancy-panel",
1676
+ host: "device-tab",
1677
+ deviceId: e
1678
+ }), /* @__PURE__ */ m(d, {
1679
+ widgetId: "pipeline-analytics/audio-metrics-panel",
1680
+ host: "device-tab",
1681
+ deviceId: e
1682
+ })]
1683
+ }),
1684
+ /* @__PURE__ */ m(d, {
1685
+ widgetId: "pipeline-analytics/audio-history-chart",
1686
+ host: "device-tab",
1687
+ deviceId: e
1688
+ }),
1689
+ /* @__PURE__ */ m(d, {
1690
+ widgetId: "pipeline-analytics/occupancy-history-chart",
1691
+ host: "device-tab",
1692
+ deviceId: e
1693
+ }),
1694
+ /* @__PURE__ */ m(d, {
1695
+ widgetId: "pipeline-analytics/motion-history-chart",
1696
+ host: "device-tab",
1697
+ deviceId: e
1698
+ }),
1699
+ /* @__PURE__ */ m(d, {
1700
+ widgetId: "pipeline-analytics/detection-history-chart",
1701
+ host: "device-tab",
1702
+ deviceId: e
1703
+ })
1704
+ ]
1705
+ });
1423
1706
  }
1424
- function O({ name: e }) {
1425
- return /* @__PURE__ */ i("div", { className: "rounded-lg border border-warning/30 bg-warning/10 px-3 py-2 text-xs text-warning", children: [
1426
- e,
1427
- " requires a deviceId"
1428
- ] });
1707
+ //#endregion
1708
+ //#region src/pipeline-analytics/widgets/index.tsx
1709
+ function $({ name: e }) {
1710
+ return /* @__PURE__ */ h("div", {
1711
+ className: "rounded-lg border border-warning/30 bg-warning/10 px-3 py-2 text-xs text-warning",
1712
+ children: [e, " requires a deviceId"]
1713
+ });
1429
1714
  }
1430
- function Kt(e) {
1431
- return e.deviceId === void 0 ? /* @__PURE__ */ n(O, { name: "AudioHistoryChart" }) : /* @__PURE__ */ n(ut, { deviceId: e.deviceId });
1715
+ function rt(e) {
1716
+ return e.deviceId === void 0 ? /* @__PURE__ */ m($, { name: "AudioHistoryChart" }) : /* @__PURE__ */ m(se, { deviceId: e.deviceId });
1432
1717
  }
1433
- function Qt(e) {
1434
- return e.deviceId === void 0 ? /* @__PURE__ */ n(O, { name: "AudioMetricsPanel" }) : /* @__PURE__ */ n(xt, { deviceId: e.deviceId });
1718
+ function it(e) {
1719
+ return e.deviceId === void 0 ? /* @__PURE__ */ m($, { name: "AudioMetricsPanel" }) : /* @__PURE__ */ m(_e, { deviceId: e.deviceId });
1435
1720
  }
1436
- function Jt(e) {
1437
- return e.deviceId === void 0 ? /* @__PURE__ */ n(O, { name: "OccupancyHistoryChart" }) : /* @__PURE__ */ n(kt, { deviceId: e.deviceId });
1721
+ function at(e) {
1722
+ return e.deviceId === void 0 ? /* @__PURE__ */ m($, { name: "OccupancyHistoryChart" }) : /* @__PURE__ */ m(we, { deviceId: e.deviceId });
1438
1723
  }
1439
- function en(e) {
1440
- return e.deviceId === void 0 ? /* @__PURE__ */ n(O, { name: "MotionHistoryChart" }) : /* @__PURE__ */ n(It, { deviceId: e.deviceId });
1724
+ function ot(e) {
1725
+ return e.deviceId === void 0 ? /* @__PURE__ */ m($, { name: "MotionHistoryChart" }) : /* @__PURE__ */ m(je, { deviceId: e.deviceId });
1441
1726
  }
1442
- function tn(e) {
1443
- return e.deviceId === void 0 ? /* @__PURE__ */ n(O, { name: "DetectionHistoryChart" }) : /* @__PURE__ */ n(Wt, { deviceId: e.deviceId });
1727
+ function st(e) {
1728
+ return e.deviceId === void 0 ? /* @__PURE__ */ m($, { name: "DetectionHistoryChart" }) : /* @__PURE__ */ m(Be, { deviceId: e.deviceId });
1444
1729
  }
1445
- function nn(e) {
1446
- return e.deviceId === void 0 ? /* @__PURE__ */ n(O, { name: "LiveOccupancyPanel" }) : /* @__PURE__ */ n(Yt, { deviceId: e.deviceId });
1730
+ function ct(e) {
1731
+ return e.deviceId === void 0 ? /* @__PURE__ */ m($, { name: "LiveOccupancyPanel" }) : /* @__PURE__ */ m(Je, { deviceId: e.deviceId });
1447
1732
  }
1448
- function rn(e) {
1449
- return e.deviceId === void 0 ? /* @__PURE__ */ n(O, { name: "LiveStats" }) : /* @__PURE__ */ n(Zt, { deviceId: e.deviceId });
1733
+ function lt(e) {
1734
+ return e.deviceId === void 0 ? /* @__PURE__ */ m($, { name: "LiveStats" }) : /* @__PURE__ */ m(nt, { deviceId: e.deviceId });
1450
1735
  }
1451
- const cn = {
1452
- "audio-history-chart": Kt,
1453
- "audio-metrics-panel": Qt,
1454
- "occupancy-history-chart": Jt,
1455
- "motion-history-chart": en,
1456
- "detection-history-chart": tn,
1457
- "live-occupancy-panel": nn,
1458
- "live-stats": rn
1459
- };
1460
- export {
1461
- cn as default
1736
+ var ut = {
1737
+ "audio-history-chart": rt,
1738
+ "audio-metrics-panel": it,
1739
+ "occupancy-history-chart": at,
1740
+ "motion-history-chart": ot,
1741
+ "detection-history-chart": st,
1742
+ "live-occupancy-panel": ct,
1743
+ "live-stats": lt
1462
1744
  };
1745
+ //#endregion
1746
+ export { ut as default };