@hakit/core
Version:
A collection of React hooks and helpers for Home Assistant to easily communicate with the Home Assistant WebSocket API.
1 lines • 20.7 kB
Source Map (JSON)
{"version":3,"file":"index-DvzmKbw2.cjs","sources":["../src/hooks/useIcon/index.tsx","../src/hooks/useEntity/index.ts"],"sourcesContent":["import { useMemo } from \"react\";\nimport { Icon as IconElement } from \"@iconify/react\";\nimport type { IconProps } from \"@iconify/react\";\nimport { useEntity, computeDomain, AllDomains, CamelToSnake, EntityName } from \"@core\";\nimport { snakeCase } from \"lodash\";\nimport { HassEntity } from \"home-assistant-js-websocket\";\n\nimport { binarySensorIcon } from \"./domains/binary_sensor\";\nimport { sensorIcon } from \"./domains/sensor\";\nimport { numberIcon } from \"./domains/number\";\nimport { coverIcon } from \"./domains/cover\";\nimport { alarmPanelIcon } from \"./domains/alarm\";\nimport { weatherIcon } from \"./domains/weather\";\nimport { FIXED_DOMAIN_ICONS } from \"./domains/constants\";\n\nexport { batteryIconByLevel } from \"./domains/battery\";\n\nexport function useIconByDomain<D extends AllDomains | CamelToSnake<AllDomains> | \"unknown\">(\n domain: D,\n iconProps?: Omit<IconProps, \"icon\">,\n) {\n const iconName = useMemo(() => {\n const convertedDomainName = snakeCase(domain) as keyof typeof FIXED_DOMAIN_ICONS;\n if (FIXED_DOMAIN_ICONS[convertedDomainName]) {\n return FIXED_DOMAIN_ICONS[convertedDomainName];\n }\n // If the domain does not match any case, we just return an info icon\n return \"mdi:information-outline\";\n }, [domain]);\n if (iconName === null) {\n return null;\n }\n return (\n <IconElement\n style={{\n fontSize: iconProps?.fontSize ?? \"24px\",\n }}\n icon={iconName}\n {...iconProps}\n />\n );\n}\n\nexport function useIcon(icon: string | null, iconProps?: Omit<IconProps, \"icon\">) {\n const Icon = useMemo(() => {\n if (icon === null) return null;\n return (\n <IconElement\n style={{\n fontSize: iconProps?.fontSize ?? \"24px\",\n }}\n icon={icon || \"octicon:info-24\"}\n {...iconProps}\n />\n );\n }, [icon, iconProps]);\n return Icon;\n}\n\nexport function getIconByEntity(domain: string, entity: HassEntity): string | undefined {\n const compareState = entity.state;\n\n switch (domain) {\n case \"alarm_control_panel\":\n return alarmPanelIcon(compareState);\n\n case \"automation\":\n return compareState === \"unavailable\" ? \"mdi:robot-confused\" : compareState === \"off\" ? \"mdi:robot-off\" : \"mdi:robot\";\n\n case \"binary_sensor\":\n return binarySensorIcon(entity);\n\n case \"button\":\n switch (entity.attributes.device_class) {\n case \"identify\":\n return \"mdi:crosshairs-question\";\n case \"restart\":\n return \"mdi:restart\";\n case \"update\":\n return \"mdi:package-up\";\n default:\n return \"mdi:button-pointer\";\n }\n\n case \"camera\":\n return compareState === \"off\" ? \"mdi:video-off\" : \"mdi:video\";\n\n case \"cover\":\n return coverIcon(entity);\n\n case \"device_tracker\":\n if (entity.attributes.source_type === \"router\") {\n return compareState === \"home\" ? \"mdi:lan-connect\" : \"mdi:lan-disconnect\";\n }\n if ([\"bluetooth\", \"bluetooth_le\"].includes(entity.attributes.source_type)) {\n return compareState === \"home\" ? \"mdi:bluetooth-connect\" : \"mdi:bluetooth\";\n }\n return compareState === \"not_home\" ? \"mdi:account-arrow-right\" : \"mdi:account\";\n\n case \"event\":\n switch (entity.attributes.device_class) {\n case \"doorbell\":\n return \"mdi:doorbell\";\n case \"button\":\n return \"mdi:gesture-tap-button\";\n case \"motion\":\n return \"mdi:motion-sensor\";\n default:\n return \"mdi:eye-check\";\n }\n\n case \"fan\":\n return compareState === \"off\" ? \"mdi:fan-off\" : \"mdi:fan\";\n\n case \"humidifier\":\n return compareState === \"off\" ? \"mdi:air-humidifier-off\" : \"mdi:air-humidifier\";\n\n case \"input_boolean\":\n return compareState === \"on\" ? \"mdi:check-circle-outline\" : \"mdi:close-circle-outline\";\n\n case \"input_datetime\":\n if (!entity.attributes.has_date) {\n return \"mdi:clock\";\n }\n if (!entity.attributes.has_time) {\n return \"mdi:calendar\";\n }\n break;\n\n case \"lock\":\n switch (compareState) {\n case \"unlocked\":\n return \"mdi:lock-open\";\n case \"jammed\":\n return \"mdi:lock-alert\";\n case \"locking\":\n case \"unlocking\":\n return \"mdi:lock-clock\";\n default:\n return \"mdi:lock\";\n }\n\n case \"media_player\":\n switch (entity.attributes.device_class) {\n case \"speaker\":\n switch (compareState) {\n case \"playing\":\n return \"mdi:speaker-play\";\n case \"paused\":\n return \"mdi:speaker-pause\";\n case \"off\":\n return \"mdi:speaker-off\";\n default:\n return \"mdi:speaker\";\n }\n case \"tv\":\n switch (compareState) {\n case \"playing\":\n return \"mdi:television-play\";\n case \"paused\":\n return \"mdi:television-pause\";\n case \"off\":\n return \"mdi:television-off\";\n default:\n return \"mdi:television\";\n }\n case \"receiver\":\n switch (compareState) {\n case \"off\":\n return \"mdi:audio-video-off\";\n default:\n return \"mdi:audio-video\";\n }\n default:\n switch (compareState) {\n case \"playing\":\n case \"paused\":\n return \"mdi:cast-connected\";\n case \"off\":\n return \"mdi:cast-off\";\n default:\n return \"mdi:cast\";\n }\n }\n\n case \"number\": {\n const icon = numberIcon(entity);\n if (icon) {\n return icon;\n }\n\n break;\n }\n\n case \"person\":\n return compareState === \"not_home\" ? \"mdi:account-arrow-right\" : \"mdi:account\";\n\n case \"switch\":\n switch (entity.attributes.device_class) {\n case \"outlet\":\n return compareState === \"on\" ? \"mdi:power-plug\" : \"mdi:power-plug-off\";\n case \"switch\":\n return compareState === \"on\" ? \"mdi:toggle-switch-variant\" : \"mdi:toggle-switch-variant-off\";\n default:\n return \"mdi:toggle-switch-variant\";\n }\n\n case \"sensor\": {\n const icon = sensorIcon(entity);\n if (icon) {\n return icon;\n }\n break;\n }\n\n case \"sun\":\n return entity.state === \"above_horizon\" ? \"mdi:white-balance-sunny\" : \"mdi:weather-night\";\n\n case \"switch_as_x\":\n return \"mdi:swap-horizontal\";\n\n case \"threshold\":\n return \"mdi:chart-sankey\";\n\n case \"update\":\n return \"mdi:package\";\n case \"water_heater\":\n return compareState === \"off\" ? \"mdi:water-boiler-off\" : \"mdi:water-boiler\";\n\n case \"weather\":\n return weatherIcon(entity.state);\n }\n\n if (domain in FIXED_DOMAIN_ICONS) {\n return FIXED_DOMAIN_ICONS[domain as keyof typeof FIXED_DOMAIN_ICONS];\n }\n\n return undefined;\n}\n\nexport function useIconByEntity<E extends EntityName>(_entity: E, iconProps?: Omit<IconProps, \"icon\">) {\n const entity = useEntity(_entity || \"unknown\", {\n returnNullIfNotFound: true,\n });\n const Icon = useMemo(() => {\n if (entity === null) return null;\n const icon = entity.attributes.icon ?? getIconByEntity(computeDomain(_entity), entity);\n if (!icon) {\n return null;\n }\n return (\n <IconElement\n style={{\n fontSize: iconProps?.fontSize ?? \"24px\",\n }}\n icon={icon}\n {...iconProps}\n />\n );\n }, [entity, _entity, iconProps]);\n return Icon;\n}\n","import { useEffect, useMemo, useState, useCallback } from \"react\";\nimport { cloneDeep, isEmpty, omit } from \"lodash\";\nimport type { HassEntityWithService, HassEntityCustom, ExtractDomain, EntityName } from \"@typings\";\nimport type { HassEntity } from \"home-assistant-js-websocket\";\nimport { useSubscribeEntity } from \"../useSubscribeEntity\";\nimport { useService } from \"../useService\";\nimport { useHistory } from \"../useHistory\";\nimport { getIconByEntity } from \"../useIcon\";\nimport { useThrottledCallback } from \"use-debounce\";\nimport { getCssColorValue } from \"@utils/colors\";\nimport { computeDomain } from \"@utils/computeDomain\";\nimport { diff } from \"deep-object-diff\";\nimport type { HistoryOptions } from \"../useHistory\";\nimport { timeAgo } from \"@utils/time/time-ago\";\nimport { useHass } from \"../useHass\";\n\ninterface UseEntityOptions {\n /** The amount of time to throttle updates in milliseconds */\n throttle?: number;\n returnNullIfNotFound?: boolean;\n historyOptions?: HistoryOptions;\n}\n\nconst DEFAULT_OPTIONS: Required<UseEntityOptions> = {\n throttle: 25,\n returnNullIfNotFound: false,\n historyOptions: {\n hoursToShow: 24,\n significantChangesOnly: true,\n minimalResponse: true,\n disable: true,\n },\n};\n\ntype UseEntityReturnType<E, O extends UseEntityOptions> = O[\"returnNullIfNotFound\"] extends true\n ? HassEntityWithService<ExtractDomain<E>> | null\n : HassEntityWithService<ExtractDomain<E>>;\n\nexport function useEntity<E extends EntityName, O extends UseEntityOptions = UseEntityOptions>(\n entity: E,\n options: O = DEFAULT_OPTIONS as O,\n): UseEntityReturnType<E, O> {\n const { throttle, returnNullIfNotFound, historyOptions } = {\n ...DEFAULT_OPTIONS,\n ...options,\n historyOptions: {\n ...DEFAULT_OPTIONS.historyOptions,\n ...options.historyOptions,\n },\n };\n const getEntity = useSubscribeEntity(entity);\n const matchedEntity = getEntity(returnNullIfNotFound);\n const domain = computeDomain(entity) as ExtractDomain<E>;\n const service = useService(domain, entity);\n const history = useHistory(entity, historyOptions);\n const { useStore } = useHass();\n const language = useStore((state) => state.config?.language);\n\n const formatEntity = useCallback(\n (entity: HassEntity): HassEntityCustom => {\n const now = new Date();\n const then = new Date(entity.attributes.last_triggered ?? entity.last_updated);\n const relativeTime = timeAgo(then, language);\n const timeDiff = Math.abs(now.getTime() - then.getTime());\n const active = relativeTime === \"just now\";\n const { hexColor, rgbColor, brightness, brightnessValue, rgbaColor, color } = getCssColorValue(entity);\n return {\n ...entity,\n custom: {\n color,\n relativeTime,\n timeDiff,\n active,\n hexColor,\n rgbColor,\n brightness,\n brightnessValue,\n rgbaColor,\n },\n };\n },\n [language],\n );\n const debounceUpdate = useThrottledCallback(\n (entity: HassEntity) => {\n setEntity(formatEntity(entity));\n },\n throttle,\n {\n leading: true,\n trailing: true,\n },\n );\n\n const [$entity, setEntity] = useState<HassEntityCustom | null>(matchedEntity !== null ? formatEntity(matchedEntity) : null);\n\n useEffect(() => {\n setEntity((entity) => (entity === null ? null : formatEntity(entity)));\n }, [formatEntity]);\n\n useEffect(() => {\n const foundEntity = getEntity(true);\n if (foundEntity && $entity) {\n // have to omit attributes.icon here as the original icon may not contain any icon,\n // however there's custom functionality to determine icon based on state which needs to be omitted from\n // this check to avoid recursive updates\n const diffed = diff(\n omit(foundEntity, \"custom\", \"last_changed\", \"last_updated\", \"context\", \"attributes.icon\"),\n omit($entity, \"custom\", \"last_changed\", \"last_updated\", \"context\", \"attributes.icon\"),\n );\n const clonedEntity = cloneDeep(foundEntity);\n // Check for icon differences\n const haHasCustomIcon = typeof clonedEntity.attributes.icon === \"string\";\n const derivedIcon = typeof $entity.attributes.icon === \"string\";\n // Logic for handling icon comparison and updates\n let shouldUpdate = !isEmpty(diffed);\n if (haHasCustomIcon && derivedIcon && clonedEntity.attributes.icon !== $entity.attributes.icon) {\n // Condition 1: Both icons are strings and differ\n shouldUpdate = true;\n } else if (!haHasCustomIcon) {\n // Condition 2: clonedEntity's icon is not a string, compute and compare\n const currentIcon = getIconByEntity(computeDomain(clonedEntity.entity_id as EntityName), clonedEntity);\n if (currentIcon !== $entity.attributes.icon) {\n // Replace clonedEntity's icon with the computed icon and mark for update\n clonedEntity.attributes.icon = currentIcon;\n shouldUpdate = true;\n }\n }\n if (shouldUpdate) {\n debounceUpdate(clonedEntity);\n }\n }\n }, [$entity, debounceUpdate, getEntity]);\n\n useEffect(() => {\n // when the initial ID doesn't match an entity, but it's updated dynamically through the hook\n // we need to update the entity state\n if (matchedEntity && !$entity) {\n setEntity(formatEntity(matchedEntity));\n }\n // when the initial ID matches an entity, but it's updated dynamically through the hook and no longer matches\n // we need to clear the entity state\n if (!matchedEntity && $entity) {\n setEntity(null);\n }\n // when the initial ID matches an entity, but it doesn't match the entity id already set, we need to update the entity\n if (matchedEntity && $entity && matchedEntity.entity_id !== $entity.entity_id) {\n setEntity(formatEntity(matchedEntity));\n }\n }, [matchedEntity, $entity, formatEntity]);\n\n return useMemo(() => {\n if ($entity === null) {\n // purposely casting here so types are correct on usage side\n return null as unknown as UseEntityReturnType<E, O>;\n }\n return {\n ...$entity,\n history,\n service,\n } as unknown as UseEntityReturnType<E, O>;\n }, [$entity, history, service]);\n}\n"],"names":["useIconByDomain","domain","iconProps","iconName","useMemo","convertedDomainName","snakeCase","FIXED_DOMAIN_ICONS","jsx","IconElement","useIcon","icon","getIconByEntity","entity","compareState","alarmPanelIcon","binarySensorIcon","coverIcon","numberIcon","sensorIcon","weatherIcon","useIconByEntity","_entity","useEntity","computeDomain","DEFAULT_OPTIONS","options","throttle","returnNullIfNotFound","historyOptions","getEntity","useSubscribeEntity","matchedEntity","service","useService","history","useHistory","useStore","useHass","language","state","formatEntity","useCallback","now","then","relativeTime","timeAgo","timeDiff","active","hexColor","rgbColor","brightness","brightnessValue","rgbaColor","color","getCssColorValue","debounceUpdate","useThrottledCallback","setEntity","$entity","useState","useEffect","foundEntity","diffed","diff","omit","clonedEntity","cloneDeep","haHasCustomIcon","derivedIcon","shouldUpdate","isEmpty","currentIcon"],"mappings":"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"}