@camstack/addon-osd-manager 0.1.157 → 0.1.161
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{MotionZonesSettings-vYt4dibj.mjs → MotionZonesSettings-CSheC3_V.mjs} +2 -2
- package/dist/{PrivacyMaskSettings-BiQ78hst.mjs → PrivacyMaskSettings-I6eE4GFM.mjs} +4 -4
- package/dist/{SceneMonitorEditor-CJtJIyMf.mjs → SceneMonitorEditor-mNJ89n0T.mjs} +3 -3
- package/dist/_stub.js +3059 -2713
- package/dist/{_virtual_mf-localSharedImportMap___mfe_internal__addon_osd_manager_page-DdAtpC7z.mjs → _virtual_mf-localSharedImportMap___mfe_internal__addon_osd_manager_page-BYQUZdGL.mjs} +2 -2
- package/dist/{_virtual_mf___mfe_internal__addon_osd_manager_page__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-BtgV-Ym5.mjs → _virtual_mf___mfe_internal__addon_osd_manager_page__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-B2mEdhqd.mjs} +1 -1
- package/dist/{hostInit-0Mc7Fm1R.mjs → hostInit-DFyjx8Xk.mjs} +1 -1
- package/dist/index.js +350 -57
- package/dist/index.mjs +322 -58
- package/dist/{player-overlays-BPyna-eI.mjs → player-overlays-DFXmMB9Y.mjs} +1 -1
- package/dist/remoteEntry.js +1 -1
- package/dist/{responsive-B0yDP9vf.mjs → responsive-DLFs-5i_.mjs} +1 -1
- package/dist/{scene-monitor-copy-BzX20O6q.mjs → scene-monitor-copy-DVNcikwa.mjs} +1 -1
- package/dist/{square-BOMOn_6j.mjs → square-Co3Eglp3.mjs} +1 -1
- package/dist/{trash-2-BolGRl2P.mjs → trash-2-DnKldIWK.mjs} +1 -1
- package/dist/{virtual_mf-REMOTE_ENTRY_ID___mfe_internal__addon_osd_manager_page__remoteEntry_js-UY9P_4V2.mjs → virtual_mf-REMOTE_ENTRY_ID___mfe_internal__addon_osd_manager_page__remoteEntry_js-C3yC0JaQ.mjs} +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -39327,22 +39327,35 @@ setOverlay: method(object({
|
|
|
39327
39327
|
}
|
|
39328
39328
|
}] }
|
|
39329
39329
|
};
|
|
39330
|
+
_enum([
|
|
39331
|
+
"value",
|
|
39332
|
+
"unit",
|
|
39333
|
+
"full"
|
|
39334
|
+
]);
|
|
39335
|
+
_enum([
|
|
39336
|
+
"value+unit",
|
|
39337
|
+
"value",
|
|
39338
|
+
"unit"
|
|
39339
|
+
]);
|
|
39330
39340
|
/**
|
|
39331
|
-
*
|
|
39332
|
-
*
|
|
39333
|
-
*
|
|
39334
|
-
* SLOTS and writes literal text into one. It has no idea WHERE that text
|
|
39335
|
-
* comes from, and it must not — a driver that grew a "show the temperature
|
|
39336
|
-
* here" feature would grow it once per vendor.
|
|
39337
|
-
*
|
|
39338
|
-
* This cap owns the other half: a per-(camera, slot) BINDING that says
|
|
39339
|
-
* which value feeds the slot, how it is formatted, and under which
|
|
39340
|
-
* conditions it is shown at all. Named TEMPLATES combine many device
|
|
39341
|
-
* fields into one overlay string (Scrypted OSD Manager parity).
|
|
39341
|
+
* How the operator reached the leaf device. `deviceId` is ALWAYS the
|
|
39342
|
+
* OSD-supported leaf that is read; `containerId` is set when the pick
|
|
39343
|
+
* went through a container (gateway) first.
|
|
39342
39344
|
*/
|
|
39343
|
-
|
|
39344
|
-
|
|
39345
|
-
deviceId: number().int()
|
|
39345
|
+
var OsdTemplatePickSchema = object({
|
|
39346
|
+
containerId: number().int().optional(),
|
|
39347
|
+
deviceId: number().int()
|
|
39348
|
+
});
|
|
39349
|
+
/**
|
|
39350
|
+
* One named binding inside a multi-device template: device path + unit
|
|
39351
|
+
* selection + precision. The parser expands `{alias}`, `{alias.value}`,
|
|
39352
|
+
* `{alias.unit}`, or `{alias.full}` from the same binding — there is no
|
|
39353
|
+
* per-binding format lock.
|
|
39354
|
+
*/
|
|
39355
|
+
var OsdTemplateBindingSchema = object({
|
|
39356
|
+
/** Token stem in the parser, e.g. `t` → `{t}` / `{t.value}`. Unique within the template. */
|
|
39357
|
+
alias: string().min(1).max(32).regex(/^[A-Za-z][A-Za-z0-9_-]*$/, "alias must start with a letter"),
|
|
39358
|
+
pick: OsdTemplatePickSchema,
|
|
39346
39359
|
capName: string().min(1).max(64),
|
|
39347
39360
|
valuePath: string().min(1).max(64),
|
|
39348
39361
|
/** Convert TO this unit at render (`tryConvertUnit`). Absent = source unit. */
|
|
@@ -39350,14 +39363,14 @@ var OsdTemplateFieldSchema = object({
|
|
|
39350
39363
|
maxDecimals: number().int().min(0).max(4).default(1)
|
|
39351
39364
|
});
|
|
39352
39365
|
/**
|
|
39353
|
-
* A named template:
|
|
39354
|
-
* `{
|
|
39366
|
+
* A named template: bindings (alias → leaf field) + a parser that
|
|
39367
|
+
* references `{alias}` / `{alias.value}` / `{alias.unit}` / `{alias.full}`.
|
|
39355
39368
|
*/
|
|
39356
39369
|
var OsdNamedTemplateSchema = object({
|
|
39357
39370
|
id: string().min(1).max(64),
|
|
39358
39371
|
name: string().min(1).max(64),
|
|
39359
|
-
|
|
39360
|
-
/** Parser with
|
|
39372
|
+
bindings: array(OsdTemplateBindingSchema).max(32).default([]),
|
|
39373
|
+
/** Parser with alias placeholders, e.g. `{t.value} {t.unit} / {h}`. */
|
|
39361
39374
|
parser: string().max(256).default("")
|
|
39362
39375
|
});
|
|
39363
39376
|
/** Where a slot's value comes from. */
|
|
@@ -45563,6 +45576,10 @@ var UNIT_TABLE = {
|
|
|
45563
45576
|
function specFor(unit) {
|
|
45564
45577
|
return Object.hasOwn(UNIT_TABLE, unit) ? UNIT_TABLE[unit] : void 0;
|
|
45565
45578
|
}
|
|
45579
|
+
/** The dimension a unit belongs to, or `undefined` for an unknown unit. */
|
|
45580
|
+
function unitDimension(unit) {
|
|
45581
|
+
return specFor(unit)?.dimension;
|
|
45582
|
+
}
|
|
45566
45583
|
/** Value in `spec`'s unit → its dimension's canonical unit. */
|
|
45567
45584
|
function toCanonical(value, spec) {
|
|
45568
45585
|
return value * spec.factor + spec.offset;
|
|
@@ -58364,14 +58381,91 @@ function readStatePath(slice, path) {
|
|
|
58364
58381
|
}
|
|
58365
58382
|
//#endregion
|
|
58366
58383
|
//#region src/template-tokens.ts
|
|
58367
|
-
/** Build
|
|
58368
|
-
function
|
|
58369
|
-
return `{${
|
|
58384
|
+
/** Build a placeholder token for one binding alias + expand kind. */
|
|
58385
|
+
function aliasToken(alias, kind = "full") {
|
|
58386
|
+
if (kind === "full") return `{${alias}}`;
|
|
58387
|
+
return `{${alias}.${kind}}`;
|
|
58388
|
+
}
|
|
58389
|
+
/** Explicit `{alias.full}` form (chips prefer this over bare `{alias}`). */
|
|
58390
|
+
function aliasFullToken(alias) {
|
|
58391
|
+
return `{${alias}.full}`;
|
|
58392
|
+
}
|
|
58393
|
+
/** Chip / parser insert options for one binding (value, unit, value+unit). */
|
|
58394
|
+
function bindingInsertChips(binding) {
|
|
58395
|
+
const alias = binding.alias;
|
|
58396
|
+
return [
|
|
58397
|
+
{
|
|
58398
|
+
id: `${alias}.value`,
|
|
58399
|
+
label: `${alias} · value`,
|
|
58400
|
+
token: aliasToken(alias, "value"),
|
|
58401
|
+
kind: "value"
|
|
58402
|
+
},
|
|
58403
|
+
{
|
|
58404
|
+
id: `${alias}.unit`,
|
|
58405
|
+
label: `${alias} · unit`,
|
|
58406
|
+
token: aliasToken(alias, "unit"),
|
|
58407
|
+
kind: "unit"
|
|
58408
|
+
},
|
|
58409
|
+
{
|
|
58410
|
+
id: `${alias}.full`,
|
|
58411
|
+
label: `${alias} · value+unit`,
|
|
58412
|
+
token: aliasFullToken(alias),
|
|
58413
|
+
kind: "full"
|
|
58414
|
+
}
|
|
58415
|
+
];
|
|
58416
|
+
}
|
|
58417
|
+
/** @deprecated Prefer `bindingInsertChips` — bare `{alias}` only. */
|
|
58418
|
+
function bindingToken(binding) {
|
|
58419
|
+
return aliasToken(binding.alias, "full");
|
|
58420
|
+
}
|
|
58421
|
+
/**
|
|
58422
|
+
* Parse `{alias}`, `{alias.value}`, `{alias.unit}`, `{alias.full}` from a
|
|
58423
|
+
* parser string. Bare `{alias}` and `{alias.full}` both mean `full`.
|
|
58424
|
+
*/
|
|
58425
|
+
function parseAliasTokens(parser) {
|
|
58426
|
+
const out = [];
|
|
58427
|
+
const seen = /* @__PURE__ */ new Set();
|
|
58428
|
+
for (const match of parser.matchAll(/\{([A-Za-z][A-Za-z0-9_-]*)(?:\.(value|unit|full))?\}/g)) {
|
|
58429
|
+
const alias = match[1];
|
|
58430
|
+
if (alias === void 0 || alias === "") continue;
|
|
58431
|
+
const suffix = match[2];
|
|
58432
|
+
const kind = suffix === "value" || suffix === "unit" ? suffix : "full";
|
|
58433
|
+
const token = match[0] ?? "";
|
|
58434
|
+
const key = `${alias}:${kind}:${token}`;
|
|
58435
|
+
if (seen.has(key)) continue;
|
|
58436
|
+
seen.add(key);
|
|
58437
|
+
out.push({
|
|
58438
|
+
alias,
|
|
58439
|
+
kind,
|
|
58440
|
+
token
|
|
58441
|
+
});
|
|
58442
|
+
}
|
|
58443
|
+
return out;
|
|
58444
|
+
}
|
|
58445
|
+
/** Unique alias stems referenced by a parser (any token kind). */
|
|
58446
|
+
function parseAliasStems(parser) {
|
|
58447
|
+
const stems = [];
|
|
58448
|
+
for (const entry of parseAliasTokens(parser)) if (!stems.includes(entry.alias)) stems.push(entry.alias);
|
|
58449
|
+
return stems;
|
|
58370
58450
|
}
|
|
58371
58451
|
/** Replace every occurrence of `token` in `parser` with `value`. */
|
|
58372
58452
|
function replaceToken(parser, token, value) {
|
|
58373
58453
|
return parser.replaceAll(token, value);
|
|
58374
58454
|
}
|
|
58455
|
+
/**
|
|
58456
|
+
* Suggest a short unique alias from a device/field name.
|
|
58457
|
+
* Falls back to `b1`, `b2`, … when the slug collides.
|
|
58458
|
+
*/
|
|
58459
|
+
function suggestAlias(seed, taken, fallbackPrefix = "b") {
|
|
58460
|
+
const slug = seed.trim().toLowerCase().replace(/[^a-z0-9]+/g, "_").replace(/^_+|_+$/g, "").replace(/^(\d)/, "a$1").slice(0, 24);
|
|
58461
|
+
const base = slug.length > 0 ? slug : fallbackPrefix;
|
|
58462
|
+
if (!taken.has(base)) return base;
|
|
58463
|
+
for (let i = 2; i < 1e3; i += 1) {
|
|
58464
|
+
const candidate = `${base}${i}`.slice(0, 32);
|
|
58465
|
+
if (!taken.has(candidate)) return candidate;
|
|
58466
|
+
}
|
|
58467
|
+
return `${fallbackPrefix}${Date.now().toString(36)}`;
|
|
58468
|
+
}
|
|
58375
58469
|
//#endregion
|
|
58376
58470
|
//#region src/unit-display.ts
|
|
58377
58471
|
/**
|
|
@@ -58379,6 +58473,16 @@ function replaceToken(parser, token, value) {
|
|
|
58379
58473
|
* UNIT_TABLE / tryConvertUnit (same set as D699).
|
|
58380
58474
|
*/
|
|
58381
58475
|
/**
|
|
58476
|
+
* Dimension for a UnitPicker from a raw source unit (may be bare `C`).
|
|
58477
|
+
* Normalize before `unitDimension` — the table only knows canonical spellings.
|
|
58478
|
+
*/
|
|
58479
|
+
function dimensionFromSourceUnit(sourceUnit) {
|
|
58480
|
+
if (sourceUnit === void 0) return void 0;
|
|
58481
|
+
const normalized = normalizeUnit(sourceUnit);
|
|
58482
|
+
if (normalized === void 0) return void 0;
|
|
58483
|
+
return unitDimension(normalized);
|
|
58484
|
+
}
|
|
58485
|
+
/**
|
|
58382
58486
|
* Convert `raw` from `sourceUnit` to `displayUnit` when both are known and
|
|
58383
58487
|
* same-dimension. On refusal, keep the raw value and the source unit so the
|
|
58384
58488
|
* label never lies about the number.
|
|
@@ -58427,24 +58531,64 @@ function inferSourceUnit(slice, valuePath) {
|
|
|
58427
58531
|
}
|
|
58428
58532
|
//#endregion
|
|
58429
58533
|
//#region src/named-template-render.ts
|
|
58534
|
+
/** Combine value/unit for a token kind. */
|
|
58535
|
+
function applyTemplateTokenKind(value, unit, kind) {
|
|
58536
|
+
if (kind === "value") return value;
|
|
58537
|
+
if (kind === "unit") return unit;
|
|
58538
|
+
const v = value.trim();
|
|
58539
|
+
const u = unit.trim();
|
|
58540
|
+
if (v === "") return u;
|
|
58541
|
+
if (u === "") return v;
|
|
58542
|
+
return `${v} ${u}`;
|
|
58543
|
+
}
|
|
58544
|
+
/**
|
|
58545
|
+
* @deprecated Prefer `applyTemplateTokenKind`. Maps legacy format enum to
|
|
58546
|
+
* the same join rules (`value+unit` → `full`).
|
|
58547
|
+
*/
|
|
58548
|
+
function applyTemplateFormat(value, unit, format) {
|
|
58549
|
+
return applyTemplateTokenKind(value, unit, format === "value" ? "value" : format === "unit" ? "unit" : "full");
|
|
58550
|
+
}
|
|
58551
|
+
/** Resolve one binding to live value/unit/formatted parts (or a reason). */
|
|
58552
|
+
function resolveBindingLive(binding, facts) {
|
|
58553
|
+
const deviceId = binding.pick.deviceId;
|
|
58554
|
+
const deviceState = facts.stateByDevice.get(deviceId);
|
|
58555
|
+
if (deviceState === void 0) return { reason: `no state mirrored for device ${deviceId}` };
|
|
58556
|
+
const slice = deviceState[binding.capName];
|
|
58557
|
+
if (slice === void 0) return { reason: `device ${deviceId} publishes no "${binding.capName}" state` };
|
|
58558
|
+
const raw = readStatePath(slice, binding.valuePath);
|
|
58559
|
+
if (raw === void 0) return { reason: `"${binding.capName}.${binding.valuePath}" is absent on device ${deviceId}` };
|
|
58560
|
+
let value;
|
|
58561
|
+
let unit = "";
|
|
58562
|
+
if (typeof raw === "number") {
|
|
58563
|
+
const converted = convertForDisplay(raw, inferSourceUnit(slice, binding.valuePath), binding.displayUnit);
|
|
58564
|
+
value = truncateDecimals(converted.value, binding.maxDecimals);
|
|
58565
|
+
unit = converted.unit;
|
|
58566
|
+
} else if (typeof raw === "boolean") value = raw ? "ON" : "OFF";
|
|
58567
|
+
else if (raw === null) value = "";
|
|
58568
|
+
else value = String(raw);
|
|
58569
|
+
return {
|
|
58570
|
+
value,
|
|
58571
|
+
unit,
|
|
58572
|
+
formatted: applyTemplateTokenKind(value, unit, "full")
|
|
58573
|
+
};
|
|
58574
|
+
}
|
|
58575
|
+
/** Substitute every token form for one alias from live parts. Longest first. */
|
|
58576
|
+
function expandBindingTokens(parser, alias, live) {
|
|
58577
|
+
let text = parser;
|
|
58578
|
+
text = replaceToken(text, aliasFullToken(alias), live.formatted);
|
|
58579
|
+
text = replaceToken(text, aliasToken(alias, "value"), live.value);
|
|
58580
|
+
text = replaceToken(text, aliasToken(alias, "unit"), live.unit);
|
|
58581
|
+
text = replaceToken(text, aliasToken(alias, "full"), live.formatted);
|
|
58582
|
+
return text;
|
|
58583
|
+
}
|
|
58430
58584
|
/** Render one named template's parser from live states. */
|
|
58431
58585
|
function renderNamedTemplate(template, facts) {
|
|
58432
58586
|
let text = template.parser;
|
|
58433
|
-
if (template.
|
|
58434
|
-
for (const
|
|
58435
|
-
const
|
|
58436
|
-
|
|
58437
|
-
|
|
58438
|
-
const slice = deviceState[field.capName];
|
|
58439
|
-
if (slice === void 0) return { reason: `device ${field.deviceId} publishes no "${field.capName}" state` };
|
|
58440
|
-
const raw = readStatePath(slice, field.valuePath);
|
|
58441
|
-
if (raw === void 0) return { reason: `"${field.capName}.${field.valuePath}" is absent on device ${field.deviceId}` };
|
|
58442
|
-
let rendered;
|
|
58443
|
-
if (typeof raw === "number") rendered = truncateDecimals(convertForDisplay(raw, inferSourceUnit(slice, field.valuePath), field.displayUnit).value, field.maxDecimals);
|
|
58444
|
-
else if (typeof raw === "boolean") rendered = raw ? "ON" : "OFF";
|
|
58445
|
-
else if (raw === null) rendered = "";
|
|
58446
|
-
else rendered = String(raw);
|
|
58447
|
-
text = replaceToken(text, token, rendered);
|
|
58587
|
+
if (template.bindings.length === 0) return text.trim() === "" ? { reason: `template "${template.id}" has no bindings` } : { text };
|
|
58588
|
+
for (const binding of template.bindings) {
|
|
58589
|
+
const live = resolveBindingLive(binding, facts);
|
|
58590
|
+
if ("reason" in live) return live;
|
|
58591
|
+
text = expandBindingTokens(text, binding.alias, live);
|
|
58448
58592
|
}
|
|
58449
58593
|
return { text };
|
|
58450
58594
|
}
|
|
@@ -58546,20 +58690,98 @@ function settle(slotId, text, previousText, outcome, reason) {
|
|
|
58546
58690
|
};
|
|
58547
58691
|
}
|
|
58548
58692
|
//#endregion
|
|
58693
|
+
//#region src/osd-source-fields.ts
|
|
58694
|
+
/** Caps the OSD source picker may bind. */
|
|
58695
|
+
var OSD_SOURCE_CAP_NAMES = new Set([
|
|
58696
|
+
"temperature-sensor",
|
|
58697
|
+
"humidity-sensor",
|
|
58698
|
+
"climate-control",
|
|
58699
|
+
"numeric-sensor",
|
|
58700
|
+
"weather",
|
|
58701
|
+
"air-quality-sensor",
|
|
58702
|
+
"lock-control",
|
|
58703
|
+
"contact",
|
|
58704
|
+
"binary",
|
|
58705
|
+
"battery"
|
|
58706
|
+
]);
|
|
58707
|
+
/**
|
|
58708
|
+
* Per-cap leaf allowlist. Absent entry ⇒ every leaf from `stateLeavesOf`
|
|
58709
|
+
* that survives bookkeeping (single-metric sensors). Present ⇒ only these
|
|
58710
|
+
* paths (climate / weather / battery).
|
|
58711
|
+
*/
|
|
58712
|
+
var OSD_SOURCE_PATHS = new Map([
|
|
58713
|
+
["climate-control", new Set([
|
|
58714
|
+
"currentTemp",
|
|
58715
|
+
"currentHumidity",
|
|
58716
|
+
"target",
|
|
58717
|
+
"targetHumidity",
|
|
58718
|
+
"mode"
|
|
58719
|
+
])],
|
|
58720
|
+
["weather", new Set([
|
|
58721
|
+
"condition",
|
|
58722
|
+
"temperature",
|
|
58723
|
+
"humidity",
|
|
58724
|
+
"pressure",
|
|
58725
|
+
"windSpeed",
|
|
58726
|
+
"windBearing"
|
|
58727
|
+
])],
|
|
58728
|
+
["battery", new Set(["percentage"])],
|
|
58729
|
+
["temperature-sensor", new Set(["celsius"])],
|
|
58730
|
+
["humidity-sensor", new Set(["percent"])],
|
|
58731
|
+
["numeric-sensor", new Set(["value"])],
|
|
58732
|
+
["air-quality-sensor", new Set([
|
|
58733
|
+
"co2Ppm",
|
|
58734
|
+
"vocPpb",
|
|
58735
|
+
"pm25",
|
|
58736
|
+
"pm10",
|
|
58737
|
+
"aqi"
|
|
58738
|
+
])],
|
|
58739
|
+
["binary", new Set(["on"])],
|
|
58740
|
+
["contact", new Set(["entryOpen"])],
|
|
58741
|
+
["lock-control", new Set(["state"])]
|
|
58742
|
+
]);
|
|
58743
|
+
function isOsdSourceCap(capName) {
|
|
58744
|
+
return OSD_SOURCE_CAP_NAMES.has(capName);
|
|
58745
|
+
}
|
|
58746
|
+
/** Bindable OSD leaves for one cap — empty when the cap is not OSD-relevant. */
|
|
58747
|
+
function osdStateLeavesOf(cap) {
|
|
58748
|
+
if (!isOsdSourceCap(cap.name)) return [];
|
|
58749
|
+
const leaves = stateLeavesOf(cap);
|
|
58750
|
+
const allowed = OSD_SOURCE_PATHS.get(cap.name);
|
|
58751
|
+
if (allowed === void 0) return leaves;
|
|
58752
|
+
return leaves.filter((leaf) => allowed.has(leaf.path));
|
|
58753
|
+
}
|
|
58754
|
+
/** Device types that never contribute their OWN catalog leaves. */
|
|
58755
|
+
var OSD_NON_LEAF_TYPES = new Set(["container"]);
|
|
58756
|
+
/** True when this device type may expose OSD leaves (not a container gateway). */
|
|
58757
|
+
function isOsdLeafDeviceType(type) {
|
|
58758
|
+
if (type === null || type === void 0) return true;
|
|
58759
|
+
return !OSD_NON_LEAF_TYPES.has(type);
|
|
58760
|
+
}
|
|
58761
|
+
/** @deprecated Prefer {@link isOsdLeafDeviceType}. */
|
|
58762
|
+
var OSD_PICKER_EXCLUDED_TYPES = OSD_NON_LEAF_TYPES;
|
|
58763
|
+
/** @deprecated Prefer {@link isOsdLeafDeviceType}. */
|
|
58764
|
+
function isOsdPickerDeviceType(type) {
|
|
58765
|
+
return isOsdLeafDeviceType(type);
|
|
58766
|
+
}
|
|
58767
|
+
function isContainerDeviceType(type) {
|
|
58768
|
+
return type === "container";
|
|
58769
|
+
}
|
|
58770
|
+
//#endregion
|
|
58549
58771
|
//#region src/source-catalog.ts
|
|
58550
58772
|
/**
|
|
58551
|
-
* Build the editor's source picker from
|
|
58552
|
-
*
|
|
58553
|
-
*
|
|
58773
|
+
* Build the editor's source picker from OSD-relevant cap definitions.
|
|
58774
|
+
* Gateway / infrastructure caps (broker, mqtt, deviceExport, …) never
|
|
58775
|
+
* appear — see `osd-source-fields.ts`.
|
|
58554
58776
|
*/
|
|
58555
58777
|
/** Turn `air-quality-sensor` + `pm25` into `Air Quality Sensor · pm25`. */
|
|
58556
58778
|
function humanizeCapName(capName) {
|
|
58557
58779
|
return capName.split("-").map((part) => part.length === 0 ? part : part[0].toUpperCase() + part.slice(1)).join(" ");
|
|
58558
58780
|
}
|
|
58559
58781
|
/**
|
|
58560
|
-
* Every bindable value across the cluster, with the camera's own
|
|
58561
|
-
* first — that is what an operator reaches for, and a picker that
|
|
58562
|
-
* it under 200 other devices is a picker nobody uses.
|
|
58782
|
+
* Every OSD-bindable value across the cluster, with the camera's own
|
|
58783
|
+
* state first — that is what an operator reaches for, and a picker that
|
|
58784
|
+
* buries it under 200 other devices is a picker nobody uses.
|
|
58563
58785
|
*/
|
|
58564
58786
|
function sourceOptionsFor(cameraDeviceId, devices, capsByDevice) {
|
|
58565
58787
|
const capsByName = new Map(ALL_CAPABILITY_DEFINITIONS.map((cap) => [cap.name, cap]));
|
|
@@ -58569,18 +58791,22 @@ function sourceOptionsFor(cameraDeviceId, devices, capsByDevice) {
|
|
|
58569
58791
|
return a.id - b.id;
|
|
58570
58792
|
});
|
|
58571
58793
|
const options = [];
|
|
58572
|
-
for (const device of ordered)
|
|
58573
|
-
|
|
58574
|
-
|
|
58575
|
-
|
|
58576
|
-
|
|
58577
|
-
|
|
58578
|
-
|
|
58579
|
-
|
|
58580
|
-
|
|
58581
|
-
|
|
58582
|
-
|
|
58583
|
-
|
|
58794
|
+
for (const device of ordered) {
|
|
58795
|
+
if (!isOsdLeafDeviceType(device.type ?? null)) continue;
|
|
58796
|
+
for (const capName of capsByDevice.get(device.id) ?? []) {
|
|
58797
|
+
if (!isOsdSourceCap(capName)) continue;
|
|
58798
|
+
const cap = capsByName.get(capName);
|
|
58799
|
+
if (cap === void 0) continue;
|
|
58800
|
+
for (const leaf of osdStateLeavesOf(cap)) options.push({
|
|
58801
|
+
deviceId: device.id,
|
|
58802
|
+
deviceName: device.name,
|
|
58803
|
+
capName,
|
|
58804
|
+
valuePath: leaf.path,
|
|
58805
|
+
label: `${humanizeCapName(capName)} · ${leaf.path}`,
|
|
58806
|
+
valueType: leaf.valueType,
|
|
58807
|
+
...leaf.enumValues !== void 0 ? { enumValues: leaf.enumValues } : {}
|
|
58808
|
+
});
|
|
58809
|
+
}
|
|
58584
58810
|
}
|
|
58585
58811
|
return options;
|
|
58586
58812
|
}
|
|
@@ -58976,7 +59202,7 @@ var OsdManager = class {
|
|
|
58976
59202
|
if (stored === void 0) throw new Error(`osd-manager: template "${template.id}" missing after upsert`);
|
|
58977
59203
|
this.logger.info("osd-manager: named template upserted", { meta: {
|
|
58978
59204
|
templateId: stored.id,
|
|
58979
|
-
|
|
59205
|
+
bindingCount: stored.bindings.length
|
|
58980
59206
|
} });
|
|
58981
59207
|
return { template: stored };
|
|
58982
59208
|
};
|
|
@@ -59064,7 +59290,7 @@ var OsdManager = class {
|
|
|
59064
59290
|
const templatesById = /* @__PURE__ */ new Map();
|
|
59065
59291
|
for (const named of allTemplates) {
|
|
59066
59292
|
templatesById.set(named.id, named);
|
|
59067
|
-
if (templateIds.has(named.id)) for (const
|
|
59293
|
+
if (templateIds.has(named.id)) for (const binding of named.bindings) wanted.add(binding.pick.deviceId);
|
|
59068
59294
|
}
|
|
59069
59295
|
const stateByDevice = /* @__PURE__ */ new Map();
|
|
59070
59296
|
const gateState = /* @__PURE__ */ new Map();
|
|
@@ -59266,7 +59492,8 @@ var OsdManagerAddon = class extends BaseAddon {
|
|
|
59266
59492
|
listDevices: async () => {
|
|
59267
59493
|
return (await ctx.api.deviceManager.listAll.query({ projection: "slim" })).map((d) => ({
|
|
59268
59494
|
id: d.id,
|
|
59269
|
-
name: d.name
|
|
59495
|
+
name: d.name,
|
|
59496
|
+
type: d.type ?? null
|
|
59270
59497
|
}));
|
|
59271
59498
|
},
|
|
59272
59499
|
listCameras: async () => {
|
|
@@ -59364,4 +59591,41 @@ var OsdManagerAddon = class extends BaseAddon {
|
|
|
59364
59591
|
}
|
|
59365
59592
|
};
|
|
59366
59593
|
//#endregion
|
|
59367
|
-
|
|
59594
|
+
//#region src/osd-picker-devices.ts
|
|
59595
|
+
/**
|
|
59596
|
+
* Devices offered to the OSD DevicePicker — containers INCLUDED so the
|
|
59597
|
+
* operator can pick a gateway, then an OSD-supported child.
|
|
59598
|
+
*/
|
|
59599
|
+
function toOsdPickerDevices(devices) {
|
|
59600
|
+
return devices.map((d) => ({
|
|
59601
|
+
id: d.id,
|
|
59602
|
+
name: d.name,
|
|
59603
|
+
type: d.type ?? null,
|
|
59604
|
+
location: d.location ?? null,
|
|
59605
|
+
parentDeviceId: d.parentDeviceId ?? null
|
|
59606
|
+
}));
|
|
59607
|
+
}
|
|
59608
|
+
/** Children of a container that have at least one OSD catalog field. */
|
|
59609
|
+
function osdSupportedChildrenOf(containerId, devices, deviceIdsWithOsdFields) {
|
|
59610
|
+
return devices.filter((d) => d.parentDeviceId === containerId && isOsdLeafDeviceType(d.type) && deviceIdsWithOsdFields.has(d.id)).toSorted((a, b) => a.name.localeCompare(b.name));
|
|
59611
|
+
}
|
|
59612
|
+
function deviceById(devices, id) {
|
|
59613
|
+
return devices.find((d) => d.id === id);
|
|
59614
|
+
}
|
|
59615
|
+
//#endregion
|
|
59616
|
+
//#region src/template-id.ts
|
|
59617
|
+
/**
|
|
59618
|
+
* Named-template ids are system-generated — never an operator text field.
|
|
59619
|
+
* Create uses a uuid; the editable surface is the template name.
|
|
59620
|
+
*/
|
|
59621
|
+
function generateTemplateId() {
|
|
59622
|
+
if (typeof crypto !== "undefined" && typeof crypto.randomUUID === "function") return crypto.randomUUID();
|
|
59623
|
+
return `tpl-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 10)}`;
|
|
59624
|
+
}
|
|
59625
|
+
/** Optional slug helper when a stable short id from the name is preferred. */
|
|
59626
|
+
function templateIdFromName(name) {
|
|
59627
|
+
const slug = name.trim().toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 48);
|
|
59628
|
+
return `${slug.length > 0 ? slug : "template"}-${Date.now().toString(36)}`;
|
|
59629
|
+
}
|
|
59630
|
+
//#endregion
|
|
59631
|
+
export { DEFAULT_TICK_MS, EMPTY_BINDINGS, OSD_BINDINGS_KEY, OSD_NON_LEAF_TYPES, OSD_PICKER_EXCLUDED_TYPES, OSD_SOURCE_CAP_NAMES, OSD_SUPPORTED_CONDITIONS, OsdBindingsStore, OsdDeviceBindingsSchema, OsdManager, OsdManagerAddon, OsdManagerAddon as default, aliasFullToken, aliasToken, applyTemplate, applyTemplateFormat, applyTemplateTokenKind, assertSupportedConditions, bindingInsertChips, bindingToken, convertForDisplay, deviceById, dimensionFromSourceUnit, displayValue, evaluateGate, expandBindingTokens, formatClock, formatSlotText, generateTemplateId, humanizeCapName, inferSourceUnit, isContainerDeviceType, isOsdLeafDeviceType, isOsdPickerDeviceType, isOsdSourceCap, limitText, osdStateLeavesOf, osdSupportedChildrenOf, parseAliasStems, parseAliasTokens, readStatePath, renderNamedTemplate, renderSlot, replaceToken, resolveBindingLive, resolveSource, sourceOptionsFor, stateLeavesOf, suggestAlias, templateIdFromName, toOsdPickerDevices, truncateDecimals, unsupportedConditionKeys, withBinding, withoutBinding };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { b as e, g as t, l as n, u as r } from "./_virtual_mf___mfe_internal__addon_osd_manager_page__loadShare__react__loadShare__.js-C5jUMd7X.mjs";
|
|
2
|
-
import { c as i, s as a } from "./responsive-
|
|
2
|
+
import { c as i, s as a } from "./responsive-DLFs-5i_.mjs";
|
|
3
3
|
import { n as o, r as s, t as c } from "./_virtual_mf___mfe_internal__addon_osd_manager_page__loadShare__react_mf_1_jsx_mf_2_runtime__loadShare__.js-DalfdIDw.mjs";
|
|
4
4
|
var l = i("chevron-down", [["path", {
|
|
5
5
|
d: "m6 9 6 6 6-6",
|
package/dist/remoteEntry.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { n as e, t } from "./virtual_mf-REMOTE_ENTRY_ID___mfe_internal__addon_osd_manager_page__remoteEntry_js-
|
|
1
|
+
import { n as e, t } from "./virtual_mf-REMOTE_ENTRY_ID___mfe_internal__addon_osd_manager_page__remoteEntry_js-C3yC0JaQ.mjs";
|
|
2
2
|
export { t as get, e as init };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { _ as e, b as t, c as n, g as r, l as i, m as a, n as o, r as s, t as c, u as l } from "./_virtual_mf___mfe_internal__addon_osd_manager_page__loadShare__react__loadShare__.js-C5jUMd7X.mjs";
|
|
2
2
|
import "./_virtual_mf___mfe_internal__addon_osd_manager_page__loadShare__react_mf_1_jsx_mf_2_runtime__loadShare__.js-DalfdIDw.mjs";
|
|
3
|
-
import { i as u } from "./_virtual_mf___mfe_internal__addon_osd_manager_page__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-
|
|
3
|
+
import { i as u } from "./_virtual_mf___mfe_internal__addon_osd_manager_page__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-B2mEdhqd.mjs";
|
|
4
4
|
//#region ../../node_modules/lucide-react/dist/esm/shared/src/utils/mergeClasses.js
|
|
5
5
|
t();
|
|
6
6
|
var d = (...e) => e.filter((e, t, n) => !!e && e.trim() !== "" && n.indexOf(e) === t).join(" ").trim(), f = (e) => e.replace(/([a-z0-9])([A-Z])/g, "$1-$2").toLowerCase(), p = (e) => e.replace(/^([A-Z])|[\s-_]+(\w)/g, (e, t, n) => n ? n.toUpperCase() : t.toLowerCase()), m = (e) => {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { b as e, c as t, g as n, m as r } from "./_virtual_mf___mfe_internal__addon_osd_manager_page__loadShare__react__loadShare__.js-C5jUMd7X.mjs";
|
|
2
|
-
import { c as i } from "./responsive-
|
|
2
|
+
import { c as i } from "./responsive-DLFs-5i_.mjs";
|
|
3
3
|
var a = i("camera", [["path", {
|
|
4
4
|
d: "M13.997 4a2 2 0 0 1 1.76 1.05l.486.9A2 2 0 0 0 18.003 7H20a2 2 0 0 1 2 2v9a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V9a2 2 0 0 1 2-2h1.997a2 2 0 0 0 1.759-1.048l.489-.904A2 2 0 0 1 10.004 4z",
|
|
5
5
|
key: "18u6gg"
|
|
@@ -2753,7 +2753,7 @@ async function rr(e) {
|
|
|
2753
2753
|
}
|
|
2754
2754
|
}
|
|
2755
2755
|
async function ir() {
|
|
2756
|
-
return tr ||= rr(() => import("./_virtual_mf-localSharedImportMap___mfe_internal__addon_osd_manager_page-
|
|
2756
|
+
return tr ||= rr(() => import("./_virtual_mf-localSharedImportMap___mfe_internal__addon_osd_manager_page-BYQUZdGL.mjs")).catch((e) => {
|
|
2757
2757
|
throw tr = void 0, e;
|
|
2758
2758
|
}), tr;
|
|
2759
2759
|
}
|