@camstack/addon-osd-manager 0.1.160 → 0.1.163

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 (18) hide show
  1. package/dist/{MotionZonesSettings-gJgHYJJc.mjs → MotionZonesSettings-D2hCddip.mjs} +2 -2
  2. package/dist/{PrivacyMaskSettings-HmUc5RFn.mjs → PrivacyMaskSettings-Y4wvw_Gu.mjs} +4 -4
  3. package/dist/{SceneMonitorEditor-Dqc4eAZT.mjs → SceneMonitorEditor-TTBo-9RR.mjs} +3 -3
  4. package/dist/_stub.js +324 -309
  5. package/dist/{_virtual_mf-localSharedImportMap___mfe_internal__addon_osd_manager_page-BX8u4O5k.mjs → _virtual_mf-localSharedImportMap___mfe_internal__addon_osd_manager_page-BzDlnSMr.mjs} +2 -2
  6. package/dist/_virtual_mf___mfe_internal__addon_osd_manager_page__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-m50hiGN8.mjs +26 -0
  7. package/dist/{hostInit-o9ggbWOT.mjs → hostInit-DUnFBCes.mjs} +1 -1
  8. package/dist/index.js +185 -44
  9. package/dist/index.mjs +178 -45
  10. package/dist/{player-overlays-BgDqoYs3.mjs → player-overlays-Jq6b7VG9.mjs} +1 -1
  11. package/dist/remoteEntry.js +1 -1
  12. package/dist/{responsive-B7zCyVCX.mjs → responsive-f0BEKhKZ.mjs} +1 -1
  13. package/dist/{scene-monitor-copy-DWIcj1X6.mjs → scene-monitor-copy-3aBK5dFt.mjs} +1 -1
  14. package/dist/{square-D0YQUHMC.mjs → square-0Yv5lztO.mjs} +1 -1
  15. package/dist/{trash-2-C_1H5SIl.mjs → trash-2-DW3JH3cd.mjs} +1 -1
  16. package/dist/{virtual_mf-REMOTE_ENTRY_ID___mfe_internal__addon_osd_manager_page__remoteEntry_js-BAuPDG6y.mjs → virtual_mf-REMOTE_ENTRY_ID___mfe_internal__addon_osd_manager_page__remoteEntry_js-BDRx238Q.mjs} +1 -1
  17. package/package.json +1 -1
  18. package/dist/_virtual_mf___mfe_internal__addon_osd_manager_page__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-BzuGVFNp.mjs +0 -26
package/dist/_stub.js CHANGED
@@ -1,18 +1,18 @@
1
1
  import "./virtualExposes-BgZ5Cn7S.mjs";
2
- import "./virtual_mf-REMOTE_ENTRY_ID___mfe_internal__addon_osd_manager_page__remoteEntry_js-BAuPDG6y.mjs";
2
+ import "./virtual_mf-REMOTE_ENTRY_ID___mfe_internal__addon_osd_manager_page__remoteEntry_js-BDRx238Q.mjs";
3
3
  import { _ as e, b as t, c as n, d as r, f as i, g as a, h as o, i as s, l as c, m as l, n as u, p as d, r as f, t as p, u as m, v as h } from "./_virtual_mf___mfe_internal__addon_osd_manager_page__loadShare__react__loadShare__.js-C5jUMd7X.mjs";
4
- import { a as g, c as _, i as v, n as y, o as b, r as x, s as S } from "./responsive-B7zCyVCX.mjs";
5
- import { d as C, l as w, s as T, u as E } from "./scene-monitor-copy-DWIcj1X6.mjs";
6
- import { i as D, r as O } from "./player-overlays-BgDqoYs3.mjs";
7
- import { i as ee, n as te, r as ne, t as k } from "./square-D0YQUHMC.mjs";
8
- import { t as re } from "./trash-2-C_1H5SIl.mjs";
4
+ import { a as g, c as _, i as v, n as y, o as b, r as x, s as S } from "./responsive-f0BEKhKZ.mjs";
5
+ import { d as C, l as w, s as T, u as E } from "./scene-monitor-copy-3aBK5dFt.mjs";
6
+ import { i as D, r as O } from "./player-overlays-Jq6b7VG9.mjs";
7
+ import { i as ee, n as te, r as ne, t as k } from "./square-0Yv5lztO.mjs";
8
+ import { t as re } from "./trash-2-DW3JH3cd.mjs";
9
9
  import { t as ie } from "./_virtual_mf___mfe_internal__addon_osd_manager_page__loadShare___mf_0_trpc_mf_1_react_mf_2_query__loadShare__.js-BpP33rwB.mjs";
10
10
  import { n as A, r as j, t as M } from "./_virtual_mf___mfe_internal__addon_osd_manager_page__loadShare__react_mf_1_jsx_mf_2_runtime__loadShare__.js-DalfdIDw.mjs";
11
11
  import { t as ae } from "./_virtual_mf___mfe_internal__addon_osd_manager_page__loadShare__react_mf_2_dom__loadShare__.js-qB5uHZAd.mjs";
12
12
  import { n as N, t as oe } from "./_virtual_mf___mfe_internal__addon_osd_manager_page__loadShare___mf_0_tanstack_mf_1_react_mf_2_query__loadShare__.js-CHxDN0gE.mjs";
13
13
  import "./_virtual_mf___mfe_internal__addon_osd_manager_page__loadShare__react_mf_2_dom_mf_1_client__loadShare__.js-Dhy3m6Ij.mjs";
14
14
  import "./_virtual_mf___mfe_internal__addon_osd_manager_page__loadShare___mf_0_trpc_mf_1_client__loadShare__.js-C7omKvJr.mjs";
15
- import { _ as P, a as F, b as I, c as se, d as L, f as ce, g as le, h as ue, l as de, m as fe, n as pe, o as me, p as he, r as ge, s as _e, t as ve, u as ye, v as R, y as be } from "./_virtual_mf___mfe_internal__addon_osd_manager_page__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-BzuGVFNp.mjs";
15
+ import { _ as P, a as F, b as I, c as se, d as L, f as ce, g as le, h as ue, l as de, m as fe, n as pe, o as me, p as he, r as ge, s as _e, t as ve, u as ye, v as R, y as be } from "./_virtual_mf___mfe_internal__addon_osd_manager_page__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-m50hiGN8.mjs";
16
16
  import "./_virtual_mf___mfe_internal__addon_osd_manager_page__loadShare___mf_0_camstack_mf_1_sdk__loadShare__.js-B_4MkXHU.mjs";
