Skip to content

Commit 559cf06

Browse files
committed
feat(39): highlight entity connections on hover
1 parent e891fa7 commit 559cf06

File tree

4 files changed

+43
-5
lines changed

4 files changed

+43
-5
lines changed

src/ha-sankey-chart.ts

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ export class SankeyChart extends LitElement {
7474
@state() private statePerPixelY = 0;
7575
@state() private lastUpdate = 0;
7676
@state() private entityStates: Map<EntityConfigInternal, NormalizedState> = new Map();
77+
@state() private highlightedEntities: EntityConfigInternal[] = [];
7778

7879
// https://lit.dev/docs/components/properties/#accessors-custom
7980
public setConfig(config: SankeyChartConfig): void {
@@ -136,6 +137,9 @@ export class SankeyChart extends LitElement {
136137
if (!this.config) {
137138
return false;
138139
}
140+
if (changedProps.has('highlightedEntities')) {
141+
return true;
142+
}
139143
const now = Date.now();
140144
if (this.config.throttle && now - this.lastUpdate < this.config.throttle) {
141145
// woah there
@@ -386,10 +390,39 @@ export class SankeyChart extends LitElement {
386390
return { boxes: result, statePerPixelY: this.statePerPixelY };
387391
}
388392

393+
private highlightPath(entityConf: EntityConfigInternal, direction: 'parents' | 'children') {
394+
this.highlightedEntities.push(entityConf);
395+
if (direction === 'children') {
396+
this.connectionsByParent.get(entityConf)?.forEach(c => {
397+
c.highlighted = true;
398+
this.highlightPath(c.child, 'children');
399+
});
400+
} else {
401+
this.connectionsByChild.get(entityConf)?.forEach(c => {
402+
c.highlighted = true;
403+
this.highlightPath(c.parent, 'parents');
404+
});
405+
}
406+
}
407+
389408
private _handleBoxClick(box: Box): void {
390409
fireEvent(this, 'hass-more-info', { entityId: box.entity_id });
391410
}
392411

412+
private _handleMouseEnter(box: Box): void {
413+
this.highlightPath(box.config, 'children');
414+
this.highlightPath(box.config, 'parents');
415+
// trigger rerender
416+
this.highlightedEntities = [...this.highlightedEntities];
417+
}
418+
419+
private _handleMouseLeave(): void {
420+
this.highlightedEntities = [];
421+
this.connections.forEach(c => {
422+
c.highlighted = false;
423+
});
424+
}
425+
393426
// private _handleAction(ev: ActionHandlerEvent): void {
394427
// console.log('@TODO');
395428
// if (this.hass && this.config && ev.detail.action) {
@@ -505,7 +538,10 @@ export class SankeyChart extends LitElement {
505538
<div
506539
style=${styleMap({ backgroundColor: box.color })}
507540
@click=${() => this._handleBoxClick(box)}
541+
@mouseenter=${() => this._handleMouseEnter(box)}
542+
@mouseleave=${this._handleMouseLeave}
508543
title=${name}
544+
class=${this.highlightedEntities.includes(box.config) ? 'hl' : ''}
509545
>
510546
${show_icons && isNotPassthrough
511547
? html`<ha-icon .icon=${stateIcon(entity as HassEntity)}></ha-icon>`
@@ -570,7 +606,7 @@ export class SankeyChart extends LitElement {
570606
<path d="M0,${c.startY} C50,${c.startY} 50,${c.endY} 100,${c.endY} L100,${c.endY + c.endSize} C50,${
571607
c.endY + c.endSize
572608
} 50,${c.startY + c.startSize} 0,${c.startY + c.startSize} Z"
573-
fill="url(#gradient${b.entity_id + i})" />
609+
fill="url(#gradient${b.entity_id + i})" fill-opacity="${c.highlighted ? 0.85 : 0.4}" />
574610
`,
575611
)}
576612
`;

src/styles.ts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,9 @@ export default css`
5555
.box.type-passthrough div:first-child {
5656
opacity: 0.4;
5757
}
58+
.box.type-passthrough div.hl:first-child {
59+
opacity: 0.85;
60+
}
5861
.box .label {
5962
flex: 1;
6063
display: flex;
@@ -78,8 +81,4 @@ export default css`
7881
width: 100%;
7982
height: 100%;
8083
}
81-
.connectors path {
82-
/* fill: var(--primary-color); */
83-
opacity: 0.4;
84-
}
8584
`;

src/types.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ export interface Connection {
8080
state: number;
8181
startColor?: string;
8282
endColor?: string;
83+
highlighted?: boolean,
8384
}
8485

8586
export interface Box {
@@ -114,6 +115,7 @@ export interface ConnectionState {
114115
prevParentState: number,
115116
prevChildState: number,
116117
ready: boolean,
118+
highlighted?: boolean,
117119
}
118120

119121
export interface NormalizedState {

src/utils.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ export function getChildConnections(parent: Box, children: Box[], connections?:
6868
endSize,
6969
endColor: child.color,
7070
state,
71+
highlighted: connection.highlighted,
7172
};
7273
});
7374
}

0 commit comments

Comments
 (0)