@camstack/ui-library 1.2.332 → 1.2.334
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-DR1g9ja3.js → MotionZonesSettings-BCU2NW7w.js} +1 -1
- package/dist/{PrivacyMaskSettings-C9wfHkiB.js → PrivacyMaskSettings-VntwpB1u.js} +1 -1
- package/dist/{SceneMonitorEditor-CrxB3ZPL.js → SceneMonitorEditor-5N2xqurW.js} +1 -1
- package/dist/composites/device-item/header.d.ts +7 -1
- package/dist/composites/device-name/DeviceName.d.ts +17 -0
- package/dist/composites/device-name/device-fleet.d.ts +29 -0
- package/dist/composites/device-name/device-name-nouns.d.ts +27 -0
- package/dist/composites/device-name/format-device-name.d.ts +46 -0
- package/dist/composites/device-name/index.d.ts +10 -0
- package/dist/composites/device-name/use-device-label.d.ts +16 -0
- package/dist/composites/index.d.ts +1 -0
- package/dist/generated/system-hooks.d.ts +2 -0
- package/dist/{icons-aFMzvquu.js → icons-Bd6sbDsv.js} +1 -35
- package/dist/{icons-pqV1UOV_.cjs → icons-CWmwnulO.cjs} +1 -35
- package/dist/index.cjs +1362 -67
- package/dist/index.js +1346 -73
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -40,6 +40,7 @@ let react_dom_client = require("react-dom/client");
|
|
|
40
40
|
react_dom_client = __toESM(react_dom_client, 1);
|
|
41
41
|
let _trpc_client = require("@trpc/client");
|
|
42
42
|
_trpc_client = __toESM(_trpc_client, 1);
|
|
43
|
+
let _camstack_types_client = require("@camstack/types/client");
|
|
43
44
|
let _camstack_sdk = require("@camstack/sdk");
|
|
44
45
|
let zod = require("zod");
|
|
45
46
|
//#region src/contexts/ui-text.tsx
|
|
@@ -4706,6 +4707,40 @@ var VolumeX = require_createLucideIcon.createLucideIcon("volume-x", [
|
|
|
4706
4707
|
* This source code is licensed under the ISC license.
|
|
4707
4708
|
* See the LICENSE file in the root directory of this source tree.
|
|
4708
4709
|
*/
|
|
4710
|
+
var WashingMachine = require_createLucideIcon.createLucideIcon("washing-machine", [
|
|
4711
|
+
["path", {
|
|
4712
|
+
d: "M3 6h3",
|
|
4713
|
+
key: "155dbl"
|
|
4714
|
+
}],
|
|
4715
|
+
["path", {
|
|
4716
|
+
d: "M17 6h.01",
|
|
4717
|
+
key: "e2y6kg"
|
|
4718
|
+
}],
|
|
4719
|
+
["rect", {
|
|
4720
|
+
width: "18",
|
|
4721
|
+
height: "20",
|
|
4722
|
+
x: "3",
|
|
4723
|
+
y: "2",
|
|
4724
|
+
rx: "2",
|
|
4725
|
+
key: "od3kk9"
|
|
4726
|
+
}],
|
|
4727
|
+
["circle", {
|
|
4728
|
+
cx: "12",
|
|
4729
|
+
cy: "13",
|
|
4730
|
+
r: "5",
|
|
4731
|
+
key: "nlbqau"
|
|
4732
|
+
}],
|
|
4733
|
+
["path", {
|
|
4734
|
+
d: "M12 18a2.5 2.5 0 0 0 0-5 2.5 2.5 0 0 1 0-5",
|
|
4735
|
+
key: "17lach"
|
|
4736
|
+
}]
|
|
4737
|
+
]);
|
|
4738
|
+
/**
|
|
4739
|
+
* @license lucide-react v0.576.0 - ISC
|
|
4740
|
+
*
|
|
4741
|
+
* This source code is licensed under the ISC license.
|
|
4742
|
+
* See the LICENSE file in the root directory of this source tree.
|
|
4743
|
+
*/
|
|
4709
4744
|
var Waves = require_createLucideIcon.createLucideIcon("waves", [
|
|
4710
4745
|
["path", {
|
|
4711
4746
|
d: "M2 6c.6.5 1.2 1 2.5 1C7 7 7 5 9.5 5c2.6 0 2.4 2 5 2 2.5 0 2.5-2 5-2 1.3 0 1.9.5 2.5 1",
|
|
@@ -5369,6 +5404,16 @@ var DEVICE_TYPE_META = {
|
|
|
5369
5404
|
icon: Waves,
|
|
5370
5405
|
labelKey: "uiLibrary.deviceMeta.type.dishwasher",
|
|
5371
5406
|
labelFallback: "Dishwasher"
|
|
5407
|
+
},
|
|
5408
|
+
[_camstack_types.DeviceType.Washer]: {
|
|
5409
|
+
icon: WashingMachine,
|
|
5410
|
+
labelKey: "uiLibrary.deviceMeta.type.washer",
|
|
5411
|
+
labelFallback: "Washing machine"
|
|
5412
|
+
},
|
|
5413
|
+
[_camstack_types.DeviceType.Dryer]: {
|
|
5414
|
+
icon: Wind,
|
|
5415
|
+
labelKey: "uiLibrary.deviceMeta.type.dryer",
|
|
5416
|
+
labelFallback: "Dryer"
|
|
5372
5417
|
}
|
|
5373
5418
|
};
|
|
5374
5419
|
var DEVICE_ROLE_META = {
|
|
@@ -5850,7 +5895,7 @@ function lucideExportName(key) {
|
|
|
5850
5895
|
function loadIconGlyphs() {
|
|
5851
5896
|
if (fullTable !== void 0) return Promise.resolve();
|
|
5852
5897
|
if (failure$1 !== void 0) return Promise.reject(failure$1);
|
|
5853
|
-
pending ??= Promise.resolve().then(() => require("./icons-
|
|
5898
|
+
pending ??= Promise.resolve().then(() => require("./icons-CWmwnulO.cjs")).then((module) => {
|
|
5854
5899
|
fullTable = module;
|
|
5855
5900
|
publish();
|
|
5856
5901
|
}, (error) => {
|
|
@@ -11349,6 +11394,8 @@ var useMeshNetworkLogout = trpc.meshNetwork.logout.useMutation;
|
|
|
11349
11394
|
var useMeshNetworkListPeers = trpc.meshNetwork.listPeers.useQuery;
|
|
11350
11395
|
/** Generated alias around `trpc.meshNetwork.testConnection.useMutation`. */
|
|
11351
11396
|
var useMeshNetworkTestConnection = trpc.meshNetwork.testConnection.useMutation;
|
|
11397
|
+
/** Generated alias around `trpc.meter.getStatus.useQuery`. */
|
|
11398
|
+
var useMeterGetStatus = trpc.meter.getStatus.useQuery;
|
|
11352
11399
|
/** Generated alias around `trpc.metricsProvider.collectSnapshot.useQuery`. */
|
|
11353
11400
|
var useMetricsProviderCollectSnapshot = trpc.metricsProvider.collectSnapshot.useQuery;
|
|
11354
11401
|
/** Generated alias around `trpc.metricsProvider.getCached.useQuery`. */
|
|
@@ -19627,6 +19674,1151 @@ function AutotrackSection({ deviceId }) {
|
|
|
19627
19674
|
});
|
|
19628
19675
|
}
|
|
19629
19676
|
//#endregion
|
|
19677
|
+
//#region src/composites/device-name/device-fleet.tsx
|
|
19678
|
+
/**
|
|
19679
|
+
* One slim fleet, shared. A row reads its parent from this index — never a
|
|
19680
|
+
* `getDevice` per row (the Customize bounded-read rule). `null` is "not
|
|
19681
|
+
* answered yet": a label then keeps the stored name, so a list does not flash
|
|
19682
|
+
* `#id` while the fleet is in flight. An empty array is an answer.
|
|
19683
|
+
*/
|
|
19684
|
+
var DeviceNameIndexContext = (0, react$1.createContext)(null);
|
|
19685
|
+
function useDeviceNameIndex() {
|
|
19686
|
+
return (0, react$1.useContext)(DeviceNameIndexContext);
|
|
19687
|
+
}
|
|
19688
|
+
function copyDevice(device) {
|
|
19689
|
+
const label = device.display?.label;
|
|
19690
|
+
const trimmed = label === void 0 || label === null ? "" : label.trim();
|
|
19691
|
+
return {
|
|
19692
|
+
id: device.id,
|
|
19693
|
+
name: device.name,
|
|
19694
|
+
type: device.type,
|
|
19695
|
+
stableId: device.stableId,
|
|
19696
|
+
role: device.role ?? null,
|
|
19697
|
+
parentDeviceId: device.parentDeviceId ?? null,
|
|
19698
|
+
location: device.location ?? null,
|
|
19699
|
+
...trimmed.length > 0 ? { display: { label: trimmed } } : {},
|
|
19700
|
+
...device.primaryChildEntityId !== void 0 ? { primaryChildEntityId: device.primaryChildEntityId } : {},
|
|
19701
|
+
...device.userNamed === void 0 ? {} : { userNamed: device.userNamed }
|
|
19702
|
+
};
|
|
19703
|
+
}
|
|
19704
|
+
/** Build the parent/child maps once per fleet answer. */
|
|
19705
|
+
function indexDeviceNames(devices) {
|
|
19706
|
+
const byId = /* @__PURE__ */ new Map();
|
|
19707
|
+
const children = /* @__PURE__ */ new Map();
|
|
19708
|
+
for (const device of devices) {
|
|
19709
|
+
const fields = copyDevice(device);
|
|
19710
|
+
byId.set(fields.id, fields);
|
|
19711
|
+
const parentId = fields.parentDeviceId;
|
|
19712
|
+
if (parentId === null || parentId === void 0 || parentId === fields.id) continue;
|
|
19713
|
+
const list = children.get(parentId);
|
|
19714
|
+
if (list === void 0) children.set(parentId, [fields.id]);
|
|
19715
|
+
else list.push(fields.id);
|
|
19716
|
+
}
|
|
19717
|
+
return {
|
|
19718
|
+
byId,
|
|
19719
|
+
childIds: children
|
|
19720
|
+
};
|
|
19721
|
+
}
|
|
19722
|
+
function DeviceFleetProvider({ devices, children }) {
|
|
19723
|
+
const index = (0, react$1.useMemo)(() => devices === null ? null : indexDeviceNames(devices), [devices]);
|
|
19724
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(DeviceNameIndexContext.Provider, {
|
|
19725
|
+
value: index,
|
|
19726
|
+
children
|
|
19727
|
+
});
|
|
19728
|
+
}
|
|
19729
|
+
/**
|
|
19730
|
+
* The one `deviceManager.listAll` subscriber for names. Same query key the
|
|
19731
|
+
* pickers already use, so a second observer does not fetch a second fleet.
|
|
19732
|
+
*/
|
|
19733
|
+
function DeviceFleetFromServer({ children }) {
|
|
19734
|
+
const query = useDeviceManagerListAll({ projection: "slim" });
|
|
19735
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(DeviceFleetProvider, {
|
|
19736
|
+
devices: query.data === void 0 ? null : query.data,
|
|
19737
|
+
children
|
|
19738
|
+
});
|
|
19739
|
+
}
|
|
19740
|
+
//#endregion
|
|
19741
|
+
//#region src/composites/device-name/format-device-name.ts
|
|
19742
|
+
/**
|
|
19743
|
+
* One display name for a device.
|
|
19744
|
+
*
|
|
19745
|
+
* Canonical copy: `packages/ui-library/src/composites/device-name/format-device-name.ts`.
|
|
19746
|
+
* The viewer mirrors this file; `scripts/check-device-name-in-sync.ts` diffs the two.
|
|
19747
|
+
* Noun strings stay outside — this file only decides which noun to ask for.
|
|
19748
|
+
*/
|
|
19749
|
+
/** Middle dot used between a container and its noun, and before a room. */
|
|
19750
|
+
var DEVICE_NAME_JOIN = " · ";
|
|
19751
|
+
var DEVICE_NAME_FORMS = [
|
|
19752
|
+
"compact",
|
|
19753
|
+
"full",
|
|
19754
|
+
"nested",
|
|
19755
|
+
"with-location"
|
|
19756
|
+
];
|
|
19757
|
+
var PARENT_SEPARATORS = [" — ", " "];
|
|
19758
|
+
/**
|
|
19759
|
+
* Readings that are never what a container is. Matches the comment on
|
|
19760
|
+
* `CONTAINER_CHILD_ROLE_PRIORITY`: battery, temperature, humidity, illuminance,
|
|
19761
|
+
* signal, last-seen, plus numeric and enum. `update` is the same kind of row.
|
|
19762
|
+
*/
|
|
19763
|
+
var DIAGNOSTIC_ROLES = new Set([
|
|
19764
|
+
"battery-sensor",
|
|
19765
|
+
"temperature-sensor",
|
|
19766
|
+
"humidity-sensor",
|
|
19767
|
+
"ambient-light-sensor",
|
|
19768
|
+
"connectivity-sensor",
|
|
19769
|
+
"datetime-sensor",
|
|
19770
|
+
"numeric-sensor",
|
|
19771
|
+
"enum-sensor"
|
|
19772
|
+
]);
|
|
19773
|
+
/** Hyphen, underscore and whitespace fold together — the namesake comparison. */
|
|
19774
|
+
function foldDeviceName(value) {
|
|
19775
|
+
return value.toLowerCase().replace(/[-_\s]+/g, " ").trim();
|
|
19776
|
+
}
|
|
19777
|
+
function sameDeviceName(left, right) {
|
|
19778
|
+
return foldDeviceName(left) === foldDeviceName(right);
|
|
19779
|
+
}
|
|
19780
|
+
/**
|
|
19781
|
+
* Drop a parent prefix. `" — "` before a space, case-insensitive, so a provider
|
|
19782
|
+
* that capitalised the parent differently still strips, and an em-dash child
|
|
19783
|
+
* does not keep a dangling dash.
|
|
19784
|
+
*/
|
|
19785
|
+
function stripDeviceParentPrefix(name, parentName) {
|
|
19786
|
+
if (parentName.length === 0) return name;
|
|
19787
|
+
const nameFold = name.toLowerCase();
|
|
19788
|
+
const parentFold = parentName.toLowerCase();
|
|
19789
|
+
for (const separator of PARENT_SEPARATORS) {
|
|
19790
|
+
const prefix = `${parentFold}${separator}`;
|
|
19791
|
+
if (!nameFold.startsWith(prefix)) continue;
|
|
19792
|
+
return name.slice(prefix.length).trim();
|
|
19793
|
+
}
|
|
19794
|
+
return name;
|
|
19795
|
+
}
|
|
19796
|
+
function roleOf(device) {
|
|
19797
|
+
const role = device.role;
|
|
19798
|
+
if (role === void 0 || role === null || role.length === 0) return null;
|
|
19799
|
+
return role;
|
|
19800
|
+
}
|
|
19801
|
+
function isDiagnostic(device) {
|
|
19802
|
+
if (device.type === "update") return true;
|
|
19803
|
+
const role = roleOf(device);
|
|
19804
|
+
return role !== null && DIAGNOSTIC_ROLES.has(role);
|
|
19805
|
+
}
|
|
19806
|
+
function displayLabel(device) {
|
|
19807
|
+
const label = device.display?.label;
|
|
19808
|
+
if (label === void 0 || label === null) return "";
|
|
19809
|
+
return label.trim();
|
|
19810
|
+
}
|
|
19811
|
+
function nounOf(device, parent, nouns) {
|
|
19812
|
+
const caption = displayLabel(device);
|
|
19813
|
+
if (caption.length > 0) return caption;
|
|
19814
|
+
const stripped = stripDeviceParentPrefix(device.name, parent.name);
|
|
19815
|
+
const shown = stripped.length > 0 ? stripped : device.name;
|
|
19816
|
+
if (device.userNamed === true) return shown;
|
|
19817
|
+
if (stripped.length === 0 || sameDeviceName(stripped, parent.name) || nouns.isStockPhrase(shown, roleOf(device), device.type)) return nouns.shortNoun(roleOf(device), device.type);
|
|
19818
|
+
return shown;
|
|
19819
|
+
}
|
|
19820
|
+
function foldsIntoParent(device, parent, noun) {
|
|
19821
|
+
if (sameDeviceName(noun, parent.name)) return true;
|
|
19822
|
+
if (displayLabel(device).length > 0 || device.userNamed === true) return false;
|
|
19823
|
+
return sameDeviceName(stripDeviceParentPrefix(device.name, parent.name), parent.name);
|
|
19824
|
+
}
|
|
19825
|
+
function meaningfulChildCount(siblings) {
|
|
19826
|
+
let count = 0;
|
|
19827
|
+
for (const sibling of siblings) if (!isDiagnostic(sibling)) count += 1;
|
|
19828
|
+
return count;
|
|
19829
|
+
}
|
|
19830
|
+
function isContainerPrimary(device, parent, siblings) {
|
|
19831
|
+
const picked = (0, _camstack_types_client.resolveContainerPrimaryChild)(siblings.map((sibling) => {
|
|
19832
|
+
const role = roleOf(sibling);
|
|
19833
|
+
return {
|
|
19834
|
+
id: sibling.id,
|
|
19835
|
+
stableId: sibling.stableId,
|
|
19836
|
+
type: sibling.type,
|
|
19837
|
+
name: sibling.name,
|
|
19838
|
+
...role === null ? {} : { role }
|
|
19839
|
+
};
|
|
19840
|
+
}), parent.primaryChildEntityId, parent.name);
|
|
19841
|
+
return picked !== null && picked.id === device.id;
|
|
19842
|
+
}
|
|
19843
|
+
function childLine(device, parent, siblings, nouns, form) {
|
|
19844
|
+
const noun = nounOf(device, parent, nouns);
|
|
19845
|
+
if (foldsIntoParent(device, parent, noun)) return parent.name;
|
|
19846
|
+
if (form === "compact" && parent.type === "container" && isContainerPrimary(device, parent, siblings) && meaningfulChildCount(siblings) === 1) return parent.name;
|
|
19847
|
+
return `${parent.name}${DEVICE_NAME_JOIN}${noun}`;
|
|
19848
|
+
}
|
|
19849
|
+
function joinLocation(label, location) {
|
|
19850
|
+
if (location === void 0 || location === null) return label;
|
|
19851
|
+
const room = location.trim();
|
|
19852
|
+
if (room.length === 0) return label;
|
|
19853
|
+
if (label.split(" · ").some((segment) => sameDeviceName(segment, room))) return label;
|
|
19854
|
+
return `${label}${DEVICE_NAME_JOIN}${room}`;
|
|
19855
|
+
}
|
|
19856
|
+
function hasParent(device, parent) {
|
|
19857
|
+
if (parent === null) return false;
|
|
19858
|
+
const parentId = device.parentDeviceId;
|
|
19859
|
+
return parentId !== null && parentId !== void 0;
|
|
19860
|
+
}
|
|
19861
|
+
/**
|
|
19862
|
+
* The label for `form`. A top-level device keeps its stored name. A child uses
|
|
19863
|
+
* the noun: `compact` may stand in for the container when this child is what
|
|
19864
|
+
* the container is, `full` always names both unless they fold together,
|
|
19865
|
+
* `nested` is the noun alone, `with-location` is `compact` plus the room.
|
|
19866
|
+
*/
|
|
19867
|
+
function formatDeviceName(device, form, context, nouns) {
|
|
19868
|
+
if (!hasParent(device, context.parent)) return form === "with-location" ? joinLocation(device.name, device.location) : device.name;
|
|
19869
|
+
if (form === "nested") return nounOf(device, context.parent, nouns);
|
|
19870
|
+
const line = childLine(device, context.parent, context.siblings, nouns, form === "full" ? "full" : "compact");
|
|
19871
|
+
return form === "with-location" ? joinLocation(line, device.location) : line;
|
|
19872
|
+
}
|
|
19873
|
+
//#endregion
|
|
19874
|
+
//#region src/composites/device-name/device-name-nouns.ts
|
|
19875
|
+
/**
|
|
19876
|
+
* Short nouns and the stock words they replace.
|
|
19877
|
+
*
|
|
19878
|
+
* Long labels are the existing role and type names, both locales, so a stored
|
|
19879
|
+
* "Motion sensor" and a stored "Sensore di movimento" are the same stock word.
|
|
19880
|
+
* The short noun is what a list shows. Where the long label is already one
|
|
19881
|
+
* word it is the short noun. Aliases are provider stock words that are not the
|
|
19882
|
+
* label ("Illumination", "Last seen").
|
|
19883
|
+
*/
|
|
19884
|
+
var DEVICE_ROLE_NOUNS = [
|
|
19885
|
+
{
|
|
19886
|
+
id: "siren",
|
|
19887
|
+
key: "uiLibrary.deviceMeta.noun.role.siren",
|
|
19888
|
+
en: "Siren",
|
|
19889
|
+
it: "Sirena",
|
|
19890
|
+
shortEn: "Siren",
|
|
19891
|
+
shortIt: "Sirena",
|
|
19892
|
+
aliases: []
|
|
19893
|
+
},
|
|
19894
|
+
{
|
|
19895
|
+
id: "floodlight",
|
|
19896
|
+
key: "uiLibrary.deviceMeta.noun.role.floodlight",
|
|
19897
|
+
en: "Floodlight",
|
|
19898
|
+
it: "Faro",
|
|
19899
|
+
shortEn: "Floodlight",
|
|
19900
|
+
shortIt: "Faro",
|
|
19901
|
+
aliases: []
|
|
19902
|
+
},
|
|
19903
|
+
{
|
|
19904
|
+
id: "spotlight",
|
|
19905
|
+
key: "uiLibrary.deviceMeta.noun.role.spotlight",
|
|
19906
|
+
en: "Spotlight",
|
|
19907
|
+
it: "Faretto",
|
|
19908
|
+
shortEn: "Spotlight",
|
|
19909
|
+
shortIt: "Faretto",
|
|
19910
|
+
aliases: []
|
|
19911
|
+
},
|
|
19912
|
+
{
|
|
19913
|
+
id: "pir-sensor",
|
|
19914
|
+
key: "uiLibrary.deviceMeta.noun.role.pirSensor",
|
|
19915
|
+
en: "PIR sensor",
|
|
19916
|
+
it: "Sensore PIR",
|
|
19917
|
+
shortEn: "PIR",
|
|
19918
|
+
shortIt: "PIR",
|
|
19919
|
+
aliases: []
|
|
19920
|
+
},
|
|
19921
|
+
{
|
|
19922
|
+
id: "chime",
|
|
19923
|
+
key: "uiLibrary.deviceMeta.noun.role.chime",
|
|
19924
|
+
en: "Chime",
|
|
19925
|
+
it: "Campanello",
|
|
19926
|
+
shortEn: "Chime",
|
|
19927
|
+
shortIt: "Campanello",
|
|
19928
|
+
aliases: []
|
|
19929
|
+
},
|
|
19930
|
+
{
|
|
19931
|
+
id: "autotrack",
|
|
19932
|
+
key: "uiLibrary.deviceMeta.noun.role.autotrack",
|
|
19933
|
+
en: "Auto-track",
|
|
19934
|
+
it: "Auto-tracking",
|
|
19935
|
+
shortEn: "Auto-track",
|
|
19936
|
+
shortIt: "Auto-tracking",
|
|
19937
|
+
aliases: []
|
|
19938
|
+
},
|
|
19939
|
+
{
|
|
19940
|
+
id: "nightvision",
|
|
19941
|
+
key: "uiLibrary.deviceMeta.noun.role.nightvision",
|
|
19942
|
+
en: "Night vision",
|
|
19943
|
+
it: "Visione notturna",
|
|
19944
|
+
shortEn: "Night",
|
|
19945
|
+
shortIt: "Notturna",
|
|
19946
|
+
aliases: []
|
|
19947
|
+
},
|
|
19948
|
+
{
|
|
19949
|
+
id: "privacy-mask",
|
|
19950
|
+
key: "uiLibrary.deviceMeta.noun.role.privacyMask",
|
|
19951
|
+
en: "Privacy mask",
|
|
19952
|
+
it: "Maschera privacy",
|
|
19953
|
+
shortEn: "Privacy",
|
|
19954
|
+
shortIt: "Privacy",
|
|
19955
|
+
aliases: []
|
|
19956
|
+
},
|
|
19957
|
+
{
|
|
19958
|
+
id: "doorbell",
|
|
19959
|
+
key: "uiLibrary.deviceMeta.noun.role.doorbell",
|
|
19960
|
+
en: "Doorbell",
|
|
19961
|
+
it: "Campanello video",
|
|
19962
|
+
shortEn: "Doorbell",
|
|
19963
|
+
shortIt: "Campanello video",
|
|
19964
|
+
aliases: []
|
|
19965
|
+
},
|
|
19966
|
+
{
|
|
19967
|
+
id: "cover-blind",
|
|
19968
|
+
key: "uiLibrary.deviceMeta.noun.role.coverBlind",
|
|
19969
|
+
en: "Blind",
|
|
19970
|
+
it: "Tapparella",
|
|
19971
|
+
shortEn: "Blind",
|
|
19972
|
+
shortIt: "Tapparella",
|
|
19973
|
+
aliases: []
|
|
19974
|
+
},
|
|
19975
|
+
{
|
|
19976
|
+
id: "cover-shutter",
|
|
19977
|
+
key: "uiLibrary.deviceMeta.noun.role.coverShutter",
|
|
19978
|
+
en: "Shutter",
|
|
19979
|
+
it: "Persiana",
|
|
19980
|
+
shortEn: "Shutter",
|
|
19981
|
+
shortIt: "Persiana",
|
|
19982
|
+
aliases: []
|
|
19983
|
+
},
|
|
19984
|
+
{
|
|
19985
|
+
id: "cover-awning",
|
|
19986
|
+
key: "uiLibrary.deviceMeta.noun.role.coverAwning",
|
|
19987
|
+
en: "Awning",
|
|
19988
|
+
it: "Tenda da sole",
|
|
19989
|
+
shortEn: "Awning",
|
|
19990
|
+
shortIt: "Tenda da sole",
|
|
19991
|
+
aliases: []
|
|
19992
|
+
},
|
|
19993
|
+
{
|
|
19994
|
+
id: "cover-curtain",
|
|
19995
|
+
key: "uiLibrary.deviceMeta.noun.role.coverCurtain",
|
|
19996
|
+
en: "Curtain",
|
|
19997
|
+
it: "Tenda",
|
|
19998
|
+
shortEn: "Curtain",
|
|
19999
|
+
shortIt: "Tenda",
|
|
20000
|
+
aliases: []
|
|
20001
|
+
},
|
|
20002
|
+
{
|
|
20003
|
+
id: "cover-garage",
|
|
20004
|
+
key: "uiLibrary.deviceMeta.noun.role.coverGarage",
|
|
20005
|
+
en: "Garage door",
|
|
20006
|
+
it: "Porta del garage",
|
|
20007
|
+
shortEn: "Garage",
|
|
20008
|
+
shortIt: "Garage",
|
|
20009
|
+
aliases: []
|
|
20010
|
+
},
|
|
20011
|
+
{
|
|
20012
|
+
id: "cover-gate",
|
|
20013
|
+
key: "uiLibrary.deviceMeta.noun.role.coverGate",
|
|
20014
|
+
en: "Gate",
|
|
20015
|
+
it: "Cancello",
|
|
20016
|
+
shortEn: "Gate",
|
|
20017
|
+
shortIt: "Cancello",
|
|
20018
|
+
aliases: []
|
|
20019
|
+
},
|
|
20020
|
+
{
|
|
20021
|
+
id: "cover-door",
|
|
20022
|
+
key: "uiLibrary.deviceMeta.noun.role.coverDoor",
|
|
20023
|
+
en: "Door",
|
|
20024
|
+
it: "Porta",
|
|
20025
|
+
shortEn: "Door",
|
|
20026
|
+
shortIt: "Porta",
|
|
20027
|
+
aliases: []
|
|
20028
|
+
},
|
|
20029
|
+
{
|
|
20030
|
+
id: "cover-window",
|
|
20031
|
+
key: "uiLibrary.deviceMeta.noun.role.coverWindow",
|
|
20032
|
+
en: "Window",
|
|
20033
|
+
it: "Finestra",
|
|
20034
|
+
shortEn: "Window",
|
|
20035
|
+
shortIt: "Finestra",
|
|
20036
|
+
aliases: []
|
|
20037
|
+
},
|
|
20038
|
+
{
|
|
20039
|
+
id: "binary-helper",
|
|
20040
|
+
key: "uiLibrary.deviceMeta.noun.role.binaryHelper",
|
|
20041
|
+
en: "Binary helper",
|
|
20042
|
+
it: "Helper binario",
|
|
20043
|
+
shortEn: "Helper",
|
|
20044
|
+
shortIt: "Helper",
|
|
20045
|
+
aliases: []
|
|
20046
|
+
},
|
|
20047
|
+
{
|
|
20048
|
+
id: "outlet",
|
|
20049
|
+
key: "uiLibrary.deviceMeta.noun.role.outlet",
|
|
20050
|
+
en: "Outlet",
|
|
20051
|
+
it: "Presa",
|
|
20052
|
+
shortEn: "Outlet",
|
|
20053
|
+
shortIt: "Presa",
|
|
20054
|
+
aliases: []
|
|
20055
|
+
},
|
|
20056
|
+
{
|
|
20057
|
+
id: "motion-sensor",
|
|
20058
|
+
key: "uiLibrary.deviceMeta.noun.role.motionSensor",
|
|
20059
|
+
en: "Motion sensor",
|
|
20060
|
+
it: "Sensore di movimento",
|
|
20061
|
+
shortEn: "Motion",
|
|
20062
|
+
shortIt: "Movimento",
|
|
20063
|
+
aliases: []
|
|
20064
|
+
},
|
|
20065
|
+
{
|
|
20066
|
+
id: "contact-sensor",
|
|
20067
|
+
key: "uiLibrary.deviceMeta.noun.role.contactSensor",
|
|
20068
|
+
en: "Contact sensor",
|
|
20069
|
+
it: "Sensore di contatto",
|
|
20070
|
+
shortEn: "Contact",
|
|
20071
|
+
shortIt: "Contatto",
|
|
20072
|
+
aliases: []
|
|
20073
|
+
},
|
|
20074
|
+
{
|
|
20075
|
+
id: "leak-sensor",
|
|
20076
|
+
key: "uiLibrary.deviceMeta.noun.role.leakSensor",
|
|
20077
|
+
en: "Leak sensor",
|
|
20078
|
+
it: "Sensore di perdite",
|
|
20079
|
+
shortEn: "Leak",
|
|
20080
|
+
shortIt: "Perdita",
|
|
20081
|
+
aliases: []
|
|
20082
|
+
},
|
|
20083
|
+
{
|
|
20084
|
+
id: "smoke-sensor",
|
|
20085
|
+
key: "uiLibrary.deviceMeta.noun.role.smokeSensor",
|
|
20086
|
+
en: "Smoke sensor",
|
|
20087
|
+
it: "Sensore di fumo",
|
|
20088
|
+
shortEn: "Smoke",
|
|
20089
|
+
shortIt: "Fumo",
|
|
20090
|
+
aliases: []
|
|
20091
|
+
},
|
|
20092
|
+
{
|
|
20093
|
+
id: "co-sensor",
|
|
20094
|
+
key: "uiLibrary.deviceMeta.noun.role.cOSensor",
|
|
20095
|
+
en: "CO sensor",
|
|
20096
|
+
it: "Sensore di CO",
|
|
20097
|
+
shortEn: "CO",
|
|
20098
|
+
shortIt: "CO",
|
|
20099
|
+
aliases: []
|
|
20100
|
+
},
|
|
20101
|
+
{
|
|
20102
|
+
id: "gas-sensor",
|
|
20103
|
+
key: "uiLibrary.deviceMeta.noun.role.gasSensor",
|
|
20104
|
+
en: "Gas sensor",
|
|
20105
|
+
it: "Sensore di gas",
|
|
20106
|
+
shortEn: "Gas",
|
|
20107
|
+
shortIt: "Gas",
|
|
20108
|
+
aliases: []
|
|
20109
|
+
},
|
|
20110
|
+
{
|
|
20111
|
+
id: "tamper-sensor",
|
|
20112
|
+
key: "uiLibrary.deviceMeta.noun.role.tamperSensor",
|
|
20113
|
+
en: "Tamper sensor",
|
|
20114
|
+
it: "Sensore antimanomissione",
|
|
20115
|
+
shortEn: "Tamper",
|
|
20116
|
+
shortIt: "Manomissione",
|
|
20117
|
+
aliases: []
|
|
20118
|
+
},
|
|
20119
|
+
{
|
|
20120
|
+
id: "vibration-sensor",
|
|
20121
|
+
key: "uiLibrary.deviceMeta.noun.role.vibrationSensor",
|
|
20122
|
+
en: "Vibration sensor",
|
|
20123
|
+
it: "Sensore di vibrazione",
|
|
20124
|
+
shortEn: "Vibration",
|
|
20125
|
+
shortIt: "Vibrazione",
|
|
20126
|
+
aliases: []
|
|
20127
|
+
},
|
|
20128
|
+
{
|
|
20129
|
+
id: "connectivity-sensor",
|
|
20130
|
+
key: "uiLibrary.deviceMeta.noun.role.connectivitySensor",
|
|
20131
|
+
en: "Connectivity",
|
|
20132
|
+
it: "Connettività",
|
|
20133
|
+
shortEn: "Connectivity",
|
|
20134
|
+
shortIt: "Connettività",
|
|
20135
|
+
aliases: []
|
|
20136
|
+
},
|
|
20137
|
+
{
|
|
20138
|
+
id: "sound-sensor",
|
|
20139
|
+
key: "uiLibrary.deviceMeta.noun.role.soundSensor",
|
|
20140
|
+
en: "Sound sensor",
|
|
20141
|
+
it: "Sensore acustico",
|
|
20142
|
+
shortEn: "Sound",
|
|
20143
|
+
shortIt: "Suono",
|
|
20144
|
+
aliases: []
|
|
20145
|
+
},
|
|
20146
|
+
{
|
|
20147
|
+
id: "binary-sensor",
|
|
20148
|
+
key: "uiLibrary.deviceMeta.noun.role.binarySensor",
|
|
20149
|
+
en: "Binary sensor",
|
|
20150
|
+
it: "Sensore binario",
|
|
20151
|
+
shortEn: "Binary",
|
|
20152
|
+
shortIt: "Binario",
|
|
20153
|
+
aliases: []
|
|
20154
|
+
},
|
|
20155
|
+
{
|
|
20156
|
+
id: "temperature-sensor",
|
|
20157
|
+
key: "uiLibrary.deviceMeta.noun.role.temperatureSensor",
|
|
20158
|
+
en: "Temperature",
|
|
20159
|
+
it: "Temperatura",
|
|
20160
|
+
shortEn: "Temperature",
|
|
20161
|
+
shortIt: "Temperatura",
|
|
20162
|
+
aliases: []
|
|
20163
|
+
},
|
|
20164
|
+
{
|
|
20165
|
+
id: "humidity-sensor",
|
|
20166
|
+
key: "uiLibrary.deviceMeta.noun.role.humiditySensor",
|
|
20167
|
+
en: "Humidity",
|
|
20168
|
+
it: "Umidità",
|
|
20169
|
+
shortEn: "Humidity",
|
|
20170
|
+
shortIt: "Umidità",
|
|
20171
|
+
aliases: []
|
|
20172
|
+
},
|
|
20173
|
+
{
|
|
20174
|
+
id: "ambient-light-sensor",
|
|
20175
|
+
key: "uiLibrary.deviceMeta.noun.role.ambientLightSensor",
|
|
20176
|
+
en: "Ambient light",
|
|
20177
|
+
it: "Luce ambientale",
|
|
20178
|
+
shortEn: "Light",
|
|
20179
|
+
shortIt: "Luce",
|
|
20180
|
+
aliases: ["Illumination"]
|
|
20181
|
+
},
|
|
20182
|
+
{
|
|
20183
|
+
id: "pressure-sensor",
|
|
20184
|
+
key: "uiLibrary.deviceMeta.noun.role.pressureSensor",
|
|
20185
|
+
en: "Pressure",
|
|
20186
|
+
it: "Pressione",
|
|
20187
|
+
shortEn: "Pressure",
|
|
20188
|
+
shortIt: "Pressione",
|
|
20189
|
+
aliases: []
|
|
20190
|
+
},
|
|
20191
|
+
{
|
|
20192
|
+
id: "wind-sensor",
|
|
20193
|
+
key: "uiLibrary.deviceMeta.noun.role.windSensor",
|
|
20194
|
+
en: "Wind",
|
|
20195
|
+
it: "Vento",
|
|
20196
|
+
shortEn: "Wind",
|
|
20197
|
+
shortIt: "Vento",
|
|
20198
|
+
aliases: []
|
|
20199
|
+
},
|
|
20200
|
+
{
|
|
20201
|
+
id: "rain-sensor",
|
|
20202
|
+
key: "uiLibrary.deviceMeta.noun.role.rainSensor",
|
|
20203
|
+
en: "Rain",
|
|
20204
|
+
it: "Pioggia",
|
|
20205
|
+
shortEn: "Rain",
|
|
20206
|
+
shortIt: "Pioggia",
|
|
20207
|
+
aliases: []
|
|
20208
|
+
},
|
|
20209
|
+
{
|
|
20210
|
+
id: "uv-sensor",
|
|
20211
|
+
key: "uiLibrary.deviceMeta.noun.role.uvSensor",
|
|
20212
|
+
en: "UV index",
|
|
20213
|
+
it: "Indice UV",
|
|
20214
|
+
shortEn: "UV index",
|
|
20215
|
+
shortIt: "Indice UV",
|
|
20216
|
+
aliases: []
|
|
20217
|
+
},
|
|
20218
|
+
{
|
|
20219
|
+
id: "solar-radiation-sensor",
|
|
20220
|
+
key: "uiLibrary.deviceMeta.noun.role.solarRadiationSensor",
|
|
20221
|
+
en: "Solar radiation",
|
|
20222
|
+
it: "Radiazione solare",
|
|
20223
|
+
shortEn: "Solar radiation",
|
|
20224
|
+
shortIt: "Radiazione solare",
|
|
20225
|
+
aliases: []
|
|
20226
|
+
},
|
|
20227
|
+
{
|
|
20228
|
+
id: "soil-moisture-sensor",
|
|
20229
|
+
key: "uiLibrary.deviceMeta.noun.role.soilMoistureSensor",
|
|
20230
|
+
en: "Soil moisture",
|
|
20231
|
+
it: "Umidità del suolo",
|
|
20232
|
+
shortEn: "Soil moisture",
|
|
20233
|
+
shortIt: "Umidità del suolo",
|
|
20234
|
+
aliases: []
|
|
20235
|
+
},
|
|
20236
|
+
{
|
|
20237
|
+
id: "power-sensor",
|
|
20238
|
+
key: "uiLibrary.deviceMeta.noun.role.powerSensor",
|
|
20239
|
+
en: "Power",
|
|
20240
|
+
it: "Potenza",
|
|
20241
|
+
shortEn: "Power",
|
|
20242
|
+
shortIt: "Potenza",
|
|
20243
|
+
aliases: []
|
|
20244
|
+
},
|
|
20245
|
+
{
|
|
20246
|
+
id: "energy-sensor",
|
|
20247
|
+
key: "uiLibrary.deviceMeta.noun.role.energySensor",
|
|
20248
|
+
en: "Energy",
|
|
20249
|
+
it: "Energia",
|
|
20250
|
+
shortEn: "Energy",
|
|
20251
|
+
shortIt: "Energia",
|
|
20252
|
+
aliases: []
|
|
20253
|
+
},
|
|
20254
|
+
{
|
|
20255
|
+
id: "voltage-sensor",
|
|
20256
|
+
key: "uiLibrary.deviceMeta.noun.role.voltageSensor",
|
|
20257
|
+
en: "Voltage",
|
|
20258
|
+
it: "Tensione",
|
|
20259
|
+
shortEn: "Voltage",
|
|
20260
|
+
shortIt: "Tensione",
|
|
20261
|
+
aliases: []
|
|
20262
|
+
},
|
|
20263
|
+
{
|
|
20264
|
+
id: "current-sensor",
|
|
20265
|
+
key: "uiLibrary.deviceMeta.noun.role.currentSensor",
|
|
20266
|
+
en: "Current",
|
|
20267
|
+
it: "Corrente",
|
|
20268
|
+
shortEn: "Current",
|
|
20269
|
+
shortIt: "Corrente",
|
|
20270
|
+
aliases: []
|
|
20271
|
+
},
|
|
20272
|
+
{
|
|
20273
|
+
id: "air-quality-sensor",
|
|
20274
|
+
key: "uiLibrary.deviceMeta.noun.role.airQualitySensor",
|
|
20275
|
+
en: "Air quality",
|
|
20276
|
+
it: "Qualità dell’aria",
|
|
20277
|
+
shortEn: "Air quality",
|
|
20278
|
+
shortIt: "Qualità dell’aria",
|
|
20279
|
+
aliases: []
|
|
20280
|
+
},
|
|
20281
|
+
{
|
|
20282
|
+
id: "battery-sensor",
|
|
20283
|
+
key: "uiLibrary.deviceMeta.noun.role.batterySensor",
|
|
20284
|
+
en: "Battery",
|
|
20285
|
+
it: "Batteria",
|
|
20286
|
+
shortEn: "Battery",
|
|
20287
|
+
shortIt: "Batteria",
|
|
20288
|
+
aliases: []
|
|
20289
|
+
},
|
|
20290
|
+
{
|
|
20291
|
+
id: "numeric-sensor",
|
|
20292
|
+
key: "uiLibrary.deviceMeta.noun.role.numericSensor",
|
|
20293
|
+
en: "Numeric sensor",
|
|
20294
|
+
it: "Sensore numerico",
|
|
20295
|
+
shortEn: "Value",
|
|
20296
|
+
shortIt: "Numerico",
|
|
20297
|
+
aliases: []
|
|
20298
|
+
},
|
|
20299
|
+
{
|
|
20300
|
+
id: "enum-sensor",
|
|
20301
|
+
key: "uiLibrary.deviceMeta.noun.role.enumSensor",
|
|
20302
|
+
en: "Enum sensor",
|
|
20303
|
+
it: "Sensore a stati",
|
|
20304
|
+
shortEn: "State",
|
|
20305
|
+
shortIt: "Stato",
|
|
20306
|
+
aliases: []
|
|
20307
|
+
},
|
|
20308
|
+
{
|
|
20309
|
+
id: "datetime-sensor",
|
|
20310
|
+
key: "uiLibrary.deviceMeta.noun.role.dateTimeSensor",
|
|
20311
|
+
en: "Date / time",
|
|
20312
|
+
it: "Data / ora",
|
|
20313
|
+
shortEn: "Time",
|
|
20314
|
+
shortIt: "Ora",
|
|
20315
|
+
aliases: ["Last seen"]
|
|
20316
|
+
},
|
|
20317
|
+
{
|
|
20318
|
+
id: "generic-sensor",
|
|
20319
|
+
key: "uiLibrary.deviceMeta.noun.role.genericSensor",
|
|
20320
|
+
en: "Sensor",
|
|
20321
|
+
it: "Sensore",
|
|
20322
|
+
shortEn: "Sensor",
|
|
20323
|
+
shortIt: "Sensore",
|
|
20324
|
+
aliases: []
|
|
20325
|
+
},
|
|
20326
|
+
{
|
|
20327
|
+
id: "numeric-control",
|
|
20328
|
+
key: "uiLibrary.deviceMeta.noun.role.numericControl",
|
|
20329
|
+
en: "Numeric control",
|
|
20330
|
+
it: "Controllo numerico",
|
|
20331
|
+
shortEn: "Number",
|
|
20332
|
+
shortIt: "Numero",
|
|
20333
|
+
aliases: []
|
|
20334
|
+
},
|
|
20335
|
+
{
|
|
20336
|
+
id: "select-control",
|
|
20337
|
+
key: "uiLibrary.deviceMeta.noun.role.selectControl",
|
|
20338
|
+
en: "Select control",
|
|
20339
|
+
it: "Controllo a selezione",
|
|
20340
|
+
shortEn: "Select",
|
|
20341
|
+
shortIt: "Selezione",
|
|
20342
|
+
aliases: []
|
|
20343
|
+
},
|
|
20344
|
+
{
|
|
20345
|
+
id: "text-control",
|
|
20346
|
+
key: "uiLibrary.deviceMeta.noun.role.textControl",
|
|
20347
|
+
en: "Text control",
|
|
20348
|
+
it: "Controllo testo",
|
|
20349
|
+
shortEn: "Text",
|
|
20350
|
+
shortIt: "Testo",
|
|
20351
|
+
aliases: []
|
|
20352
|
+
},
|
|
20353
|
+
{
|
|
20354
|
+
id: "datetime-control",
|
|
20355
|
+
key: "uiLibrary.deviceMeta.noun.role.dateTimeControl",
|
|
20356
|
+
en: "Date / time control",
|
|
20357
|
+
it: "Controllo data / ora",
|
|
20358
|
+
shortEn: "Time",
|
|
20359
|
+
shortIt: "Ora",
|
|
20360
|
+
aliases: []
|
|
20361
|
+
},
|
|
20362
|
+
{
|
|
20363
|
+
id: "mobile-push-notifier",
|
|
20364
|
+
key: "uiLibrary.deviceMeta.noun.role.mobilePushNotifier",
|
|
20365
|
+
en: "Mobile push",
|
|
20366
|
+
it: "Push su mobile",
|
|
20367
|
+
shortEn: "Push",
|
|
20368
|
+
shortIt: "Push",
|
|
20369
|
+
aliases: []
|
|
20370
|
+
},
|
|
20371
|
+
{
|
|
20372
|
+
id: "messaging-notifier",
|
|
20373
|
+
key: "uiLibrary.deviceMeta.noun.role.messagingNotifier",
|
|
20374
|
+
en: "Messaging",
|
|
20375
|
+
it: "Messaggistica",
|
|
20376
|
+
shortEn: "Messaging",
|
|
20377
|
+
shortIt: "Messaggistica",
|
|
20378
|
+
aliases: []
|
|
20379
|
+
},
|
|
20380
|
+
{
|
|
20381
|
+
id: "email-notifier",
|
|
20382
|
+
key: "uiLibrary.deviceMeta.noun.role.emailNotifier",
|
|
20383
|
+
en: "Email",
|
|
20384
|
+
it: "Email",
|
|
20385
|
+
shortEn: "Email",
|
|
20386
|
+
shortIt: "Email",
|
|
20387
|
+
aliases: []
|
|
20388
|
+
},
|
|
20389
|
+
{
|
|
20390
|
+
id: "generic-notifier",
|
|
20391
|
+
key: "uiLibrary.deviceMeta.noun.role.genericNotifier",
|
|
20392
|
+
en: "Notifier",
|
|
20393
|
+
it: "Notificatore",
|
|
20394
|
+
shortEn: "Notifier",
|
|
20395
|
+
shortIt: "Notificatore",
|
|
20396
|
+
aliases: []
|
|
20397
|
+
}
|
|
20398
|
+
];
|
|
20399
|
+
var DEVICE_TYPE_NOUNS = [
|
|
20400
|
+
{
|
|
20401
|
+
id: "camera",
|
|
20402
|
+
key: "uiLibrary.deviceMeta.noun.type.camera",
|
|
20403
|
+
en: "Camera",
|
|
20404
|
+
it: "Telecamera",
|
|
20405
|
+
shortEn: "Camera",
|
|
20406
|
+
shortIt: "Telecamera",
|
|
20407
|
+
aliases: []
|
|
20408
|
+
},
|
|
20409
|
+
{
|
|
20410
|
+
id: "hub",
|
|
20411
|
+
key: "uiLibrary.deviceMeta.noun.type.hub",
|
|
20412
|
+
en: "Hub",
|
|
20413
|
+
it: "Hub",
|
|
20414
|
+
shortEn: "Hub",
|
|
20415
|
+
shortIt: "Hub",
|
|
20416
|
+
aliases: []
|
|
20417
|
+
},
|
|
20418
|
+
{
|
|
20419
|
+
id: "light",
|
|
20420
|
+
key: "uiLibrary.deviceMeta.noun.type.light",
|
|
20421
|
+
en: "Light",
|
|
20422
|
+
it: "Luce",
|
|
20423
|
+
shortEn: "Light",
|
|
20424
|
+
shortIt: "Luce",
|
|
20425
|
+
aliases: []
|
|
20426
|
+
},
|
|
20427
|
+
{
|
|
20428
|
+
id: "siren",
|
|
20429
|
+
key: "uiLibrary.deviceMeta.noun.type.siren",
|
|
20430
|
+
en: "Siren",
|
|
20431
|
+
it: "Sirena",
|
|
20432
|
+
shortEn: "Siren",
|
|
20433
|
+
shortIt: "Sirena",
|
|
20434
|
+
aliases: []
|
|
20435
|
+
},
|
|
20436
|
+
{
|
|
20437
|
+
id: "switch",
|
|
20438
|
+
key: "uiLibrary.deviceMeta.noun.type.switch",
|
|
20439
|
+
en: "Switch",
|
|
20440
|
+
it: "Interruttore",
|
|
20441
|
+
shortEn: "Switch",
|
|
20442
|
+
shortIt: "Interruttore",
|
|
20443
|
+
aliases: []
|
|
20444
|
+
},
|
|
20445
|
+
{
|
|
20446
|
+
id: "sensor",
|
|
20447
|
+
key: "uiLibrary.deviceMeta.noun.type.sensor",
|
|
20448
|
+
en: "Sensor",
|
|
20449
|
+
it: "Sensore",
|
|
20450
|
+
shortEn: "Sensor",
|
|
20451
|
+
shortIt: "Sensore",
|
|
20452
|
+
aliases: []
|
|
20453
|
+
},
|
|
20454
|
+
{
|
|
20455
|
+
id: "thermostat",
|
|
20456
|
+
key: "uiLibrary.deviceMeta.noun.type.thermostat",
|
|
20457
|
+
en: "Thermostat",
|
|
20458
|
+
it: "Termostato",
|
|
20459
|
+
shortEn: "Thermostat",
|
|
20460
|
+
shortIt: "Termostato",
|
|
20461
|
+
aliases: []
|
|
20462
|
+
},
|
|
20463
|
+
{
|
|
20464
|
+
id: "climate",
|
|
20465
|
+
key: "uiLibrary.deviceMeta.noun.type.climate",
|
|
20466
|
+
en: "Air conditioner",
|
|
20467
|
+
it: "Condizionatore",
|
|
20468
|
+
shortEn: "Climate",
|
|
20469
|
+
shortIt: "Condizionatore",
|
|
20470
|
+
aliases: []
|
|
20471
|
+
},
|
|
20472
|
+
{
|
|
20473
|
+
id: "button",
|
|
20474
|
+
key: "uiLibrary.deviceMeta.noun.type.button",
|
|
20475
|
+
en: "Button",
|
|
20476
|
+
it: "Pulsante",
|
|
20477
|
+
shortEn: "Button",
|
|
20478
|
+
shortIt: "Pulsante",
|
|
20479
|
+
aliases: []
|
|
20480
|
+
},
|
|
20481
|
+
{
|
|
20482
|
+
id: "event-emitter",
|
|
20483
|
+
key: "uiLibrary.deviceMeta.noun.type.eventEmitter",
|
|
20484
|
+
en: "Event Emitter",
|
|
20485
|
+
it: "Emettitore di eventi",
|
|
20486
|
+
shortEn: "Event",
|
|
20487
|
+
shortIt: "Evento",
|
|
20488
|
+
aliases: []
|
|
20489
|
+
},
|
|
20490
|
+
{
|
|
20491
|
+
id: "update",
|
|
20492
|
+
key: "uiLibrary.deviceMeta.noun.type.update",
|
|
20493
|
+
en: "Update",
|
|
20494
|
+
it: "Aggiornamento",
|
|
20495
|
+
shortEn: "Update",
|
|
20496
|
+
shortIt: "Aggiornamento",
|
|
20497
|
+
aliases: []
|
|
20498
|
+
},
|
|
20499
|
+
{
|
|
20500
|
+
id: "generic",
|
|
20501
|
+
key: "uiLibrary.deviceMeta.noun.type.generic",
|
|
20502
|
+
en: "Generic",
|
|
20503
|
+
it: "Generico",
|
|
20504
|
+
shortEn: "Generic",
|
|
20505
|
+
shortIt: "Generico",
|
|
20506
|
+
aliases: []
|
|
20507
|
+
},
|
|
20508
|
+
{
|
|
20509
|
+
id: "notifier",
|
|
20510
|
+
key: "uiLibrary.deviceMeta.noun.type.notifier",
|
|
20511
|
+
en: "Notifier",
|
|
20512
|
+
it: "Notificatore",
|
|
20513
|
+
shortEn: "Notifier",
|
|
20514
|
+
shortIt: "Notificatore",
|
|
20515
|
+
aliases: []
|
|
20516
|
+
},
|
|
20517
|
+
{
|
|
20518
|
+
id: "script",
|
|
20519
|
+
key: "uiLibrary.deviceMeta.noun.type.script",
|
|
20520
|
+
en: "Script",
|
|
20521
|
+
it: "Script",
|
|
20522
|
+
shortEn: "Script",
|
|
20523
|
+
shortIt: "Script",
|
|
20524
|
+
aliases: []
|
|
20525
|
+
},
|
|
20526
|
+
{
|
|
20527
|
+
id: "automation",
|
|
20528
|
+
key: "uiLibrary.deviceMeta.noun.type.automation",
|
|
20529
|
+
en: "Automation",
|
|
20530
|
+
it: "Automazione",
|
|
20531
|
+
shortEn: "Automation",
|
|
20532
|
+
shortIt: "Automazione",
|
|
20533
|
+
aliases: []
|
|
20534
|
+
},
|
|
20535
|
+
{
|
|
20536
|
+
id: "lock",
|
|
20537
|
+
key: "uiLibrary.deviceMeta.noun.type.lock",
|
|
20538
|
+
en: "Lock",
|
|
20539
|
+
it: "Serratura",
|
|
20540
|
+
shortEn: "Lock",
|
|
20541
|
+
shortIt: "Serratura",
|
|
20542
|
+
aliases: []
|
|
20543
|
+
},
|
|
20544
|
+
{
|
|
20545
|
+
id: "cover",
|
|
20546
|
+
key: "uiLibrary.deviceMeta.noun.type.cover",
|
|
20547
|
+
en: "Cover",
|
|
20548
|
+
it: "Copertura",
|
|
20549
|
+
shortEn: "Cover",
|
|
20550
|
+
shortIt: "Copertura",
|
|
20551
|
+
aliases: []
|
|
20552
|
+
},
|
|
20553
|
+
{
|
|
20554
|
+
id: "valve",
|
|
20555
|
+
key: "uiLibrary.deviceMeta.noun.type.valve",
|
|
20556
|
+
en: "Valve",
|
|
20557
|
+
it: "Valvola",
|
|
20558
|
+
shortEn: "Valve",
|
|
20559
|
+
shortIt: "Valvola",
|
|
20560
|
+
aliases: []
|
|
20561
|
+
},
|
|
20562
|
+
{
|
|
20563
|
+
id: "humidifier",
|
|
20564
|
+
key: "uiLibrary.deviceMeta.noun.type.humidifier",
|
|
20565
|
+
en: "Humidifier",
|
|
20566
|
+
it: "Umidificatore",
|
|
20567
|
+
shortEn: "Humidifier",
|
|
20568
|
+
shortIt: "Umidificatore",
|
|
20569
|
+
aliases: []
|
|
20570
|
+
},
|
|
20571
|
+
{
|
|
20572
|
+
id: "water-heater",
|
|
20573
|
+
key: "uiLibrary.deviceMeta.noun.type.waterHeater",
|
|
20574
|
+
en: "Water heater",
|
|
20575
|
+
it: "Scaldabagno",
|
|
20576
|
+
shortEn: "Heater",
|
|
20577
|
+
shortIt: "Scaldabagno",
|
|
20578
|
+
aliases: []
|
|
20579
|
+
},
|
|
20580
|
+
{
|
|
20581
|
+
id: "fan",
|
|
20582
|
+
key: "uiLibrary.deviceMeta.noun.type.fan",
|
|
20583
|
+
en: "Fan",
|
|
20584
|
+
it: "Ventilatore",
|
|
20585
|
+
shortEn: "Fan",
|
|
20586
|
+
shortIt: "Ventilatore",
|
|
20587
|
+
aliases: []
|
|
20588
|
+
},
|
|
20589
|
+
{
|
|
20590
|
+
id: "media-player",
|
|
20591
|
+
key: "uiLibrary.deviceMeta.noun.type.mediaPlayer",
|
|
20592
|
+
en: "Media player",
|
|
20593
|
+
it: "Lettore multimediale",
|
|
20594
|
+
shortEn: "Player",
|
|
20595
|
+
shortIt: "Lettore",
|
|
20596
|
+
aliases: []
|
|
20597
|
+
},
|
|
20598
|
+
{
|
|
20599
|
+
id: "alarm-panel",
|
|
20600
|
+
key: "uiLibrary.deviceMeta.noun.type.alarmPanel",
|
|
20601
|
+
en: "Alarm panel",
|
|
20602
|
+
it: "Pannello allarme",
|
|
20603
|
+
shortEn: "Alarm",
|
|
20604
|
+
shortIt: "Allarme",
|
|
20605
|
+
aliases: []
|
|
20606
|
+
},
|
|
20607
|
+
{
|
|
20608
|
+
id: "control",
|
|
20609
|
+
key: "uiLibrary.deviceMeta.noun.type.control",
|
|
20610
|
+
en: "Control",
|
|
20611
|
+
it: "Controllo",
|
|
20612
|
+
shortEn: "Control",
|
|
20613
|
+
shortIt: "Controllo",
|
|
20614
|
+
aliases: []
|
|
20615
|
+
},
|
|
20616
|
+
{
|
|
20617
|
+
id: "presence",
|
|
20618
|
+
key: "uiLibrary.deviceMeta.noun.type.presence",
|
|
20619
|
+
en: "Presence",
|
|
20620
|
+
it: "Presenza",
|
|
20621
|
+
shortEn: "Presence",
|
|
20622
|
+
shortIt: "Presenza",
|
|
20623
|
+
aliases: []
|
|
20624
|
+
},
|
|
20625
|
+
{
|
|
20626
|
+
id: "weather",
|
|
20627
|
+
key: "uiLibrary.deviceMeta.noun.type.weather",
|
|
20628
|
+
en: "Weather",
|
|
20629
|
+
it: "Meteo",
|
|
20630
|
+
shortEn: "Weather",
|
|
20631
|
+
shortIt: "Meteo",
|
|
20632
|
+
aliases: []
|
|
20633
|
+
},
|
|
20634
|
+
{
|
|
20635
|
+
id: "vacuum",
|
|
20636
|
+
key: "uiLibrary.deviceMeta.noun.type.vacuum",
|
|
20637
|
+
en: "Vacuum",
|
|
20638
|
+
it: "Aspirapolvere",
|
|
20639
|
+
shortEn: "Vacuum",
|
|
20640
|
+
shortIt: "Aspirapolvere",
|
|
20641
|
+
aliases: []
|
|
20642
|
+
},
|
|
20643
|
+
{
|
|
20644
|
+
id: "lawn-mower",
|
|
20645
|
+
key: "uiLibrary.deviceMeta.noun.type.lawnMower",
|
|
20646
|
+
en: "Lawn mower",
|
|
20647
|
+
it: "Tagliaerba",
|
|
20648
|
+
shortEn: "Mower",
|
|
20649
|
+
shortIt: "Tagliaerba",
|
|
20650
|
+
aliases: []
|
|
20651
|
+
},
|
|
20652
|
+
{
|
|
20653
|
+
id: "container",
|
|
20654
|
+
key: "uiLibrary.deviceMeta.noun.type.container",
|
|
20655
|
+
en: "Container",
|
|
20656
|
+
it: "Contenitore",
|
|
20657
|
+
shortEn: "Container",
|
|
20658
|
+
shortIt: "Contenitore",
|
|
20659
|
+
aliases: []
|
|
20660
|
+
},
|
|
20661
|
+
{
|
|
20662
|
+
id: "image",
|
|
20663
|
+
key: "uiLibrary.deviceMeta.noun.type.image",
|
|
20664
|
+
en: "Image",
|
|
20665
|
+
it: "Immagine",
|
|
20666
|
+
shortEn: "Image",
|
|
20667
|
+
shortIt: "Immagine",
|
|
20668
|
+
aliases: []
|
|
20669
|
+
},
|
|
20670
|
+
{
|
|
20671
|
+
id: "pet-feeder",
|
|
20672
|
+
key: "uiLibrary.deviceMeta.noun.type.petFeeder",
|
|
20673
|
+
en: "Pet feeder",
|
|
20674
|
+
it: "Distributore di cibo per animali",
|
|
20675
|
+
shortEn: "Feeder",
|
|
20676
|
+
shortIt: "Distributore",
|
|
20677
|
+
aliases: []
|
|
20678
|
+
},
|
|
20679
|
+
{
|
|
20680
|
+
id: "dishwasher",
|
|
20681
|
+
key: "uiLibrary.deviceMeta.noun.type.dishwasher",
|
|
20682
|
+
en: "Dishwasher",
|
|
20683
|
+
it: "Lavastoviglie",
|
|
20684
|
+
shortEn: "Dishwasher",
|
|
20685
|
+
shortIt: "Lavastoviglie",
|
|
20686
|
+
aliases: []
|
|
20687
|
+
}
|
|
20688
|
+
];
|
|
20689
|
+
var FALLBACK_NOUN = {
|
|
20690
|
+
id: "",
|
|
20691
|
+
key: "uiLibrary.deviceMeta.noun.fallback",
|
|
20692
|
+
en: "Device",
|
|
20693
|
+
it: "Dispositivo",
|
|
20694
|
+
shortEn: "Device",
|
|
20695
|
+
shortIt: "Dispositivo",
|
|
20696
|
+
aliases: []
|
|
20697
|
+
};
|
|
20698
|
+
function findNoun(list, id) {
|
|
20699
|
+
if (id === null || id.length === 0) return void 0;
|
|
20700
|
+
return list.find((spec) => spec.id === id);
|
|
20701
|
+
}
|
|
20702
|
+
/** Role wins when it has a noun; otherwise the type. Unknown types fall back. */
|
|
20703
|
+
function nounSpecFor(role, type) {
|
|
20704
|
+
if (role !== null) {
|
|
20705
|
+
const byRole = findNoun(DEVICE_ROLE_NOUNS, role);
|
|
20706
|
+
if (byRole !== void 0) return byRole;
|
|
20707
|
+
}
|
|
20708
|
+
return findNoun(DEVICE_TYPE_NOUNS, type) ?? FALLBACK_NOUN;
|
|
20709
|
+
}
|
|
20710
|
+
function stockPhrases(role, type) {
|
|
20711
|
+
const phrases = [];
|
|
20712
|
+
const specs = [findNoun(DEVICE_ROLE_NOUNS, role), findNoun(DEVICE_TYPE_NOUNS, type)];
|
|
20713
|
+
for (const spec of specs) {
|
|
20714
|
+
if (spec === void 0) continue;
|
|
20715
|
+
phrases.push(spec.en, spec.it, spec.shortEn, spec.shortIt, ...spec.aliases);
|
|
20716
|
+
}
|
|
20717
|
+
return phrases;
|
|
20718
|
+
}
|
|
20719
|
+
function isDeviceNameStock(text, role, type) {
|
|
20720
|
+
const folded = foldDeviceName(text);
|
|
20721
|
+
if (folded.length === 0) return true;
|
|
20722
|
+
return stockPhrases(role, type).some((phrase) => foldDeviceName(phrase) === folded);
|
|
20723
|
+
}
|
|
20724
|
+
/** Noun table for a locale. Tests and the viewer parity spec use this directly. */
|
|
20725
|
+
function deviceNameNouns(locale) {
|
|
20726
|
+
return {
|
|
20727
|
+
shortNoun(role, type) {
|
|
20728
|
+
const spec = nounSpecFor(role, type);
|
|
20729
|
+
return locale === "it" ? spec.shortIt : spec.shortEn;
|
|
20730
|
+
},
|
|
20731
|
+
isStockPhrase(text, role, type) {
|
|
20732
|
+
return isDeviceNameStock(text, role, type);
|
|
20733
|
+
}
|
|
20734
|
+
};
|
|
20735
|
+
}
|
|
20736
|
+
//#endregion
|
|
20737
|
+
//#region src/composites/device-name/use-device-label.ts
|
|
20738
|
+
/**
|
|
20739
|
+
* `useDeviceLabel` is the string `DeviceName` renders — sort keys, aria
|
|
20740
|
+
* labels, confirm copy and search titles call it instead of painting
|
|
20741
|
+
* `device.name`.
|
|
20742
|
+
*/
|
|
20743
|
+
function useDeviceNameNouns() {
|
|
20744
|
+
const t = useUiText();
|
|
20745
|
+
return {
|
|
20746
|
+
shortNoun(role, type) {
|
|
20747
|
+
const spec = nounSpecFor(role, type);
|
|
20748
|
+
return t(spec.key, spec.shortEn);
|
|
20749
|
+
},
|
|
20750
|
+
isStockPhrase(text, role, type) {
|
|
20751
|
+
return isDeviceNameStock(text, role, type);
|
|
20752
|
+
}
|
|
20753
|
+
};
|
|
20754
|
+
}
|
|
20755
|
+
function placeholderParent(id) {
|
|
20756
|
+
return {
|
|
20757
|
+
id,
|
|
20758
|
+
name: `#${String(id)}`,
|
|
20759
|
+
type: "unknown",
|
|
20760
|
+
stableId: "",
|
|
20761
|
+
role: null,
|
|
20762
|
+
parentDeviceId: null
|
|
20763
|
+
};
|
|
20764
|
+
}
|
|
20765
|
+
function parentFromIndex(device, index) {
|
|
20766
|
+
const parentId = device.parentDeviceId;
|
|
20767
|
+
if (parentId === null || parentId === void 0) return null;
|
|
20768
|
+
return index.byId.get(parentId) ?? placeholderParent(parentId);
|
|
20769
|
+
}
|
|
20770
|
+
function siblingsFromIndex(device, index) {
|
|
20771
|
+
const parentId = device.parentDeviceId;
|
|
20772
|
+
if (parentId === null || parentId === void 0) return [];
|
|
20773
|
+
const ids = index.childIds.get(parentId) ?? [];
|
|
20774
|
+
const siblings = [];
|
|
20775
|
+
for (const id of ids) {
|
|
20776
|
+
const row = index.byId.get(id);
|
|
20777
|
+
if (row !== void 0) siblings.push(row);
|
|
20778
|
+
}
|
|
20779
|
+
if (!siblings.some((sibling) => sibling.id === device.id)) siblings.push(device);
|
|
20780
|
+
return siblings;
|
|
20781
|
+
}
|
|
20782
|
+
/**
|
|
20783
|
+
* Label for a device the caller already holds. While the fleet has not
|
|
20784
|
+
* answered and no parent was passed, this is the stored name — not `#id`.
|
|
20785
|
+
*/
|
|
20786
|
+
function resolveDeviceLabel(device, form, index, nouns, scope) {
|
|
20787
|
+
const subject = index?.byId.get(device.id) ?? device;
|
|
20788
|
+
const parentId = subject.parentDeviceId;
|
|
20789
|
+
if (parentId !== null && parentId !== void 0 && index === null && scope?.parent === void 0) return subject.name;
|
|
20790
|
+
return formatDeviceName(subject, form, {
|
|
20791
|
+
parent: scope?.parent !== void 0 ? scope.parent : index === null ? null : parentFromIndex(subject, index),
|
|
20792
|
+
siblings: scope?.siblings ?? (index === null ? [] : siblingsFromIndex(subject, index))
|
|
20793
|
+
}, nouns);
|
|
20794
|
+
}
|
|
20795
|
+
function useDeviceLabel(device, form, scope) {
|
|
20796
|
+
return resolveDeviceLabel(device, form, useDeviceNameIndex(), useDeviceNameNouns(), scope);
|
|
20797
|
+
}
|
|
20798
|
+
/** `#id` until the fleet answers, and `#id` when the id is not in it. */
|
|
20799
|
+
function useDeviceLabelById(id, form, pendingName) {
|
|
20800
|
+
const index = useDeviceNameIndex();
|
|
20801
|
+
const nouns = useDeviceNameNouns();
|
|
20802
|
+
if (index === null) return pendingName ?? `#${String(id)}`;
|
|
20803
|
+
const device = index.byId.get(id);
|
|
20804
|
+
if (device === void 0) return `#${String(id)}`;
|
|
20805
|
+
return resolveDeviceLabel(device, form, index, nouns);
|
|
20806
|
+
}
|
|
20807
|
+
//#endregion
|
|
20808
|
+
//#region src/composites/device-name/DeviceName.tsx
|
|
20809
|
+
function DeviceName({ device, form, parent, siblings, className, testId }) {
|
|
20810
|
+
const label = useDeviceLabel(device, form, {
|
|
20811
|
+
...parent !== void 0 ? { parent } : {},
|
|
20812
|
+
...siblings !== void 0 ? { siblings } : {}
|
|
20813
|
+
});
|
|
20814
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
20815
|
+
className,
|
|
20816
|
+
title: label,
|
|
20817
|
+
"data-testid": testId,
|
|
20818
|
+
children: label
|
|
20819
|
+
});
|
|
20820
|
+
}
|
|
20821
|
+
//#endregion
|
|
19630
20822
|
//#region src/hooks/use-device-proxy.ts
|
|
19631
20823
|
/**
|
|
19632
20824
|
* useDeviceProxy — canonical React entry point for a device.
|
|
@@ -20529,6 +21721,9 @@ function GridCellBox({ cell, selected, onSelect, onDragStart }) {
|
|
|
20529
21721
|
}, handle))
|
|
20530
21722
|
});
|
|
20531
21723
|
}
|
|
21724
|
+
function CameraOptionLabel({ camera }) {
|
|
21725
|
+
return useDeviceLabel(camera, "compact");
|
|
21726
|
+
}
|
|
20532
21727
|
function CellInspector({ cell, index, cameras, onChange, onRemove }) {
|
|
20533
21728
|
const t = useUiText();
|
|
20534
21729
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
@@ -20559,7 +21754,7 @@ function CellInspector({ cell, index, cameras, onChange, onRemove }) {
|
|
|
20559
21754
|
className: "flex-1 rounded border border-border bg-transparent px-1 py-0.5",
|
|
20560
21755
|
children: cameras.map((camera) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
20561
21756
|
value: String(camera.id),
|
|
20562
|
-
children: camera
|
|
21757
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CameraOptionLabel, { camera })
|
|
20563
21758
|
}, camera.id))
|
|
20564
21759
|
})]
|
|
20565
21760
|
}),
|
|
@@ -48247,17 +49442,19 @@ function SensorHeroInner({ trpc, device }) {
|
|
|
48247
49442
|
if (resolution.kind === "quiet") return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
48248
49443
|
className: "flex flex-col items-center justify-center gap-2 rounded-lg border border-border bg-surface p-4 min-h-[96px]",
|
|
48249
49444
|
"data-testid": "sensor-hero-quiet",
|
|
48250
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(
|
|
48251
|
-
|
|
48252
|
-
|
|
49445
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(DeviceName, {
|
|
49446
|
+
device,
|
|
49447
|
+
form: "full",
|
|
49448
|
+
className: "text-sm text-foreground-subtle"
|
|
48253
49449
|
})
|
|
48254
49450
|
});
|
|
48255
49451
|
const slice = resolution.kind === "value" ? resolution.slice : void 0;
|
|
48256
49452
|
if (descriptor === void 0 || slice === void 0) return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
48257
49453
|
className: "flex flex-col items-center justify-center gap-2 rounded-lg border border-border bg-surface p-4 min-h-[96px]",
|
|
48258
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(
|
|
48259
|
-
|
|
48260
|
-
|
|
49454
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(DeviceName, {
|
|
49455
|
+
device,
|
|
49456
|
+
form: "full",
|
|
49457
|
+
className: "text-sm text-foreground-subtle"
|
|
48261
49458
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
48262
49459
|
className: "text-xs text-foreground-subtle italic",
|
|
48263
49460
|
children: t("uiLibrary.sensorHeroCard.awaiting", "Awaiting state…")
|
|
@@ -48297,9 +49494,10 @@ function SensorHeroInner({ trpc, device }) {
|
|
|
48297
49494
|
"data-testid": "sensor-hero-occupancy",
|
|
48298
49495
|
children: occupancyOn ? t("uiLibrary.sensorHeroCard.occupied", "Occupied") : t("uiLibrary.sensorHeroCard.clear", "Clear")
|
|
48299
49496
|
}),
|
|
48300
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(
|
|
48301
|
-
|
|
48302
|
-
|
|
49497
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(DeviceName, {
|
|
49498
|
+
device,
|
|
49499
|
+
form: "full",
|
|
49500
|
+
className: "text-sm text-foreground-subtle"
|
|
48303
49501
|
})
|
|
48304
49502
|
]
|
|
48305
49503
|
});
|
|
@@ -48314,9 +49512,10 @@ function SensorHeroInner({ trpc, device }) {
|
|
|
48314
49512
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
48315
49513
|
className: cn("inline-flex items-center rounded px-3 py-1.5 text-lg font-semibold", active ? "bg-warning/15 text-warning" : "bg-surface-subtle text-foreground-subtle"),
|
|
48316
49514
|
children: label
|
|
48317
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(
|
|
48318
|
-
|
|
48319
|
-
|
|
49515
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(DeviceName, {
|
|
49516
|
+
device,
|
|
49517
|
+
form: "full",
|
|
49518
|
+
className: "text-sm text-foreground-subtle"
|
|
48320
49519
|
})]
|
|
48321
49520
|
});
|
|
48322
49521
|
}
|
|
@@ -48324,9 +49523,10 @@ function SensorHeroInner({ trpc, device }) {
|
|
|
48324
49523
|
if (!isStringSliceValue(slice)) return null;
|
|
48325
49524
|
if (slice.value === "") return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
48326
49525
|
className: "flex flex-col items-center justify-center gap-2 rounded-lg border border-border bg-surface p-4 min-h-[96px]",
|
|
48327
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(
|
|
48328
|
-
|
|
48329
|
-
|
|
49526
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(DeviceName, {
|
|
49527
|
+
device,
|
|
49528
|
+
form: "full",
|
|
49529
|
+
className: "text-sm text-foreground-subtle"
|
|
48330
49530
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
48331
49531
|
className: "text-xs text-foreground-subtle italic",
|
|
48332
49532
|
children: t("uiLibrary.sensorHeroCard.awaiting", "Awaiting state…")
|
|
@@ -48338,9 +49538,10 @@ function SensorHeroInner({ trpc, device }) {
|
|
|
48338
49538
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
48339
49539
|
className: "text-3xl font-semibold tabular-nums text-foreground",
|
|
48340
49540
|
children: formatControlDateTime(slice.value, format)
|
|
48341
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(
|
|
48342
|
-
|
|
48343
|
-
|
|
49541
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(DeviceName, {
|
|
49542
|
+
device,
|
|
49543
|
+
form: "full",
|
|
49544
|
+
className: "text-sm text-foreground-subtle"
|
|
48344
49545
|
})]
|
|
48345
49546
|
});
|
|
48346
49547
|
}
|
|
@@ -48352,9 +49553,10 @@ function SensorHeroInner({ trpc, device }) {
|
|
|
48352
49553
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
48353
49554
|
className: "text-xl font-semibold text-foreground",
|
|
48354
49555
|
children: slice.value
|
|
48355
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(
|
|
48356
|
-
|
|
48357
|
-
|
|
49556
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(DeviceName, {
|
|
49557
|
+
device,
|
|
49558
|
+
form: "full",
|
|
49559
|
+
className: "text-sm text-foreground-subtle"
|
|
48358
49560
|
})]
|
|
48359
49561
|
});
|
|
48360
49562
|
}
|
|
@@ -48365,9 +49567,10 @@ function SensorHeroInner({ trpc, device }) {
|
|
|
48365
49567
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
48366
49568
|
className: cn("inline-flex items-center rounded px-3 py-1.5 text-lg font-semibold", slice.state === "home" ? "bg-success/15 text-success" : "bg-surface-subtle text-foreground-subtle"),
|
|
48367
49569
|
children: label
|
|
48368
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(
|
|
48369
|
-
|
|
48370
|
-
|
|
49570
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(DeviceName, {
|
|
49571
|
+
device,
|
|
49572
|
+
form: "full",
|
|
49573
|
+
className: "text-sm text-foreground-subtle"
|
|
48371
49574
|
})]
|
|
48372
49575
|
});
|
|
48373
49576
|
}
|
|
@@ -55122,7 +56325,9 @@ var CONTROL_FILLS = {
|
|
|
55122
56325
|
[_camstack_types.DeviceType.Container]: false,
|
|
55123
56326
|
[_camstack_types.DeviceType.Image]: false,
|
|
55124
56327
|
[_camstack_types.DeviceType.PetFeeder]: false,
|
|
55125
|
-
[_camstack_types.DeviceType.Dishwasher]: false
|
|
56328
|
+
[_camstack_types.DeviceType.Dishwasher]: false,
|
|
56329
|
+
[_camstack_types.DeviceType.Washer]: false,
|
|
56330
|
+
[_camstack_types.DeviceType.Dryer]: false
|
|
55126
56331
|
};
|
|
55127
56332
|
var DEVICE_TYPE_VALUES = new Set(Object.values(_camstack_types.DeviceType));
|
|
55128
56333
|
/**
|
|
@@ -56378,6 +57583,7 @@ function useContainerChildren(deviceId) {
|
|
|
56378
57583
|
var SENSOR_VALUE_TYPES = new Set([_camstack_types.DeviceType.Sensor, _camstack_types.DeviceType.Presence]);
|
|
56379
57584
|
function DeviceItemActions({ trpc, device, controlPlacement }) {
|
|
56380
57585
|
const containerChildren = useContainerChildren(device.id);
|
|
57586
|
+
const deviceLabel = useDeviceLabel(device, "compact");
|
|
56381
57587
|
const placement = controlPlacement ?? "right";
|
|
56382
57588
|
if (!!device.disabled) return null;
|
|
56383
57589
|
if (device.type === _camstack_types.DeviceType.Container) {
|
|
@@ -56433,7 +57639,7 @@ function DeviceItemActions({ trpc, device, controlPlacement }) {
|
|
|
56433
57639
|
showReboot && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(RebootQuickAction, {
|
|
56434
57640
|
trpc,
|
|
56435
57641
|
deviceId: device.id,
|
|
56436
|
-
deviceName:
|
|
57642
|
+
deviceName: deviceLabel
|
|
56437
57643
|
}),
|
|
56438
57644
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(AdminLinkQuickAction, {
|
|
56439
57645
|
trpc,
|
|
@@ -56669,9 +57875,16 @@ function ChildRow$1({ trpc, child, onNavigate, parentName }) {
|
|
|
56669
57875
|
running: runningSlice === void 0 || runningSlice.running === null ? null : runningSlice.running,
|
|
56670
57876
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ChildIcon, { className: "h-3 w-3 text-foreground-subtle flex-shrink-0" })
|
|
56671
57877
|
}),
|
|
56672
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(
|
|
56673
|
-
|
|
56674
|
-
|
|
57878
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(DeviceName, {
|
|
57879
|
+
device: child,
|
|
57880
|
+
form: "nested",
|
|
57881
|
+
parent: {
|
|
57882
|
+
id: child.parentDeviceId ?? 0,
|
|
57883
|
+
name: parentName,
|
|
57884
|
+
type: "unknown",
|
|
57885
|
+
stableId: ""
|
|
57886
|
+
},
|
|
57887
|
+
className: "text-[10.5px] text-foreground flex-1 truncate"
|
|
56675
57888
|
}),
|
|
56676
57889
|
showMotionTrigger && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ChildMotionTriggerToggle, {
|
|
56677
57890
|
trpc,
|
|
@@ -56778,8 +57991,9 @@ function IconAction({ icon: Icon, label, onClick, danger = false }) {
|
|
|
56778
57991
|
function DeviceDeleteAction({ device, onDelete }) {
|
|
56779
57992
|
const t = useUiText();
|
|
56780
57993
|
const confirm = useConfirm();
|
|
57994
|
+
const deviceLabel = useDeviceLabel(device, "full");
|
|
56781
57995
|
const requestDelete = async () => {
|
|
56782
|
-
const label =
|
|
57996
|
+
const label = deviceLabel.trim() !== "" ? deviceLabel : `#${String(device.id)}`;
|
|
56783
57997
|
if (await confirm({
|
|
56784
57998
|
title: t("uiLibrary.deviceDeleteAction.title", "Delete device?"),
|
|
56785
57999
|
message: t("uiLibrary.deviceDeleteAction.message", "This will remove \"{{label}}\" and all its settings. This action cannot be undone.", { label }),
|
|
@@ -57062,7 +58276,7 @@ var CHEVRON_SLOT_CLASS = {
|
|
|
57062
58276
|
horizontal: "h-3.5 w-3.5",
|
|
57063
58277
|
stacked: "h-4 w-4 mt-0.5"
|
|
57064
58278
|
};
|
|
57065
|
-
function DeviceItemHeader({ trpc, device, variant, flags, parent, integrationIcon, hasChildren, expanded, onToggleExpand, onNavigateToParent, stacked = false, nameOverflow = "truncate" }) {
|
|
58279
|
+
function DeviceItemHeader({ trpc, device, variant, flags, parent, integrationIcon, hasChildren, expanded, onToggleExpand, onNavigateToParent, stacked = false, nameOverflow = "truncate", nameForm = "compact" }) {
|
|
57066
58280
|
const t = useUiText();
|
|
57067
58281
|
const containerChildren = useContainerChildren(device.id);
|
|
57068
58282
|
const roleDefaults = useRoleDisplayDefaults();
|
|
@@ -57073,6 +58287,13 @@ function DeviceItemHeader({ trpc, device, variant, flags, parent, integrationIco
|
|
|
57073
58287
|
const slotClass = stacked ? CHEVRON_SLOT_CLASS.stacked : CHEVRON_SLOT_CLASS.horizontal;
|
|
57074
58288
|
const iconClass = cn("text-foreground-subtle flex-shrink-0", stacked ? "h-4 w-4 mt-0.5" : variant === "minimal" ? "h-3 w-3" : "h-3.5 w-3.5");
|
|
57075
58289
|
const lineClass = nameOverflow === "scroll" ? NAME_TEXT_CLASS : "truncate";
|
|
58290
|
+
const nameParent = nameForm === "nested" && parent !== null ? {
|
|
58291
|
+
id: parent.id,
|
|
58292
|
+
name: parent.name,
|
|
58293
|
+
type: parent.type ?? "unknown",
|
|
58294
|
+
stableId: ""
|
|
58295
|
+
} : void 0;
|
|
58296
|
+
const parentLabel = useDeviceLabelById(parent?.id ?? 0, "compact", parent?.name);
|
|
57076
58297
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
57077
58298
|
className: cn(stacked ? "flex items-start gap-2 w-full min-w-0" : "flex items-center gap-2 flex-1 min-w-0"),
|
|
57078
58299
|
children: [
|
|
@@ -57103,11 +58324,12 @@ function DeviceItemHeader({ trpc, device, variant, flags, parent, integrationIco
|
|
|
57103
58324
|
children: [flags.showIntegrationIcon && integrationIcon && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
57104
58325
|
className: "flex-shrink-0",
|
|
57105
58326
|
children: integrationIcon
|
|
57106
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(
|
|
57107
|
-
|
|
57108
|
-
|
|
57109
|
-
|
|
57110
|
-
|
|
58327
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(DeviceName, {
|
|
58328
|
+
device,
|
|
58329
|
+
form: nameForm,
|
|
58330
|
+
...nameParent !== void 0 ? { parent: nameParent } : {},
|
|
58331
|
+
testId: "device-name",
|
|
58332
|
+
className: cn("font-semibold text-foreground", stacked ? "text-[13px] leading-snug line-clamp-2 break-words" : cn(lineClass, variant === "minimal" ? "text-[10.5px]" : "text-[11px]"))
|
|
57111
58333
|
})]
|
|
57112
58334
|
}),
|
|
57113
58335
|
(flags.showId || flags.showStableId) && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
@@ -57136,12 +58358,12 @@ function DeviceItemHeader({ trpc, device, variant, flags, parent, integrationIco
|
|
|
57136
58358
|
},
|
|
57137
58359
|
className: cn("mt-0.5 inline-flex items-center gap-1 text-[9px] text-foreground-subtle hover:text-primary transition-colors", nameOverflow === "scroll" ? "md:max-w-full" : "max-w-full"),
|
|
57138
58360
|
title: t("uiLibrary.deviceItemHeader.openParent", "Open parent: {{name}} (#{{id}})", {
|
|
57139
|
-
name:
|
|
58361
|
+
name: parentLabel,
|
|
57140
58362
|
id: parent.id
|
|
57141
58363
|
}),
|
|
57142
58364
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Network, { className: "h-2.5 w-2.5 shrink-0" }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
57143
58365
|
className: lineClass,
|
|
57144
|
-
children: t("uiLibrary.deviceItemHeader.under", "Under: {{name}}", { name:
|
|
58366
|
+
children: t("uiLibrary.deviceItemHeader.under", "Under: {{name}}", { name: parentLabel })
|
|
57145
58367
|
})]
|
|
57146
58368
|
})
|
|
57147
58369
|
]
|
|
@@ -57270,7 +58492,9 @@ function HoverZoomImage({ src, alt, caption, placeholder = "No image", thumbClas
|
|
|
57270
58492
|
* the 288 px hover zoom. */
|
|
57271
58493
|
var PREVIEW_SNAPSHOT_WIDTH = 480;
|
|
57272
58494
|
function DeviceItemPreview({ trpc, device, status, enabled, showStatusPills = false }) {
|
|
57273
|
-
const
|
|
58495
|
+
const liveActive = enabled && device.online;
|
|
58496
|
+
const deviceLabel = useDeviceLabel(device, "compact");
|
|
58497
|
+
const snapshot = useDeviceSnapshotImage(liveActive ? device.id : null, { width: PREVIEW_SNAPSHOT_WIDTH });
|
|
57274
58498
|
const isBatteryOperated = (device.features ?? []).includes("battery-operated");
|
|
57275
58499
|
const wantPills = showStatusPills && isBatteryOperated && !device.disabled;
|
|
57276
58500
|
const batteryStatus = useDeviceBattery(trpc, wantPills ? device.id : null);
|
|
@@ -57286,7 +58510,7 @@ function DeviceItemPreview({ trpc, device, status, enabled, showStatusPills = fa
|
|
|
57286
58510
|
wantLinkPill && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(NetworkLinkBadge, { status: linkStatus }),
|
|
57287
58511
|
enabled && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(HoverZoomImage, {
|
|
57288
58512
|
src: offline ? null : snapshot.src,
|
|
57289
|
-
alt:
|
|
58513
|
+
alt: deviceLabel,
|
|
57290
58514
|
placeholder,
|
|
57291
58515
|
thumbClassName: "h-7 w-7 rounded"
|
|
57292
58516
|
})
|
|
@@ -57509,6 +58733,14 @@ function DeviceItem(props) {
|
|
|
57509
58733
|
const flags = resolveFlags(props);
|
|
57510
58734
|
const variant = props.variant ?? "compact";
|
|
57511
58735
|
const view = props.view ?? "card";
|
|
58736
|
+
const nameForm = props.isAccessoryRow ? "nested" : "compact";
|
|
58737
|
+
const nameParent = nameForm === "nested" && parent ? {
|
|
58738
|
+
id: parent.id,
|
|
58739
|
+
name: parent.name,
|
|
58740
|
+
type: parent.type ?? "unknown",
|
|
58741
|
+
stableId: ""
|
|
58742
|
+
} : void 0;
|
|
58743
|
+
const rowLabel = useDeviceLabel(device, nameForm, nameParent !== void 0 ? { parent: nameParent } : void 0);
|
|
57512
58744
|
const enabled = !device.disabled;
|
|
57513
58745
|
const isCamera = device.isCamera ?? device.type.toLowerCase() === "camera";
|
|
57514
58746
|
const childrenList = props.children ?? [];
|
|
@@ -57584,7 +58816,7 @@ function DeviceItem(props) {
|
|
|
57584
58816
|
checked: selection.selected,
|
|
57585
58817
|
onChange: selection.onToggle,
|
|
57586
58818
|
onClick: (e) => e.stopPropagation(),
|
|
57587
|
-
"aria-label": t("uiLibrary.deviceItem.select", "Select {{name}}", { name:
|
|
58819
|
+
"aria-label": t("uiLibrary.deviceItem.select", "Select {{name}}", { name: rowLabel }),
|
|
57588
58820
|
className: "flex-shrink-0"
|
|
57589
58821
|
}),
|
|
57590
58822
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(DeviceItemHeader, {
|
|
@@ -57593,6 +58825,7 @@ function DeviceItem(props) {
|
|
|
57593
58825
|
variant,
|
|
57594
58826
|
flags,
|
|
57595
58827
|
parent: parent ?? null,
|
|
58828
|
+
nameForm,
|
|
57596
58829
|
integrationIcon: integrationIcon ?? null,
|
|
57597
58830
|
hasChildren,
|
|
57598
58831
|
expanded,
|
|
@@ -57661,7 +58894,7 @@ function DeviceItem(props) {
|
|
|
57661
58894
|
checked: selection.selected,
|
|
57662
58895
|
onChange: selection.onToggle,
|
|
57663
58896
|
onClick: (e) => e.stopPropagation(),
|
|
57664
|
-
"aria-label": t("uiLibrary.deviceItem.select", "Select {{name}}", { name:
|
|
58897
|
+
"aria-label": t("uiLibrary.deviceItem.select", "Select {{name}}", { name: rowLabel }),
|
|
57665
58898
|
className: "flex-shrink-0 mt-0.5"
|
|
57666
58899
|
}),
|
|
57667
58900
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(DeviceItemHeader, {
|
|
@@ -57670,6 +58903,7 @@ function DeviceItem(props) {
|
|
|
57670
58903
|
variant,
|
|
57671
58904
|
flags,
|
|
57672
58905
|
parent: parent ?? null,
|
|
58906
|
+
nameForm,
|
|
57673
58907
|
integrationIcon: integrationIcon ?? null,
|
|
57674
58908
|
hasChildren,
|
|
57675
58909
|
expanded,
|
|
@@ -57730,6 +58964,14 @@ function DeviceItemTableRow(props) {
|
|
|
57730
58964
|
const t = useUiText();
|
|
57731
58965
|
const { trpc, device, variant, flags, parent, integrationIcon, accessoryCount, adoptedCount, hasChildren, expanded, onToggleExpand, onNavigate, onRowClick, rowSelects, rowSelected, displayStatus, isCamera, showSnapshot, isAccessoryRow, indentLevel, className, renderRowAction, onDelete, selection, showTypeCell, showManufacturerCell, showFeaturesCell } = props;
|
|
57732
58966
|
const containerChildren = useContainerChildren(device.id);
|
|
58967
|
+
const nameForm = isAccessoryRow ? "nested" : "compact";
|
|
58968
|
+
const nameParent = nameForm === "nested" && parent ? {
|
|
58969
|
+
id: parent.id,
|
|
58970
|
+
name: parent.name,
|
|
58971
|
+
type: parent.type ?? "unknown",
|
|
58972
|
+
stableId: ""
|
|
58973
|
+
} : void 0;
|
|
58974
|
+
const rowLabel = useDeviceLabel(device, nameForm, nameParent !== void 0 ? { parent: nameParent } : void 0);
|
|
57733
58975
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("tr", {
|
|
57734
58976
|
onClick: onRowClick,
|
|
57735
58977
|
...rowSelects ? {
|
|
@@ -57754,7 +58996,7 @@ function DeviceItemTableRow(props) {
|
|
|
57754
58996
|
checked: selection.selected,
|
|
57755
58997
|
onChange: selection.onToggle,
|
|
57756
58998
|
onClick: (e) => e.stopPropagation(),
|
|
57757
|
-
"aria-label": t("uiLibrary.deviceItem.select", "Select {{name}}", { name:
|
|
58999
|
+
"aria-label": t("uiLibrary.deviceItem.select", "Select {{name}}", { name: rowLabel }),
|
|
57758
59000
|
className: "flex-shrink-0"
|
|
57759
59001
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(DeviceItemHeader, {
|
|
57760
59002
|
trpc,
|
|
@@ -57762,6 +59004,7 @@ function DeviceItemTableRow(props) {
|
|
|
57762
59004
|
variant,
|
|
57763
59005
|
flags,
|
|
57764
59006
|
parent,
|
|
59007
|
+
nameForm,
|
|
57765
59008
|
integrationIcon,
|
|
57766
59009
|
hasChildren,
|
|
57767
59010
|
expanded,
|
|
@@ -58500,13 +59743,13 @@ function TableRowGroup({ parent, accessories, hasAccessories, expanded, onToggle
|
|
|
58500
59743
|
function AccessorySubRow({ trpc, accessory, parentName, showType, showManufacturer, showFeatures, onNavigate, muted }) {
|
|
58501
59744
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(DeviceItem, {
|
|
58502
59745
|
trpc,
|
|
58503
|
-
device:
|
|
58504
|
-
...accessory,
|
|
58505
|
-
name: childListName(accessory, parentName)
|
|
58506
|
-
},
|
|
59746
|
+
device: accessory,
|
|
58507
59747
|
view: "table",
|
|
58508
59748
|
integrationIcon: null,
|
|
58509
|
-
parent: null
|
|
59749
|
+
parent: accessory.parentDeviceId === null ? null : {
|
|
59750
|
+
id: accessory.parentDeviceId,
|
|
59751
|
+
name: parentName
|
|
59752
|
+
},
|
|
58510
59753
|
isAccessoryRow: true,
|
|
58511
59754
|
showChildrenAccordion: false,
|
|
58512
59755
|
onNavigate: onNavigate ?? void 0,
|
|
@@ -59305,6 +60548,15 @@ function DeviceExportSetup({ addonId }) {
|
|
|
59305
60548
|
}), status.setup && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SetupSection, { setup: status.setup })]
|
|
59306
60549
|
});
|
|
59307
60550
|
}
|
|
60551
|
+
function ExportSelectCell({ device, checked, onToggle }) {
|
|
60552
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
60553
|
+
type: "checkbox",
|
|
60554
|
+
checked,
|
|
60555
|
+
onChange: onToggle,
|
|
60556
|
+
onClick: (e) => e.stopPropagation(),
|
|
60557
|
+
"aria-label": useUiText()("uiLibrary.deviceExport.select", "Select {{name}}", { name: useDeviceLabel(device, "compact") })
|
|
60558
|
+
});
|
|
60559
|
+
}
|
|
59308
60560
|
/**
|
|
59309
60561
|
* Per-row Expose/Exposed toggle. Reflects whether the row's device is exposed
|
|
59310
60562
|
* to THIS exporter and flips it through the SAME runner the bulk buttons use —
|
|
@@ -59316,6 +60568,7 @@ function DeviceExportSetup({ addonId }) {
|
|
|
59316
60568
|
*/
|
|
59317
60569
|
function ExportRowToggle({ addonId, device, exposed, busy, onToggle }) {
|
|
59318
60570
|
const t = useUiText();
|
|
60571
|
+
const deviceLabel = useDeviceLabel(device, "compact");
|
|
59319
60572
|
const handleClick = (e) => {
|
|
59320
60573
|
e.stopPropagation();
|
|
59321
60574
|
if (busy) return;
|
|
@@ -59326,7 +60579,7 @@ function ExportRowToggle({ addonId, device, exposed, busy, onToggle }) {
|
|
|
59326
60579
|
variant: exposed ? "ghost" : "primary",
|
|
59327
60580
|
disabled: busy,
|
|
59328
60581
|
onClick: handleClick,
|
|
59329
|
-
"aria-label": exposed ? t("uiLibrary.deviceExport.unexposeDevice", "Unexpose {{name}}", { name:
|
|
60582
|
+
"aria-label": exposed ? t("uiLibrary.deviceExport.unexposeDevice", "Unexpose {{name}}", { name: deviceLabel }) : t("uiLibrary.deviceExport.exposeDevice", "Expose {{name}}", { name: deviceLabel }),
|
|
59330
60583
|
title: exposed ? t("uiLibrary.deviceExport.stopTitle", "Stop exposing to \"{{addon}}\"", { addon: addonId }) : t("uiLibrary.deviceExport.exposeTitle", "Expose to \"{{addon}}\"", { addon: addonId }),
|
|
59331
60584
|
children: exposed ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Unlink2, { className: "mr-1 h-3.5 w-3.5" }), t("uiLibrary.deviceExport.exposed", "Exposed")] }) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Share2, { className: "mr-1 h-3.5 w-3.5" }), t("uiLibrary.deviceExport.expose", "Expose")] })
|
|
59332
60585
|
});
|
|
@@ -59542,12 +60795,10 @@ function DeviceExportPanel({ addonId, onOpenDevice, showSetup = true }) {
|
|
|
59542
60795
|
key: "select",
|
|
59543
60796
|
header: "",
|
|
59544
60797
|
headerClassName: "w-8",
|
|
59545
|
-
cell: (device) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(
|
|
59546
|
-
|
|
60798
|
+
cell: (device) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ExportSelectCell, {
|
|
60799
|
+
device,
|
|
59547
60800
|
checked: selectedIds.has(String(device.id)),
|
|
59548
|
-
|
|
59549
|
-
onClick: (e) => e.stopPropagation(),
|
|
59550
|
-
"aria-label": t("uiLibrary.deviceExport.select", "Select {{name}}", { name: device.name })
|
|
60801
|
+
onToggle: () => toggleSelection(String(device.id))
|
|
59551
60802
|
})
|
|
59552
60803
|
},
|
|
59553
60804
|
{
|
|
@@ -59566,9 +60817,10 @@ function DeviceExportPanel({ addonId, onOpenDevice, showSetup = true }) {
|
|
|
59566
60817
|
{
|
|
59567
60818
|
key: "name",
|
|
59568
60819
|
header: t("uiLibrary.deviceExport.colName", "Name"),
|
|
59569
|
-
cell: (device) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(
|
|
59570
|
-
|
|
59571
|
-
|
|
60820
|
+
cell: (device) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(DeviceName, {
|
|
60821
|
+
device,
|
|
60822
|
+
form: "compact",
|
|
60823
|
+
className: "text-xs font-medium text-foreground"
|
|
59572
60824
|
})
|
|
59573
60825
|
},
|
|
59574
60826
|
{
|
|
@@ -66381,6 +67633,26 @@ function deviceGroupTitle(group, t = defaultUiText) {
|
|
|
66381
67633
|
function isDeviceNoun(noun) {
|
|
66382
67634
|
return noun === "camera" || noun === "device";
|
|
66383
67635
|
}
|
|
67636
|
+
/** Compact label for a device id. String ids (nodes, packages) keep the stored text. */
|
|
67637
|
+
function usePickerDeviceLabel(id, stored) {
|
|
67638
|
+
const lookedUp = useDeviceLabelById(typeof id === "number" ? id : 0, "compact", stored);
|
|
67639
|
+
return typeof id === "number" ? lookedUp : stored;
|
|
67640
|
+
}
|
|
67641
|
+
function PickerDeviceName({ id, stored, className }) {
|
|
67642
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
67643
|
+
className,
|
|
67644
|
+
children: usePickerDeviceLabel(id, stored)
|
|
67645
|
+
});
|
|
67646
|
+
}
|
|
67647
|
+
function PickerChip({ id, stored, removed, onRemove }) {
|
|
67648
|
+
const label = usePickerDeviceLabel(id, stored);
|
|
67649
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SelectedChip, {
|
|
67650
|
+
testId: `picker-chip-${String(id)}`,
|
|
67651
|
+
label,
|
|
67652
|
+
warning: removed,
|
|
67653
|
+
...onRemove !== void 0 ? { onRemove } : {}
|
|
67654
|
+
});
|
|
67655
|
+
}
|
|
66384
67656
|
function chipsOf(value, devices, fleet, noun, t) {
|
|
66385
67657
|
const byId = new Map(devices.map((device) => [device.id, device.name]));
|
|
66386
67658
|
const orphans = new Map(offListSelections(value, devices, fleet.devices, fleet.state).map((row) => [row.id, row]));
|
|
@@ -66416,7 +67688,7 @@ function DevicePicker({ devices: devicesIn, listState, fleet, value, onChange, s
|
|
|
66416
67688
|
const t = useUiText();
|
|
66417
67689
|
const groupTitle = groupTitleProp ?? ((group) => deviceGroupTitle(group, t));
|
|
66418
67690
|
const lockedNote = lockedNoteProp ?? t("uiLibrary.devicePicker.alreadyAdded", "Already added");
|
|
66419
|
-
const devices = (0, react$1.useMemo)(() => withResolvedParentDetail(devicesIn), [devicesIn]);
|
|
67691
|
+
const devices = (0, react$1.useMemo)(() => isDeviceNoun(noun) ? devicesIn : withResolvedParentDetail(devicesIn), [devicesIn, noun]);
|
|
66420
67692
|
const judge = fleet ?? {
|
|
66421
67693
|
state: listState,
|
|
66422
67694
|
devices: listState === "answered" ? devices : void 0
|
|
@@ -66451,10 +67723,10 @@ function DevicePicker({ devices: devicesIn, listState, fleet, value, onChange, s
|
|
|
66451
67723
|
chips.length === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
66452
67724
|
className: "text-[11px] text-foreground-subtle",
|
|
66453
67725
|
children: emptyLabel ?? (emptyMeansAll ? t("uiLibrary.devicePicker.everyNoRestriction", "Every {{noun}} — no restriction", { noun: pickerNounLabel(noun, t) }) : t("uiLibrary.devicePicker.noneSelected", "None selected"))
|
|
66454
|
-
}) : overflow.shown.map((chip) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(
|
|
66455
|
-
|
|
66456
|
-
|
|
66457
|
-
|
|
67726
|
+
}) : overflow.shown.map((chip) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(PickerChip, {
|
|
67727
|
+
id: chip.id,
|
|
67728
|
+
stored: chip.label,
|
|
67729
|
+
removed: chip.removed,
|
|
66458
67730
|
...!disabled ? { onRemove: () => onChange(value.filter((id) => id !== chip.id)) } : {}
|
|
66459
67731
|
}, chip.id)),
|
|
66460
67732
|
overflow.hidden > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
@@ -66747,9 +68019,10 @@ function PickerRowView({ row, value, onChange, onToggleGroup, annotate, groupTit
|
|
|
66747
68019
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
66748
68020
|
className: "flex min-w-0 flex-1 flex-col",
|
|
66749
68021
|
children: [
|
|
66750
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(
|
|
66751
|
-
|
|
66752
|
-
|
|
68022
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(PickerDeviceName, {
|
|
68023
|
+
id: row.device.id,
|
|
68024
|
+
stored: row.device.name,
|
|
68025
|
+
className: "truncate"
|
|
66753
68026
|
}),
|
|
66754
68027
|
second !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
66755
68028
|
className: "truncate text-[10px] text-foreground-subtle",
|
|
@@ -69840,10 +71113,14 @@ exports.DEVICE_COLUMNS = DEVICE_COLUMNS;
|
|
|
69840
71113
|
exports.DEVICE_EXPORT_PAGE_SIZE_KEY = DEVICE_EXPORT_PAGE_SIZE_KEY;
|
|
69841
71114
|
exports.DEVICE_LIST_PAGE_SIZE_KEY = DEVICE_LIST_PAGE_SIZE_KEY;
|
|
69842
71115
|
exports.DEVICE_LIST_PAGE_SIZE_OPTIONS = DEVICE_LIST_PAGE_SIZE_OPTIONS;
|
|
71116
|
+
exports.DEVICE_NAME_FORMS = DEVICE_NAME_FORMS;
|
|
71117
|
+
exports.DEVICE_NAME_JOIN = DEVICE_NAME_JOIN;
|
|
69843
71118
|
exports.DEVICE_PICKER_GROUP_STORAGE_KEY = DEVICE_PICKER_GROUP_STORAGE_KEY;
|
|
69844
71119
|
exports.DEVICE_ROLE_META = DEVICE_ROLE_META;
|
|
71120
|
+
exports.DEVICE_ROLE_NOUNS = DEVICE_ROLE_NOUNS;
|
|
69845
71121
|
exports.DEVICE_TYPE_CONTROL = DEVICE_TYPE_CONTROL;
|
|
69846
71122
|
exports.DEVICE_TYPE_META = DEVICE_TYPE_META;
|
|
71123
|
+
exports.DEVICE_TYPE_NOUNS = DEVICE_TYPE_NOUNS;
|
|
69847
71124
|
exports.DataRecordsHub = DataRecordsHub;
|
|
69848
71125
|
exports.DataTable = DataTable;
|
|
69849
71126
|
exports.DataTableFilterBar = DataTableFilterBar;
|
|
@@ -69860,11 +71137,14 @@ exports.DeviceContextProvider = DeviceContextProvider;
|
|
|
69860
71137
|
exports.DeviceExportPanel = DeviceExportPanel;
|
|
69861
71138
|
exports.DeviceExportSetup = DeviceExportSetup;
|
|
69862
71139
|
exports.DeviceFilterBar = DeviceFilterBar;
|
|
71140
|
+
exports.DeviceFleetFromServer = DeviceFleetFromServer;
|
|
71141
|
+
exports.DeviceFleetProvider = DeviceFleetProvider;
|
|
69863
71142
|
exports.DeviceGrid = DeviceGrid;
|
|
69864
71143
|
exports.DeviceHistoryView = DeviceHistoryView;
|
|
69865
71144
|
exports.DeviceItem = DeviceItem;
|
|
69866
71145
|
exports.DeviceList = DeviceList;
|
|
69867
71146
|
exports.DeviceMultiSelectField = DeviceMultiSelectField;
|
|
71147
|
+
exports.DeviceName = DeviceName;
|
|
69868
71148
|
exports.DevicePicker = DevicePicker;
|
|
69869
71149
|
exports.DeviceQuickDetailProvider = DeviceQuickDetailProvider;
|
|
69870
71150
|
exports.DeviceSelectField = DeviceSelectField;
|
|
@@ -70293,6 +71573,7 @@ exports.ViewSwitch = ViewSwitch;
|
|
|
70293
71573
|
exports.VodPlaybackProvider = VodPlaybackProvider;
|
|
70294
71574
|
exports.Volume2 = Volume2;
|
|
70295
71575
|
exports.VolumeX = VolumeX;
|
|
71576
|
+
exports.WashingMachine = WashingMachine;
|
|
70296
71577
|
exports.WaterHeaterHeroCard = WaterHeaterHeroCard;
|
|
70297
71578
|
exports.WaterHeaterInlineControl = WaterHeaterInlineControl;
|
|
70298
71579
|
exports.Waves = Waves;
|
|
@@ -70395,6 +71676,7 @@ exports.describeDeviceSelector = describeDeviceSelector;
|
|
|
70395
71676
|
exports.deviceIntegrationResolver = deviceIntegrationResolver;
|
|
70396
71677
|
exports.deviceListStateOf = deviceListStateOf;
|
|
70397
71678
|
exports.deviceMatchesFilter = deviceMatchesFilter;
|
|
71679
|
+
exports.deviceNameNouns = deviceNameNouns;
|
|
70398
71680
|
exports.deviceOptionLabel = deviceOptionLabel;
|
|
70399
71681
|
exports.deviceRoleMeta = deviceRoleMeta;
|
|
70400
71682
|
exports.deviceRoleMetaOf = deviceRoleMetaOf;
|
|
@@ -70422,10 +71704,12 @@ exports.findTimezone = _camstack_types.findTimezone;
|
|
|
70422
71704
|
exports.flattenPickerGrouping = flattenPickerGrouping;
|
|
70423
71705
|
exports.flattenPickerRows = flattenPickerRows;
|
|
70424
71706
|
exports.fleetViewOf = fleetViewOf;
|
|
71707
|
+
exports.foldDeviceName = foldDeviceName;
|
|
70425
71708
|
exports.formatChartBytes = formatChartBytes;
|
|
70426
71709
|
exports.formatChartNumber = formatChartNumber;
|
|
70427
71710
|
exports.formatChartValue = formatChartValue;
|
|
70428
71711
|
exports.formatControlDateTime = formatControlDateTime;
|
|
71712
|
+
exports.formatDeviceName = formatDeviceName;
|
|
70429
71713
|
exports.formatLastSeen = formatLastSeen;
|
|
70430
71714
|
exports.formatNumeric = formatNumeric;
|
|
70431
71715
|
exports.formatSettingValue = formatSettingValue;
|
|
@@ -70453,6 +71737,7 @@ exports.humanizeName = humanizeName;
|
|
|
70453
71737
|
exports.humidifierTint = humidifierTint;
|
|
70454
71738
|
exports.iconGlyphsFailed = iconGlyphsFailed;
|
|
70455
71739
|
exports.iconGlyphsLoaded = iconGlyphsLoaded;
|
|
71740
|
+
exports.indexDeviceNames = indexDeviceNames;
|
|
70456
71741
|
exports.initialScrubState = initialScrubState;
|
|
70457
71742
|
exports.insertAtSelection = insertAtSelection;
|
|
70458
71743
|
exports.isAbsentProvider = isAbsentProvider;
|
|
@@ -70460,6 +71745,7 @@ exports.isAbsentProvider$1 = isAbsentProvider;
|
|
|
70460
71745
|
exports.isByteUnit = isByteUnit;
|
|
70461
71746
|
exports.isConsumableLevelField = isConsumableLevelField;
|
|
70462
71747
|
exports.isDataTableFilterActive = isDataTableFilterActive;
|
|
71748
|
+
exports.isDeviceNameStock = isDeviceNameStock;
|
|
70463
71749
|
Object.defineProperty(exports, "isDrawableSubjectPath", {
|
|
70464
71750
|
enumerable: true,
|
|
70465
71751
|
get: function() {
|
|
@@ -70501,6 +71787,7 @@ exports.nodeTextColorClass = nodeTextColorClass;
|
|
|
70501
71787
|
exports.normalizeForSearch = normalizeForSearch;
|
|
70502
71788
|
exports.normalizeLanguage = normalizeLanguage;
|
|
70503
71789
|
exports.normalizeSelection = normalizeSelection;
|
|
71790
|
+
exports.nounSpecFor = nounSpecFor;
|
|
70504
71791
|
exports.occupancyFacets = occupancyFacets;
|
|
70505
71792
|
exports.occupancyLines = occupancyLines;
|
|
70506
71793
|
exports.offListSelections = offListSelections;
|
|
@@ -70555,6 +71842,7 @@ exports.resolveContainerPrimary = resolveContainerPrimary;
|
|
|
70555
71842
|
exports.resolveControlAlign = resolveControlAlign;
|
|
70556
71843
|
exports.resolveDeviceControl = resolveDeviceControl;
|
|
70557
71844
|
exports.resolveDeviceIntegration = resolveDeviceIntegration;
|
|
71845
|
+
exports.resolveDeviceLabel = resolveDeviceLabel;
|
|
70558
71846
|
exports.resolveDisplayIcon = resolveDisplayIcon;
|
|
70559
71847
|
exports.resolveEffectiveDefaultModel = resolveEffectiveDefaultModel;
|
|
70560
71848
|
exports.resolveEffectiveStepModel = resolveEffectiveStepModel;
|
|
@@ -70573,6 +71861,7 @@ exports.rootSourceState = rootSourceState;
|
|
|
70573
71861
|
exports.routerBasename = routerBasename;
|
|
70574
71862
|
exports.runningDurationSince = runningDurationSince;
|
|
70575
71863
|
exports.runningStatusParts = runningStatusParts;
|
|
71864
|
+
exports.sameDeviceName = sameDeviceName;
|
|
70576
71865
|
exports.sameLocationSuggestions = sameLocationSuggestions;
|
|
70577
71866
|
exports.scrubReducer = scrubReducer;
|
|
70578
71867
|
exports.searchSteps = searchSteps;
|
|
@@ -70606,6 +71895,7 @@ exports.stepFieldDomId = stepFieldDomId;
|
|
|
70606
71895
|
exports.stepHasModelForFormat = stepHasModelForFormat;
|
|
70607
71896
|
exports.stepLocalFields = stepLocalFields;
|
|
70608
71897
|
exports.stepModelOptions = stepModelOptions;
|
|
71898
|
+
exports.stripDeviceParentPrefix = stripDeviceParentPrefix;
|
|
70609
71899
|
exports.stripParentNamePrefix = stripParentNamePrefix;
|
|
70610
71900
|
Object.defineProperty(exports, "subjectPathSampleFromBox", {
|
|
70611
71901
|
enumerable: true,
|
|
@@ -70903,6 +72193,8 @@ exports.useDeviceHistoryRecord = useDeviceHistoryRecord;
|
|
|
70903
72193
|
exports.useDeviceHistoryRecordBuckets = useDeviceHistoryRecordBuckets;
|
|
70904
72194
|
exports.useDeviceHistorySetDeviceEnabled = useDeviceHistorySetDeviceEnabled;
|
|
70905
72195
|
exports.useDeviceId = useDeviceId;
|
|
72196
|
+
exports.useDeviceLabel = useDeviceLabel;
|
|
72197
|
+
exports.useDeviceLabelById = useDeviceLabelById;
|
|
70906
72198
|
exports.useDeviceListPageSize = useDeviceListPageSize;
|
|
70907
72199
|
exports.useDeviceManagerAddLocation = useDeviceManagerAddLocation;
|
|
70908
72200
|
exports.useDeviceManagerAdoptDevice = useDeviceManagerAdoptDevice;
|
|
@@ -70996,6 +72288,8 @@ exports.useDeviceManagerTestField = useDeviceManagerTestField;
|
|
|
70996
72288
|
exports.useDeviceManagerUpdateConfig = useDeviceManagerUpdateConfig;
|
|
70997
72289
|
exports.useDeviceManagerUpdateDeviceField = useDeviceManagerUpdateDeviceField;
|
|
70998
72290
|
exports.useDeviceManagerUpdateDeviceFieldsBatch = useDeviceManagerUpdateDeviceFieldsBatch;
|
|
72291
|
+
exports.useDeviceNameIndex = useDeviceNameIndex;
|
|
72292
|
+
exports.useDeviceNameNouns = useDeviceNameNouns;
|
|
70999
72293
|
exports.useDeviceNetworkLink = useDeviceNetworkLink;
|
|
71000
72294
|
exports.useDeviceOpsGetConfigEntries = useDeviceOpsGetConfigEntries;
|
|
71001
72295
|
exports.useDeviceOpsGetRawState = useDeviceOpsGetRawState;
|
|
@@ -71213,6 +72507,7 @@ exports.useMeshNetworkListPeers = useMeshNetworkListPeers;
|
|
|
71213
72507
|
exports.useMeshNetworkLogout = useMeshNetworkLogout;
|
|
71214
72508
|
exports.useMeshNetworkStartLogin = useMeshNetworkStartLogin;
|
|
71215
72509
|
exports.useMeshNetworkTestConnection = useMeshNetworkTestConnection;
|
|
72510
|
+
exports.useMeterGetStatus = useMeterGetStatus;
|
|
71216
72511
|
exports.useMetricsProviderCollectSnapshot = useMetricsProviderCollectSnapshot;
|
|
71217
72512
|
exports.useMetricsProviderGetAddonStats = useMetricsProviderGetAddonStats;
|
|
71218
72513
|
exports.useMetricsProviderGetCached = useMetricsProviderGetCached;
|