mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-28 03:36:44 +00:00
Clean domain icons (#19533)
* Use state icon inside alarm control panel card * Add domain icon component and clean old files * Clean code * Migrate area card * Remove some icon rules * Update ha-bar-media-player.ts Co-authored-by: Bram Kragten <mail@bramkragten.nl> * Update ha-domain-icon.ts Co-authored-by: Bram Kragten <mail@bramkragten.nl> --------- Co-authored-by: Bram Kragten <mail@bramkragten.nl>
This commit is contained in:
parent
6dcc70f6fc
commit
314499005d
@ -1,6 +1,7 @@
|
|||||||
/** Constants to be used in the frontend. */
|
/** Constants to be used in the frontend. */
|
||||||
|
|
||||||
import {
|
import {
|
||||||
|
mdiAccount,
|
||||||
mdiAirFilter,
|
mdiAirFilter,
|
||||||
mdiAlert,
|
mdiAlert,
|
||||||
mdiAngleAcute,
|
mdiAngleAcute,
|
||||||
@ -50,8 +51,10 @@ import {
|
|||||||
mdiProgressClock,
|
mdiProgressClock,
|
||||||
mdiRayVertex,
|
mdiRayVertex,
|
||||||
mdiRemote,
|
mdiRemote,
|
||||||
|
mdiRobot,
|
||||||
mdiRobotMower,
|
mdiRobotMower,
|
||||||
mdiRobotVacuum,
|
mdiRobotVacuum,
|
||||||
|
mdiRoomService,
|
||||||
mdiScriptText,
|
mdiScriptText,
|
||||||
mdiSineWave,
|
mdiSineWave,
|
||||||
mdiSpeakerMessage,
|
mdiSpeakerMessage,
|
||||||
@ -61,6 +64,7 @@ import {
|
|||||||
mdiThermometerLines,
|
mdiThermometerLines,
|
||||||
mdiThermostat,
|
mdiThermostat,
|
||||||
mdiTimerOutline,
|
mdiTimerOutline,
|
||||||
|
mdiToggleSwitch,
|
||||||
mdiTransmissionTower,
|
mdiTransmissionTower,
|
||||||
mdiWater,
|
mdiWater,
|
||||||
mdiWaterPercent,
|
mdiWaterPercent,
|
||||||
@ -69,6 +73,7 @@ import {
|
|||||||
mdiWeatherRainy,
|
mdiWeatherRainy,
|
||||||
mdiWeatherWindy,
|
mdiWeatherWindy,
|
||||||
mdiWeight,
|
mdiWeight,
|
||||||
|
mdiWhiteBalanceSunny,
|
||||||
mdiWifi,
|
mdiWifi,
|
||||||
} from "@mdi/js";
|
} from "@mdi/js";
|
||||||
|
|
||||||
@ -78,6 +83,9 @@ import { mdiHomeAssistant } from "../resources/home-assistant-logo-svg";
|
|||||||
// Arrays with values should be alphabetically sorted if order doesn't matter.
|
// Arrays with values should be alphabetically sorted if order doesn't matter.
|
||||||
// Each constant should have a description what it is supposed to be used for.
|
// Each constant should have a description what it is supposed to be used for.
|
||||||
|
|
||||||
|
/** Icon to use when no icon specified for service. */
|
||||||
|
export const DEFAULT_SERVICE_ICON = mdiRoomService;
|
||||||
|
|
||||||
/** Icon to use when no icon specified for domain. */
|
/** Icon to use when no icon specified for domain. */
|
||||||
export const DEFAULT_DOMAIN_ICON = mdiBookmark;
|
export const DEFAULT_DOMAIN_ICON = mdiBookmark;
|
||||||
|
|
||||||
@ -85,20 +93,23 @@ export const DEFAULT_DOMAIN_ICON = mdiBookmark;
|
|||||||
export const FIXED_DOMAIN_ICONS = {
|
export const FIXED_DOMAIN_ICONS = {
|
||||||
air_quality: mdiAirFilter,
|
air_quality: mdiAirFilter,
|
||||||
alert: mdiAlert,
|
alert: mdiAlert,
|
||||||
|
automation: mdiRobot,
|
||||||
calendar: mdiCalendar,
|
calendar: mdiCalendar,
|
||||||
climate: mdiThermostat,
|
climate: mdiThermostat,
|
||||||
configurator: mdiCog,
|
configurator: mdiCog,
|
||||||
conversation: mdiMicrophoneMessage,
|
conversation: mdiMicrophoneMessage,
|
||||||
counter: mdiCounter,
|
counter: mdiCounter,
|
||||||
datetime: mdiCalendarClock,
|
|
||||||
date: mdiCalendar,
|
date: mdiCalendar,
|
||||||
|
datetime: mdiCalendarClock,
|
||||||
demo: mdiHomeAssistant,
|
demo: mdiHomeAssistant,
|
||||||
|
device_tracker: mdiAccount,
|
||||||
google_assistant: mdiGoogleAssistant,
|
google_assistant: mdiGoogleAssistant,
|
||||||
group: mdiGoogleCirclesCommunities,
|
group: mdiGoogleCirclesCommunities,
|
||||||
homeassistant: mdiHomeAssistant,
|
homeassistant: mdiHomeAssistant,
|
||||||
homekit: mdiHomeAutomation,
|
homekit: mdiHomeAutomation,
|
||||||
image: mdiImage,
|
|
||||||
image_processing: mdiImageFilterFrames,
|
image_processing: mdiImageFilterFrames,
|
||||||
|
image: mdiImage,
|
||||||
|
input_boolean: mdiToggleSwitch,
|
||||||
input_button: mdiButtonPointer,
|
input_button: mdiButtonPointer,
|
||||||
input_datetime: mdiCalendarClock,
|
input_datetime: mdiCalendarClock,
|
||||||
input_number: mdiRayVertex,
|
input_number: mdiRayVertex,
|
||||||
@ -110,6 +121,7 @@ export const FIXED_DOMAIN_ICONS = {
|
|||||||
notify: mdiCommentAlert,
|
notify: mdiCommentAlert,
|
||||||
number: mdiRayVertex,
|
number: mdiRayVertex,
|
||||||
persistent_notification: mdiBell,
|
persistent_notification: mdiBell,
|
||||||
|
person: mdiAccount,
|
||||||
plant: mdiFlower,
|
plant: mdiFlower,
|
||||||
proximity: mdiAppleSafari,
|
proximity: mdiAppleSafari,
|
||||||
remote: mdiRemote,
|
remote: mdiRemote,
|
||||||
@ -121,10 +133,11 @@ export const FIXED_DOMAIN_ICONS = {
|
|||||||
simple_alarm: mdiBell,
|
simple_alarm: mdiBell,
|
||||||
siren: mdiBullhorn,
|
siren: mdiBullhorn,
|
||||||
stt: mdiMicrophoneMessage,
|
stt: mdiMicrophoneMessage,
|
||||||
|
sun: mdiWhiteBalanceSunny,
|
||||||
text: mdiFormTextbox,
|
text: mdiFormTextbox,
|
||||||
todo: mdiClipboardList,
|
|
||||||
time: mdiClock,
|
time: mdiClock,
|
||||||
timer: mdiTimerOutline,
|
timer: mdiTimerOutline,
|
||||||
|
todo: mdiClipboardList,
|
||||||
tts: mdiSpeakerMessage,
|
tts: mdiSpeakerMessage,
|
||||||
vacuum: mdiRobotVacuum,
|
vacuum: mdiRobotVacuum,
|
||||||
wake_word: mdiChatSleep,
|
wake_word: mdiChatSleep,
|
||||||
|
@ -1,36 +0,0 @@
|
|||||||
/** Return an icon representing a alarm panel state. */
|
|
||||||
|
|
||||||
import {
|
|
||||||
mdiShieldLock,
|
|
||||||
mdiShieldAirplane,
|
|
||||||
mdiShieldHome,
|
|
||||||
mdiShieldMoon,
|
|
||||||
mdiSecurity,
|
|
||||||
mdiShieldOutline,
|
|
||||||
mdiBellRing,
|
|
||||||
mdiShieldOff,
|
|
||||||
mdiShield,
|
|
||||||
} from "@mdi/js";
|
|
||||||
|
|
||||||
export const alarmPanelIcon = (state?: string) => {
|
|
||||||
switch (state) {
|
|
||||||
case "armed_away":
|
|
||||||
return mdiShieldLock;
|
|
||||||
case "armed_vacation":
|
|
||||||
return mdiShieldAirplane;
|
|
||||||
case "armed_home":
|
|
||||||
return mdiShieldHome;
|
|
||||||
case "armed_night":
|
|
||||||
return mdiShieldMoon;
|
|
||||||
case "armed_custom_bypass":
|
|
||||||
return mdiSecurity;
|
|
||||||
case "pending":
|
|
||||||
return mdiShieldOutline;
|
|
||||||
case "triggered":
|
|
||||||
return mdiBellRing;
|
|
||||||
case "disarmed":
|
|
||||||
return mdiShieldOff;
|
|
||||||
default:
|
|
||||||
return mdiShield;
|
|
||||||
}
|
|
||||||
};
|
|
@ -1,92 +1,59 @@
|
|||||||
/** Return an icon representing a battery state. */
|
|
||||||
import {
|
|
||||||
mdiBattery,
|
|
||||||
mdiBattery10,
|
|
||||||
mdiBattery20,
|
|
||||||
mdiBattery30,
|
|
||||||
mdiBattery40,
|
|
||||||
mdiBattery50,
|
|
||||||
mdiBattery60,
|
|
||||||
mdiBattery70,
|
|
||||||
mdiBattery80,
|
|
||||||
mdiBattery90,
|
|
||||||
mdiBatteryAlert,
|
|
||||||
mdiBatteryAlertVariantOutline,
|
|
||||||
mdiBatteryCharging,
|
|
||||||
mdiBatteryCharging10,
|
|
||||||
mdiBatteryCharging20,
|
|
||||||
mdiBatteryCharging30,
|
|
||||||
mdiBatteryCharging40,
|
|
||||||
mdiBatteryCharging50,
|
|
||||||
mdiBatteryCharging60,
|
|
||||||
mdiBatteryCharging70,
|
|
||||||
mdiBatteryCharging80,
|
|
||||||
mdiBatteryCharging90,
|
|
||||||
mdiBatteryChargingOutline,
|
|
||||||
mdiBatteryUnknown,
|
|
||||||
} from "@mdi/js";
|
|
||||||
import { HassEntity } from "home-assistant-js-websocket";
|
import { HassEntity } from "home-assistant-js-websocket";
|
||||||
|
|
||||||
const BATTERY_ICONS = {
|
const BATTERY_ICONS = {
|
||||||
10: mdiBattery10,
|
10: "mdi:battery-10",
|
||||||
20: mdiBattery20,
|
20: "mdi:battery-20",
|
||||||
30: mdiBattery30,
|
30: "mdi:battery-30",
|
||||||
40: mdiBattery40,
|
40: "mdi:battery-40",
|
||||||
50: mdiBattery50,
|
50: "mdi:battery-50",
|
||||||
60: mdiBattery60,
|
60: "mdi:battery-60",
|
||||||
70: mdiBattery70,
|
70: "mdi:battery-70",
|
||||||
80: mdiBattery80,
|
80: "mdi:battery-80",
|
||||||
90: mdiBattery90,
|
90: "mdi:battery-90",
|
||||||
100: mdiBattery,
|
100: "mdi:battery",
|
||||||
};
|
};
|
||||||
const BATTERY_CHARGING_ICONS = {
|
const BATTERY_CHARGING_ICONS = {
|
||||||
10: mdiBatteryCharging10,
|
10: "mdi:battery-charging-10",
|
||||||
20: mdiBatteryCharging20,
|
20: "mdi:battery-charging-20",
|
||||||
30: mdiBatteryCharging30,
|
30: "mdi:battery-charging-30",
|
||||||
40: mdiBatteryCharging40,
|
40: "mdi:battery-charging-40",
|
||||||
50: mdiBatteryCharging50,
|
50: "mdi:battery-charging-50",
|
||||||
60: mdiBatteryCharging60,
|
60: "mdi:battery-charging-60",
|
||||||
70: mdiBatteryCharging70,
|
70: "mdi:battery-charging-70",
|
||||||
80: mdiBatteryCharging80,
|
80: "mdi:battery-charging-80",
|
||||||
90: mdiBatteryCharging90,
|
90: "mdi:battery-charging-90",
|
||||||
100: mdiBatteryCharging,
|
100: "mdi:battery-charging",
|
||||||
};
|
};
|
||||||
|
|
||||||
export const batteryStateIcon = (
|
export const batteryIcon = (stateObj: HassEntity, state?: string) => {
|
||||||
batteryState: HassEntity,
|
const level = state ?? stateObj.state;
|
||||||
batteryChargingState?: HassEntity
|
return batteryLevelIcon(level);
|
||||||
) => {
|
|
||||||
const battery = batteryState.state;
|
|
||||||
const batteryCharging =
|
|
||||||
batteryChargingState && batteryChargingState.state === "on";
|
|
||||||
|
|
||||||
return batteryIcon(battery, batteryCharging);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export const batteryIcon = (
|
export const batteryLevelIcon = (
|
||||||
batteryState: number | string,
|
batteryLevel: number | string,
|
||||||
batteryCharging?: boolean
|
isBatteryCharging?: boolean
|
||||||
) => {
|
): string => {
|
||||||
const batteryValue = Number(batteryState);
|
const batteryValue = Number(batteryLevel);
|
||||||
if (isNaN(batteryValue)) {
|
if (isNaN(batteryValue)) {
|
||||||
if (batteryState === "off") {
|
if (batteryLevel === "off") {
|
||||||
return mdiBattery;
|
return "mdi:battery";
|
||||||
}
|
}
|
||||||
if (batteryState === "on") {
|
if (batteryLevel === "on") {
|
||||||
return mdiBatteryAlert;
|
return "mdi:battery-alert";
|
||||||
}
|
}
|
||||||
return mdiBatteryUnknown;
|
return "mdi:battery-unknown";
|
||||||
}
|
}
|
||||||
|
|
||||||
const batteryRound = Math.round(batteryValue / 10) * 10;
|
const batteryRound = Math.round(batteryValue / 10) * 10;
|
||||||
if (batteryCharging && batteryValue >= 10) {
|
if (isBatteryCharging && batteryValue >= 10) {
|
||||||
return BATTERY_CHARGING_ICONS[batteryRound];
|
return BATTERY_CHARGING_ICONS[batteryRound];
|
||||||
}
|
}
|
||||||
if (batteryCharging) {
|
if (isBatteryCharging) {
|
||||||
return mdiBatteryChargingOutline;
|
return "mdi:battery-charging-outline";
|
||||||
}
|
}
|
||||||
if (batteryValue <= 5) {
|
if (batteryValue <= 5) {
|
||||||
return mdiBatteryAlertVariantOutline;
|
return "mdi:battery-alert-variant-outline";
|
||||||
}
|
}
|
||||||
return BATTERY_ICONS[batteryRound];
|
return BATTERY_ICONS[batteryRound];
|
||||||
};
|
};
|
||||||
|
@ -1,108 +0,0 @@
|
|||||||
import {
|
|
||||||
mdiAlertCircle,
|
|
||||||
mdiBattery,
|
|
||||||
mdiBatteryCharging,
|
|
||||||
mdiBatteryOutline,
|
|
||||||
mdiBrightness5,
|
|
||||||
mdiBrightness7,
|
|
||||||
mdiCheckboxMarkedCircle,
|
|
||||||
mdiCheckNetworkOutline,
|
|
||||||
mdiCloseNetworkOutline,
|
|
||||||
mdiCheckCircle,
|
|
||||||
mdiCropPortrait,
|
|
||||||
mdiDoorClosed,
|
|
||||||
mdiDoorOpen,
|
|
||||||
mdiFire,
|
|
||||||
mdiGarage,
|
|
||||||
mdiGarageOpen,
|
|
||||||
mdiHome,
|
|
||||||
mdiHomeOutline,
|
|
||||||
mdiLock,
|
|
||||||
mdiLockOpen,
|
|
||||||
mdiMusicNote,
|
|
||||||
mdiMusicNoteOff,
|
|
||||||
mdiMotionSensor,
|
|
||||||
mdiMotionSensorOff,
|
|
||||||
mdiPackage,
|
|
||||||
mdiPackageUp,
|
|
||||||
mdiPlay,
|
|
||||||
mdiPowerPlug,
|
|
||||||
mdiPowerPlugOff,
|
|
||||||
mdiRadioboxBlank,
|
|
||||||
mdiSnowflake,
|
|
||||||
mdiSmokeDetector,
|
|
||||||
mdiSmokeDetectorAlert,
|
|
||||||
mdiSmokeDetectorVariant,
|
|
||||||
mdiSmokeDetectorVariantAlert,
|
|
||||||
mdiSquare,
|
|
||||||
mdiSquareOutline,
|
|
||||||
mdiStop,
|
|
||||||
mdiThermometer,
|
|
||||||
mdiVibrate,
|
|
||||||
mdiWater,
|
|
||||||
mdiWaterOff,
|
|
||||||
mdiWindowClosed,
|
|
||||||
mdiWindowOpen,
|
|
||||||
} from "@mdi/js";
|
|
||||||
import { HassEntity } from "home-assistant-js-websocket";
|
|
||||||
|
|
||||||
/** Return an icon representing a binary sensor state. */
|
|
||||||
|
|
||||||
export const binarySensorIcon = (state?: string, stateObj?: HassEntity) => {
|
|
||||||
const is_off = state === "off";
|
|
||||||
switch (stateObj?.attributes.device_class) {
|
|
||||||
case "battery":
|
|
||||||
return is_off ? mdiBattery : mdiBatteryOutline;
|
|
||||||
case "battery_charging":
|
|
||||||
return is_off ? mdiBattery : mdiBatteryCharging;
|
|
||||||
case "carbon_monoxide":
|
|
||||||
return is_off ? mdiSmokeDetector : mdiSmokeDetectorAlert;
|
|
||||||
case "cold":
|
|
||||||
return is_off ? mdiThermometer : mdiSnowflake;
|
|
||||||
case "connectivity":
|
|
||||||
return is_off ? mdiCloseNetworkOutline : mdiCheckNetworkOutline;
|
|
||||||
case "door":
|
|
||||||
return is_off ? mdiDoorClosed : mdiDoorOpen;
|
|
||||||
case "garage_door":
|
|
||||||
return is_off ? mdiGarage : mdiGarageOpen;
|
|
||||||
case "power":
|
|
||||||
return is_off ? mdiPowerPlugOff : mdiPowerPlug;
|
|
||||||
case "gas":
|
|
||||||
case "problem":
|
|
||||||
case "safety":
|
|
||||||
case "tamper":
|
|
||||||
return is_off ? mdiCheckCircle : mdiAlertCircle;
|
|
||||||
case "smoke":
|
|
||||||
return is_off ? mdiSmokeDetectorVariant : mdiSmokeDetectorVariantAlert;
|
|
||||||
case "heat":
|
|
||||||
return is_off ? mdiThermometer : mdiFire;
|
|
||||||
case "light":
|
|
||||||
return is_off ? mdiBrightness5 : mdiBrightness7;
|
|
||||||
case "lock":
|
|
||||||
return is_off ? mdiLock : mdiLockOpen;
|
|
||||||
case "moisture":
|
|
||||||
return is_off ? mdiWaterOff : mdiWater;
|
|
||||||
case "motion":
|
|
||||||
return is_off ? mdiMotionSensorOff : mdiMotionSensor;
|
|
||||||
case "occupancy":
|
|
||||||
return is_off ? mdiHomeOutline : mdiHome;
|
|
||||||
case "opening":
|
|
||||||
return is_off ? mdiSquare : mdiSquareOutline;
|
|
||||||
case "plug":
|
|
||||||
return is_off ? mdiPowerPlugOff : mdiPowerPlug;
|
|
||||||
case "presence":
|
|
||||||
return is_off ? mdiHomeOutline : mdiHome;
|
|
||||||
case "running":
|
|
||||||
return is_off ? mdiStop : mdiPlay;
|
|
||||||
case "sound":
|
|
||||||
return is_off ? mdiMusicNoteOff : mdiMusicNote;
|
|
||||||
case "update":
|
|
||||||
return is_off ? mdiPackage : mdiPackageUp;
|
|
||||||
case "vibration":
|
|
||||||
return is_off ? mdiCropPortrait : mdiVibrate;
|
|
||||||
case "window":
|
|
||||||
return is_off ? mdiWindowClosed : mdiWindowOpen;
|
|
||||||
default:
|
|
||||||
return is_off ? mdiRadioboxBlank : mdiCheckboxMarkedCircle;
|
|
||||||
}
|
|
||||||
};
|
|
@ -1,132 +1,12 @@
|
|||||||
/** Return an icon representing a cover state. */
|
/** Return an icon representing a cover state. */
|
||||||
import {
|
import {
|
||||||
mdiArrowUpBox,
|
|
||||||
mdiArrowDownBox,
|
|
||||||
mdiGarage,
|
|
||||||
mdiGarageOpen,
|
|
||||||
mdiGateArrowRight,
|
|
||||||
mdiGate,
|
|
||||||
mdiGateOpen,
|
|
||||||
mdiDoorOpen,
|
|
||||||
mdiDoorClosed,
|
|
||||||
mdiCircle,
|
|
||||||
mdiWindowShutter,
|
|
||||||
mdiWindowShutterOpen,
|
|
||||||
mdiBlindsHorizontal,
|
|
||||||
mdiBlindsHorizontalClosed,
|
|
||||||
mdiRollerShade,
|
|
||||||
mdiRollerShadeClosed,
|
|
||||||
mdiWindowClosed,
|
|
||||||
mdiWindowOpen,
|
|
||||||
mdiArrowExpandHorizontal,
|
|
||||||
mdiArrowUp,
|
|
||||||
mdiArrowCollapseHorizontal,
|
mdiArrowCollapseHorizontal,
|
||||||
mdiArrowDown,
|
mdiArrowDown,
|
||||||
mdiCircleSlice8,
|
mdiArrowExpandHorizontal,
|
||||||
mdiArrowSplitVertical,
|
mdiArrowUp,
|
||||||
mdiCurtains,
|
|
||||||
mdiCurtainsClosed,
|
|
||||||
} from "@mdi/js";
|
} from "@mdi/js";
|
||||||
import { HassEntity } from "home-assistant-js-websocket";
|
import { HassEntity } from "home-assistant-js-websocket";
|
||||||
|
|
||||||
export const coverIcon = (state?: string, stateObj?: HassEntity): string => {
|
|
||||||
const open = state !== "closed";
|
|
||||||
|
|
||||||
switch (stateObj?.attributes.device_class) {
|
|
||||||
case "garage":
|
|
||||||
switch (state) {
|
|
||||||
case "opening":
|
|
||||||
return mdiArrowUpBox;
|
|
||||||
case "closing":
|
|
||||||
return mdiArrowDownBox;
|
|
||||||
case "closed":
|
|
||||||
return mdiGarage;
|
|
||||||
default:
|
|
||||||
return mdiGarageOpen;
|
|
||||||
}
|
|
||||||
case "gate":
|
|
||||||
switch (state) {
|
|
||||||
case "opening":
|
|
||||||
case "closing":
|
|
||||||
return mdiGateArrowRight;
|
|
||||||
case "closed":
|
|
||||||
return mdiGate;
|
|
||||||
default:
|
|
||||||
return mdiGateOpen;
|
|
||||||
}
|
|
||||||
case "door":
|
|
||||||
return open ? mdiDoorOpen : mdiDoorClosed;
|
|
||||||
case "damper":
|
|
||||||
return open ? mdiCircle : mdiCircleSlice8;
|
|
||||||
case "shutter":
|
|
||||||
switch (state) {
|
|
||||||
case "opening":
|
|
||||||
return mdiArrowUpBox;
|
|
||||||
case "closing":
|
|
||||||
return mdiArrowDownBox;
|
|
||||||
case "closed":
|
|
||||||
return mdiWindowShutter;
|
|
||||||
default:
|
|
||||||
return mdiWindowShutterOpen;
|
|
||||||
}
|
|
||||||
case "curtain":
|
|
||||||
switch (state) {
|
|
||||||
case "opening":
|
|
||||||
return mdiArrowSplitVertical;
|
|
||||||
case "closing":
|
|
||||||
return mdiArrowCollapseHorizontal;
|
|
||||||
case "closed":
|
|
||||||
return mdiCurtainsClosed;
|
|
||||||
default:
|
|
||||||
return mdiCurtains;
|
|
||||||
}
|
|
||||||
case "blind":
|
|
||||||
switch (state) {
|
|
||||||
case "opening":
|
|
||||||
return mdiArrowUpBox;
|
|
||||||
case "closing":
|
|
||||||
return mdiArrowDownBox;
|
|
||||||
case "closed":
|
|
||||||
return mdiBlindsHorizontalClosed;
|
|
||||||
default:
|
|
||||||
return mdiBlindsHorizontal;
|
|
||||||
}
|
|
||||||
case "shade":
|
|
||||||
switch (state) {
|
|
||||||
case "opening":
|
|
||||||
return mdiArrowUpBox;
|
|
||||||
case "closing":
|
|
||||||
return mdiArrowDownBox;
|
|
||||||
case "closed":
|
|
||||||
return mdiRollerShadeClosed;
|
|
||||||
default:
|
|
||||||
return mdiRollerShade;
|
|
||||||
}
|
|
||||||
case "window":
|
|
||||||
switch (state) {
|
|
||||||
case "opening":
|
|
||||||
return mdiArrowUpBox;
|
|
||||||
case "closing":
|
|
||||||
return mdiArrowDownBox;
|
|
||||||
case "closed":
|
|
||||||
return mdiWindowClosed;
|
|
||||||
default:
|
|
||||||
return mdiWindowOpen;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (state) {
|
|
||||||
case "opening":
|
|
||||||
return mdiArrowUpBox;
|
|
||||||
case "closing":
|
|
||||||
return mdiArrowDownBox;
|
|
||||||
case "closed":
|
|
||||||
return mdiWindowClosed;
|
|
||||||
default:
|
|
||||||
return mdiWindowOpen;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
export const computeOpenIcon = (stateObj: HassEntity): string => {
|
export const computeOpenIcon = (stateObj: HassEntity): string => {
|
||||||
switch (stateObj.attributes.device_class) {
|
switch (stateObj.attributes.device_class) {
|
||||||
case "awning":
|
case "awning":
|
||||||
|
16
src/common/entity/device_tracker_icon.ts
Normal file
16
src/common/entity/device_tracker_icon.ts
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
import { HassEntity } from "home-assistant-js-websocket";
|
||||||
|
|
||||||
|
export const deviceTrackerIcon = (stateObj: HassEntity, state?: string) => {
|
||||||
|
const compareState = state ?? stateObj.state;
|
||||||
|
if (stateObj?.attributes.source_type === "router") {
|
||||||
|
return compareState === "home" ? "mdi:lan-connect" : "mdi:lan-disconnect";
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
["bluetooth", "bluetooth_le"].includes(stateObj?.attributes.source_type)
|
||||||
|
) {
|
||||||
|
return compareState === "home" ? "mdi:bluetooth-connect" : "mdi:bluetooth";
|
||||||
|
}
|
||||||
|
return compareState === "not_home"
|
||||||
|
? "mdi:account-arrow-right"
|
||||||
|
: "mdi:account";
|
||||||
|
};
|
@ -1,301 +0,0 @@
|
|||||||
import {
|
|
||||||
mdiAccount,
|
|
||||||
mdiAccountArrowRight,
|
|
||||||
mdiAirHumidifier,
|
|
||||||
mdiAirHumidifierOff,
|
|
||||||
mdiAudioVideo,
|
|
||||||
mdiAudioVideoOff,
|
|
||||||
mdiBluetooth,
|
|
||||||
mdiBluetoothConnect,
|
|
||||||
mdiButtonPointer,
|
|
||||||
mdiCalendar,
|
|
||||||
mdiCast,
|
|
||||||
mdiCastConnected,
|
|
||||||
mdiCastOff,
|
|
||||||
mdiChartSankey,
|
|
||||||
mdiCheckCircleOutline,
|
|
||||||
mdiClock,
|
|
||||||
mdiCloseCircleOutline,
|
|
||||||
mdiCrosshairsQuestion,
|
|
||||||
mdiDoorbell,
|
|
||||||
mdiEyeCheck,
|
|
||||||
mdiFan,
|
|
||||||
mdiFanOff,
|
|
||||||
mdiGestureTapButton,
|
|
||||||
mdiLanConnect,
|
|
||||||
mdiLanDisconnect,
|
|
||||||
mdiLock,
|
|
||||||
mdiLockAlert,
|
|
||||||
mdiLockClock,
|
|
||||||
mdiLockOpen,
|
|
||||||
mdiMeterGas,
|
|
||||||
mdiMotionSensor,
|
|
||||||
mdiPackage,
|
|
||||||
mdiPackageDown,
|
|
||||||
mdiPackageUp,
|
|
||||||
mdiPipeValve,
|
|
||||||
mdiPowerPlug,
|
|
||||||
mdiPowerPlugOff,
|
|
||||||
mdiRestart,
|
|
||||||
mdiRobot,
|
|
||||||
mdiRobotConfused,
|
|
||||||
mdiRobotOff,
|
|
||||||
mdiSpeaker,
|
|
||||||
mdiSpeakerOff,
|
|
||||||
mdiSpeakerPause,
|
|
||||||
mdiSpeakerPlay,
|
|
||||||
mdiSwapHorizontal,
|
|
||||||
mdiTelevision,
|
|
||||||
mdiTelevisionOff,
|
|
||||||
mdiTelevisionPause,
|
|
||||||
mdiTelevisionPlay,
|
|
||||||
mdiToggleSwitchVariant,
|
|
||||||
mdiToggleSwitchVariantOff,
|
|
||||||
mdiVideo,
|
|
||||||
mdiVideoOff,
|
|
||||||
mdiWaterBoiler,
|
|
||||||
mdiWaterBoilerOff,
|
|
||||||
mdiWeatherNight,
|
|
||||||
mdiWhiteBalanceSunny,
|
|
||||||
} from "@mdi/js";
|
|
||||||
import { HassEntity } from "home-assistant-js-websocket";
|
|
||||||
import { UpdateEntity, updateIsInstalling } from "../../data/update";
|
|
||||||
import { weatherIcon } from "../../data/weather";
|
|
||||||
/**
|
|
||||||
* Return the icon to be used for a domain.
|
|
||||||
*
|
|
||||||
* Optionally pass in a state to influence the domain icon.
|
|
||||||
*/
|
|
||||||
import { DEFAULT_DOMAIN_ICON, FIXED_DOMAIN_ICONS } from "../const";
|
|
||||||
import { alarmPanelIcon } from "./alarm_panel_icon";
|
|
||||||
import { binarySensorIcon } from "./binary_sensor_icon";
|
|
||||||
import { coverIcon } from "./cover_icon";
|
|
||||||
import { numberIcon } from "./number_icon";
|
|
||||||
import { sensorIcon } from "./sensor_icon";
|
|
||||||
|
|
||||||
export const domainIcon = (
|
|
||||||
domain: string,
|
|
||||||
stateObj?: HassEntity,
|
|
||||||
state?: string
|
|
||||||
): string => {
|
|
||||||
const icon = domainIconWithoutDefault(domain, stateObj, state);
|
|
||||||
if (icon) {
|
|
||||||
return icon;
|
|
||||||
}
|
|
||||||
// eslint-disable-next-line
|
|
||||||
console.warn(`Unable to find icon for domain ${domain}`);
|
|
||||||
return DEFAULT_DOMAIN_ICON;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const domainIconWithoutDefault = (
|
|
||||||
domain: string,
|
|
||||||
stateObj?: HassEntity,
|
|
||||||
state?: string
|
|
||||||
): string | undefined => {
|
|
||||||
const compareState = state !== undefined ? state : stateObj?.state;
|
|
||||||
|
|
||||||
switch (domain) {
|
|
||||||
case "alarm_control_panel":
|
|
||||||
return alarmPanelIcon(compareState);
|
|
||||||
|
|
||||||
case "automation":
|
|
||||||
return compareState === "unavailable"
|
|
||||||
? mdiRobotConfused
|
|
||||||
: compareState === "off"
|
|
||||||
? mdiRobotOff
|
|
||||||
: mdiRobot;
|
|
||||||
|
|
||||||
case "binary_sensor":
|
|
||||||
return binarySensorIcon(compareState, stateObj);
|
|
||||||
|
|
||||||
case "button":
|
|
||||||
switch (stateObj?.attributes.device_class) {
|
|
||||||
case "identify":
|
|
||||||
return mdiCrosshairsQuestion;
|
|
||||||
case "restart":
|
|
||||||
return mdiRestart;
|
|
||||||
case "update":
|
|
||||||
return mdiPackageUp;
|
|
||||||
default:
|
|
||||||
return mdiButtonPointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
case "camera":
|
|
||||||
return compareState === "off" ? mdiVideoOff : mdiVideo;
|
|
||||||
|
|
||||||
case "cover":
|
|
||||||
return coverIcon(compareState, stateObj);
|
|
||||||
|
|
||||||
case "device_tracker":
|
|
||||||
if (stateObj?.attributes.source_type === "router") {
|
|
||||||
return compareState === "home" ? mdiLanConnect : mdiLanDisconnect;
|
|
||||||
}
|
|
||||||
if (
|
|
||||||
["bluetooth", "bluetooth_le"].includes(stateObj?.attributes.source_type)
|
|
||||||
) {
|
|
||||||
return compareState === "home" ? mdiBluetoothConnect : mdiBluetooth;
|
|
||||||
}
|
|
||||||
return compareState === "not_home" ? mdiAccountArrowRight : mdiAccount;
|
|
||||||
|
|
||||||
case "event":
|
|
||||||
switch (stateObj?.attributes.device_class) {
|
|
||||||
case "doorbell":
|
|
||||||
return mdiDoorbell;
|
|
||||||
case "button":
|
|
||||||
return mdiGestureTapButton;
|
|
||||||
case "motion":
|
|
||||||
return mdiMotionSensor;
|
|
||||||
default:
|
|
||||||
return mdiEyeCheck;
|
|
||||||
}
|
|
||||||
|
|
||||||
case "fan":
|
|
||||||
return compareState === "off" ? mdiFanOff : mdiFan;
|
|
||||||
|
|
||||||
case "humidifier":
|
|
||||||
return compareState === "off" ? mdiAirHumidifierOff : mdiAirHumidifier;
|
|
||||||
|
|
||||||
case "input_boolean":
|
|
||||||
return compareState === "on"
|
|
||||||
? mdiCheckCircleOutline
|
|
||||||
: mdiCloseCircleOutline;
|
|
||||||
|
|
||||||
case "input_datetime":
|
|
||||||
if (!stateObj?.attributes.has_date) {
|
|
||||||
return mdiClock;
|
|
||||||
}
|
|
||||||
if (!stateObj.attributes.has_time) {
|
|
||||||
return mdiCalendar;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "lock":
|
|
||||||
switch (compareState) {
|
|
||||||
case "unlocked":
|
|
||||||
return mdiLockOpen;
|
|
||||||
case "jammed":
|
|
||||||
return mdiLockAlert;
|
|
||||||
case "locking":
|
|
||||||
case "unlocking":
|
|
||||||
return mdiLockClock;
|
|
||||||
default:
|
|
||||||
return mdiLock;
|
|
||||||
}
|
|
||||||
|
|
||||||
case "media_player":
|
|
||||||
switch (stateObj?.attributes.device_class) {
|
|
||||||
case "speaker":
|
|
||||||
switch (compareState) {
|
|
||||||
case "playing":
|
|
||||||
return mdiSpeakerPlay;
|
|
||||||
case "paused":
|
|
||||||
return mdiSpeakerPause;
|
|
||||||
case "off":
|
|
||||||
return mdiSpeakerOff;
|
|
||||||
default:
|
|
||||||
return mdiSpeaker;
|
|
||||||
}
|
|
||||||
case "tv":
|
|
||||||
switch (compareState) {
|
|
||||||
case "playing":
|
|
||||||
return mdiTelevisionPlay;
|
|
||||||
case "paused":
|
|
||||||
return mdiTelevisionPause;
|
|
||||||
case "off":
|
|
||||||
return mdiTelevisionOff;
|
|
||||||
default:
|
|
||||||
return mdiTelevision;
|
|
||||||
}
|
|
||||||
case "receiver":
|
|
||||||
switch (compareState) {
|
|
||||||
case "off":
|
|
||||||
return mdiAudioVideoOff;
|
|
||||||
default:
|
|
||||||
return mdiAudioVideo;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
switch (compareState) {
|
|
||||||
case "playing":
|
|
||||||
case "paused":
|
|
||||||
return mdiCastConnected;
|
|
||||||
case "off":
|
|
||||||
return mdiCastOff;
|
|
||||||
default:
|
|
||||||
return mdiCast;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
case "number": {
|
|
||||||
const icon = numberIcon(stateObj);
|
|
||||||
if (icon) {
|
|
||||||
return icon;
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case "person":
|
|
||||||
return compareState === "not_home" ? mdiAccountArrowRight : mdiAccount;
|
|
||||||
|
|
||||||
case "switch":
|
|
||||||
switch (stateObj?.attributes.device_class) {
|
|
||||||
case "outlet":
|
|
||||||
return compareState === "on" ? mdiPowerPlug : mdiPowerPlugOff;
|
|
||||||
case "switch":
|
|
||||||
return compareState === "on"
|
|
||||||
? mdiToggleSwitchVariant
|
|
||||||
: mdiToggleSwitchVariantOff;
|
|
||||||
default:
|
|
||||||
return mdiToggleSwitchVariant;
|
|
||||||
}
|
|
||||||
|
|
||||||
case "sensor": {
|
|
||||||
const icon = sensorIcon(stateObj);
|
|
||||||
if (icon) {
|
|
||||||
return icon;
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case "sun":
|
|
||||||
return stateObj?.state === "above_horizon"
|
|
||||||
? mdiWhiteBalanceSunny
|
|
||||||
: mdiWeatherNight;
|
|
||||||
|
|
||||||
case "switch_as_x":
|
|
||||||
return mdiSwapHorizontal;
|
|
||||||
|
|
||||||
case "threshold":
|
|
||||||
return mdiChartSankey;
|
|
||||||
|
|
||||||
case "update":
|
|
||||||
return compareState === "on"
|
|
||||||
? updateIsInstalling(stateObj as UpdateEntity)
|
|
||||||
? mdiPackageDown
|
|
||||||
: mdiPackageUp
|
|
||||||
: mdiPackage;
|
|
||||||
|
|
||||||
case "valve":
|
|
||||||
switch (stateObj?.attributes.device_class) {
|
|
||||||
case "water":
|
|
||||||
return mdiPipeValve;
|
|
||||||
case "gas":
|
|
||||||
return mdiMeterGas;
|
|
||||||
default:
|
|
||||||
return mdiPipeValve;
|
|
||||||
}
|
|
||||||
|
|
||||||
case "water_heater":
|
|
||||||
return compareState === "off" ? mdiWaterBoilerOff : mdiWaterBoiler;
|
|
||||||
|
|
||||||
case "weather":
|
|
||||||
return weatherIcon(stateObj?.state);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (domain in FIXED_DOMAIN_ICONS) {
|
|
||||||
return FIXED_DOMAIN_ICONS[domain];
|
|
||||||
}
|
|
||||||
|
|
||||||
return undefined;
|
|
||||||
};
|
|
@ -1,13 +0,0 @@
|
|||||||
/** Return an icon representing a number state. */
|
|
||||||
import { HassEntity } from "home-assistant-js-websocket";
|
|
||||||
import { FIXED_DEVICE_CLASS_ICONS } from "../const";
|
|
||||||
|
|
||||||
export const numberIcon = (stateObj?: HassEntity): string | undefined => {
|
|
||||||
const dclass = stateObj?.attributes.device_class;
|
|
||||||
|
|
||||||
if (dclass && dclass in FIXED_DEVICE_CLASS_ICONS) {
|
|
||||||
return FIXED_DEVICE_CLASS_ICONS[dclass];
|
|
||||||
}
|
|
||||||
|
|
||||||
return undefined;
|
|
||||||
};
|
|
@ -1,25 +0,0 @@
|
|||||||
/** Return an icon representing a sensor state. */
|
|
||||||
import { mdiBattery, mdiThermometer } from "@mdi/js";
|
|
||||||
import { HassEntity } from "home-assistant-js-websocket";
|
|
||||||
import { SENSOR_DEVICE_CLASS_BATTERY } from "../../data/sensor";
|
|
||||||
import { FIXED_DEVICE_CLASS_ICONS, UNIT_C, UNIT_F } from "../const";
|
|
||||||
import { batteryStateIcon } from "./battery_icon";
|
|
||||||
|
|
||||||
export const sensorIcon = (stateObj?: HassEntity): string | undefined => {
|
|
||||||
const dclass = stateObj?.attributes.device_class;
|
|
||||||
|
|
||||||
if (dclass && dclass in FIXED_DEVICE_CLASS_ICONS) {
|
|
||||||
return FIXED_DEVICE_CLASS_ICONS[dclass];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dclass === SENSOR_DEVICE_CLASS_BATTERY) {
|
|
||||||
return stateObj ? batteryStateIcon(stateObj) : mdiBattery;
|
|
||||||
}
|
|
||||||
|
|
||||||
const unit = stateObj?.attributes.unit_of_measurement;
|
|
||||||
if (unit === UNIT_C || unit === UNIT_F) {
|
|
||||||
return mdiThermometer;
|
|
||||||
}
|
|
||||||
|
|
||||||
return undefined;
|
|
||||||
};
|
|
42
src/common/entity/state_icon.ts
Normal file
42
src/common/entity/state_icon.ts
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
import { HassEntity } from "home-assistant-js-websocket";
|
||||||
|
import { computeStateDomain } from "./compute_state_domain";
|
||||||
|
import { updateIcon } from "./update_icon";
|
||||||
|
import { deviceTrackerIcon } from "./device_tracker_icon";
|
||||||
|
import { batteryIcon } from "./battery_icon";
|
||||||
|
|
||||||
|
export const stateIcon = (
|
||||||
|
stateObj: HassEntity,
|
||||||
|
state?: string
|
||||||
|
): string | undefined => {
|
||||||
|
const domain = computeStateDomain(stateObj);
|
||||||
|
const compareState = state ?? stateObj.state;
|
||||||
|
const dc = stateObj.attributes.device_class;
|
||||||
|
switch (domain) {
|
||||||
|
case "update":
|
||||||
|
return updateIcon(stateObj, compareState);
|
||||||
|
|
||||||
|
case "sensor":
|
||||||
|
if (dc === "battery") {
|
||||||
|
return batteryIcon(stateObj, compareState);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "device_tracker":
|
||||||
|
return deviceTrackerIcon(stateObj, compareState);
|
||||||
|
|
||||||
|
case "sun":
|
||||||
|
return compareState === "above_horizon"
|
||||||
|
? "mdi:white-balance-sunny"
|
||||||
|
: "mdi:weather-night";
|
||||||
|
|
||||||
|
case "input_datetime":
|
||||||
|
if (!stateObj.attributes.has_date) {
|
||||||
|
return "mdi:clock";
|
||||||
|
}
|
||||||
|
if (!stateObj.attributes.has_time) {
|
||||||
|
return "mdi:calendar";
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return undefined;
|
||||||
|
};
|
@ -1,12 +0,0 @@
|
|||||||
/** Return an icon representing a state. */
|
|
||||||
import { HassEntity } from "home-assistant-js-websocket";
|
|
||||||
import { DEFAULT_DOMAIN_ICON } from "../const";
|
|
||||||
import { computeDomain } from "./compute_domain";
|
|
||||||
import { domainIcon } from "./domain_icon";
|
|
||||||
|
|
||||||
export const stateIconPath = (state: HassEntity | undefined) => {
|
|
||||||
if (!state) {
|
|
||||||
return DEFAULT_DOMAIN_ICON;
|
|
||||||
}
|
|
||||||
return domainIcon(computeDomain(state.entity_id), state);
|
|
||||||
};
|
|
11
src/common/entity/update_icon.ts
Normal file
11
src/common/entity/update_icon.ts
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
import { HassEntity } from "home-assistant-js-websocket";
|
||||||
|
import { UpdateEntity, updateIsInstalling } from "../../data/update";
|
||||||
|
|
||||||
|
export const updateIcon = (stateObj: HassEntity, state?: string) => {
|
||||||
|
const compareState = state ?? stateObj.state;
|
||||||
|
return compareState === "on"
|
||||||
|
? updateIsInstalling(stateObj as UpdateEntity)
|
||||||
|
? "mdi:package-down"
|
||||||
|
: "mdi:package-up"
|
||||||
|
: "mdi:package";
|
||||||
|
};
|
@ -764,10 +764,12 @@ export class HaDataTable extends LitElement {
|
|||||||
text-align: right;
|
text-align: right;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mdc-data-table__cell--icon:first-child ha-icon,
|
|
||||||
.mdc-data-table__cell--icon:first-child img,
|
.mdc-data-table__cell--icon:first-child img,
|
||||||
|
.mdc-data-table__cell--icon:first-child ha-icon,
|
||||||
|
.mdc-data-table__cell--icon:first-child ha-svg-icon,
|
||||||
.mdc-data-table__cell--icon:first-child ha-state-icon,
|
.mdc-data-table__cell--icon:first-child ha-state-icon,
|
||||||
.mdc-data-table__cell--icon:first-child ha-svg-icon {
|
.mdc-data-table__cell--icon:first-child ha-domain-icon,
|
||||||
|
.mdc-data-table__cell--icon:first-child ha-service-icon {
|
||||||
margin-left: 8px;
|
margin-left: 8px;
|
||||||
}
|
}
|
||||||
:host([dir="rtl"]) .mdc-data-table__cell--icon:first-child ha-icon,
|
:host([dir="rtl"]) .mdc-data-table__cell--icon:first-child ha-icon,
|
||||||
|
@ -1,22 +1,25 @@
|
|||||||
import { html, LitElement } from "lit";
|
import { HassEntity } from "home-assistant-js-websocket";
|
||||||
|
import { html, LitElement, nothing } from "lit";
|
||||||
import { customElement, property } from "lit/decorators";
|
import { customElement, property } from "lit/decorators";
|
||||||
import { batteryStateIcon } from "../../common/entity/battery_icon";
|
import { batteryLevelIcon } from "../../common/entity/battery_icon";
|
||||||
import "../ha-svg-icon";
|
import "../ha-icon";
|
||||||
|
|
||||||
@customElement("ha-battery-icon")
|
@customElement("ha-battery-icon")
|
||||||
export class HaBatteryIcon extends LitElement {
|
export class HaBatteryIcon extends LitElement {
|
||||||
@property() public batteryStateObj;
|
@property({ attribute: false }) public batteryStateObj?: HassEntity;
|
||||||
|
|
||||||
@property() public batteryChargingStateObj;
|
@property({ attribute: false }) public batteryChargingStateObj?: HassEntity;
|
||||||
|
|
||||||
protected render() {
|
protected render() {
|
||||||
|
if (!this.batteryStateObj) return nothing;
|
||||||
|
|
||||||
return html`
|
return html`
|
||||||
<ha-svg-icon
|
<ha-icon
|
||||||
.path=${batteryStateIcon(
|
.icon=${batteryLevelIcon(
|
||||||
this.batteryStateObj,
|
this.batteryStateObj.state,
|
||||||
this.batteryChargingStateObj
|
this.batteryChargingStateObj?.state === "on"
|
||||||
)}
|
)}
|
||||||
></ha-svg-icon>
|
></ha-icon>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
84
src/components/ha-domain-icon.ts
Normal file
84
src/components/ha-domain-icon.ts
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
import { css, CSSResultGroup, html, LitElement, nothing } from "lit";
|
||||||
|
import { customElement, property } from "lit/decorators";
|
||||||
|
import { until } from "lit/directives/until";
|
||||||
|
import { DEFAULT_DOMAIN_ICON, FIXED_DOMAIN_ICONS } from "../common/const";
|
||||||
|
import { domainIcon } from "../data/icons";
|
||||||
|
import { HomeAssistant } from "../types";
|
||||||
|
import { brandsUrl } from "../util/brands-url";
|
||||||
|
import "./ha-icon";
|
||||||
|
|
||||||
|
@customElement("ha-domain-icon")
|
||||||
|
export class HaDomainIcon extends LitElement {
|
||||||
|
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||||
|
|
||||||
|
@property() public domain?: string;
|
||||||
|
|
||||||
|
@property() public deviceClass?: string;
|
||||||
|
|
||||||
|
@property() public icon?: string;
|
||||||
|
|
||||||
|
@property({ type: Boolean }) public brandFallback?: boolean;
|
||||||
|
|
||||||
|
protected render() {
|
||||||
|
if (this.icon) {
|
||||||
|
return html`<ha-icon .icon=${this.icon}></ha-icon>`;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this.domain) {
|
||||||
|
return nothing;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this.hass) {
|
||||||
|
return this._renderFallback();
|
||||||
|
}
|
||||||
|
|
||||||
|
const icon = domainIcon(this.hass, this.domain, this.deviceClass).then(
|
||||||
|
(icn) => {
|
||||||
|
if (icn) {
|
||||||
|
return html`<ha-icon .icon=${icn}></ha-icon>`;
|
||||||
|
}
|
||||||
|
return this._renderFallback();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
return html`${until(icon)}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
private _renderFallback() {
|
||||||
|
if (this.domain! in FIXED_DOMAIN_ICONS) {
|
||||||
|
return html`
|
||||||
|
<ha-svg-icon .path=${FIXED_DOMAIN_ICONS[this.domain!]}></ha-svg-icon>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
if (this.brandFallback) {
|
||||||
|
const image = brandsUrl({
|
||||||
|
domain: this.domain!,
|
||||||
|
type: "icon",
|
||||||
|
darkOptimized: this.hass.themes?.darkMode,
|
||||||
|
});
|
||||||
|
return html`
|
||||||
|
<img
|
||||||
|
alt=""
|
||||||
|
src=${image}
|
||||||
|
crossorigin="anonymous"
|
||||||
|
referrerpolicy="no-referrer"
|
||||||
|
/>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
return html`<ha-svg-icon .path=${DEFAULT_DOMAIN_ICON}></ha-svg-icon>`;
|
||||||
|
}
|
||||||
|
|
||||||
|
static get styles(): CSSResultGroup {
|
||||||
|
return css`
|
||||||
|
img {
|
||||||
|
width: var(--mdc-icon-size, 24px);
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
interface HTMLElementTagNameMap {
|
||||||
|
"ha-domain-icon": HaDomainIcon;
|
||||||
|
}
|
||||||
|
}
|
@ -1,9 +1,8 @@
|
|||||||
import { mdiRoomService } from "@mdi/js";
|
|
||||||
import { html, LitElement, nothing } from "lit";
|
import { html, LitElement, nothing } from "lit";
|
||||||
import { customElement, property } from "lit/decorators";
|
import { customElement, property } from "lit/decorators";
|
||||||
import { until } from "lit/directives/until";
|
import { until } from "lit/directives/until";
|
||||||
|
import { DEFAULT_SERVICE_ICON, FIXED_DOMAIN_ICONS } from "../common/const";
|
||||||
import { computeDomain } from "../common/entity/compute_domain";
|
import { computeDomain } from "../common/entity/compute_domain";
|
||||||
import { domainIconWithoutDefault } from "../common/entity/domain_icon";
|
|
||||||
import { serviceIcon } from "../data/icons";
|
import { serviceIcon } from "../data/icons";
|
||||||
import { HomeAssistant } from "../types";
|
import { HomeAssistant } from "../types";
|
||||||
import "./ha-icon";
|
import "./ha-icon";
|
||||||
@ -41,10 +40,11 @@ export class HaServiceIcon extends LitElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private _renderFallback() {
|
private _renderFallback() {
|
||||||
|
const domain = computeDomain(this.service!);
|
||||||
|
|
||||||
return html`
|
return html`
|
||||||
<ha-svg-icon
|
<ha-svg-icon
|
||||||
.path=${domainIconWithoutDefault(computeDomain(this.service!)) ||
|
.path=${FIXED_DOMAIN_ICONS[domain] || DEFAULT_SERVICE_ICON}
|
||||||
mdiRoomService}
|
|
||||||
></ha-svg-icon>
|
></ha-svg-icon>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,8 @@ import { HassEntity } from "home-assistant-js-websocket";
|
|||||||
import { html, LitElement, nothing } from "lit";
|
import { html, LitElement, nothing } from "lit";
|
||||||
import { customElement, property } from "lit/decorators";
|
import { customElement, property } from "lit/decorators";
|
||||||
import { until } from "lit/directives/until";
|
import { until } from "lit/directives/until";
|
||||||
import { stateIconPath } from "../common/entity/state_icon_path";
|
import { DEFAULT_DOMAIN_ICON, FIXED_DOMAIN_ICONS } from "../common/const";
|
||||||
|
import { computeStateDomain } from "../common/entity/compute_state_domain";
|
||||||
import { entityIcon } from "../data/icons";
|
import { entityIcon } from "../data/icons";
|
||||||
import { HomeAssistant } from "../types";
|
import { HomeAssistant } from "../types";
|
||||||
import "./ha-icon";
|
import "./ha-icon";
|
||||||
@ -44,9 +45,13 @@ export class HaStateIcon extends LitElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private _renderFallback() {
|
private _renderFallback() {
|
||||||
return html`<ha-svg-icon
|
const domain = computeStateDomain(this.stateObj!);
|
||||||
.path=${stateIconPath(this.stateObj)}
|
|
||||||
></ha-svg-icon>`;
|
return html`
|
||||||
|
<ha-svg-icon
|
||||||
|
.path=${FIXED_DOMAIN_ICONS[domain] || DEFAULT_DOMAIN_ICON}
|
||||||
|
></ha-svg-icon>
|
||||||
|
`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,10 +17,11 @@ import {
|
|||||||
mdiRoomService,
|
mdiRoomService,
|
||||||
mdiShuffleDisabled,
|
mdiShuffleDisabled,
|
||||||
} from "@mdi/js";
|
} from "@mdi/js";
|
||||||
import { css, html, LitElement, PropertyValues } from "lit";
|
import { LitElement, PropertyValues, css, html } from "lit";
|
||||||
import { customElement, property } from "lit/decorators";
|
import { customElement, property } from "lit/decorators";
|
||||||
import { fireEvent } from "../../common/dom/fire_event";
|
|
||||||
import { ensureArray } from "../../common/array/ensure-array";
|
import { ensureArray } from "../../common/array/ensure-array";
|
||||||
|
import { fireEvent } from "../../common/dom/fire_event";
|
||||||
|
import { ACTION_ICONS } from "../../data/action";
|
||||||
import { Condition, Trigger } from "../../data/automation";
|
import { Condition, Trigger } from "../../data/automation";
|
||||||
import {
|
import {
|
||||||
Action,
|
Action,
|
||||||
@ -45,7 +46,6 @@ import "./hat-graph-branch";
|
|||||||
import { BRANCH_HEIGHT, NODE_SIZE, SPACING } from "./hat-graph-const";
|
import { BRANCH_HEIGHT, NODE_SIZE, SPACING } from "./hat-graph-const";
|
||||||
import "./hat-graph-node";
|
import "./hat-graph-node";
|
||||||
import "./hat-graph-spacer";
|
import "./hat-graph-spacer";
|
||||||
import { ACTION_ICONS } from "../../data/action";
|
|
||||||
|
|
||||||
export interface NodeInfo {
|
export interface NodeInfo {
|
||||||
path: string;
|
path: string;
|
||||||
|
@ -2,6 +2,7 @@ import { HassEntity } from "home-assistant-js-websocket";
|
|||||||
import { computeDomain } from "../common/entity/compute_domain";
|
import { computeDomain } from "../common/entity/compute_domain";
|
||||||
import { computeObjectId } from "../common/entity/compute_object_id";
|
import { computeObjectId } from "../common/entity/compute_object_id";
|
||||||
import { computeStateDomain } from "../common/entity/compute_state_domain";
|
import { computeStateDomain } from "../common/entity/compute_state_domain";
|
||||||
|
import { stateIcon } from "../common/entity/state_icon";
|
||||||
import { HomeAssistant } from "../types";
|
import { HomeAssistant } from "../types";
|
||||||
import {
|
import {
|
||||||
EntityRegistryDisplayEntry,
|
EntityRegistryDisplayEntry,
|
||||||
@ -49,7 +50,7 @@ interface ComponentIcons {
|
|||||||
}
|
}
|
||||||
|
|
||||||
interface ServiceIcons {
|
interface ServiceIcons {
|
||||||
[domain: string]: Record<string, string>;
|
[service: string]: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type IconCategory = "entity" | "entity_component" | "services";
|
export type IconCategory = "entity" | "entity_component" | "services";
|
||||||
@ -127,26 +128,18 @@ export const getServiceIcons = async (
|
|||||||
|
|
||||||
export const entityIcon = async (
|
export const entityIcon = async (
|
||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
state: HassEntity,
|
stateObj: HassEntity,
|
||||||
stateValue?: string
|
state?: string
|
||||||
) => {
|
) => {
|
||||||
const entity = hass.entities?.[state.entity_id] as
|
const entry = hass.entities?.[stateObj.entity_id] as
|
||||||
| EntityRegistryDisplayEntry
|
| EntityRegistryDisplayEntry
|
||||||
| undefined;
|
| undefined;
|
||||||
if (entity?.icon) {
|
if (entry?.icon) {
|
||||||
return entity.icon;
|
return entry.icon;
|
||||||
}
|
}
|
||||||
const domain = computeStateDomain(state);
|
const domain = computeStateDomain(stateObj);
|
||||||
const deviceClass = state.attributes.device_class;
|
|
||||||
|
|
||||||
return getEntityIcon(
|
return getEntityIcon(hass, domain, stateObj, state, entry);
|
||||||
hass,
|
|
||||||
domain,
|
|
||||||
deviceClass,
|
|
||||||
stateValue ?? state.state,
|
|
||||||
entity?.platform,
|
|
||||||
entity?.translation_key
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export const entryIcon = async (
|
export const entryIcon = async (
|
||||||
@ -157,39 +150,41 @@ export const entryIcon = async (
|
|||||||
return entry.icon;
|
return entry.icon;
|
||||||
}
|
}
|
||||||
const domain = computeDomain(entry.entity_id);
|
const domain = computeDomain(entry.entity_id);
|
||||||
return getEntityIcon(
|
return getEntityIcon(hass, domain, undefined, undefined, entry);
|
||||||
hass,
|
|
||||||
domain,
|
|
||||||
undefined,
|
|
||||||
undefined,
|
|
||||||
entry.platform,
|
|
||||||
entry.translation_key
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const getEntityIcon = async (
|
const getEntityIcon = async (
|
||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
domain: string,
|
domain: string,
|
||||||
deviceClass?: string,
|
stateObj?: HassEntity,
|
||||||
value?: string,
|
stateValue?: string,
|
||||||
platform?: string,
|
entry?: EntityRegistryEntry | EntityRegistryDisplayEntry
|
||||||
translation_key?: string
|
|
||||||
) => {
|
) => {
|
||||||
|
const platform = entry?.platform;
|
||||||
|
const translation_key = entry?.translation_key;
|
||||||
|
const device_class = stateObj?.attributes.device_class;
|
||||||
|
const state = stateValue ?? stateObj?.state;
|
||||||
|
|
||||||
let icon: string | undefined;
|
let icon: string | undefined;
|
||||||
if (translation_key && platform) {
|
if (translation_key && platform) {
|
||||||
const platformIcons = await getPlatformIcons(hass, platform);
|
const platformIcons = await getPlatformIcons(hass, platform);
|
||||||
if (platformIcons) {
|
if (platformIcons) {
|
||||||
const translations = platformIcons[domain]?.[translation_key];
|
const translations = platformIcons[domain]?.[translation_key];
|
||||||
icon = (value && translations?.state?.[value]) || translations?.default;
|
icon = (state && translations?.state?.[state]) || translations?.default;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!icon && stateObj) {
|
||||||
|
icon = stateIcon(stateObj, state);
|
||||||
|
}
|
||||||
|
|
||||||
if (!icon) {
|
if (!icon) {
|
||||||
const entityComponentIcons = await getComponentIcons(hass, domain);
|
const entityComponentIcons = await getComponentIcons(hass, domain);
|
||||||
if (entityComponentIcons) {
|
if (entityComponentIcons) {
|
||||||
const translations =
|
const translations =
|
||||||
(deviceClass && entityComponentIcons[deviceClass]) ||
|
(device_class && entityComponentIcons[device_class]) ||
|
||||||
entityComponentIcons._;
|
entityComponentIcons._;
|
||||||
icon = (value && translations?.state?.[value]) || translations?.default;
|
icon = (state && translations?.state?.[state]) || translations?.default;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return icon;
|
return icon;
|
||||||
@ -234,12 +229,34 @@ export const attributeIcon = async (
|
|||||||
return icon;
|
return icon;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const serviceIcon = async (hass: HomeAssistant, service: string) => {
|
export const serviceIcon = async (
|
||||||
|
hass: HomeAssistant,
|
||||||
|
service: string
|
||||||
|
): Promise<string | undefined> => {
|
||||||
|
let icon: string | undefined;
|
||||||
const domain = computeDomain(service);
|
const domain = computeDomain(service);
|
||||||
const serviceName = computeObjectId(service);
|
const serviceName = computeObjectId(service);
|
||||||
const serviceIcons = await getServiceIcons(hass, domain);
|
const serviceIcons = await getServiceIcons(hass, domain);
|
||||||
if (serviceIcons) {
|
if (serviceIcons) {
|
||||||
return serviceIcons[serviceName];
|
icon = serviceIcons[serviceName];
|
||||||
|
}
|
||||||
|
if (!icon) {
|
||||||
|
icon = await domainIcon(hass, domain);
|
||||||
|
}
|
||||||
|
return icon;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const domainIcon = async (
|
||||||
|
hass: HomeAssistant,
|
||||||
|
domain: string,
|
||||||
|
deviceClass?: string
|
||||||
|
): Promise<string | undefined> => {
|
||||||
|
const entityComponentIcons = await getComponentIcons(hass, domain);
|
||||||
|
if (entityComponentIcons) {
|
||||||
|
const translations =
|
||||||
|
(deviceClass && entityComponentIcons[deviceClass]) ||
|
||||||
|
entityComponentIcons._;
|
||||||
|
return translations?.default;
|
||||||
}
|
}
|
||||||
return undefined;
|
return undefined;
|
||||||
};
|
};
|
||||||
|
@ -8,7 +8,6 @@ import {
|
|||||||
mdiWeatherLightning,
|
mdiWeatherLightning,
|
||||||
mdiWeatherLightningRainy,
|
mdiWeatherLightningRainy,
|
||||||
mdiWeatherNight,
|
mdiWeatherNight,
|
||||||
mdiWeatherNightPartlyCloudy,
|
|
||||||
mdiWeatherPartlyCloudy,
|
mdiWeatherPartlyCloudy,
|
||||||
mdiWeatherPouring,
|
mdiWeatherPouring,
|
||||||
mdiWeatherRainy,
|
mdiWeatherRainy,
|
||||||
@ -520,13 +519,6 @@ export const getWeatherStateIcon = (
|
|||||||
return undefined;
|
return undefined;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const weatherIcon = (state?: string, nightTime?: boolean): string =>
|
|
||||||
!state
|
|
||||||
? undefined
|
|
||||||
: nightTime && state === "partlycloudy"
|
|
||||||
? mdiWeatherNightPartlyCloudy
|
|
||||||
: weatherIcons[state];
|
|
||||||
|
|
||||||
const EIGHT_HOURS = 28800000;
|
const EIGHT_HOURS = 28800000;
|
||||||
const DAY_IN_MILLISECONDS = 86400000;
|
const DAY_IN_MILLISECONDS = 86400000;
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@ import {
|
|||||||
mdiReload,
|
mdiReload,
|
||||||
mdiServerNetwork,
|
mdiServerNetwork,
|
||||||
} from "@mdi/js";
|
} from "@mdi/js";
|
||||||
import { LitElement, css, html, nothing } from "lit";
|
import { LitElement, TemplateResult, css, html, nothing } from "lit";
|
||||||
import { customElement, property, query, state } from "lit/decorators";
|
import { customElement, property, query, state } from "lit/decorators";
|
||||||
import { ifDefined } from "lit/directives/if-defined";
|
import { ifDefined } from "lit/directives/if-defined";
|
||||||
import { styleMap } from "lit/directives/style-map";
|
import { styleMap } from "lit/directives/style-map";
|
||||||
@ -17,9 +17,7 @@ import { canShowPage } from "../../common/config/can_show_page";
|
|||||||
import { componentsWithService } from "../../common/config/components_with_service";
|
import { componentsWithService } from "../../common/config/components_with_service";
|
||||||
import { isComponentLoaded } from "../../common/config/is_component_loaded";
|
import { isComponentLoaded } from "../../common/config/is_component_loaded";
|
||||||
import { fireEvent } from "../../common/dom/fire_event";
|
import { fireEvent } from "../../common/dom/fire_event";
|
||||||
import { computeDomain } from "../../common/entity/compute_domain";
|
|
||||||
import { computeStateName } from "../../common/entity/compute_state_name";
|
import { computeStateName } from "../../common/entity/compute_state_name";
|
||||||
import { domainIcon } from "../../common/entity/domain_icon";
|
|
||||||
import { navigate } from "../../common/navigate";
|
import { navigate } from "../../common/navigate";
|
||||||
import { caseInsensitiveStringCompare } from "../../common/string/compare";
|
import { caseInsensitiveStringCompare } from "../../common/string/compare";
|
||||||
import {
|
import {
|
||||||
@ -27,9 +25,9 @@ import {
|
|||||||
fuzzyFilterSort,
|
fuzzyFilterSort,
|
||||||
} from "../../common/string/filter/sequence-matching";
|
} from "../../common/string/filter/sequence-matching";
|
||||||
import { debounce } from "../../common/util/debounce";
|
import { debounce } from "../../common/util/debounce";
|
||||||
import "../../components/ha-label";
|
|
||||||
import "../../components/ha-circular-progress";
|
import "../../components/ha-circular-progress";
|
||||||
import "../../components/ha-icon-button";
|
import "../../components/ha-icon-button";
|
||||||
|
import "../../components/ha-label";
|
||||||
import "../../components/ha-list-item";
|
import "../../components/ha-list-item";
|
||||||
import "../../components/ha-textfield";
|
import "../../components/ha-textfield";
|
||||||
import { fetchHassioAddonsInfo } from "../../data/hassio/addon";
|
import { fetchHassioAddonsInfo } from "../../data/hassio/addon";
|
||||||
@ -56,7 +54,7 @@ interface CommandItem extends QuickBarItem {
|
|||||||
|
|
||||||
interface EntityItem extends QuickBarItem {
|
interface EntityItem extends QuickBarItem {
|
||||||
altText: string;
|
altText: string;
|
||||||
icon?: string;
|
icon?: TemplateResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
const isCommandItem = (item: QuickBarItem): item is CommandItem =>
|
const isCommandItem = (item: QuickBarItem): item is CommandItem =>
|
||||||
@ -296,16 +294,14 @@ export class QuickBar extends LitElement {
|
|||||||
graphic="icon"
|
graphic="icon"
|
||||||
>
|
>
|
||||||
${item.iconPath
|
${item.iconPath
|
||||||
? html`<ha-svg-icon
|
? html`
|
||||||
|
<ha-svg-icon
|
||||||
.path=${item.iconPath}
|
.path=${item.iconPath}
|
||||||
class="entity"
|
class="entity"
|
||||||
slot="graphic"
|
slot="graphic"
|
||||||
></ha-svg-icon>`
|
></ha-svg-icon>
|
||||||
: html`<ha-icon
|
`
|
||||||
.icon=${item.icon}
|
: html`<span slot="graphic">${item.icon}</span>`}
|
||||||
class="entity"
|
|
||||||
slot="graphic"
|
|
||||||
></ha-icon>`}
|
|
||||||
<span>${item.primaryText}</span>
|
<span>${item.primaryText}</span>
|
||||||
${item.altText
|
${item.altText
|
||||||
? html`
|
? html`
|
||||||
@ -476,10 +472,12 @@ export class QuickBar extends LitElement {
|
|||||||
const entityItem = {
|
const entityItem = {
|
||||||
primaryText: computeStateName(entityState),
|
primaryText: computeStateName(entityState),
|
||||||
altText: entityId,
|
altText: entityId,
|
||||||
icon: entityState.attributes.icon,
|
icon: html`
|
||||||
iconPath: entityState.attributes.icon
|
<ha-state-icon
|
||||||
? undefined
|
.hass=${this.hass}
|
||||||
: domainIcon(computeDomain(entityId), entityState),
|
.stateObj=${entityState}
|
||||||
|
></ha-state-icon>
|
||||||
|
`,
|
||||||
action: () => fireEvent(this, "hass-more-info", { entityId }),
|
action: () => fireEvent(this, "hass-more-info", { entityId }),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import "@material/mwc-list/mwc-list";
|
import "@material/mwc-list/mwc-list";
|
||||||
|
import "@material/web/divider/divider";
|
||||||
import { mdiClose, mdiContentPaste, mdiPlus } from "@mdi/js";
|
import { mdiClose, mdiContentPaste, mdiPlus } from "@mdi/js";
|
||||||
import Fuse, { IFuseOptions } from "fuse.js";
|
import Fuse, { IFuseOptions } from "fuse.js";
|
||||||
import {
|
import {
|
||||||
@ -16,17 +17,21 @@ import { repeat } from "lit/directives/repeat";
|
|||||||
import { styleMap } from "lit/directives/style-map";
|
import { styleMap } from "lit/directives/style-map";
|
||||||
import memoizeOne from "memoize-one";
|
import memoizeOne from "memoize-one";
|
||||||
import { fireEvent } from "../../../common/dom/fire_event";
|
import { fireEvent } from "../../../common/dom/fire_event";
|
||||||
import { domainIconWithoutDefault } from "../../../common/entity/domain_icon";
|
import { computeDomain } from "../../../common/entity/compute_domain";
|
||||||
import { stringCompare } from "../../../common/string/compare";
|
import { stringCompare } from "../../../common/string/compare";
|
||||||
import { LocalizeFunc } from "../../../common/translations/localize";
|
import { LocalizeFunc } from "../../../common/translations/localize";
|
||||||
|
import { deepEqual } from "../../../common/util/deep-equal";
|
||||||
import "../../../components/ha-dialog";
|
import "../../../components/ha-dialog";
|
||||||
import type { HaDialog } from "../../../components/ha-dialog";
|
import type { HaDialog } from "../../../components/ha-dialog";
|
||||||
import "../../../components/ha-dialog-header";
|
import "../../../components/ha-dialog-header";
|
||||||
|
import "../../../components/ha-domain-icon";
|
||||||
import "../../../components/ha-icon-button";
|
import "../../../components/ha-icon-button";
|
||||||
import "../../../components/ha-icon-button-prev";
|
import "../../../components/ha-icon-button-prev";
|
||||||
import "../../../components/ha-icon-next";
|
import "../../../components/ha-icon-next";
|
||||||
import "../../../components/ha-list-new";
|
|
||||||
import "../../../components/ha-list-item-new";
|
import "../../../components/ha-list-item-new";
|
||||||
|
import "../../../components/ha-list-new";
|
||||||
|
import "../../../components/ha-service-icon";
|
||||||
|
import "../../../components/search-input";
|
||||||
import {
|
import {
|
||||||
ACTION_GROUPS,
|
ACTION_GROUPS,
|
||||||
ACTION_ICONS,
|
ACTION_ICONS,
|
||||||
@ -36,6 +41,7 @@ import {
|
|||||||
} from "../../../data/action";
|
} from "../../../data/action";
|
||||||
import { AutomationElementGroup } from "../../../data/automation";
|
import { AutomationElementGroup } from "../../../data/automation";
|
||||||
import { CONDITION_GROUPS, CONDITION_ICONS } from "../../../data/condition";
|
import { CONDITION_GROUPS, CONDITION_ICONS } from "../../../data/condition";
|
||||||
|
import { getServiceIcons } from "../../../data/icons";
|
||||||
import {
|
import {
|
||||||
IntegrationManifest,
|
IntegrationManifest,
|
||||||
domainToName,
|
domainToName,
|
||||||
@ -45,16 +51,10 @@ import { TRIGGER_GROUPS, TRIGGER_ICONS } from "../../../data/trigger";
|
|||||||
import { HassDialog } from "../../../dialogs/make-dialog-manager";
|
import { HassDialog } from "../../../dialogs/make-dialog-manager";
|
||||||
import { haStyle, haStyleDialog } from "../../../resources/styles";
|
import { haStyle, haStyleDialog } from "../../../resources/styles";
|
||||||
import { HomeAssistant } from "../../../types";
|
import { HomeAssistant } from "../../../types";
|
||||||
import { brandsUrl } from "../../../util/brands-url";
|
|
||||||
import {
|
import {
|
||||||
AddAutomationElementDialogParams,
|
AddAutomationElementDialogParams,
|
||||||
PASTE_VALUE,
|
PASTE_VALUE,
|
||||||
} from "./show-add-automation-element-dialog";
|
} from "./show-add-automation-element-dialog";
|
||||||
import { computeDomain } from "../../../common/entity/compute_domain";
|
|
||||||
import { deepEqual } from "../../../common/util/deep-equal";
|
|
||||||
import "../../../components/search-input";
|
|
||||||
import "@material/web/divider/divider";
|
|
||||||
import { getServiceIcons } from "../../../data/icons";
|
|
||||||
|
|
||||||
const TYPES = {
|
const TYPES = {
|
||||||
trigger: { groups: TRIGGER_GROUPS, icons: TRIGGER_ICONS },
|
trigger: { groups: TRIGGER_GROUPS, icons: TRIGGER_ICONS },
|
||||||
@ -74,7 +74,6 @@ interface ListItem {
|
|||||||
description: string;
|
description: string;
|
||||||
iconPath?: string;
|
iconPath?: string;
|
||||||
icon?: TemplateResult;
|
icon?: TemplateResult;
|
||||||
image?: string;
|
|
||||||
group: boolean;
|
group: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -318,17 +317,15 @@ class DialogAddAutomationElement extends LitElement implements HassDialog {
|
|||||||
(!domainUsed && manifest?.integration_type === "entity") ||
|
(!domainUsed && manifest?.integration_type === "entity") ||
|
||||||
!["helper", "entity"].includes(manifest?.integration_type || "")))
|
!["helper", "entity"].includes(manifest?.integration_type || "")))
|
||||||
) {
|
) {
|
||||||
const icon = domainIconWithoutDefault(domain);
|
|
||||||
result.push({
|
result.push({
|
||||||
group: true,
|
group: true,
|
||||||
iconPath: icon,
|
icon: html`
|
||||||
image: !icon
|
<ha-domain-icon
|
||||||
? brandsUrl({
|
.hass=${this.hass}
|
||||||
domain,
|
.domain=${domain}
|
||||||
type: "icon",
|
brandFallback
|
||||||
darkOptimized: this.hass.themes?.darkMode,
|
></ha-domain-icon>
|
||||||
})
|
`,
|
||||||
: undefined,
|
|
||||||
key: `${SERVICE_PREFIX}${domain}`,
|
key: `${SERVICE_PREFIX}${domain}`,
|
||||||
name: domainToName(localize, domain, manifest),
|
name: domainToName(localize, domain, manifest),
|
||||||
description: "",
|
description: "",
|
||||||
@ -364,10 +361,12 @@ class DialogAddAutomationElement extends LitElement implements HassDialog {
|
|||||||
for (const service of services_keys) {
|
for (const service of services_keys) {
|
||||||
result.push({
|
result.push({
|
||||||
group: false,
|
group: false,
|
||||||
icon: html`<ha-service-icon
|
icon: html`
|
||||||
|
<ha-service-icon
|
||||||
.hass=${this.hass}
|
.hass=${this.hass}
|
||||||
.service=${`${dmn}.${service}`}
|
.service=${`${dmn}.${service}`}
|
||||||
></ha-service-icon>`,
|
></ha-service-icon>
|
||||||
|
`,
|
||||||
key: `${SERVICE_PREFIX}${dmn}.${service}`,
|
key: `${SERVICE_PREFIX}${dmn}.${service}`,
|
||||||
name: `${domain ? "" : `${domainToName(localize, dmn)}: `}${
|
name: `${domain ? "" : `${domainToName(localize, dmn)}: `}${
|
||||||
this.hass.localize(`component.${dmn}.services.${service}.name`) ||
|
this.hass.localize(`component.${dmn}.services.${service}.name`) ||
|
||||||
@ -578,13 +577,7 @@ class DialogAddAutomationElement extends LitElement implements HassDialog {
|
|||||||
slot="start"
|
slot="start"
|
||||||
.path=${item.iconPath}
|
.path=${item.iconPath}
|
||||||
></ha-svg-icon>`
|
></ha-svg-icon>`
|
||||||
: html`<img
|
: nothing}
|
||||||
alt=""
|
|
||||||
slot="start"
|
|
||||||
src=${item.image!}
|
|
||||||
crossorigin="anonymous"
|
|
||||||
referrerpolicy="no-referrer"
|
|
||||||
/>`}
|
|
||||||
${item.group
|
${item.group
|
||||||
? html`<ha-icon-next slot="end"></ha-icon-next>`
|
? html`<ha-icon-next slot="end"></ha-icon-next>`
|
||||||
: html`<ha-svg-icon
|
: html`<ha-svg-icon
|
||||||
|
@ -12,11 +12,11 @@ import { classMap } from "lit/directives/class-map";
|
|||||||
import { styleMap } from "lit/directives/style-map";
|
import { styleMap } from "lit/directives/style-map";
|
||||||
import { applyThemesOnElement } from "../../../common/dom/apply_themes_on_element";
|
import { applyThemesOnElement } from "../../../common/dom/apply_themes_on_element";
|
||||||
import { fireEvent } from "../../../common/dom/fire_event";
|
import { fireEvent } from "../../../common/dom/fire_event";
|
||||||
import { alarmPanelIcon } from "../../../common/entity/alarm_panel_icon";
|
|
||||||
import { stateColorCss } from "../../../common/entity/state_color";
|
import { stateColorCss } from "../../../common/entity/state_color";
|
||||||
import { supportsFeature } from "../../../common/entity/supports-feature";
|
import { supportsFeature } from "../../../common/entity/supports-feature";
|
||||||
import "../../../components/chips/ha-assist-chip";
|
import "../../../components/chips/ha-assist-chip";
|
||||||
import "../../../components/ha-card";
|
import "../../../components/ha-card";
|
||||||
|
import "../../../components/ha-state-icon";
|
||||||
import "../../../components/ha-textfield";
|
import "../../../components/ha-textfield";
|
||||||
import type { HaTextField } from "../../../components/ha-textfield";
|
import type { HaTextField } from "../../../components/ha-textfield";
|
||||||
import {
|
import {
|
||||||
@ -199,8 +199,11 @@ class HuiAlarmPanelCard extends LitElement implements LovelaceCard {
|
|||||||
@click=${this._handleMoreInfo}
|
@click=${this._handleMoreInfo}
|
||||||
.label=${stateLabel}
|
.label=${stateLabel}
|
||||||
>
|
>
|
||||||
<ha-svg-icon slot="icon" .path=${alarmPanelIcon(stateObj.state)}>
|
<ha-state-icon
|
||||||
</ha-svg-icon>
|
slot="icon"
|
||||||
|
.hass=${this.hass}
|
||||||
|
.stateObj=${stateObj}
|
||||||
|
></ha-state-icon>
|
||||||
</ha-assist-chip>
|
</ha-assist-chip>
|
||||||
</h1>
|
</h1>
|
||||||
<div id="armActions" class="actions">
|
<div id="armActions" class="actions">
|
||||||
|
@ -23,9 +23,8 @@ import { customElement, property, state } from "lit/decorators";
|
|||||||
import { classMap } from "lit/directives/class-map";
|
import { classMap } from "lit/directives/class-map";
|
||||||
import { styleMap } from "lit/directives/style-map";
|
import { styleMap } from "lit/directives/style-map";
|
||||||
import memoizeOne from "memoize-one";
|
import memoizeOne from "memoize-one";
|
||||||
import { FIXED_DEVICE_CLASS_ICONS, STATES_OFF } from "../../../common/const";
|
import { STATES_OFF } from "../../../common/const";
|
||||||
import { applyThemesOnElement } from "../../../common/dom/apply_themes_on_element";
|
import { applyThemesOnElement } from "../../../common/dom/apply_themes_on_element";
|
||||||
import { binarySensorIcon } from "../../../common/entity/binary_sensor_icon";
|
|
||||||
import { computeDomain } from "../../../common/entity/compute_domain";
|
import { computeDomain } from "../../../common/entity/compute_domain";
|
||||||
import { navigate } from "../../../common/navigate";
|
import { navigate } from "../../../common/navigate";
|
||||||
import {
|
import {
|
||||||
@ -36,8 +35,9 @@ import { blankBeforeUnit } from "../../../common/translations/blank_before_unit"
|
|||||||
import parseAspectRatio from "../../../common/util/parse-aspect-ratio";
|
import parseAspectRatio from "../../../common/util/parse-aspect-ratio";
|
||||||
import { subscribeOne } from "../../../common/util/subscribe-one";
|
import { subscribeOne } from "../../../common/util/subscribe-one";
|
||||||
import "../../../components/ha-card";
|
import "../../../components/ha-card";
|
||||||
|
import "../../../components/ha-domain-icon";
|
||||||
import "../../../components/ha-icon-button";
|
import "../../../components/ha-icon-button";
|
||||||
import "../../../components/ha-svg-icon";
|
import "../../../components/ha-state-icon";
|
||||||
import {
|
import {
|
||||||
AreaRegistryEntry,
|
AreaRegistryEntry,
|
||||||
subscribeAreaRegistry,
|
subscribeAreaRegistry,
|
||||||
@ -388,13 +388,16 @@ export class HuiAreaCard
|
|||||||
(entity) => entity.attributes.device_class === deviceClass
|
(entity) => entity.attributes.device_class === deviceClass
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
const icon = FIXED_DEVICE_CLASS_ICONS[deviceClass];
|
sensors.push(html`
|
||||||
sensors.push(
|
<div class="sensor">
|
||||||
html`<div class="sensor">
|
<ha-domain-icon
|
||||||
${icon ? html`<ha-svg-icon .path=${icon}></ha-svg-icon>` : ""}
|
.hass=${this.hass}
|
||||||
|
.domain=${domain}
|
||||||
|
.deviceClass=${deviceClass}
|
||||||
|
></ha-domain-icon>
|
||||||
${this._average(domain, deviceClass)}
|
${this._average(domain, deviceClass)}
|
||||||
</div> `
|
</div>
|
||||||
);
|
`);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -434,16 +437,18 @@ export class HuiAreaCard
|
|||||||
<div class="alerts">
|
<div class="alerts">
|
||||||
${ALERT_DOMAINS.map((domain) => {
|
${ALERT_DOMAINS.map((domain) => {
|
||||||
if (!(domain in entitiesByDomain)) {
|
if (!(domain in entitiesByDomain)) {
|
||||||
return "";
|
return nothing;
|
||||||
}
|
}
|
||||||
return this._deviceClasses[domain].map((deviceClass) => {
|
return this._deviceClasses[domain].map((deviceClass) => {
|
||||||
const entity = this._isOn(domain, deviceClass);
|
const entity = this._isOn(domain, deviceClass);
|
||||||
return entity
|
return entity
|
||||||
? html`<ha-svg-icon
|
? html`
|
||||||
|
<ha-state-icon
|
||||||
class="alert"
|
class="alert"
|
||||||
.path=${DOMAIN_ICONS[domain][deviceClass] ||
|
.hass=${this.hass}
|
||||||
binarySensorIcon(entity.state, entity)}
|
.stateObj=${entity}
|
||||||
></ha-svg-icon>`
|
></ha-state-icon>
|
||||||
|
`
|
||||||
: nothing;
|
: nothing;
|
||||||
});
|
});
|
||||||
})}
|
})}
|
||||||
@ -574,7 +579,14 @@ export class HuiAreaCard
|
|||||||
padding: 16px;
|
padding: 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.alerts ha-svg-icon {
|
ha-state-icon {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.alerts ha-state-icon {
|
||||||
background: var(--accent-color);
|
background: var(--accent-color);
|
||||||
color: var(--text-accent-color, var(--text-primary-color));
|
color: var(--text-accent-color, var(--text-primary-color));
|
||||||
padding: 8px;
|
padding: 8px;
|
||||||
|
@ -16,7 +16,7 @@ import {
|
|||||||
import { customElement, property, state } from "lit/decorators";
|
import { customElement, property, state } from "lit/decorators";
|
||||||
import { applyThemesOnElement } from "../../../common/dom/apply_themes_on_element";
|
import { applyThemesOnElement } from "../../../common/dom/apply_themes_on_element";
|
||||||
import { fireEvent } from "../../../common/dom/fire_event";
|
import { fireEvent } from "../../../common/dom/fire_event";
|
||||||
import { batteryIcon } from "../../../common/entity/battery_icon";
|
import { batteryLevelIcon } from "../../../common/entity/battery_icon";
|
||||||
import { computeStateName } from "../../../common/entity/compute_state_name";
|
import { computeStateName } from "../../../common/entity/compute_state_name";
|
||||||
import "../../../components/ha-card";
|
import "../../../components/ha-card";
|
||||||
import "../../../components/ha-svg-icon";
|
import "../../../components/ha-svg-icon";
|
||||||
@ -252,7 +252,7 @@ class HuiPlantStatusCard extends LitElement implements LovelaceCard {
|
|||||||
|
|
||||||
private computeIcon(attr: string, batLvl: number): string {
|
private computeIcon(attr: string, batLvl: number): string {
|
||||||
if (attr === "battery") {
|
if (attr === "battery") {
|
||||||
return batteryIcon(batLvl);
|
return batteryLevelIcon(batLvl);
|
||||||
}
|
}
|
||||||
return SENSOR_ICONS[attr];
|
return SENSOR_ICONS[attr];
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,5 @@
|
|||||||
import "@material/mwc-button/mwc-button";
|
|
||||||
import "@material/mwc-linear-progress/mwc-linear-progress";
|
import "@material/mwc-linear-progress/mwc-linear-progress";
|
||||||
import type { LinearProgress } from "@material/mwc-linear-progress/mwc-linear-progress";
|
import type { LinearProgress } from "@material/mwc-linear-progress/mwc-linear-progress";
|
||||||
import "@material/mwc-list/mwc-list-item";
|
|
||||||
import {
|
import {
|
||||||
mdiChevronDown,
|
mdiChevronDown,
|
||||||
mdiMonitor,
|
mdiMonitor,
|
||||||
@ -12,11 +10,11 @@ import {
|
|||||||
mdiVolumeHigh,
|
mdiVolumeHigh,
|
||||||
} from "@mdi/js";
|
} from "@mdi/js";
|
||||||
import {
|
import {
|
||||||
css,
|
|
||||||
CSSResultGroup,
|
CSSResultGroup,
|
||||||
html,
|
|
||||||
LitElement,
|
LitElement,
|
||||||
PropertyValues,
|
PropertyValues,
|
||||||
|
css,
|
||||||
|
html,
|
||||||
nothing,
|
nothing,
|
||||||
} from "lit";
|
} from "lit";
|
||||||
import { customElement, property, query, state } from "lit/decorators";
|
import { customElement, property, query, state } from "lit/decorators";
|
||||||
@ -26,25 +24,29 @@ import { fireEvent } from "../../common/dom/fire_event";
|
|||||||
import { computeDomain } from "../../common/entity/compute_domain";
|
import { computeDomain } from "../../common/entity/compute_domain";
|
||||||
import { computeStateDomain } from "../../common/entity/compute_state_domain";
|
import { computeStateDomain } from "../../common/entity/compute_state_domain";
|
||||||
import { computeStateName } from "../../common/entity/compute_state_name";
|
import { computeStateName } from "../../common/entity/compute_state_name";
|
||||||
import { domainIcon } from "../../common/entity/domain_icon";
|
|
||||||
import { supportsFeature } from "../../common/entity/supports-feature";
|
import { supportsFeature } from "../../common/entity/supports-feature";
|
||||||
|
import { debounce } from "../../common/util/debounce";
|
||||||
import "../../components/ha-button";
|
import "../../components/ha-button";
|
||||||
import "../../components/ha-button-menu";
|
import "../../components/ha-button-menu";
|
||||||
import "../../components/ha-circular-progress";
|
import "../../components/ha-circular-progress";
|
||||||
|
import "../../components/ha-domain-icon";
|
||||||
import "../../components/ha-icon-button";
|
import "../../components/ha-icon-button";
|
||||||
|
import "../../components/ha-list-item";
|
||||||
|
import "../../components/ha-state-icon";
|
||||||
|
import "../../components/ha-svg-icon";
|
||||||
import { UNAVAILABLE } from "../../data/entity";
|
import { UNAVAILABLE } from "../../data/entity";
|
||||||
import {
|
import {
|
||||||
BROWSER_PLAYER,
|
BROWSER_PLAYER,
|
||||||
cleanupMediaTitle,
|
|
||||||
computeMediaControls,
|
|
||||||
computeMediaDescription,
|
|
||||||
ControlButton,
|
ControlButton,
|
||||||
formatMediaTime,
|
|
||||||
getCurrentProgress,
|
|
||||||
handleMediaControlClick,
|
|
||||||
MediaPlayerEntity,
|
MediaPlayerEntity,
|
||||||
MediaPlayerEntityFeature,
|
MediaPlayerEntityFeature,
|
||||||
MediaPlayerItem,
|
MediaPlayerItem,
|
||||||
|
cleanupMediaTitle,
|
||||||
|
computeMediaControls,
|
||||||
|
computeMediaDescription,
|
||||||
|
formatMediaTime,
|
||||||
|
getCurrentProgress,
|
||||||
|
handleMediaControlClick,
|
||||||
setMediaPlayerVolume,
|
setMediaPlayerVolume,
|
||||||
} from "../../data/media-player";
|
} from "../../data/media-player";
|
||||||
import { ResolvedMediaSource } from "../../data/media_source";
|
import { ResolvedMediaSource } from "../../data/media_source";
|
||||||
@ -56,7 +58,6 @@ import {
|
|||||||
BrowserMediaPlayer,
|
BrowserMediaPlayer,
|
||||||
ERR_UNSUPPORTED_MEDIA,
|
ERR_UNSUPPORTED_MEDIA,
|
||||||
} from "./browser-media-player";
|
} from "./browser-media-player";
|
||||||
import { debounce } from "../../common/util/debounce";
|
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
interface HASSDomEvents {
|
interface HASSDomEvents {
|
||||||
@ -320,22 +321,19 @@ export class BarMediaPlayer extends SubscribeMixin(LitElement) {
|
|||||||
: ""
|
: ""
|
||||||
}
|
}
|
||||||
|
|
||||||
<ha-button-menu >
|
<ha-button-menu>
|
||||||
${
|
${
|
||||||
this.narrow
|
this.narrow
|
||||||
? html`
|
? html`
|
||||||
<ha-icon-button
|
<ha-icon-button slot="trigger">
|
||||||
slot="trigger"
|
${this._renderIcon(isBrowser, stateObj)}
|
||||||
.path=${isBrowser
|
</ha-icon-button>
|
||||||
? mdiMonitor
|
|
||||||
: domainIcon(computeDomain(this.entityId), stateObj)}
|
|
||||||
></ha-icon-button>
|
|
||||||
`
|
`
|
||||||
: html`
|
: html`
|
||||||
<ha-button
|
<ha-button
|
||||||
slot="trigger"
|
slot="trigger"
|
||||||
.label=${this.narrow
|
.label=${this.narrow
|
||||||
? ""
|
? nothing
|
||||||
: `${
|
: `${
|
||||||
stateObj
|
stateObj
|
||||||
? computeStateName(stateObj)
|
? computeStateName(stateObj)
|
||||||
@ -343,12 +341,9 @@ export class BarMediaPlayer extends SubscribeMixin(LitElement) {
|
|||||||
}
|
}
|
||||||
`}
|
`}
|
||||||
>
|
>
|
||||||
<ha-svg-icon
|
<span slot="icon">
|
||||||
slot="icon"
|
${this._renderIcon(isBrowser, stateObj)}
|
||||||
.path=${isBrowser
|
</span>
|
||||||
? mdiMonitor
|
|
||||||
: domainIcon(computeDomain(this.entityId), stateObj)}
|
|
||||||
></ha-svg-icon>
|
|
||||||
<ha-svg-icon
|
<ha-svg-icon
|
||||||
slot="trailingIcon"
|
slot="trailingIcon"
|
||||||
.path=${mdiChevronDown}
|
.path=${mdiChevronDown}
|
||||||
@ -356,23 +351,23 @@ export class BarMediaPlayer extends SubscribeMixin(LitElement) {
|
|||||||
</ha-button>
|
</ha-button>
|
||||||
`
|
`
|
||||||
}
|
}
|
||||||
<mwc-list-item
|
<ha-list-item
|
||||||
.player=${BROWSER_PLAYER}
|
.player=${BROWSER_PLAYER}
|
||||||
?selected=${isBrowser}
|
?selected=${isBrowser}
|
||||||
@click=${this._selectPlayer}
|
@click=${this._selectPlayer}
|
||||||
>
|
>
|
||||||
${this.hass.localize("ui.components.media-browser.web-browser")}
|
${this.hass.localize("ui.components.media-browser.web-browser")}
|
||||||
</mwc-list-item>
|
</ha-list-item>
|
||||||
${this._mediaPlayerEntities.map(
|
${this._mediaPlayerEntities.map(
|
||||||
(source) => html`
|
(source) => html`
|
||||||
<mwc-list-item
|
<ha-list-item
|
||||||
?selected=${source.entity_id === this.entityId}
|
?selected=${source.entity_id === this.entityId}
|
||||||
.disabled=${source.state === UNAVAILABLE}
|
.disabled=${source.state === UNAVAILABLE}
|
||||||
.player=${source.entity_id}
|
.player=${source.entity_id}
|
||||||
@click=${this._selectPlayer}
|
@click=${this._selectPlayer}
|
||||||
>
|
>
|
||||||
${computeStateName(source)}
|
${computeStateName(source)}
|
||||||
</mwc-list-item>
|
</ha-list-item>
|
||||||
`
|
`
|
||||||
)}
|
)}
|
||||||
</ha-button-menu>
|
</ha-button-menu>
|
||||||
@ -382,6 +377,23 @@ export class BarMediaPlayer extends SubscribeMixin(LitElement) {
|
|||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private _renderIcon(isBrowser: boolean, stateObj?: MediaPlayerEntity) {
|
||||||
|
if (isBrowser) {
|
||||||
|
return html`<ha-svg-icon .path=${mdiMonitor}></ha-svg-icon>`;
|
||||||
|
}
|
||||||
|
if (stateObj) {
|
||||||
|
return html`
|
||||||
|
<ha-state-icon .hass=${this.hass} .stateObj=${stateObj}></ha-state-icon>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
return html`
|
||||||
|
<ha-domain-icon
|
||||||
|
.hass=${this.hass}
|
||||||
|
.domain=${computeDomain(this.entityId)}
|
||||||
|
></ha-domain-icon>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
public willUpdate(changedProps: PropertyValues) {
|
public willUpdate(changedProps: PropertyValues) {
|
||||||
super.willUpdate(changedProps);
|
super.willUpdate(changedProps);
|
||||||
if (changedProps.has("entityId")) {
|
if (changedProps.has("entityId")) {
|
||||||
@ -571,9 +583,10 @@ export class BarMediaPlayer extends SubscribeMixin(LitElement) {
|
|||||||
--mdc-theme-primary: var(--secondary-text-color);
|
--mdc-theme-primary: var(--secondary-text-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
mwc-button[slot="trigger"] {
|
ha-button-menu ha-button[slot="trigger"] {
|
||||||
|
line-height: 1;
|
||||||
--mdc-theme-primary: var(--primary-text-color);
|
--mdc-theme-primary: var(--primary-text-color);
|
||||||
--mdc-icon-size: 36px;
|
--mdc-icon-size: 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.info {
|
.info {
|
||||||
@ -655,10 +668,6 @@ export class BarMediaPlayer extends SubscribeMixin(LitElement) {
|
|||||||
margin: 16px 0 16px 16px;
|
margin: 16px 0 16px 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
ha-button-menu mwc-button {
|
|
||||||
line-height: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
:host([narrow]) {
|
:host([narrow]) {
|
||||||
height: 57px;
|
height: 57px;
|
||||||
}
|
}
|
||||||
@ -705,10 +714,15 @@ export class BarMediaPlayer extends SubscribeMixin(LitElement) {
|
|||||||
left: 0;
|
left: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
mwc-list-item[selected] {
|
ha-list-item[selected] {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
span[slot="icon"] {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
ha-svg-icon[slot="trailingIcon"] {
|
ha-svg-icon[slot="trailingIcon"] {
|
||||||
margin-inline-start: 8px !important;
|
margin-inline-start: 8px !important;
|
||||||
margin-inline-end: 0px !important;
|
margin-inline-end: 0px !important;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user