@camstack/addon-agent-ui 1.2.313 → 1.2.315
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/CHANGELOG.md +12 -0
- package/dist/.bundle-modules.json +7 -7
- package/dist/addon.js +233 -44
- package/dist/assets/{MotionZonesSettings-B5LVS3-q.js → MotionZonesSettings-bgrKuCjb.js} +1 -1
- package/dist/assets/{PrivacyMaskSettings-DBY2agTe.js → PrivacyMaskSettings-aAj3HzsY.js} +1 -1
- package/dist/assets/{SceneMonitorEditor-Cis_4ZaK.js → SceneMonitorEditor-CsNjduqX.js} +1 -1
- package/dist/assets/index-BV77JC4K.css +2 -0
- package/dist/assets/{index-D5vO_ttL.js → index-MaQ1EcJ3.js} +16 -16
- package/dist/index.html +2 -2
- package/package.json +2 -2
- package/dist/assets/index-D9M7j6hZ.css +0 -2
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,18 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [1.2.315] - 2026-11-02
|
|
11
|
+
|
|
12
|
+
### Changed
|
|
13
|
+
|
|
14
|
+
- Rebuilt against updated dependencies.
|
|
15
|
+
|
|
16
|
+
## [1.2.314] - 2026-11-02
|
|
17
|
+
|
|
18
|
+
### Changed
|
|
19
|
+
|
|
20
|
+
- Rebuilt against updated dependencies.
|
|
21
|
+
|
|
10
22
|
## [1.2.313] - 2026-11-02
|
|
11
23
|
|
|
12
24
|
### Changed
|
|
@@ -362,13 +362,13 @@
|
|
|
362
362
|
"server/server/packages/addon-agent-ui/src/updates-panel.tsx": "ec6b5b3701322bbb68dbe581703409cd373418cf9227ce829ea0945e70e60d54",
|
|
363
363
|
"server/server/packages/addon-agent-ui/src/use-pairing-status.ts": "46193a1e83a64250dfff75d417448d74ba0159465e710861b996e903b03e427a",
|
|
364
364
|
"server/server/packages/sdk/dist/index.js": "89409bfb9632c46ed63ee4882c70b7994c1ff90c67d27a5d4b86b0990c41a131",
|
|
365
|
-
"server/server/packages/types/dist/client.mjs": "
|
|
366
|
-
"server/server/packages/types/dist/composition-
|
|
367
|
-
"server/server/packages/types/dist/device-type-
|
|
365
|
+
"server/server/packages/types/dist/client.mjs": "50205f786fd40359dcdedc87bbcb4cb8ecc6f9872c722457c9a44337b381545b",
|
|
366
|
+
"server/server/packages/types/dist/composition-Dh3RfMx5.mjs": "3bd5440c77222424fd992b3c3c5c68953abfccce331a639c311c36dd9d523e26",
|
|
367
|
+
"server/server/packages/types/dist/device-type-CfHw_quR.mjs": "a925875f57dabf69331e51c8d28fbade95a6a0ba92ab5bfe362f49c212290846",
|
|
368
368
|
"server/server/packages/types/dist/event-category-BmPm98n0.mjs": "3617fc3941b34f1dcc8ebd3c1360e8c302747400d43e3ab694388496c2bb568d",
|
|
369
|
-
"server/server/packages/types/dist/index.mjs": "
|
|
369
|
+
"server/server/packages/types/dist/index.mjs": "bcab27d609d10b949f60c65ab290ecd970628ce66b45c5a0982b3802d65299c4",
|
|
370
370
|
"server/server/packages/types/dist/node-color.mjs": "942e663074f0a4ed2f8643848ec139eba4b5fd16d0d01c8a23e08a4819a8843b",
|
|
371
|
-
"server/server/packages/types/dist/sleep-
|
|
371
|
+
"server/server/packages/types/dist/sleep-QsoHs66J.mjs": "dd8a98c45a8cd12e44f1bd0ffba0c461c8d3c4e471225acdd8647926843668dd",
|
|
372
372
|
"server/server/packages/ui-library/src/composites/adaptive-downlink.ts": "6e9698e97721461b72a3750f930dd7214d049be865491bfb5a64b87c032b0e22",
|
|
373
373
|
"server/server/packages/ui-library/src/composites/camera-stream-player.tsx": "c04809229b4e091fed09e2bcfe643d6b36cb3a39e294229b49f8a095e4e6ebd3",
|
|
374
374
|
"server/server/packages/ui-library/src/composites/cap-settings/CameraGridLayoutEditor.tsx": "bfe36ccad931ef0981fe24fa315f136d35dbc3164df221346806173447178324",
|
|
@@ -435,7 +435,7 @@
|
|
|
435
435
|
"server/server/packages/ui-library/src/composites/device-controls/valve-control.tsx": "373f34532ac55a02db9163927a7e63be9cdbba52b5d16e9e10b71bb7802e0131",
|
|
436
436
|
"server/server/packages/ui-library/src/composites/device-controls/water-heater-control.tsx": "4a2bad97090f2d115973c68eb60a2973c8edbb02d40a58daecdaffcd5a49b971",
|
|
437
437
|
"server/server/packages/ui-library/src/composites/device-controls/weather-control.tsx": "46cab536e8388072e0123f7b84b1b66d837791c4216b4df0df47a7a34fbca75b",
|
|
438
|
-
"server/server/packages/ui-library/src/composites/device-export-panel.tsx": "
|
|
438
|
+
"server/server/packages/ui-library/src/composites/device-export-panel.tsx": "168098ec1ecd6dc75515f9788ef829ae1ce00cd27ce4c72cadf8b686ae5784ba",
|
|
439
439
|
"server/server/packages/ui-library/src/composites/device-history/history-selection.ts": "472d8a88d824218318707fbc017f5bcce3a777e88c2d7c59c0563ae88530aa8b",
|
|
440
440
|
"server/server/packages/ui-library/src/composites/device-history/history-window.ts": "8b34ddb19c75be312a4efda5bc4ce3a02c53b391dfbf7226f0491c87612bd951",
|
|
441
441
|
"server/server/packages/ui-library/src/composites/device-item/actions.tsx": "8d56da1265444e7e49a17acb33e498b9ca47a4921e56c18216ac0a1095bb4693",
|
|
@@ -479,7 +479,7 @@
|
|
|
479
479
|
"server/server/packages/ui-library/src/contexts/vod-playback.tsx": "c07bc3ecc786182ef2f27d13bec3f520288e0b47367edd7ddf1c2e7b4a2bbaee",
|
|
480
480
|
"server/server/packages/ui-library/src/contexts/widget-registry.tsx": "71a2815c645abe96821a9e9e5668e321187527d569414f5ca197d615856cc17a",
|
|
481
481
|
"server/server/packages/ui-library/src/contexts/zone-editing.tsx": "275f680304ab09dd747fd9e859dc5aa0535df33eb2d33eb669a6de66bdd848d0",
|
|
482
|
-
"server/server/packages/ui-library/src/generated/system-hooks.ts": "
|
|
482
|
+
"server/server/packages/ui-library/src/generated/system-hooks.ts": "cf09d4a765ce36b589615ca6954d1a01adca02906c950ae03fed218e7ce5c5b7",
|
|
483
483
|
"server/server/packages/ui-library/src/hooks/turn-server-cache.ts": "fab22f069c3761e0d268449e056d9c499b6ea63b879684a40023735b34bad061",
|
|
484
484
|
"server/server/packages/ui-library/src/hooks/use-device-capability.ts": "b74ede60be8039c45f6c712a407ee838ab208610435870ddabaa8598cb7cd7f3",
|
|
485
485
|
"server/server/packages/ui-library/src/hooks/use-device-detections.ts": "61cc54cf2e7f53864e5aa533c05679e4c204c4004a0296f63ab169b003888611",
|
package/dist/addon.js
CHANGED
|
@@ -786,7 +786,7 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
|
786
786
|
return EventCategory;
|
|
787
787
|
}({});
|
|
788
788
|
//#endregion
|
|
789
|
-
//#region ../types/dist/device-type-
|
|
789
|
+
//#region ../types/dist/device-type-CfHw_quR.mjs
|
|
790
790
|
/**
|
|
791
791
|
import { errMsg } from '@camstack/types'
|
|
792
792
|
* Extract a human-readable message from an unknown error value.
|
|
@@ -975,6 +975,9 @@ var DeviceFeature = /* @__PURE__ */ function(DeviceFeature) {
|
|
|
975
975
|
DeviceFeature["CoverPositionable"] = "cover-positionable";
|
|
976
976
|
/** Cover exposes slat-tilt control. Gates the tilt slider UI. */
|
|
977
977
|
DeviceFeature["CoverTilt"] = "cover-tilt";
|
|
978
|
+
/** Cover has a real stop: `stop` halts the travel in place. Gates the stop
|
|
979
|
+
* control in exporters; a provider whose `stop` is a no-op never declares it. */
|
|
980
|
+
DeviceFeature["CoverStoppable"] = "cover-stoppable";
|
|
978
981
|
/** Valve exposes intermediate position control (0..100). Gates the
|
|
979
982
|
* position slider / drag surface UI. */
|
|
980
983
|
DeviceFeature["ValvePositionable"] = "valve-positionable";
|
|
@@ -5840,7 +5843,7 @@ var ZodIssueCode = {
|
|
|
5840
5843
|
var ZodFirstPartyTypeKind;
|
|
5841
5844
|
ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
|
|
5842
5845
|
//#endregion
|
|
5843
|
-
//#region ../types/dist/sleep-
|
|
5846
|
+
//#region ../types/dist/sleep-QsoHs66J.mjs
|
|
5844
5847
|
/**
|
|
5845
5848
|
* The audio chunk plane's byte format, and the ONE expansion from a coded
|
|
5846
5849
|
* window to float samples (D455).
|
|
@@ -5957,7 +5960,7 @@ function isKeychainStoredField(field) {
|
|
|
5957
5960
|
var SECRET_CLEAR = { $secretClear: true };
|
|
5958
5961
|
/** The `'***'` token D634 redaction writes for non-admins. */
|
|
5959
5962
|
var LEGACY_DEVICE_REDACTION = "***";
|
|
5960
|
-
function isRecord$
|
|
5963
|
+
function isRecord$7(value) {
|
|
5961
5964
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
5962
5965
|
}
|
|
5963
5966
|
function makeSecretMarker(ref) {
|
|
@@ -5968,12 +5971,12 @@ function makeSecretMarker(ref) {
|
|
|
5968
5971
|
}
|
|
5969
5972
|
/** A stored marker: an object whose `$secret` is a non-empty string. */
|
|
5970
5973
|
function isSecretMarker(value) {
|
|
5971
|
-
if (!isRecord$
|
|
5974
|
+
if (!isRecord$7(value)) return false;
|
|
5972
5975
|
const ref = value["$secret"];
|
|
5973
5976
|
return typeof ref === "string" && ref.length > 0;
|
|
5974
5977
|
}
|
|
5975
5978
|
function isSecretClear(value) {
|
|
5976
|
-
return isRecord$
|
|
5979
|
+
return isRecord$7(value) && value["$secretClear"] === true;
|
|
5977
5980
|
}
|
|
5978
5981
|
/**
|
|
5979
5982
|
* The UI view of a stored secret field value: a marker becomes "set", inline
|
|
@@ -6679,7 +6682,7 @@ var KeychainWriteRefusedError = class extends Error {
|
|
|
6679
6682
|
}
|
|
6680
6683
|
};
|
|
6681
6684
|
var KEEP = { kind: "keep" };
|
|
6682
|
-
function isRecord$
|
|
6685
|
+
function isRecord$6(value) {
|
|
6683
6686
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
6684
6687
|
}
|
|
6685
6688
|
function defaultMintId() {
|
|
@@ -6692,7 +6695,7 @@ function collectSecretMarkerRefs(value, out = []) {
|
|
|
6692
6695
|
return out;
|
|
6693
6696
|
}
|
|
6694
6697
|
if (Array.isArray(value)) for (const item of value) collectSecretMarkerRefs(item, out);
|
|
6695
|
-
else if (isRecord$
|
|
6698
|
+
else if (isRecord$6(value)) for (const child of Object.values(value)) collectSecretMarkerRefs(child, out);
|
|
6696
6699
|
return out;
|
|
6697
6700
|
}
|
|
6698
6701
|
async function storedValueEquals(secrets, marker, candidate) {
|
|
@@ -6747,7 +6750,7 @@ function rowId(row, idKey) {
|
|
|
6747
6750
|
return null;
|
|
6748
6751
|
}
|
|
6749
6752
|
async function writeArray(ctx, node, incoming, stored, fieldPath) {
|
|
6750
|
-
const storedRows = Array.isArray(stored) ? stored.filter(isRecord$
|
|
6753
|
+
const storedRows = Array.isArray(stored) ? stored.filter(isRecord$6) : [];
|
|
6751
6754
|
if (!Array.isArray(incoming)) {
|
|
6752
6755
|
ctx.deletes.push(...collectSecretMarkerRefs(storedRows));
|
|
6753
6756
|
return {
|
|
@@ -6763,7 +6766,7 @@ async function writeArray(ctx, node, incoming, stored, fieldPath) {
|
|
|
6763
6766
|
const kept = /* @__PURE__ */ new Set();
|
|
6764
6767
|
const rows = [];
|
|
6765
6768
|
for (const row of incoming) {
|
|
6766
|
-
if (!isRecord$
|
|
6769
|
+
if (!isRecord$6(row)) {
|
|
6767
6770
|
rows.push(row);
|
|
6768
6771
|
continue;
|
|
6769
6772
|
}
|
|
@@ -6788,7 +6791,7 @@ async function writeNode(ctx, node, incoming, stored, fieldPath) {
|
|
|
6788
6791
|
case "leaf": return writeLeaf(ctx, incoming, stored, fieldPath);
|
|
6789
6792
|
case "array": return writeArray(ctx, node, incoming, stored, fieldPath);
|
|
6790
6793
|
case "object": {
|
|
6791
|
-
if (!isRecord$
|
|
6794
|
+
if (!isRecord$6(incoming)) {
|
|
6792
6795
|
if (incoming === void 0) return KEEP;
|
|
6793
6796
|
ctx.deletes.push(...collectSecretMarkerRefs(stored));
|
|
6794
6797
|
return {
|
|
@@ -6796,7 +6799,7 @@ async function writeNode(ctx, node, incoming, stored, fieldPath) {
|
|
|
6796
6799
|
value: incoming
|
|
6797
6800
|
};
|
|
6798
6801
|
}
|
|
6799
|
-
const storedObj = isRecord$
|
|
6802
|
+
const storedObj = isRecord$6(stored) ? stored : {};
|
|
6800
6803
|
return {
|
|
6801
6804
|
kind: "value",
|
|
6802
6805
|
value: await writeMembers(ctx, node.children, incoming, storedObj, (m) => `${fieldPath}.${m}`)
|
|
@@ -6919,7 +6922,7 @@ async function resolveSecretMarkers(value, secrets, options = {}) {
|
|
|
6919
6922
|
value: items
|
|
6920
6923
|
};
|
|
6921
6924
|
}
|
|
6922
|
-
if (isRecord$
|
|
6925
|
+
if (isRecord$6(v)) {
|
|
6923
6926
|
const out = {};
|
|
6924
6927
|
for (const [k, child] of Object.entries(v)) {
|
|
6925
6928
|
const s = substitute(child);
|
|
@@ -6951,7 +6954,7 @@ var SecretOverwriteRefusedError = class extends Error {
|
|
|
6951
6954
|
this.name = "SecretOverwriteRefusedError";
|
|
6952
6955
|
}
|
|
6953
6956
|
};
|
|
6954
|
-
function isRecord$
|
|
6957
|
+
function isRecord$5(value) {
|
|
6955
6958
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
6956
6959
|
}
|
|
6957
6960
|
function resolvedValue(pass, marker) {
|
|
@@ -6980,7 +6983,7 @@ function inArray(pass, incoming, stored) {
|
|
|
6980
6983
|
return incoming.map((item, index) => {
|
|
6981
6984
|
const twin = stored[index];
|
|
6982
6985
|
if (isSecretMarker(twin)) return typeof item === "string" && item === resolvedValue(pass, twin) ? twin : item;
|
|
6983
|
-
if (isRecord$
|
|
6986
|
+
if (isRecord$5(item) && isRecord$5(twin)) return inArrayRow(pass, item, twin);
|
|
6984
6987
|
if (Array.isArray(item) && Array.isArray(twin)) return inArray(pass, item, twin);
|
|
6985
6988
|
return item;
|
|
6986
6989
|
});
|
|
@@ -6991,7 +6994,7 @@ function inArrayRow(pass, incoming, stored) {
|
|
|
6991
6994
|
const twin = stored[key];
|
|
6992
6995
|
if (isSecretMarker(twin)) {
|
|
6993
6996
|
if (typeof value === "string" && value === resolvedValue(pass, twin)) out[key] = twin;
|
|
6994
|
-
} else if (isRecord$
|
|
6997
|
+
} else if (isRecord$5(value) && isRecord$5(twin)) out[key] = inArrayRow(pass, value, twin);
|
|
6995
6998
|
else if (Array.isArray(value) && Array.isArray(twin)) out[key] = inArray(pass, value, twin);
|
|
6996
6999
|
}
|
|
6997
7000
|
return out;
|
|
@@ -6999,7 +7002,7 @@ function inArrayRow(pass, incoming, stored) {
|
|
|
6999
7002
|
async function walk(pass, incoming, stored) {
|
|
7000
7003
|
if (isSecretMarker(stored)) return atMarker(pass, incoming, stored);
|
|
7001
7004
|
if (Array.isArray(incoming) && Array.isArray(stored)) return inArray(pass, incoming, stored);
|
|
7002
|
-
if (!isRecord$
|
|
7005
|
+
if (!isRecord$5(incoming) || !isRecord$5(stored)) return incoming;
|
|
7003
7006
|
const out = { ...incoming };
|
|
7004
7007
|
for (const [key, value] of Object.entries(incoming)) out[key] = await walk(pass, value, stored[key]);
|
|
7005
7008
|
return out;
|
|
@@ -7030,7 +7033,7 @@ async function restoreUnchangedSecrets(input) {
|
|
|
7030
7033
|
function isJsonEqual(a, b) {
|
|
7031
7034
|
if (Object.is(a, b)) return true;
|
|
7032
7035
|
if (Array.isArray(a)) return Array.isArray(b) && a.length === b.length && a.every((v, i) => isJsonEqual(v, b[i]));
|
|
7033
|
-
if (isRecord$
|
|
7036
|
+
if (isRecord$5(a) && isRecord$5(b)) {
|
|
7034
7037
|
const keys = Object.keys(a);
|
|
7035
7038
|
if (keys.length !== Object.keys(b).length) return false;
|
|
7036
7039
|
return keys.every((k) => Object.prototype.hasOwnProperty.call(b, k) && isJsonEqual(a[k], b[k]));
|
|
@@ -7054,7 +7057,7 @@ function markerKeysOf(blob, owner) {
|
|
|
7054
7057
|
}
|
|
7055
7058
|
function nodeFromStored(value, owner) {
|
|
7056
7059
|
if (isSecretMarker(value)) return isSecretRefOwnedBy(value.$secret, owner) ? { kind: "leaf" } : null;
|
|
7057
|
-
if (!isRecord$
|
|
7060
|
+
if (!isRecord$5(value)) return null;
|
|
7058
7061
|
const children = /* @__PURE__ */ new Map();
|
|
7059
7062
|
for (const [key, child] of Object.entries(value)) {
|
|
7060
7063
|
const node = nodeFromStored(child, owner);
|
|
@@ -7673,6 +7676,44 @@ var BaseAddon = class {
|
|
|
7673
7676
|
return null;
|
|
7674
7677
|
}
|
|
7675
7678
|
/**
|
|
7679
|
+
* D986 scoped settings: the form shape of the CLUSTER-wide settings one capability this addon
|
|
7680
|
+
* provides owns, or `null` when it has none. `cap` is a capability name the addon's manifest
|
|
7681
|
+
* declares. Stored as `addon-settings` rows `<addonId>.<field>`. The keys of this schema, of
|
|
7682
|
+
* {@link nodeSettingsSchema} and of {@link deviceDefaultsSchema} are disjoint, and a key never
|
|
7683
|
+
* contains `@` (guard `check-scoped-settings-declared`). SHAPE only: values are read by scope.
|
|
7684
|
+
*/
|
|
7685
|
+
async clusterSettingsSchema(_cap) {
|
|
7686
|
+
return null;
|
|
7687
|
+
}
|
|
7688
|
+
/**
|
|
7689
|
+
* D986: the form shape of the settings one capability owns PER NODE, or `null`. Stored as
|
|
7690
|
+
* `addon-settings` rows `<addonId>.<field>@<nodeId>` carrying `nodeId` in the row data, so a
|
|
7691
|
+
* forgotten node's rows go in one central delete.
|
|
7692
|
+
*/
|
|
7693
|
+
async nodeSettingsSchema(_cap) {
|
|
7694
|
+
return null;
|
|
7695
|
+
}
|
|
7696
|
+
/**
|
|
7697
|
+
* D986: the form shape of the FLEET DEFAULTS of the per-device settings one capability owns,
|
|
7698
|
+
* or `null`. Stored as `addon-settings` rows `<addonId>.<field>`; a device resolves its value
|
|
7699
|
+
* as device row, then this default, then the schema default (`resolveDeviceSettings`).
|
|
7700
|
+
*/
|
|
7701
|
+
async deviceDefaultsSchema(_cap) {
|
|
7702
|
+
return null;
|
|
7703
|
+
}
|
|
7704
|
+
/**
|
|
7705
|
+
* The host's read of the scoped declarations: the schema one capability declares for `scope`,
|
|
7706
|
+
* or `null`. Beside {@link getIntegrationFormSchema}, the same shape: the hook is protected, the
|
|
7707
|
+
* host asks this method.
|
|
7708
|
+
*/
|
|
7709
|
+
async getScopedSettingsSchema(scope, cap) {
|
|
7710
|
+
switch (scope) {
|
|
7711
|
+
case "cluster": return this.clusterSettingsSchema(cap);
|
|
7712
|
+
case "node": return this.nodeSettingsSchema(cap);
|
|
7713
|
+
case "device-defaults": return this.deviceDefaultsSchema(cap);
|
|
7714
|
+
}
|
|
7715
|
+
}
|
|
7716
|
+
/**
|
|
7676
7717
|
* What the create wizard and the integration edit page render for one instance: the addon's
|
|
7677
7718
|
* per-instance schema when it declares one, else its global schema (what they always showed).
|
|
7678
7719
|
*/
|
|
@@ -8466,6 +8507,21 @@ function normalizeAddonInitResult(result) {
|
|
|
8466
8507
|
if (Array.isArray(result)) return { providers: result };
|
|
8467
8508
|
return result;
|
|
8468
8509
|
}
|
|
8510
|
+
/** Limits and names of `ctx.records` (D881). One authority; the engine and the facade read it. */
|
|
8511
|
+
/** The files a kind may live in. `history` is device-history's (D850), never records. */
|
|
8512
|
+
var RECORD_DATABASES = ["settings", "events"];
|
|
8513
|
+
/** The classes of a kind: the `@durable` vocabulary, one authority (replaces the annotation). */
|
|
8514
|
+
var RECORD_CLASSES = [
|
|
8515
|
+
"config",
|
|
8516
|
+
"ledger",
|
|
8517
|
+
"audit",
|
|
8518
|
+
"mirror",
|
|
8519
|
+
"ephemeral"
|
|
8520
|
+
];
|
|
8521
|
+
var RECORD_DEFAULT_MAX_DATA_BYTES = 64 * 1024;
|
|
8522
|
+
var RECORD_MAX_DATA_BYTES = 1024 * 1024;
|
|
8523
|
+
var RECORD_BATCH_MAX = 1e3;
|
|
8524
|
+
var RECORD_QUERY_MAX = 1e3;
|
|
8469
8525
|
/**
|
|
8470
8526
|
* The share-view scope kinds a share-link token can carry. The hub mints
|
|
8471
8527
|
* and validates them (`ShareViewGrantSchema` builds its
|
|
@@ -8490,21 +8546,6 @@ var PeerBytesTicketSchema = object({
|
|
|
8490
8546
|
*/
|
|
8491
8547
|
declaredBytes: number().int().nonnegative().nullable()
|
|
8492
8548
|
});
|
|
8493
|
-
/** Limits and names of `ctx.records` (D881). One authority; the engine and the facade read it. */
|
|
8494
|
-
/** The files a kind may live in. `history` is device-history's (D850), never records. */
|
|
8495
|
-
var RECORD_DATABASES = ["settings", "events"];
|
|
8496
|
-
/** The classes of a kind: the `@durable` vocabulary, one authority (replaces the annotation). */
|
|
8497
|
-
var RECORD_CLASSES = [
|
|
8498
|
-
"config",
|
|
8499
|
-
"ledger",
|
|
8500
|
-
"audit",
|
|
8501
|
-
"mirror",
|
|
8502
|
-
"ephemeral"
|
|
8503
|
-
];
|
|
8504
|
-
var RECORD_DEFAULT_MAX_DATA_BYTES = 64 * 1024;
|
|
8505
|
-
var RECORD_MAX_DATA_BYTES = 1024 * 1024;
|
|
8506
|
-
var RECORD_BATCH_MAX = 1e3;
|
|
8507
|
-
var RECORD_QUERY_MAX = 1e3;
|
|
8508
8549
|
/**
|
|
8509
8550
|
* Record kinds (D881): the declaration an addon makes of one kind of fact, the
|
|
8510
8551
|
* Zod row schema that describes it, and the helper that turns the two into the
|
|
@@ -9304,6 +9345,7 @@ var CAP_NAMES = Object.freeze([
|
|
|
9304
9345
|
"humidity-sensor",
|
|
9305
9346
|
"image",
|
|
9306
9347
|
"image-settings",
|
|
9348
|
+
"integration-instances",
|
|
9307
9349
|
"integrations",
|
|
9308
9350
|
"intercom",
|
|
9309
9351
|
"ir-transmitter",
|
|
@@ -11237,7 +11279,7 @@ object({
|
|
|
11237
11279
|
params: record(string(), union([string(), number()])).optional()
|
|
11238
11280
|
});
|
|
11239
11281
|
//#endregion
|
|
11240
|
-
//#region ../types/dist/composition-
|
|
11282
|
+
//#region ../types/dist/composition-Dh3RfMx5.mjs
|
|
11241
11283
|
/**
|
|
11242
11284
|
* The ffmpeg build every CamStack node downloads, per platform and arch.
|
|
11243
11285
|
*
|
|
@@ -20720,6 +20762,7 @@ var SYSTEM_CAP_VOCABULARY = {
|
|
|
20720
20762
|
"load-contribution": system(INTERNAL),
|
|
20721
20763
|
"local-network": system(NETWORK),
|
|
20722
20764
|
"log-channels": system(INTERNAL),
|
|
20765
|
+
"integration-instances": system(INTERNAL),
|
|
20723
20766
|
"log-destination": system(INTERNAL),
|
|
20724
20767
|
"login-method": system(IDENTITY),
|
|
20725
20768
|
"mesh-network": system(NETWORK),
|
|
@@ -42866,7 +42909,7 @@ var TargetKindCapsSchema = object({
|
|
|
42866
42909
|
* the union is large and not meant for runtime validation here; the exported
|
|
42867
42910
|
* `TargetKind` type re-tightens `configSchema` to `ConfigUISchema`.
|
|
42868
42911
|
*/
|
|
42869
|
-
var ConfigSchemaPassthrough$
|
|
42912
|
+
var ConfigSchemaPassthrough$4 = unknown();
|
|
42870
42913
|
var TargetKindSchema = object({
|
|
42871
42914
|
kind: string(),
|
|
42872
42915
|
label: string(),
|
|
@@ -42903,7 +42946,7 @@ var TargetKindSchema = object({
|
|
|
42903
42946
|
* its raster path, which is the safe default for an unknown image.
|
|
42904
42947
|
*/
|
|
42905
42948
|
iconMediaType: string().optional(),
|
|
42906
|
-
configSchema: ConfigSchemaPassthrough$
|
|
42949
|
+
configSchema: ConfigSchemaPassthrough$4,
|
|
42907
42950
|
/**
|
|
42908
42951
|
* The config keys that decide WHERE this kind's secrets are sent (server,
|
|
42909
42952
|
* base URL, instance, chat, recipient). A save that changes any of them
|
|
@@ -52623,6 +52666,78 @@ method(_void(), array(IntegrationWithStateSchema)), method(object({ id: string()
|
|
|
52623
52666
|
auth: "admin"
|
|
52624
52667
|
});
|
|
52625
52668
|
/**
|
|
52669
|
+
* `integration-instances` - the connection of an addon that holds ONE or SEVERAL
|
|
52670
|
+
* (an account, a relay, a destination) as typed records (D985, D986). The addon's
|
|
52671
|
+
* own function page reads and writes them (Logging for Loki); the Integrations
|
|
52672
|
+
* page lists only the integrations that bring devices (D996).
|
|
52673
|
+
*
|
|
52674
|
+
* A collection of providers: each addon that holds connections registers one and a
|
|
52675
|
+
* caller reaches a provider with the pinned `addonId`.
|
|
52676
|
+
*
|
|
52677
|
+
* Identity: the instance id is immutable and opaque to the caller. A record the
|
|
52678
|
+
* Loki migration made keeps the `integrations` registry id it was created under
|
|
52679
|
+
* (`int_NNNN`); a single instance made by its function page takes the addon id.
|
|
52680
|
+
* `name` is the editable label.
|
|
52681
|
+
*
|
|
52682
|
+
* Secrets: every field the instance kind marks `.meta({ secret: true })` reaches
|
|
52683
|
+
* the form as a `SecretFieldView`, never text (D789). A patch value omitted, `''`
|
|
52684
|
+
* or the redaction token KEEPS the stored secret; `{ $secretClear: true }`
|
|
52685
|
+
* clears it.
|
|
52686
|
+
*/
|
|
52687
|
+
var ConfigSchemaPassthrough$3 = custom();
|
|
52688
|
+
var IntegrationInstanceIdSchema = string().min(1);
|
|
52689
|
+
var IntegrationInstanceDescriptionSchema = object({
|
|
52690
|
+
/** `single`: at most one instance can exist (Loki). `multiple`: an account each. */
|
|
52691
|
+
instanceMode: _enum(["single", "multiple"]),
|
|
52692
|
+
/** What the instance is, for the UI (`destination`, `relay`, `account`). */
|
|
52693
|
+
kind: string(),
|
|
52694
|
+
/** True when `testInstance` really probes the remote. */
|
|
52695
|
+
canTest: boolean()
|
|
52696
|
+
});
|
|
52697
|
+
var IntegrationInstanceStatusSchema = object({
|
|
52698
|
+
state: _enum([
|
|
52699
|
+
"ok",
|
|
52700
|
+
"off",
|
|
52701
|
+
"error",
|
|
52702
|
+
"unknown"
|
|
52703
|
+
]),
|
|
52704
|
+
detail: string().optional()
|
|
52705
|
+
});
|
|
52706
|
+
var IntegrationInstanceSchema = object({
|
|
52707
|
+
id: IntegrationInstanceIdSchema,
|
|
52708
|
+
name: string(),
|
|
52709
|
+
/** The addon's own rule (an URL is present, a client id is present...). */
|
|
52710
|
+
configured: boolean(),
|
|
52711
|
+
/** Values for the instance form; a secret is a `SecretFieldView`, never text. */
|
|
52712
|
+
formValues: record(string(), unknown()),
|
|
52713
|
+
status: IntegrationInstanceStatusSchema.optional()
|
|
52714
|
+
});
|
|
52715
|
+
var IntegrationInstancePatchSchema = object({
|
|
52716
|
+
id: IntegrationInstanceIdSchema,
|
|
52717
|
+
name: string().min(1).optional(),
|
|
52718
|
+
/** Omitted / '' / redaction token keeps a secret; `{ $secretClear: true }` clears it. */
|
|
52719
|
+
values: record(string(), unknown())
|
|
52720
|
+
});
|
|
52721
|
+
method(_void(), IntegrationInstanceDescriptionSchema, { auth: "admin" }), method(object({ id: IntegrationInstanceIdSchema.nullable() }), ConfigSchemaPassthrough$3, { auth: "admin" }), method(_void(), array(IntegrationInstanceSchema).readonly(), { auth: "admin" }), method(object({ id: IntegrationInstanceIdSchema }), IntegrationInstanceSchema.nullable(), { auth: "admin" }), method(object({
|
|
52722
|
+
id: IntegrationInstanceIdSchema,
|
|
52723
|
+
name: string().min(1)
|
|
52724
|
+
}), object({ id: string() }), {
|
|
52725
|
+
kind: "mutation",
|
|
52726
|
+
auth: "admin"
|
|
52727
|
+
}), method(IntegrationInstancePatchSchema, object({ ok: literal(true) }), {
|
|
52728
|
+
kind: "mutation",
|
|
52729
|
+
auth: "admin"
|
|
52730
|
+
}), method(object({ id: IntegrationInstanceIdSchema }), object({ ok: literal(true) }), {
|
|
52731
|
+
kind: "mutation",
|
|
52732
|
+
auth: "admin"
|
|
52733
|
+
}), optionalMethod(object({
|
|
52734
|
+
id: IntegrationInstanceIdSchema.nullable(),
|
|
52735
|
+
values: record(string(), unknown())
|
|
52736
|
+
}), TestConnectionResultSchema$1, {
|
|
52737
|
+
kind: "mutation",
|
|
52738
|
+
auth: "admin"
|
|
52739
|
+
});
|
|
52740
|
+
/**
|
|
52626
52741
|
* Two-way audio / talk-back cap. Clients open a WebRTC audio-only
|
|
52627
52742
|
* session (server-initiated offer pattern, identical to the main
|
|
52628
52743
|
* video WebRTC flow) and the browser captures the mic; the server
|
|
@@ -62655,7 +62770,14 @@ var NcMediaPolicySchema = object({
|
|
|
62655
62770
|
*/
|
|
62656
62771
|
profile: CamProfileSchema.optional(),
|
|
62657
62772
|
/** See {@link NcLinkedCameraModeSchema}. */
|
|
62658
|
-
linkedCameras: NcLinkedCameraModeSchema.optional()
|
|
62773
|
+
linkedCameras: NcLinkedCameraModeSchema.optional(),
|
|
62774
|
+
/**
|
|
62775
|
+
* Sensor rules only: may this rule wake a SLEEPING battery camera to take
|
|
62776
|
+
* the linked still it attaches (D998)? Absent means yes, an explicit `false`
|
|
62777
|
+
* opts out. Deliberately not a Zod default: a rule that never chose keeps
|
|
62778
|
+
* following the hub's. One bounded wake per event; nothing is attached later.
|
|
62779
|
+
*/
|
|
62780
|
+
wakeSleepingCamera: boolean().optional()
|
|
62659
62781
|
});
|
|
62660
62782
|
/**
|
|
62661
62783
|
* Cooldown GRANULARITY over the subject's class — how much a fired
|
|
@@ -70323,7 +70445,16 @@ DeviceType.Sensor;
|
|
|
70323
70445
|
* future fields without breaking the existing call sites.
|
|
70324
70446
|
*/
|
|
70325
70447
|
var EmailAddressSchema = email();
|
|
70448
|
+
/**
|
|
70449
|
+
* Which relay of a multi-relay provider answers (D996). Absent = the provider's first / default
|
|
70450
|
+
* relay, so a caller written before relays existed keeps working unchanged. A provider with one
|
|
70451
|
+
* fixed relay ignores it. This is the integration instance id (`int_NNNN`), NOT the addon id: the
|
|
70452
|
+
* collection pin `addonId` still picks the provider, `instanceId` picks the relay inside it.
|
|
70453
|
+
*/
|
|
70454
|
+
var InstanceIdSchema = string().min(1).optional();
|
|
70455
|
+
var RelayPinSchema = object({ instanceId: InstanceIdSchema });
|
|
70326
70456
|
var SendEmailInputSchema = object({
|
|
70457
|
+
instanceId: InstanceIdSchema,
|
|
70327
70458
|
to: union([EmailAddressSchema, array(EmailAddressSchema).min(1)]),
|
|
70328
70459
|
cc: array(EmailAddressSchema).optional(),
|
|
70329
70460
|
bcc: array(EmailAddressSchema).optional(),
|
|
@@ -70359,11 +70490,11 @@ method(SendEmailInputSchema, SendEmailResultSchema, {
|
|
|
70359
70490
|
kind: "mutation",
|
|
70360
70491
|
auth: "admin",
|
|
70361
70492
|
access: "create"
|
|
70362
|
-
}), method(
|
|
70493
|
+
}), method(RelayPinSchema, SmtpStatusSchema, {
|
|
70363
70494
|
kind: "mutation",
|
|
70364
70495
|
auth: "admin",
|
|
70365
70496
|
access: "view"
|
|
70366
|
-
}), method(
|
|
70497
|
+
}), method(RelayPinSchema, SmtpStatusSchema, { auth: "admin" });
|
|
70367
70498
|
/**
|
|
70368
70499
|
* A single device snapshot returned as base64 JPEG/PNG.
|
|
70369
70500
|
*
|
|
@@ -70395,10 +70526,12 @@ DeviceType.Camera, method(object({
|
|
|
70395
70526
|
* even when the cache is well within the device's
|
|
70396
70527
|
* `snapshotMaxAgeS` window.
|
|
70397
70528
|
*
|
|
70398
|
-
* **`force` is
|
|
70529
|
+
* **`force` is a demand with a named principal, not a freshness
|
|
70530
|
+
* preference** — an operator button, the scheduled refresh (D847), or a
|
|
70531
|
+
* notification rule that left the camera's wake allowed (D998). On a
|
|
70399
70532
|
* battery camera it is the one thing that walks past the wrapper's
|
|
70400
|
-
* sleep gate and wakes the camera, so a
|
|
70401
|
-
*
|
|
70533
|
+
* sleep gate and wakes the camera, so a poller, a thumbnail or a
|
|
70534
|
+
* prestream must NEVER set it. Every such caller
|
|
70402
70535
|
* gets the cached frame, which on a sleeping battery camera is the
|
|
70403
70536
|
* correct answer: stale but honest beats woken.
|
|
70404
70537
|
*/
|
|
@@ -74356,7 +74489,7 @@ discriminatedUnion("kind", [object({
|
|
|
74356
74489
|
kind: literal("pronto"),
|
|
74357
74490
|
code: string()
|
|
74358
74491
|
})]);
|
|
74359
|
-
DeviceFeature.FanSpeed, DeviceFeature.FanPreset, DeviceFeature.FanDirection, DeviceFeature.FanOscillating, DeviceFeature.CoverPositionable, DeviceFeature.CoverTilt, DeviceFeature.ValvePositionable, DeviceFeature.MediaPlayerVolume, DeviceFeature.ClimateFanMode;
|
|
74492
|
+
DeviceFeature.FanSpeed, DeviceFeature.FanPreset, DeviceFeature.FanDirection, DeviceFeature.FanOscillating, DeviceFeature.CoverStoppable, DeviceFeature.CoverPositionable, DeviceFeature.CoverTilt, DeviceFeature.ValvePositionable, DeviceFeature.MediaPlayerVolume, DeviceFeature.ClimateFanMode;
|
|
74360
74493
|
SOURCE_CAPS.filter((cap) => cap !== "switch" && cap !== "motion");
|
|
74361
74494
|
String.raw`rose\(active(\d+), changed(\d+), (\d+(?:\.\d+)?)\)`;
|
|
74362
74495
|
DeviceRole.BinarySensor, DeviceRole.MotionSensor;
|
|
@@ -77976,6 +78109,62 @@ Object.freeze({
|
|
|
77976
78109
|
access: "create",
|
|
77977
78110
|
role: "admin"
|
|
77978
78111
|
},
|
|
78112
|
+
"integrationInstances.createInstance": {
|
|
78113
|
+
capName: "integration-instances",
|
|
78114
|
+
capScope: "system",
|
|
78115
|
+
addonId: null,
|
|
78116
|
+
access: "create",
|
|
78117
|
+
role: "admin"
|
|
78118
|
+
},
|
|
78119
|
+
"integrationInstances.deleteInstance": {
|
|
78120
|
+
capName: "integration-instances",
|
|
78121
|
+
capScope: "system",
|
|
78122
|
+
addonId: null,
|
|
78123
|
+
access: "delete",
|
|
78124
|
+
role: "admin"
|
|
78125
|
+
},
|
|
78126
|
+
"integrationInstances.describe": {
|
|
78127
|
+
capName: "integration-instances",
|
|
78128
|
+
capScope: "system",
|
|
78129
|
+
addonId: null,
|
|
78130
|
+
access: "view",
|
|
78131
|
+
role: "admin"
|
|
78132
|
+
},
|
|
78133
|
+
"integrationInstances.getInstance": {
|
|
78134
|
+
capName: "integration-instances",
|
|
78135
|
+
capScope: "system",
|
|
78136
|
+
addonId: null,
|
|
78137
|
+
access: "view",
|
|
78138
|
+
role: "admin"
|
|
78139
|
+
},
|
|
78140
|
+
"integrationInstances.instanceFormSchema": {
|
|
78141
|
+
capName: "integration-instances",
|
|
78142
|
+
capScope: "system",
|
|
78143
|
+
addonId: null,
|
|
78144
|
+
access: "view",
|
|
78145
|
+
role: "admin"
|
|
78146
|
+
},
|
|
78147
|
+
"integrationInstances.listInstances": {
|
|
78148
|
+
capName: "integration-instances",
|
|
78149
|
+
capScope: "system",
|
|
78150
|
+
addonId: null,
|
|
78151
|
+
access: "view",
|
|
78152
|
+
role: "admin"
|
|
78153
|
+
},
|
|
78154
|
+
"integrationInstances.testInstance": {
|
|
78155
|
+
capName: "integration-instances",
|
|
78156
|
+
capScope: "system",
|
|
78157
|
+
addonId: null,
|
|
78158
|
+
access: "create",
|
|
78159
|
+
role: "admin"
|
|
78160
|
+
},
|
|
78161
|
+
"integrationInstances.updateInstance": {
|
|
78162
|
+
capName: "integration-instances",
|
|
78163
|
+
capScope: "system",
|
|
78164
|
+
addonId: null,
|
|
78165
|
+
access: "create",
|
|
78166
|
+
role: "admin"
|
|
78167
|
+
},
|
|
77979
78168
|
"integrations.create": {
|
|
77980
78169
|
capName: "integrations",
|
|
77981
78170
|
capScope: "system",
|
|
@@ -89281,7 +89470,7 @@ var AgentUIAddon = class extends BaseAddon {
|
|
|
89281
89470
|
capability: adminUiCapability,
|
|
89282
89471
|
provider: {
|
|
89283
89472
|
getStaticDir: async () => ({ staticDir: path.resolve(__dirname) }),
|
|
89284
|
-
getVersion: async () => ({ version: "1.2.
|
|
89473
|
+
getVersion: async () => ({ version: "1.2.315" })
|
|
89285
89474
|
}
|
|
89286
89475
|
}];
|
|
89287
89476
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{a as e,i as t,l as n,n as r,o as i}from"./scheduler-0XZJE03d.js";import{c as a,d as o,g as s,l as c,p as l,t as u,w as d}from"./index-
|
|
1
|
+
import{a as e,i as t,l as n,n as r,o as i}from"./scheduler-0XZJE03d.js";import{c as a,d as o,g as s,l as c,p as l,t as u,w as d}from"./index-MaQ1EcJ3.js";import{MaskShapeCanvas as f}from"./MaskShapeCanvas-BTvl6Rin.js";var p=d(`grid-2x2`,[[`path`,{d:`M12 3v18`,key:`108xh3`}],[`path`,{d:`M3 12h18`,key:`1i2n21`}],[`rect`,{x:`3`,y:`3`,width:`18`,height:`18`,rx:`2`,key:`h1oib`}]]),m=n(i(),1),h=n(e(),1),g=110,_=`motion-zones`,v=0,y=[1,2,3],b=1,x=`rounded-md border border-border bg-surface px-2 py-1 text-[11px] font-medium text-foreground-subtle hover:bg-surface-hover disabled:opacity-40 transition-colors`,S=`rounded-md border border-primary/50 bg-primary/15 px-2.5 py-1 text-[11px] font-medium text-primary hover:bg-primary/25 disabled:opacity-40 transition-colors`;function C(e,t,n){let r=t*n,i=Array.from({length:r});for(let t=0;t<r;t+=1)i[t]=e[t]===!0;return i}function w(e,t){if(e.length!==t.length)return!1;for(let n=0;n<e.length;n+=1)if(e[n]!==t[n])return!1;return!0}function T(e,t){return Math.ceil(e/t)}function E(e,t,n){return Math.min(n-1,Math.floor((e+.5)/t*n))}function D(e,t,n,r){let i=T(t,r),a=T(n,r),o=Array.from({length:i*a},()=>!1);for(let r=0;r<n;r+=1){let s=E(r,n,a);for(let n=0;n<t;n+=1)e[r*t+n]===!0&&(o[s*i+E(n,t,i)]=!0)}return o}function O(e,t,n,r){let i=T(t,r),a=T(n,r),o=Array.from({length:t*n},()=>!1);for(let r=0;r<n;r+=1){let s=E(r,n,a);for(let n=0;n<t;n+=1)o[r*t+n]=e[s*i+E(n,t,i)]===!0}return o}function k({deviceId:e}){let n=t(),i=o(s().trpcClient,e),[d,E]=(0,m.useState)(null),[k,A]=(0,m.useState)(!1),[j,M]=(0,m.useState)(null),[N,P]=(0,m.useState)(null),[F,I]=(0,m.useState)(b),[L,R]=(0,m.useState)(!1),[z,B]=(0,m.useState)(!1),V=(0,m.useRef)(!1);(0,m.useEffect)(()=>{if(!i)return;let e=!1;return V.current=!1,E(null),A(!1),M(null),P(null),I(b),B(!1),(async()=>{try{let t=await i.motionZones?.getOptions({});if(e)return;if(!t)throw Error(`device proxy not ready`);if(E(t),V.current)return;let n=await i.motionZones?.getStatus({});if(e)return;if(!n)throw Error(`device proxy not ready`);V.current=!0;let r=n.regions.find(e=>e.shape.kind===`grid`),a=C(r?r.shape.cells:[],t.grid.width,t.grid.height);P(a),M(D(a,t.grid.width,t.grid.height,b))}catch(t){if(e)return;c(t)?A(!0):console.error(`Motion Zones load failed`,t)}})(),()=>{e=!0}},[i]);let H=d?d.grid.width:0,U=d?d.grid.height:0,W=T(H,F),G=T(U,F),K=(0,m.useMemo)(()=>j&&d?O(j,H,U,F):null,[j,d,H,U,F]),q=(0,m.useMemo)(()=>K!==null&&N!==null&&!w(K,N),[K,N]),J=(0,m.useMemo)(()=>K?K.reduce((e,t)=>t?e+1:e,0):0,[K]),Y=H*U,X=W*G,Z=(0,m.useCallback)(e=>{X>0&&M(Array.from({length:X},()=>e))},[X]),ee=(0,m.useCallback)(()=>{M(e=>e&&e.map(e=>!e))},[]),te=(0,m.useCallback)(()=>{N&&d&&M(D(N,H,U,F))},[N,d,H,U,F]),ne=(0,m.useCallback)(e=>{e===F||!d||M(t=>{if(!t)return I(e),t;let n=D(O(t,H,U,F),H,U,e);return I(e),n})},[F,d,H,U]),Q=(0,m.useMemo)(()=>d&&j?[{id:v,shape:{kind:`grid`,gridWidth:W,gridHeight:G,cells:[...j]}}]:[],[d,j,W,G]),$=(0,m.useCallback)((e,t)=>{t.kind===`grid`&&M(t.cells)},[]),re=(0,m.useCallback)(async()=>{if(!(!i||!j||!d)){R(!0);try{let e=O(j,d.grid.width,d.grid.height,F),t={kind:`grid`,gridWidth:d.grid.width,gridHeight:d.grid.height,cells:e};await i.motionZones?.setZone({patch:{regions:[{id:v,enabled:!0,shape:t}]}});let n=await i.motionZones?.getStatus({});if(n){let e=n.regions.find(e=>e.shape.kind===`grid`),t=C(e?e.shape.cells:[],d.grid.width,d.grid.height);P(t),M(D(t,d.grid.width,d.grid.height,F))}}catch(e){console.error(`Motion Zones save failed`,e)}finally{R(!1)}}},[i,j,d,F]);u((0,m.useMemo)(()=>z&&!k&&d&&j?{id:_,order:g,node:(0,h.jsx)(f,{transparent:!0,items:Q,supportedShapes:[`grid`],grid:{width:W,height:G},selectedId:v,onSelect:()=>{},onShapeChange:$,onDrawComplete:()=>{},drawingKind:null})}:null,[z,k,d,j,Q,$,W,G]));let ie=!k&&d!==null&&j!==null;return i?(0,h.jsx)(l,{title:n(`uiLibrary.motionZones.title`,`Motion Zones`),icon:(0,h.jsx)(p,{className:`h-3.5 w-3.5 text-foreground-subtle`}),children:(0,h.jsx)(`div`,{className:`flex flex-col gap-3`,children:k?(0,h.jsx)(`p`,{className:`${a} leading-relaxed`,children:n(`uiLibrary.motionZones.unsupported`,`This camera doesn't expose an on-board motion zones grid.`)}):ie?(0,h.jsxs)(h.Fragment,{children:[(0,h.jsx)(`p`,{className:`${a} leading-relaxed`,children:(0,h.jsx)(r,{uiKey:`uiLibrary.motionZones.intro`,fallback:`Toggle <0>Edit grid</0> to paint the region directly on the live frame, then <1>Save</1> to push the mask to the camera. Pick a bigger <2>Cell size</2> for quicker, broad-stroke painting — it's resampled to the camera's native {{width}}×{{height}} grid on save (×1 is the finest).`,components:[(0,h.jsx)(`strong`,{className:`text-foreground`},`e`),(0,h.jsx)(`strong`,{className:`text-foreground`},`s`),(0,h.jsx)(`strong`,{className:`text-foreground`},`c`)],values:{width:d.grid.width,height:d.grid.height}})}),(0,h.jsxs)(`div`,{className:`flex items-center gap-2 flex-wrap`,children:[(0,h.jsx)(`button`,{type:`button`,onClick:()=>B(e=>!e),disabled:L,"aria-pressed":z,className:z?S:x,children:z?n(`uiLibrary.motionZones.doneEditing`,`Done editing`):n(`uiLibrary.motionZones.editGrid`,`Edit grid`)}),(0,h.jsx)(`button`,{type:`button`,onClick:()=>Z(!0),disabled:L,className:x,children:n(`uiLibrary.motionZones.allOn`,`All on`)}),(0,h.jsx)(`button`,{type:`button`,onClick:()=>Z(!1),disabled:L,className:x,children:n(`uiLibrary.motionZones.allOff`,`All off`)}),(0,h.jsx)(`button`,{type:`button`,onClick:ee,disabled:L,className:x,children:n(`uiLibrary.motionZones.invert`,`Invert`)}),(0,h.jsxs)(`div`,{className:`flex items-center gap-1 ml-1`,role:`group`,"aria-label":n(`uiLibrary.motionZones.cellSize`,`Cell size`),children:[(0,h.jsx)(`span`,{className:`${a} mr-0.5`,children:n(`uiLibrary.motionZones.cellSize`,`Cell size`)}),y.map(e=>(0,h.jsxs)(`button`,{type:`button`,onClick:()=>ne(e),disabled:L,"aria-pressed":F===e,title:e===1?n(`uiLibrary.motionZones.cameraGrid`,`Camera grid {{width}}×{{height}} (finest)`,{width:H,height:U}):n(`uiLibrary.motionZones.paintingGrid`,`{{width}}×{{height}} painting grid · cells ×{{factor}} bigger`,{width:T(H,e),height:T(U,e),factor:e}),className:F===e?S:x,children:[`×`,e]},e))]}),(0,h.jsxs)(`span`,{className:`${a} ml-1 tabular-nums`,children:[n(`uiLibrary.motionZones.cells`,`{{active}} / {{total}} cells · {{width}}×{{height}}`,{active:J,total:Y,width:d.grid.width,height:d.grid.height}),F===1?``:n(`uiLibrary.motionZones.paintSuffix`,` · paint {{width}}×{{height}}`,{width:W,height:G})]}),(0,h.jsx)(`span`,{className:`flex-1`}),(0,h.jsx)(`button`,{type:`button`,onClick:te,disabled:L||!q,className:`rounded-md border border-border bg-surface px-2 py-1 text-[11px] text-foreground-subtle hover:bg-surface-hover disabled:opacity-40 transition-colors`,children:n(`uiLibrary.motionZones.revert`,`Revert`)}),(0,h.jsx)(`button`,{type:`button`,onClick:()=>void re(),disabled:L||!q,className:S,children:L?n(`uiLibrary.motionZones.saving`,`Saving…`):n(`uiLibrary.motionZones.save`,`Save`)})]})]}):(0,h.jsx)(`p`,{className:`${a} leading-relaxed`,children:n(`uiLibrary.motionZones.loading`,`Loading the camera's grid…`)})})}):null}export{k as MotionZonesSettings};
|