17
17
  var xe = _("activity", [["path", {
18
18
  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",
@@ -6100,7 +6100,7 @@ t(), t(), t(), S("camstack:recorded-playback", {
6100
6100
  mode: "live",
6101
6101
  positionMs: null,
6102
6102
  send: () => !1
6103
- }), t(), t(), t(), t(), t(), t(), s(() => import("./MotionZonesSettings-gJgHYJJc.mjs").then((e) => ({ default: e.MotionZonesSettings }))), s(() => import("./PrivacyMaskSettings-HmUc5RFn.mjs").then((e) => ({ default: e.PrivacyMaskSettings }))), t(), t();
6103
+ }), t(), t(), t(), t(), t(), t(), s(() => import("./MotionZonesSettings-D2hCddip.mjs").then((e) => ({ default: e.MotionZonesSettings }))), s(() => import("./PrivacyMaskSettings-Y4wvw_Gu.mjs").then((e) => ({ default: e.PrivacyMaskSettings }))), t(), t();
6104
6104
  var Oo = Object.defineProperty, ko = Object.getOwnPropertySymbols, Ao = Object.prototype.hasOwnProperty, jo = Object.prototype.propertyIsEnumerable, Mo = (e, t, n) => t in e ? Oo(e, t, {
6105
6105
  enumerable: !0,
6106
6106
  configurable: !0,
@@ -22468,7 +22468,7 @@ var IT = class {
22468
22468
  } catch {}
22469
22469
  }
22470
22470
  };
22471
- t(), new IT(), t(), t(), t(), s(() => import("./MaskShapeCanvas-BT714ljC.mjs").then((e) => ({ default: e.MaskShapeCanvas }))), s(() => import("./MotionZonesSettings-gJgHYJJc.mjs").then((e) => ({ default: e.MotionZonesSettings }))), s(() => import("./SceneMonitorEditor-Dqc4eAZT.mjs").then((e) => ({ default: e.SceneMonitorEditor }))), s(() => import("./PrivacyMaskSettings-HmUc5RFn.mjs").then((e) => ({ default: e.PrivacyMaskSettings })));
22471
+ t(), new IT(), t(), t(), t(), s(() => import("./MaskShapeCanvas-BT714ljC.mjs").then((e) => ({ default: e.MaskShapeCanvas }))), s(() => import("./MotionZonesSettings-D2hCddip.mjs").then((e) => ({ default: e.MotionZonesSettings }))), s(() => import("./SceneMonitorEditor-TTBo-9RR.mjs").then((e) => ({ default: e.SceneMonitorEditor }))), s(() => import("./PrivacyMaskSettings-Y4wvw_Gu.mjs").then((e) => ({ default: e.PrivacyMaskSettings })));
22472
22472
  //#endregion
22473
22473
  //#region src/ui/osd-page-model.ts
22474
22474
  function LT() {
@@ -22717,23 +22717,60 @@ function yE(e, t) {
22717
22717
  return e.find((e) => e.id === t);
22718
22718
  }
22719
22719
  //#endregion
22720
- //#region src/components/DeviceStateSourceEditor.tsx
22721
- t();
22720
+ //#region src/unit-display.ts
22722
22721
  function bE(e) {
22723
- return `${e.deviceId}:${e.capName}:${e.valuePath}`;
22724
- }
22725
- function xE(e) {
22726
22722
  if (e === void 0) return;
22727
22723
  let t = F(e);
22728
- return t === void 0 ? void 0 : L(t);
22724
+ if (t !== void 0) return L(t);
22725
+ }
22726
+ function xE(e, t, n) {
22727
+ let r = t === void 0 ? void 0 : F(t), i = n === void 0 ? void 0 : F(n);
22728
+ if (r === void 0 || i === void 0 || r === i) return {
22729
+ value: e,
22730
+ unit: i ?? r ?? ""
22731
+ };
22732
+ let a = ye(e, r, i);
22733
+ return a === void 0 ? {
22734
+ value: e,
22735
+ unit: r
22736
+ } : {
22737
+ value: a,
22738
+ unit: i
22739
+ };
22740
+ }
22741
+ function SE(e, t) {
22742
+ if (typeof e != "object" || !e || Array.isArray(e)) return;
22743
+ let n = { ...e }, r = t.split(".");
22744
+ if (r.length >= 1) {
22745
+ let e = n;
22746
+ for (let t of r.slice(0, -1)) {
22747
+ if (typeof e != "object" || !e || Array.isArray(e)) {
22748
+ e = void 0;
22749
+ break;
22750
+ }
22751
+ e = { ...e }[t];
22752
+ }
22753
+ if (typeof e == "object" && e && !Array.isArray(e)) {
22754
+ let t = { ...e }.unit;
22755
+ if (typeof t == "string" && t.length > 0) return t;
22756
+ }
22757
+ }
22758
+ let i = n.unit;
22759
+ return typeof i == "string" && i.length > 0 ? i : void 0;
22760
+ }
22761
+ //#endregion
22762
+ //#region src/components/DeviceStateSourceEditor.tsx
22763
+ t();
22764
+ function CE(e) {
22765
+ return `${e.deviceId}:${e.capName}:${e.valuePath}`;
22729
22766
  }
22730
- function SE(e) {
22767
+ function wE(e) {
22731
22768
  let t = e.toLowerCase();
22732
22769
  if (t.includes("temp")) return "°C";
22733
22770
  if (t.includes("humid")) return "%";
22734
22771
  if (t.includes("pressure") || t.includes("hpa")) return "hPa";
22735
22772
  }
22736
- function CE(e) {
22773
+ function TE(e) {
22737
22774
  return e.map((e) => ({
22738
22775
  id: e.id,
22739
22776
  name: e.name,
@@ -22742,12 +22779,12 @@ function CE(e) {
22742
22779
  parentDeviceId: "parentDeviceId" in e && typeof e.parentDeviceId == "number" ? e.parentDeviceId : null
22743
22780
  }));
22744
22781
  }
22745
- function wE({ source: e, sources: t, pickerDevices: n, listState: r, onChange: i }) {
22746
- let o = l(() => CE(n), [n]), s = l(() => new Set(t.map((e) => e.deviceId)), [t]), [c, u] = a(void 0), d = e.deviceId, f = c ?? d, p = c !== void 0 && gE(yE(o, c)?.type) ? c : void 0, m = p === void 0 ? [] : vE(p, o, s), h = l(() => d === void 0 || p !== void 0 ? void 0 : dE(t, d), [
22782
+ function EE({ source: e, sources: t, pickerDevices: n, listState: r, onChange: i }) {
22783
+ let o = l(() => TE(n), [n]), s = l(() => new Set(t.map((e) => e.deviceId)), [t]), [c, u] = a(void 0), d = e.deviceId, f = c ?? d, p = c !== void 0 && gE(yE(o, c)?.type) ? c : void 0, m = p === void 0 ? [] : vE(p, o, s), h = l(() => d === void 0 || p !== void 0 ? void 0 : dE(t, d), [
22747
22784
  t,
22748
22785
  d,
22749
22786
  p
22750
- ]), g = d === void 0 || p !== void 0 ? void 0 : t.find((t) => t.deviceId === d && t.capName === e.capName && t.valuePath === e.valuePath), _ = SE(e.valuePath), v = xE(e.displayUnit ?? _);
22787
+ ]), g = d === void 0 || p !== void 0 ? void 0 : t.find((t) => t.deviceId === d && t.capName === e.capName && t.valuePath === e.valuePath), _ = wE(e.valuePath), v = bE(_);
22751
22788
  return /* @__PURE__ */ j("div", {
22752
22789
  className: "space-y-2",
22753
22790
  "data-testid": "osd-device-state-editor",
@@ -22854,17 +22891,17 @@ function wE({ source: e, sources: t, pickerDevices: n, listState: r, onChange: i
22854
22891
  }), /* @__PURE__ */ A(po, {
22855
22892
  id: "osd-field-pick",
22856
22893
  "data-testid": "osd-field-pick",
22857
- value: bE(g || {
22894
+ value: CE(g || {
22858
22895
  deviceId: d ?? 0,
22859
22896
  capName: e.capName,
22860
22897
  valuePath: e.valuePath
22861
22898
  }),
22862
22899
  options: h.fields.map((e) => ({
22863
- value: bE(e),
22900
+ value: CE(e),
22864
22901
  label: e.label
22865
22902
  })),
22866
22903
  onChange: (t) => {
22867
- let n = h.fields.find((e) => bE(e) === t.target.value);
22904
+ let n = h.fields.find((e) => CE(e) === t.target.value);
22868
22905
  n && i({
22869
22906
  kind: "device-state",
22870
22907
  deviceId: n.deviceId,
@@ -22906,7 +22943,7 @@ function wE({ source: e, sources: t, pickerDevices: n, listState: r, onChange: i
22906
22943
  //#endregion
22907
22944
  //#region src/components/SourceEditor.tsx
22908
22945
  t();
22909
- var TE = [
22946
+ var DE = [
22910
22947
  {
22911
22948
  value: "static",
22912
22949
  label: "Static text"
@@ -22928,7 +22965,7 @@ var TE = [
22928
22965
  label: "Named template"
22929
22966
  }
22930
22967
  ];
22931
- function EE({ source: e, sources: t, pickerDevices: n, listState: r, templates: i, onChange: a }) {
22968
+ function OE({ source: e, sources: t, pickerDevices: n, listState: r, templates: i, onChange: a }) {
22932
22969
  let o = l(() => i.map((e) => ({
22933
22970
  value: e.id,
22934
22971
  label: e.name || e.id
@@ -22942,7 +22979,7 @@ function EE({ source: e, sources: t, pickerDevices: n, listState: r, templates:
22942
22979
  }), /* @__PURE__ */ A(po, {
22943
22980
  id: "osd-source-kind",
22944
22981
  value: e.kind,
22945
- options: TE,
22982
+ options: DE,
22946
22983
  onChange: (e) => {
22947
22984
  let t = e.target.value;
22948
22985
  if (t === "static") a({
@@ -23013,7 +23050,7 @@ function EE({ source: e, sources: t, pickerDevices: n, listState: r, templates:
23013
23050
  })
23014
23051
  })] })]
23015
23052
  }),
23016
- e.kind === "device-state" && /* @__PURE__ */ A(wE, {
23053
+ e.kind === "device-state" && /* @__PURE__ */ A(EE, {
23017
23054
  source: e,
23018
23055
  sources: t,
23019
23056
  pickerDevices: n,
@@ -23058,7 +23095,7 @@ function EE({ source: e, sources: t, pickerDevices: n, listState: r, templates:
23058
23095
  }
23059
23096
  //#endregion
23060
23097
  //#region src/components/ValueMapEditor.tsx
23061
- function DE({ valueMap: e, onChange: t }) {
23098
+ function kE({ valueMap: e, onChange: t }) {
23062
23099
  let n = Object.entries(e ?? {});
23063
23100
  function r(e) {
23064
23101
  if (e.length === 0) {
@@ -23118,13 +23155,13 @@ function DE({ valueMap: e, onChange: t }) {
23118
23155
  }
23119
23156
  //#endregion
23120
23157
  //#region src/components/ScheduleEditor.tsx
23121
- function OE(e, t, n) {
23158
+ function AE(e, t, n) {
23122
23159
  return {
23123
23160
  ...e,
23124
23161
  windows: e.windows.map((e, r) => r === t ? n : e)
23125
23162
  };
23126
23163
  }
23127
- function kE({ schedule: e, onChange: t }) {
23164
+ function jE({ schedule: e, onChange: t }) {
23128
23165
  let n = e !== void 0;
23129
23166
  return /* @__PURE__ */ j("div", {
23130
23167
  className: "space-y-3",
@@ -23145,7 +23182,7 @@ function kE({ schedule: e, onChange: t }) {
23145
23182
  type: "button",
23146
23183
  "aria-pressed": n.days.includes(a),
23147
23184
  className: ["px-1.5 py-0.5 rounded text-[10px] font-medium", n.days.includes(a) ? "bg-primary text-primary-foreground" : "bg-surface-hover text-foreground-muted"].join(" "),
23148
- onClick: () => t(OE(e, r, sE(n, a))),
23185
+ onClick: () => t(AE(e, r, sE(n, a))),
23149
23186
  children: i
23150
23187
  }, a))
23151
23188
  }),
@@ -23159,7 +23196,7 @@ function kE({ schedule: e, onChange: t }) {
23159
23196
  type: "time",
23160
23197
  className: "h-7 w-full px-2 text-xs bg-surface border border-border rounded-md text-foreground",
23161
23198
  value: aE(n.startMinute),
23162
- onChange: (i) => t(OE(e, r, {
23199
+ onChange: (i) => t(AE(e, r, {
23163
23200
  ...n,
23164
23201
  startMinute: oE(i.target.value)
23165
23202
  }))
@@ -23171,7 +23208,7 @@ function kE({ schedule: e, onChange: t }) {
23171
23208
  type: "time",
23172
23209
  className: "h-7 w-full px-2 text-xs bg-surface border border-border rounded-md text-foreground",
23173
23210
  value: aE(n.endMinute),
23174
- onChange: (i) => t(OE(e, r, {
23211
+ onChange: (i) => t(AE(e, r, {
23175
23212
  ...n,
23176
23213
  endMinute: oE(i.target.value)
23177
23214
  }))
@@ -23203,7 +23240,7 @@ function kE({ schedule: e, onChange: t }) {
23203
23240
  }
23204
23241
  //#endregion
23205
23242
  //#region src/components/ConditionsEditor.tsx
23206
- function AE({ conditions: e, supported: t, devices: n, deviceStateSnapshot: r, onSelectDeviceStateDevice: i, onChange: a }) {
23243
+ function ME({ conditions: e, supported: t, devices: n, deviceStateSnapshot: r, onSelectDeviceStateDevice: i, onChange: a }) {
23207
23244
  let o = t.includes("deviceState"), s = lE(r);
23208
23245
  return /* @__PURE__ */ j("div", {
23209
23246
  className: "space-y-3",
@@ -23274,7 +23311,7 @@ function AE({ conditions: e, supported: t, devices: n, deviceStateSnapshot: r, o
23274
23311
  //#endregion
23275
23312
  //#region src/components/SlotEditor.tsx
23276
23313
  t();
23277
- function jE({ deviceId: e, slot: t, sources: n, conditionSupport: r, devices: i, pickerDevices: o, listState: s, templates: c, onClose: u, onSaved: d }) {
23314
+ function NE({ deviceId: e, slot: t, sources: n, conditionSupport: r, devices: i, pickerDevices: o, listState: s, templates: c, onClose: u, onSaved: d }) {
23278
23315
  let [f, p] = a(() => RT(t)), [m, h] = a(f.conditions?.deviceState?.deviceId), [g, _] = a(void 0), v = gi({ deviceId: m ?? 0 }, { enabled: m !== void 0 }), y = xi(), b = Si(), x = wi(), S = y.isPending || b.isPending || x.isPending, C = y.error ?? b.error ?? x.error, w = l(() => [{
23279
23316
  id: "value",
23280
23317
  label: "${value}",
@@ -23342,7 +23379,7 @@ function jE({ deviceId: e, slot: t, sources: n, conditionSupport: r, devices: i,
23342
23379
  }))
23343
23380
  }), "Binding enabled"]
23344
23381
  }),
23345
- /* @__PURE__ */ A(EE, {
23382
+ /* @__PURE__ */ A(OE, {
23346
23383
  source: f.source,
23347
23384
  sources: n,
23348
23385
  pickerDevices: o,
@@ -23433,21 +23470,21 @@ function jE({ deviceId: e, slot: t, sources: n, conditionSupport: r, devices: i,
23433
23470
  })
23434
23471
  ]
23435
23472
  }),
23436
- /* @__PURE__ */ A(DE, {
23473
+ /* @__PURE__ */ A(kE, {
23437
23474
  valueMap: f.valueMap,
23438
23475
  onChange: (e) => p((t) => ({
23439
23476
  ...t,
23440
23477
  valueMap: e
23441
23478
  }))
23442
23479
  }),
23443
- /* @__PURE__ */ A(kE, {
23480
+ /* @__PURE__ */ A(jE, {
23444
23481
  schedule: f.schedule,
23445
23482
  onChange: (e) => p((t) => ({
23446
23483
  ...t,
23447
23484
  schedule: e
23448
23485
  }))
23449
23486
  }),
23450
- /* @__PURE__ */ A(AE, {
23487
+ /* @__PURE__ */ A(ME, {
23451
23488
  conditions: f.conditions,
23452
23489
  supported: r,
23453
23490
  devices: i,
@@ -23505,7 +23542,7 @@ function jE({ deviceId: e, slot: t, sources: n, conditionSupport: r, devices: i,
23505
23542
  //#endregion
23506
23543
  //#region src/components/DuplicateIntoAction.tsx
23507
23544
  t();
23508
- function ME({ source: e, destinations: t, onDuplicated: n }) {
23545
+ function PE({ source: e, destinations: t, onDuplicated: n }) {
23509
23546
  let [r, i] = a(!1), [o, s] = a(void 0), [c, l] = a(void 0), [u, d] = a(void 0), f = Ci();
23510
23547
  if (t.length === 0) return null;
23511
23548
  function p() {
@@ -23600,7 +23637,7 @@ function ME({ source: e, destinations: t, onDuplicated: n }) {
23600
23637
  //#endregion
23601
23638
  //#region src/components/CameraOsdRow.tsx
23602
23639
  t();
23603
- function NE({ cameraId: e, supportsOsd: t, onRefetchReady: n }) {
23640
+ function FE({ cameraId: e, supportsOsd: t, onRefetchReady: n }) {
23604
23641
  let r = vi({ deviceId: e }, { enabled: t });
23605
23642
  if (m(() => {
23606
23643
  t && n(e, () => void r.refetch());
@@ -23615,7 +23652,7 @@ function NE({ cameraId: e, supportsOsd: t, onRefetchReady: n }) {
23615
23652
  children: WT(i)
23616
23653
  });
23617
23654
  }
23618
- function PE({ cameraId: e, supportsOsd: t, deviceNameById: n }) {
23655
+ function IE({ cameraId: e, supportsOsd: t, deviceNameById: n }) {
23619
23656
  let r = vi({ deviceId: e }, { enabled: t });
23620
23657
  if (!t) return /* @__PURE__ */ A("span", {
23621
23658
  className: "text-xs text-foreground-subtle",
@@ -23638,7 +23675,7 @@ function PE({ cameraId: e, supportsOsd: t, deviceNameById: n }) {
23638
23675
  }, e.key))
23639
23676
  });
23640
23677
  }
23641
- function FE({ camera: e, allDevices: t, conditionSupport: n, pickerDevices: r, listState: i, templates: o, destinations: s, onRefetchReady: c, refetchCamera: u }) {
23678
+ function LE({ camera: e, allDevices: t, conditionSupport: n, pickerDevices: r, listState: i, templates: o, destinations: s, onRefetchReady: c, refetchCamera: u }) {
23642
23679
  let [d, f] = a(null), [p, h] = a(0), g = vi({ deviceId: e.id }, { enabled: e.supportsOsd }), _ = g.data?.slots ?? [], v = l(() => d !== null && _.some((e) => e.slotId === d) ? d : XT(_), [d, _]), y = _.find((e) => e.slotId === v), b = yi({ deviceId: e.id }, { enabled: e.supportsOsd && y !== void 0 && !y.readOnly }), x = Ti();
23643
23680
  m(() => {
23644
23681
  e.supportsOsd && c(e.id, () => void g.refetch());
@@ -23667,7 +23704,7 @@ function FE({ camera: e, allDevices: t, conditionSupport: n, pickerDevices: r, l
23667
23704
  disabled: x.isPending,
23668
23705
  onClick: () => x.mutate({ deviceId: e.id }, { onSuccess: () => void g.refetch() }),
23669
23706
  children: [x.isPending ? /* @__PURE__ */ A(un, { className: "h-3.5 w-3.5 animate-spin" }) : null, "Render now"]
23670
- }) : null, e.supportsOsd ? /* @__PURE__ */ A(ME, {
23707
+ }) : null, e.supportsOsd ? /* @__PURE__ */ A(PE, {
23671
23708
  source: e,
23672
23709
  destinations: s,
23673
23710
  onDuplicated: (e) => {
@@ -23701,9 +23738,9 @@ function FE({ camera: e, allDevices: t, conditionSupport: n, pickerDevices: r, l
23701
23738
  },
23702
23739
  children: /* @__PURE__ */ A(Rs, {
23703
23740
  className: "mb-3",
23704
- children: _.map((e) => /* @__PURE__ */ A(IE, { slot: e }, e.slotId))
23741
+ children: _.map((e) => /* @__PURE__ */ A(RE, { slot: e }, e.slotId))
23705
23742
  })
23706
- }), y === void 0 ? null : /* @__PURE__ */ A(LE, {
23743
+ }), y === void 0 ? null : /* @__PURE__ */ A(zE, {
23707
23744
  cameraId: e.id,
23708
23745
  slot: y,
23709
23746
  editorEpoch: p,
@@ -23721,7 +23758,7 @@ function FE({ camera: e, allDevices: t, conditionSupport: n, pickerDevices: r, l
23721
23758
  ]
23722
23759
  });
23723
23760
  }
23724
- function IE({ slot: e }) {
23761
+ function RE({ slot: e }) {
23725
23762
  let t = qT(e);
23726
23763
  return /* @__PURE__ */ j(zs, {
23727
23764
  value: e.slotId,
@@ -23732,7 +23769,7 @@ function IE({ slot: e }) {
23732
23769
  })]
23733
23770
  });
23734
23771
  }
23735
- function LE({ cameraId: e, slot: t, editorEpoch: n, sources: r, conditionSupport: i, devices: a, pickerDevices: o, listState: s, templates: c, onSaved: l }) {
23772
+ function zE({ cameraId: e, slot: t, editorEpoch: n, sources: r, conditionSupport: i, devices: a, pickerDevices: o, listState: s, templates: c, onSaved: l }) {
23736
23773
  return t.readOnly ? /* @__PURE__ */ j("div", {
23737
23774
  className: "rounded-lg border border-border bg-surface p-4 space-y-2",
23738
23775
  "data-testid": "osd-slot-readonly",
@@ -23764,7 +23801,7 @@ function LE({ cameraId: e, slot: t, editorEpoch: n, sources: r, conditionSupport
23764
23801
  children: VT(t.binding)
23765
23802
  })
23766
23803
  ]
23767
- }) : /* @__PURE__ */ A(jE, {
23804
+ }) : /* @__PURE__ */ A(NE, {
23768
23805
  deviceId: e,
23769
23806
  slot: t,
23770
23807
  sources: r,
@@ -23779,7 +23816,7 @@ function LE({ cameraId: e, slot: t, editorEpoch: n, sources: r, conditionSupport
23779
23816
  //#endregion
23780
23817
  //#region src/components/CameraOsdTable.tsx
23781
23818
  t();
23782
- function RE({ cameras: e, osdCapableIds: t, allDevices: n, conditionSupport: r, pickerDevices: i, listState: s, templates: c }) {
23819
+ function BE({ cameras: e, osdCapableIds: t, allDevices: n, conditionSupport: r, pickerDevices: i, listState: s, templates: c }) {
23783
23820
  let [u, d] = a(void 0), f = o(/* @__PURE__ */ new Map()), p = l(() => new Map(n.map((e) => [e.id, e.name])), [n]), m = l(() => e.map((e) => ({
23784
23821
  id: e.id,
23785
23822
  name: e.name,
@@ -23840,7 +23877,7 @@ function RE({ cameras: e, osdCapableIds: t, allDevices: n, conditionSupport: r,
23840
23877
  {
23841
23878
  key: "status",
23842
23879
  header: "Status",
23843
- cell: (e) => /* @__PURE__ */ A(NE, {
23880
+ cell: (e) => /* @__PURE__ */ A(FE, {
23844
23881
  cameraId: e.id,
23845
23882
  supportsOsd: e.supportsOsd,
23846
23883
  onRefetchReady: h
@@ -23849,7 +23886,7 @@ function RE({ cameras: e, osdCapableIds: t, allDevices: n, conditionSupport: r,
23849
23886
  {
23850
23887
  key: "sources",
23851
23888
  header: "Active sources",
23852
- cell: (e) => /* @__PURE__ */ A(PE, {
23889
+ cell: (e) => /* @__PURE__ */ A(IE, {
23853
23890
  cameraId: e.id,
23854
23891
  supportsOsd: e.supportsOsd,
23855
23892
  deviceNameById: p
@@ -23859,7 +23896,7 @@ function RE({ cameras: e, osdCapableIds: t, allDevices: n, conditionSupport: r,
23859
23896
  isExpanded: (e) => u === e.id,
23860
23897
  renderExpanded: (e) => /* @__PURE__ */ A("div", {
23861
23898
  id: `osd-camera-detail-${e.id}`,
23862
- children: /* @__PURE__ */ A(FE, {
23899
+ children: /* @__PURE__ */ A(LE, {
23863
23900
  camera: e,
23864
23901
  allDevices: n,
23865
23902
  conditionSupport: r,
@@ -23877,7 +23914,7 @@ function RE({ cameras: e, osdCapableIds: t, allDevices: n, conditionSupport: r,
23877
23914
  }
23878
23915
  //#endregion
23879
23916
  //#region src/format.ts
23880
- function zE(e, t) {
23917
+ function VE(e, t) {
23881
23918
  if (!Number.isFinite(e)) return "";
23882
23919
  if (t <= 0) return String(Math.trunc(e));
23883
23920
  let n = 10 ** t, r = Math.trunc(e * n) / n;
@@ -23885,16 +23922,39 @@ function zE(e, t) {
23885
23922
  }
23886
23923
  //#endregion
23887
23924
  //#region src/template-tokens.ts
23888
- function BE(e) {
23889
- return `{${e}}`;
23925
+ function HE(e, t = "full") {
23926
+ return t === "full" ? `{${e}}` : `{${e}.${t}}`;
23927
+ }
23928
+ function UE(e) {
23929
+ return `{${e}.full}`;
23890
23930
  }
23891
- function VE(e) {
23892
- return BE(e.alias);
23931
+ function WE(e) {
23932
+ let t = e.alias;
23933
+ return [
23934
+ {
23935
+ id: `${t}.value`,
23936
+ label: `${t} · value`,
23937
+ token: HE(t, "value"),
23938
+ kind: "value"
23939
+ },
23940
+ {
23941
+ id: `${t}.unit`,
23942
+ label: `${t} · unit`,
23943
+ token: HE(t, "unit"),
23944
+ kind: "unit"
23945
+ },
23946
+ {
23947
+ id: `${t}.full`,
23948
+ label: `${t} · value+unit`,
23949
+ token: UE(t),
23950
+ kind: "full"
23951
+ }
23952
+ ];
23893
23953
  }
23894
- function HE(e, t, n) {
23954
+ function GE(e, t, n) {
23895
23955
  return e.replaceAll(t, n);
23896
23956
  }
23897
- function UE(e, t, n = "b") {
23957
+ function KE(e, t, n = "b") {
23898
23958
  let r = e.trim().toLowerCase().replace(/[^a-z0-9]+/g, "_").replace(/^_+|_+$/g, "").replace(/^(\d)/, "a$1").slice(0, 24), i = r.length > 0 ? r : n;
23899
23959
  if (!t.has(i)) return i;
23900
23960
  for (let e = 2; e < 1e3; e += 1) {
@@ -23904,51 +23964,14 @@ function UE(e, t, n = "b") {
23904
23964
  return `${n}${Date.now().toString(36)}`;
23905
23965
  }
23906
23966
  //#endregion
23907
- //#region src/unit-display.ts
23908
- function WE(e, t, n) {
23909
- let r = t === void 0 ? void 0 : F(t), i = n === void 0 ? void 0 : F(n);
23910
- if (r === void 0 || i === void 0 || r === i) return {
23911
- value: e,
23912
- unit: i ?? r ?? ""
23913
- };
23914
- let a = ye(e, r, i);
23915
- return a === void 0 ? {
23916
- value: e,
23917
- unit: r
23918
- } : {
23919
- value: a,
23920
- unit: i
23921
- };
23922
- }
23923
- function GE(e, t) {
23924
- if (typeof e != "object" || !e || Array.isArray(e)) return;
23925
- let n = { ...e }, r = t.split(".");
23926
- if (r.length >= 1) {
23927
- let e = n;
23928
- for (let t of r.slice(0, -1)) {
23929
- if (typeof e != "object" || !e || Array.isArray(e)) {
23930
- e = void 0;
23931
- break;
23932
- }
23933
- e = { ...e }[t];
23934
- }
23935
- if (typeof e == "object" && e && !Array.isArray(e)) {
23936
- let t = { ...e }.unit;
23937
- if (typeof t == "string" && t.length > 0) return t;
23938
- }
23939
- }
23940
- let i = n.unit;
23941
- return typeof i == "string" && i.length > 0 ? i : void 0;
23942
- }
23943
- //#endregion
23944
23967
  //#region src/named-template-render.ts
23945
- function KE(e, t, n) {
23968
+ function qE(e, t, n) {
23946
23969
  if (n === "value") return e;
23947
23970
  if (n === "unit") return t;
23948
23971
  let r = e.trim(), i = t.trim();
23949
23972
  return r === "" ? i : i === "" ? r : `${r} ${i}`;
23950
23973
  }
23951
- function qE(e, t) {
23974
+ function JE(e, t) {
23952
23975
  let n = e.pick.deviceId, r = t.stateByDevice.get(n);
23953
23976
  if (r === void 0) return { reason: `no state mirrored for device ${n}` };
23954
23977
  let i = r[e.capName];
@@ -23957,61 +23980,56 @@ function qE(e, t) {
23957
23980
  if (a === void 0) return { reason: `"${e.capName}.${e.valuePath}" is absent on device ${n}` };
23958
23981
  let o, s = "";
23959
23982
  if (typeof a == "number") {
23960
- let t = WE(a, GE(i, e.valuePath), e.displayUnit);
23961
- o = zE(t.value, e.maxDecimals), s = t.unit;
23983
+ let t = xE(a, SE(i, e.valuePath), e.displayUnit);
23984
+ o = VE(t.value, e.maxDecimals), s = t.unit;
23962
23985
  } else o = typeof a == "boolean" ? a ? "ON" : "OFF" : a === null ? "" : String(a);
23963
23986
  return {
23964
23987
  value: o,
23965
23988
  unit: s,
23966
- formatted: KE(o, s, e.format)
23989
+ formatted: qE(o, s, "full")
23967
23990
  };
23968
23991
  }
23969
- function JE(e, t) {
23992
+ function YE(e, t, n) {
23993
+ let r = e;
23994
+ return r = GE(r, UE(t), n.formatted), r = GE(r, HE(t, "value"), n.value), r = GE(r, HE(t, "unit"), n.unit), r = GE(r, HE(t, "full"), n.formatted), r;
23995
+ }
23996
+ function XE(e, t) {
23970
23997
  let n = e.parser;
23971
23998
  if (e.bindings.length === 0) return n.trim() === "" ? { reason: `template "${e.id}" has no bindings` } : { text: n };
23972
23999
  for (let r of e.bindings) {
23973
- let e = qE(r, t);
24000
+ let e = JE(r, t);
23974
24001
  if ("reason" in e) return e;
23975
- n = HE(n, BE(r.alias), e.formatted);
24002
+ n = YE(n, r.alias, e);
23976
24003
  }
23977
24004
  return { text: n };
23978
24005
  }
23979
24006
  //#endregion
23980
24007
  //#region src/template-id.ts
23981
- function YE() {
24008
+ function ZE() {
23982
24009
  return typeof crypto < "u" && typeof crypto.randomUUID == "function" ? crypto.randomUUID() : `tpl-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 10)}`;
23983
24010
  }
23984
24011
  //#endregion
23985
24012
  //#region src/components/TemplatesPanel.tsx
23986
24013
  t();
23987
- var XE = [
23988
- {
23989
- value: "value+unit",
23990
- label: "Value + unit"
23991
- },
23992
- {
23993
- value: "value",
23994
- label: "Value"
23995
- },
23996
- {
23997
- value: "unit",
23998
- label: "Unit"
23999
- }
24000
- ];
24001
- function ZE(e) {
24002
- if (e === void 0) return;
24003
- let t = F(e);
24004
- return t === void 0 ? void 0 : L(t);
24005
- }
24006
- function QE(e) {
24007
- return e.pick.containerId ?? e.pick.deviceId;
24008
- }
24014
+ var QE = 0;
24009
24015
  function $E(e, t) {
24010
24016
  let n = /* @__PURE__ */ new Set();
24011
24017
  for (let r = 0; r < e.length; r += 1) r !== t && n.add(e[r].alias);
24012
24018
  return n;
24013
24019
  }
24014
- function eD() {
24020
+ function eD(e) {
24021
+ return {
24022
+ alias: KE("sensor", e),
24023
+ pick: { deviceId: QE },
24024
+ capName: "",
24025
+ valuePath: "",
24026
+ maxDecimals: 1
24027
+ };
24028
+ }
24029
+ function tD(e) {
24030
+ return e.pick.deviceId > 0 && e.capName !== "" && e.valuePath !== "" && e.alias !== "";
24031
+ }
24032
+ function nD() {
24015
24033
  let e = Ei({}), t = pi({ projection: "slim" }), n = Di(), r = Oi(), [i, o] = a(null), s = l(() => _E(t.data ?? []), [t.data]), c = t.isError ? "failed" : t.isSuccess ? "answered" : "pending", u = e.error ?? n.error ?? r.error;
24016
24034
  return /* @__PURE__ */ j("div", {
24017
24035
  className: "space-y-4",
@@ -24024,13 +24042,13 @@ function eD() {
24024
24042
  children: "Named templates"
24025
24043
  }), /* @__PURE__ */ A("p", {
24026
24044
  className: "text-xs text-foreground-muted mt-0.5",
24027
- children: "Combine sensors into one overlay string via alias bindings. Slot kind Template picks one of these by id."
24045
+ children: "Combine sensors into one overlay string via alias bindings. Each binding picks its own device (a container may contribute more than one child). Slot kind Template picks one of these by id."
24028
24046
  })] }), /* @__PURE__ */ A(G, {
24029
24047
  type: "button",
24030
24048
  size: "sm",
24031
24049
  "data-testid": "osd-template-new",
24032
24050
  onClick: () => o({
24033
- id: YE(),
24051
+ id: ZE(),
24034
24052
  name: "New template",
24035
24053
  bindings: [],
24036
24054
  parser: ""
@@ -24087,7 +24105,7 @@ function eD() {
24087
24105
  })]
24088
24106
  }, t.id))
24089
24107
  }),
24090
- i !== null && /* @__PURE__ */ A(tD, {
24108
+ i !== null && /* @__PURE__ */ A(rD, {
24091
24109
  draft: i,
24092
24110
  pickerDevices: s,
24093
24111
  listState: c,
@@ -24101,15 +24119,11 @@ function eD() {
24101
24119
  ]
24102
24120
  });
24103
24121
  }
24104
- function tD({ draft: e, pickerDevices: t, listState: n, busy: r, onChange: i, onCancel: o, onSave: s }) {
24105
- let c = t.find((e) => !gE(e.type))?.id ?? 0, u = yi({ deviceId: c }, { enabled: c > 0 }).data?.sources ?? [], d = l(() => new Set(u.map((e) => e.deviceId)), [u]), [f, p] = a([]), m = l(() => {
24106
- let t = e.bindings.map(QE);
24107
- return [...new Set([...t, ...f])];
24108
- }, [e.bindings, f]), h = l(() => e.bindings.map((e) => ({
24109
- id: e.alias,
24110
- label: `{${e.alias}}`,
24111
- token: VE(e)
24112
- })), [e.bindings]), g = rD(e.bindings), _ = l(() => JE(e, { stateByDevice: g }), [e, g]), v = e.name.trim().length > 0 && f.length === 0 && e.bindings.every((e) => e.capName !== "" && e.valuePath !== "" && e.alias !== "");
24122
+ function rD({ draft: e, pickerDevices: t, listState: n, busy: r, onChange: i, onCancel: a, onSave: o }) {
24123
+ let s = t.find((e) => !gE(e.type))?.id ?? 0, c = yi({ deviceId: s }, { enabled: s > 0 }).data?.sources ?? [], u = l(() => e.bindings.filter(tD).flatMap((e) => WE(e)), [e.bindings]), d = aD(e.bindings), f = l(() => XE({
24124
+ ...e,
24125
+ bindings: e.bindings.filter(tD)
24126
+ }, { stateByDevice: d }), [e, d]), p = e.name.trim().length > 0 && e.bindings.every(tD);
24113
24127
  return /* @__PURE__ */ j(xo, {
24114
24128
  className: "p-4 space-y-3",
24115
24129
  "data-testid": "osd-template-editor",
@@ -24127,121 +24141,48 @@ function tD({ draft: e, pickerDevices: t, listState: n, busy: r, onChange: i, on
24127
24141
  name: t.target.value
24128
24142
  })
24129
24143
  })] }),
24130
- /* @__PURE__ */ j("div", { children: [
24131
- /* @__PURE__ */ A(K, { children: "Devices" }),
24132
- /* @__PURE__ */ A(vT, {
24133
- devices: t,
24134
- listState: n,
24135
- value: m,
24136
- onChange: (n) => {
24137
- let r = new Set(n), a = e.bindings.filter((e) => r.has(QE(e))), o = new Set(a.map(QE)), s = [], c = [], l = $E(a);
24138
- for (let e of n) {
24139
- if (o.has(e) || f.includes(e)) {
24140
- f.includes(e) && r.has(e) && s.push(e);
24141
- continue;
24142
- }
24143
- let n = yE(t, e);
24144
- if (n === void 0) continue;
24145
- if (gE(n.type)) {
24146
- s.push(e);
24147
- continue;
24148
- }
24149
- if (!d.has(e)) continue;
24150
- let i = dE(u, e), a = i.auto ?? fE(i.fields);
24151
- if (a === void 0) continue;
24152
- let p = UE(n.name || a.valuePath, l);
24153
- l.add(p), c.push({
24154
- alias: p,
24155
- pick: { deviceId: e },
24156
- capName: a.capName,
24157
- valuePath: a.valuePath,
24158
- format: "value+unit",
24159
- maxDecimals: 1
24160
- });
24161
- }
24162
- for (let e of f) r.has(e) && !s.includes(e) && !o.has(e) && s.push(e);
24163
- p(s), i({
24164
- ...e,
24165
- bindings: [...a, ...c]
24166
- });
24167
- },
24168
- noun: "device",
24169
- testId: "osd-tpl-devices"
24170
- }),
24171
- /* @__PURE__ */ A("p", {
24172
- className: "text-[10px] text-foreground-muted mt-1",
24173
- children: "Containers are allowed — pick an OSD-supported child next."
24174
- })
24175
- ] }),
24176
- f.map((n) => {
24177
- let r = yE(t, n), a = vE(n, t, d);
24178
- return /* @__PURE__ */ j("div", {
24179
- className: "rounded border border-border p-2 space-y-2",
24180
- "data-testid": `osd-tpl-pending-container-${n}`,
24181
- children: [
24182
- /* @__PURE__ */ j("p", {
24144
+ /* @__PURE__ */ j("div", {
24145
+ className: "space-y-2",
24146
+ children: [
24147
+ /* @__PURE__ */ j("div", {
24148
+ className: "flex items-center justify-between gap-2",
24149
+ children: [/* @__PURE__ */ A("p", {
24183
24150
  className: "text-xs font-medium text-foreground",
24184
- children: [r?.name ?? `#${n}`, " — pick a child"]
24185
- }),
24186
- a.length === 0 ? /* @__PURE__ */ A("p", {
24187
- className: "text-xs text-foreground-muted",
24188
- children: "No OSD-supported children on this container."
24189
- }) : /* @__PURE__ */ A(po, {
24190
- "data-testid": `osd-tpl-child-${n}`,
24191
- value: "",
24192
- options: [{
24193
- value: "",
24194
- label: "Select child…"
24195
- }, ...a.map((e) => ({
24196
- value: String(e.id),
24197
- label: e.name
24198
- }))],
24199
- onChange: (r) => {
24200
- let a = Number(r.target.value);
24201
- if (!Number.isFinite(a) || a <= 0) return;
24202
- let o = yE(t, a), s = dE(u, a), c = s.auto ?? fE(s.fields);
24203
- if (c === void 0) return;
24204
- let l = $E(e.bindings), d = UE(o?.name ?? c.valuePath, l);
24205
- p(f.filter((e) => e !== n)), i({
24206
- ...e,
24207
- bindings: [...e.bindings, {
24208
- alias: d,
24209
- pick: {
24210
- containerId: n,
24211
- deviceId: a
24212
- },
24213
- capName: c.capName,
24214
- valuePath: c.valuePath,
24215
- format: "value+unit",
24216
- maxDecimals: 1
24217
- }]
24218
- });
24219
- }
24220
- }),
24221
- /* @__PURE__ */ A(G, {
24151
+ children: "Bindings"
24152
+ }), /* @__PURE__ */ A(G, {
24222
24153
  type: "button",
24223
24154
  size: "sm",
24224
- variant: "ghost",
24225
- onClick: () => p(f.filter((e) => e !== n)),
24226
- children: "Cancel"
24227
- })
24228
- ]
24229
- }, `pending-${n}`);
24230
- }),
24231
- e.bindings.length > 0 && /* @__PURE__ */ j("div", {
24232
- className: "space-y-2",
24233
- children: [/* @__PURE__ */ A("p", {
24234
- className: "text-xs font-medium text-foreground",
24235
- children: "Bindings"
24236
- }), e.bindings.map((n, r) => /* @__PURE__ */ A(nD, {
24237
- binding: n,
24238
- index: r,
24239
- draft: e,
24240
- pickerDevices: t,
24241
- sources: u,
24242
- stateByDevice: g,
24243
- onChange: i
24244
- }, `${n.alias}-${r}`))]
24155
+ variant: "secondary",
24156
+ "data-testid": "osd-tpl-add-binding",
24157
+ onClick: () => {
24158
+ let t = $E(e.bindings);
24159
+ i({
24160
+ ...e,
24161
+ bindings: [...e.bindings, eD(t)]
24162
+ });
24163
+ },
24164
+ children: "Add binding"
24165
+ })]
24166
+ }),
24167
+ /* @__PURE__ */ A("p", {
24168
+ className: "text-[10px] text-foreground-muted",
24169
+ children: "Each binding picks device → child (if a container) → field. The same container can appear on more than one binding."
24170
+ }),
24171
+ e.bindings.length === 0 && /* @__PURE__ */ A("p", {
24172
+ className: "text-xs text-foreground-muted",
24173
+ children: "No bindings yet — add one to start."
24174
+ }),
24175
+ e.bindings.map((r, a) => /* @__PURE__ */ A(iD, {
24176
+ binding: r,
24177
+ index: a,
24178
+ draft: e,
24179
+ pickerDevices: t,
24180
+ listState: n,
24181
+ sources: c,
24182
+ stateByDevice: d,
24183
+ onChange: i
24184
+ }, `binding-${a}`))
24185
+ ]
24245
24186
  }),
24246
24187
  /* @__PURE__ */ A(AT, {
24247
24188
  label: "Parser",
@@ -24250,9 +24191,9 @@ function tD({ draft: e, pickerDevices: t, listState: n, busy: r, onChange: i, on
24250
24191
  ...e,
24251
24192
  parser: t
24252
24193
  }),
24253
- chips: h,
24194
+ chips: u,
24254
24195
  multiline: !0,
24255
- placeholder: "e.g. {t} / {h}",
24196
+ placeholder: "e.g. {t.value} {t.unit} / {h.full}",
24256
24197
  testId: "osd-tpl-parser",
24257
24198
  maxLength: 256
24258
24199
  }),
@@ -24262,12 +24203,12 @@ function tD({ draft: e, pickerDevices: t, listState: n, busy: r, onChange: i, on
24262
24203
  children: [/* @__PURE__ */ A("p", {
24263
24204
  className: "text-[10px] uppercase tracking-wide text-foreground-muted",
24264
24205
  children: "Live preview"
24265
- }), "text" in _ ? /* @__PURE__ */ A("p", {
24206
+ }), "text" in f ? /* @__PURE__ */ A("p", {
24266
24207
  className: "text-sm font-mono text-foreground mt-0.5",
24267
- children: _.text === "" ? "(empty)" : _.text
24208
+ children: f.text === "" ? "(empty)" : f.text
24268
24209
  }) : /* @__PURE__ */ A("p", {
24269
24210
  className: "text-xs text-foreground-muted mt-0.5",
24270
- children: _.reason
24211
+ children: f.reason
24271
24212
  })]
24272
24213
  }),
24273
24214
  /* @__PURE__ */ j("div", {
@@ -24275,39 +24216,128 @@ function tD({ draft: e, pickerDevices: t, listState: n, busy: r, onChange: i, on
24275
24216
  children: [/* @__PURE__ */ A(G, {
24276
24217
  type: "button",
24277
24218
  size: "sm",
24278
- disabled: r || !v,
24279
- onClick: () => void s(),
24219
+ disabled: r || !p,
24220
+ onClick: () => void o(),
24280
24221
  children: "Save template"
24281
24222
  }), /* @__PURE__ */ A(G, {
24282
24223
  type: "button",
24283
24224
  size: "sm",
24284
24225
  variant: "ghost",
24285
- onClick: o,
24226
+ onClick: a,
24286
24227
  children: "Cancel"
24287
24228
  })]
24288
24229
  })
24289
24230
  ]
24290
24231
  });
24291
24232
  }
24292
- function nD({ binding: e, index: t, draft: n, pickerDevices: r, sources: i, stateByDevice: a, onChange: o }) {
24293
- let s = dE(i, e.pick.deviceId), c = yE(r, e.pick.deviceId), l = e.pick.containerId === void 0 ? void 0 : yE(r, e.pick.containerId), u = l === void 0 ? c?.name ?? `#${e.pick.deviceId}` : `${l.name} › ${c?.name ?? `#${e.pick.deviceId}`}`, d = qE(e, { stateByDevice: a }), f = (e) => {
24294
- o({
24233
+ function iD({ binding: e, index: t, draft: n, pickerDevices: r, listState: i, sources: o, stateByDevice: s, onChange: c }) {
24234
+ let u = l(() => new Set(o.map((e) => e.deviceId)), [o]), [d, f] = a(e.pick.containerId);
24235
+ m(() => {
24236
+ f(e.pick.containerId);
24237
+ }, [e.pick.containerId, e.pick.deviceId]);
24238
+ let p = e.pick.deviceId > 0 ? e.pick.deviceId : void 0, h = d ?? p, g = d !== void 0 && gE(yE(r, d)?.type) ? d : void 0, _ = g === void 0 ? [] : vE(g, r, u), v = p === void 0 ? void 0 : dE(o, p), y = p === void 0 ? void 0 : yE(r, p), b = e.pick.containerId === void 0 ? void 0 : yE(r, e.pick.containerId), x = g !== void 0 && p === void 0 ? `${yE(r, g)?.name ?? `#${g}`} › …` : b === void 0 ? y?.name ?? (p === void 0 ? "No device" : `#${e.pick.deviceId}`) : `${b.name} › ${y?.name ?? `#${e.pick.deviceId}`}`, S = tD(e) ? JE(e, { stateByDevice: s }) : { reason: "Pick a device and field" }, C = SE(p === void 0 ? void 0 : s.get(p)?.[e.capName], e.valuePath), w = bE(C), T = (e) => {
24239
+ c({
24295
24240
  ...n,
24296
24241
  bindings: n.bindings.map((n, r) => r === t ? e : n)
24297
24242
  });
24243
+ }, E = (i, a) => {
24244
+ let s = dE(o, i), c = s.auto ?? fE(s.fields), l = yE(r, i), u = $E(n.bindings, t), d = e.alias !== "" && !u.has(e.alias) ? e.alias : KE(l?.name ?? c?.valuePath ?? "sensor", u);
24245
+ T({
24246
+ ...e,
24247
+ alias: d,
24248
+ pick: a === void 0 ? { deviceId: i } : {
24249
+ containerId: a,
24250
+ deviceId: i
24251
+ },
24252
+ capName: c?.capName ?? "",
24253
+ valuePath: c?.valuePath ?? ""
24254
+ });
24298
24255
  };
24299
24256
  return /* @__PURE__ */ j("div", {
24300
24257
  className: "rounded border border-border p-2 grid grid-cols-3 gap-2",
24301
- "data-testid": `osd-tpl-binding-${e.alias}`,
24258
+ "data-testid": `osd-tpl-binding-${t}`,
24302
24259
  children: [
24303
24260
  /* @__PURE__ */ j("div", {
24304
24261
  className: "col-span-3 flex items-center justify-between gap-2",
24305
24262
  children: [/* @__PURE__ */ A("p", {
24306
24263
  className: "text-[11px] text-foreground-muted truncate",
24307
- children: u
24308
- }), /* @__PURE__ */ A("p", {
24264
+ children: x
24265
+ }), e.alias !== "" && /* @__PURE__ */ j("p", {
24309
24266
  className: "text-[10px] font-mono text-foreground-muted shrink-0",
24310
- children: BE(e.alias)
24267
+ children: [
24268
+ HE(e.alias),
24269
+ " · ",
24270
+ HE(e.alias, "value"),
24271
+ " ·",
24272
+ " ",
24273
+ HE(e.alias, "unit")
24274
+ ]
24275
+ })]
24276
+ }),
24277
+ /* @__PURE__ */ j("div", {
24278
+ className: "col-span-3 space-y-2",
24279
+ children: [
24280
+ /* @__PURE__ */ A(K, { children: "Device" }),
24281
+ /* @__PURE__ */ A(vT, {
24282
+ devices: r,
24283
+ listState: i,
24284
+ value: h === void 0 ? [] : [h],
24285
+ onChange: (t) => {
24286
+ let n = t.length === 0 ? void 0 : t.length === 1 ? t[0] : t.find((e) => e !== h) ?? t[t.length - 1];
24287
+ if (n === void 0) {
24288
+ f(void 0), T({
24289
+ ...e,
24290
+ pick: { deviceId: QE },
24291
+ capName: "",
24292
+ valuePath: ""
24293
+ });
24294
+ return;
24295
+ }
24296
+ let i = yE(r, n);
24297
+ if (i !== void 0 && gE(i.type)) {
24298
+ f(n), T({
24299
+ ...e,
24300
+ pick: {
24301
+ containerId: n,
24302
+ deviceId: QE
24303
+ },
24304
+ capName: "",
24305
+ valuePath: ""
24306
+ });
24307
+ return;
24308
+ }
24309
+ f(void 0), E(n, void 0);
24310
+ },
24311
+ noun: "device",
24312
+ emptyLabel: "Pick a device",
24313
+ testId: `osd-tpl-device-${t}`
24314
+ }),
24315
+ /* @__PURE__ */ A("p", {
24316
+ className: "text-[10px] text-foreground-muted",
24317
+ children: "Single selection for this binding. Containers are allowed — then pick a child."
24318
+ })
24319
+ ]
24320
+ }),
24321
+ g !== void 0 && /* @__PURE__ */ j("div", {
24322
+ className: "col-span-3",
24323
+ "data-testid": `osd-tpl-child-pick-${t}`,
24324
+ children: [/* @__PURE__ */ A(K, { children: "Child" }), _.length === 0 ? /* @__PURE__ */ A("p", {
24325
+ className: "text-xs text-foreground-muted",
24326
+ children: "No OSD-supported children on this container."
24327
+ }) : /* @__PURE__ */ A(po, {
24328
+ "data-testid": `osd-tpl-child-${t}`,
24329
+ value: p === void 0 ? "" : String(p),
24330
+ options: [{
24331
+ value: "",
24332
+ label: "Select child…"
24333
+ }, ..._.map((e) => ({
24334
+ value: String(e.id),
24335
+ label: e.name
24336
+ }))],
24337
+ onChange: (e) => {
24338
+ let t = Number(e.target.value);
24339
+ !Number.isFinite(t) || t <= 0 || E(t, g);
24340
+ }
24311
24341
  })]
24312
24342
  }),
24313
24343
  /* @__PURE__ */ j("div", { children: [/* @__PURE__ */ A(K, { children: "Alias" }), /* @__PURE__ */ A(os, {
@@ -24316,23 +24346,28 @@ function nD({ binding: e, index: t, draft: n, pickerDevices: r, sources: i, stat
24316
24346
  maxLength: 32,
24317
24347
  onChange: (r) => {
24318
24348
  let i = r.target.value, a = $E(n.bindings, t);
24319
- i !== "" && a.has(i) || f({
24349
+ i !== "" && a.has(i) || T({
24320
24350
  ...e,
24321
24351
  alias: i
24322
24352
  });
24323
24353
  }
24324
24354
  })] }),
24325
- (s.mode === "pick" || s.mode === "auto") && /* @__PURE__ */ j("div", {
24355
+ v !== void 0 && (v.mode === "pick" || v.mode === "auto") && /* @__PURE__ */ j("div", {
24326
24356
  className: "col-span-2",
24327
- children: [/* @__PURE__ */ A(K, { children: "Field" }), /* @__PURE__ */ A(po, {
24357
+ children: [/* @__PURE__ */ A(K, { children: "Field" }), v.mode === "auto" && v.auto !== void 0 ? /* @__PURE__ */ A("p", {
24358
+ className: "text-xs text-foreground-muted mt-1.5",
24359
+ "data-testid": `osd-tpl-field-auto-${t}`,
24360
+ children: v.auto.label
24361
+ }) : /* @__PURE__ */ A(po, {
24362
+ "data-testid": `osd-tpl-field-${t}`,
24328
24363
  value: `${e.capName}:${e.valuePath}`,
24329
- options: s.fields.map((e) => ({
24364
+ options: v.fields.map((e) => ({
24330
24365
  value: `${e.capName}:${e.valuePath}`,
24331
24366
  label: e.label
24332
24367
  })),
24333
24368
  onChange: (t) => {
24334
- let n = s.fields.find((e) => `${e.capName}:${e.valuePath}` === t.target.value);
24335
- n && f({
24369
+ let n = v.fields.find((e) => `${e.capName}:${e.valuePath}` === t.target.value);
24370
+ n && T({
24336
24371
  ...e,
24337
24372
  capName: n.capName,
24338
24373
  valuePath: n.valuePath
@@ -24340,44 +24375,23 @@ function nD({ binding: e, index: t, draft: n, pickerDevices: r, sources: i, stat
24340
24375
  }
24341
24376
  })]
24342
24377
  }),
24343
- /* @__PURE__ */ j("div", {
24344
- className: "col-span-3",
24345
- children: [/* @__PURE__ */ A(K, { children: "Format" }), /* @__PURE__ */ A("div", {
24346
- className: "flex gap-1 mt-1",
24347
- role: "radiogroup",
24348
- "aria-label": `Format for ${e.alias}`,
24349
- "data-testid": `osd-tpl-format-${t}`,
24350
- children: XE.map((t) => /* @__PURE__ */ A(G, {
24351
- type: "button",
24352
- size: "sm",
24353
- variant: e.format === t.value ? "primary" : "outline",
24354
- "aria-checked": e.format === t.value,
24355
- role: "radio",
24356
- onClick: () => f({
24357
- ...e,
24358
- format: t.value
24359
- }),
24360
- children: t.label
24361
- }, t.value))
24362
- })]
24363
- }),
24364
24378
  /* @__PURE__ */ j("div", { children: [/* @__PURE__ */ A(K, { children: "Unit" }), /* @__PURE__ */ A(ET, {
24365
- dimension: ZE(e.displayUnit),
24379
+ dimension: w,
24366
24380
  value: e.displayUnit ?? "",
24367
- onChange: (t) => f({
24381
+ onChange: (t) => T({
24368
24382
  ...e,
24369
24383
  displayUnit: t === "" ? void 0 : t
24370
24384
  }),
24371
24385
  inheritLabel: "Source",
24372
- emptyReason: "Pick a unit family via a known unit first",
24373
- "aria-label": `Unit for ${e.alias}`
24386
+ emptyReason: C === void 0 ? "Source unit unknown (waiting for sensor state)" : "Source unit has no same-dimension conversions",
24387
+ "aria-label": `Unit for ${e.alias || `binding ${t + 1}`}`
24374
24388
  })] }),
24375
24389
  /* @__PURE__ */ j("div", { children: [/* @__PURE__ */ A(K, { children: "Decimals" }), /* @__PURE__ */ A(os, {
24376
24390
  type: "number",
24377
24391
  min: 0,
24378
24392
  max: 4,
24379
24393
  value: e.maxDecimals,
24380
- onChange: (t) => f({
24394
+ onChange: (t) => T({
24381
24395
  ...e,
24382
24396
  maxDecimals: Number(t.target.value)
24383
24397
  })
@@ -24388,7 +24402,8 @@ function nD({ binding: e, index: t, draft: n, pickerDevices: r, sources: i, stat
24388
24402
  type: "button",
24389
24403
  size: "sm",
24390
24404
  variant: "ghost",
24391
- onClick: () => o({
24405
+ "data-testid": `osd-tpl-remove-${t}`,
24406
+ onClick: () => c({
24392
24407
  ...n,
24393
24408
  bindings: n.bindings.filter((e, n) => n !== t)
24394
24409
  }),
@@ -24398,16 +24413,16 @@ function nD({ binding: e, index: t, draft: n, pickerDevices: r, sources: i, stat
24398
24413
  /* @__PURE__ */ A("p", {
24399
24414
  className: "col-span-3 text-xs font-mono text-foreground",
24400
24415
  "data-testid": `osd-tpl-live-${t}`,
24401
- children: "formatted" in d ? /* @__PURE__ */ j(M, { children: ["Live: ", d.formatted === "" ? "(empty)" : d.formatted] }) : /* @__PURE__ */ A("span", {
24416
+ children: "formatted" in S ? /* @__PURE__ */ j(M, { children: ["Live: ", S.formatted === "" ? "(empty)" : S.formatted] }) : /* @__PURE__ */ A("span", {
24402
24417
  className: "text-foreground-muted",
24403
- children: d.reason
24418
+ children: S.reason
24404
24419
  })
24405
24420
  })
24406
24421
  ]
24407
24422
  });
24408
24423
  }
24409
- function rD(e) {
24410
- let t = l(() => new Set(e.map((e) => e.pick.deviceId)), [e]), n = _i({}, {
24424
+ function aD(e) {
24425
+ let t = l(() => new Set(e.map((e) => e.pick.deviceId).filter((e) => e > 0)), [e]), n = _i({}, {
24411
24426
  enabled: t.size > 0,
24412
24427
  refetchInterval: 5e3
24413
24428
  });
@@ -24424,7 +24439,7 @@ function rD(e) {
24424
24439
  //#endregion
24425
24440
  //#region src/page.tsx
24426
24441
  t();
24427
- function iD(e) {
24442
+ function oD(e) {
24428
24443
  let [t, n] = a("cameras"), r = pi({ projection: "slim" }), i = hi({}), o = Ei({}), s = l(() => (r.data ?? []).filter((e) => e.isCamera).map((e) => ({
24429
24444
  id: e.id,
24430
24445
  name: e.name
@@ -24471,7 +24486,7 @@ function iD(e) {
24471
24486
  }) : null,
24472
24487
  !h && t === "templates" ? /* @__PURE__ */ A(xo, {
24473
24488
  className: "p-4",
24474
- children: /* @__PURE__ */ A(eD, {})
24489
+ children: /* @__PURE__ */ A(nD, {})
24475
24490
  }) : null,
24476
24491
  !h && t === "cameras" && s.length === 0 ? /* @__PURE__ */ A("div", {
24477
24492
  className: "text-xs text-foreground-subtle text-center py-16",
@@ -24480,7 +24495,7 @@ function iD(e) {
24480
24495
  !h && t === "cameras" && s.length > 0 ? /* @__PURE__ */ A(xo, {
24481
24496
  className: "p-4",
24482
24497
  "data-testid": "osd-cameras",
24483
- children: /* @__PURE__ */ A(RE, {
24498
+ children: /* @__PURE__ */ A(BE, {
24484
24499
  cameras: s,
24485
24500
  osdCapableIds: f,
24486
24501
  allDevices: c,
@@ -24494,4 +24509,4 @@ function iD(e) {
24494
24509
  });
24495
24510
  }
24496
24511
  //#endregion
24497
- export { iD as default };
24512
+ export { oD as default };