-
Notifications
You must be signed in to change notification settings - Fork 68
Expand file tree
/
Copy pathutil.js
More file actions
91 lines (79 loc) · 3.94 KB
/
Copy pathutil.js
File metadata and controls
91 lines (79 loc) · 3.94 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
import { LAST_CHANGED, LAST_UPDATED, SECONDARY_INFO_VALUES, UNAVAILABLE_STATES } from './lib/constants';
export const isObject = (obj) => typeof obj === 'object' && !Array.isArray(obj) && !!obj;
// bubbles + composed so the event crosses our shadow root up to HA's root-level listener.
export const fireEvent = (node, type, detail) => {
const event = new Event(type, { bubbles: true, composed: true });
event.detail = detail;
node.dispatchEvent(event);
};
export const isUnavailable = (stateObj) => !stateObj || UNAVAILABLE_STATES.includes(stateObj.state);
export const hideUnavailable = (stateObj, config) =>
config.hide_unavailable &&
(isUnavailable(stateObj) ||
(config.attribute &&
![LAST_CHANGED, LAST_UPDATED].includes(config.attribute) &&
stateObj.attributes[config.attribute] === undefined));
export const hideIf = (stateObj, config, hass) => {
if (hideUnavailable(stateObj, config)) {
return true;
}
if (config.hide_if === undefined) {
return false;
}
let value;
if (isObject(config.hide_if) && (config.hide_if.entity || config.hide_if.attribute)) {
// Evaluate against another entity and/or attribute instead of the displayed value (see
// #280). A missing referenced entity yields undefined, so no criteria match and the
// entity stays visible - deliberately not falling back to the entity's own state, which
// would silently hide/show on the wrong value.
const sourceObj = config.hide_if.entity ? hass?.states[config.hide_if.entity] : stateObj;
value = config.hide_if.attribute ? sourceObj?.attributes[config.hide_if.attribute] : sourceObj?.state;
} else {
value = config.attribute ? stateObj.attributes[config.attribute] : stateObj.state;
}
let hideValues = [];
if (isObject(config.hide_if)) {
if (config.hide_if.below && value < config.hide_if.below) {
return true;
}
if (config.hide_if.above && value > config.hide_if.above) {
return true;
}
if (config.hide_if.value) {
hideValues = hideValues.concat(config.hide_if.value);
}
} else {
hideValues = hideValues.concat(config.hide_if);
}
return hideValues.some((hideValue) => (typeof hideValue === 'number' ? hideValue === +value : hideValue === value));
};
export const hasGenericSecondaryInfo = (config) => typeof config === 'string' && SECONDARY_INFO_VALUES.includes(config);
// hide_if.entity ids must be tracked too, or hasConfigOrEntitiesChanged would skip re-rendering
// when only the referenced entity's state changes and the row would never hide/unhide.
export const getEntityIds = (config) =>
[config.entity, config.secondary_info?.entity, config.secondary_info?.hide_if?.entity]
.concat(
config.entities?.flatMap((entity) =>
typeof entity === 'string' ? entity : [entity.entity, entity.hide_if?.entity]
)
)
.filter((entity) => entity);
// HA installs stub formatEntityName/formatEntityState/formatEntityAttributeValue functions on
// initial connection (returning raw, unformatted values) and replaces them asynchronously with
// the real implementations once translations load. None of that swap is otherwise observable, so
// without this check a row can get stuck showing stale/raw output until some unrelated entity
// state change happens to force a re-render.
const HASS_FORMATTER_KEYS = ['formatEntityName', 'formatEntityState', 'formatEntityAttributeValue'];
export const hasConfigOrEntitiesChanged = (node, changedProps) => {
if (changedProps.has('config')) {
return true;
}
const oldHass = changedProps.get('_hass');
if (oldHass) {
if (HASS_FORMATTER_KEYS.some((key) => oldHass[key] !== node._hass[key])) {
return true;
}
return node.entityIds.some((entity) => oldHass.states[entity] !== node._hass.states[entity]);
}
return false;
};