mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-22 16:56:35 +00:00
Custom iconsets in Icon Picker (#10399)
Co-authored-by: Bram Kragten <mail@bramkragten.nl>
This commit is contained in:
parent
5ef7a37c20
commit
df572d59c5
@ -7,6 +7,7 @@ import { css, html, LitElement, TemplateResult } from "lit";
|
||||
import { ComboBoxLitRenderer, comboBoxRenderer } from "lit-vaadin-helpers";
|
||||
import { customElement, property, query, state } from "lit/decorators";
|
||||
import { fireEvent } from "../common/dom/fire_event";
|
||||
import { customIcons } from "../data/custom_icons";
|
||||
import { PolymerChangedEvent } from "../polymer-types";
|
||||
import "./ha-icon";
|
||||
import "./ha-icon-button";
|
||||
@ -111,11 +112,36 @@ export class HaIconPicker extends LitElement {
|
||||
this._opened = ev.detail.value;
|
||||
if (this._opened && !iconItems.length) {
|
||||
const iconList = await import("../../build/mdi/iconList.json");
|
||||
|
||||
iconItems = iconList.default.map((icon) => ({
|
||||
icon: `mdi:${icon.name}`,
|
||||
keywords: icon.keywords,
|
||||
}));
|
||||
|
||||
(this.comboBox as any).filteredItems = iconItems;
|
||||
|
||||
Object.keys(customIcons).forEach((iconSet) => {
|
||||
this._loadCustomIconItems(iconSet);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private async _loadCustomIconItems(iconsetPrefix: string) {
|
||||
try {
|
||||
const getIconList = customIcons[iconsetPrefix].getIconList;
|
||||
if (typeof getIconList !== "function") {
|
||||
return;
|
||||
}
|
||||
const iconList = await getIconList();
|
||||
const customIconItems = iconList.map((icon) => ({
|
||||
icon: `${iconsetPrefix}:${icon.name}`,
|
||||
keywords: icon.keywords ?? [],
|
||||
}));
|
||||
iconItems.push(...customIconItems);
|
||||
(this.comboBox as any).filteredItems = iconItems;
|
||||
} catch (e) {
|
||||
// eslint-disable-next-line
|
||||
console.warn(`Unable to load icon list for ${iconsetPrefix} iconset`);
|
||||
}
|
||||
}
|
||||
|
||||
@ -158,7 +184,9 @@ export class HaIconPicker extends LitElement {
|
||||
if (filteredItems.length > 0) {
|
||||
(this.comboBox as any).filteredItems = filteredItems;
|
||||
} else {
|
||||
(this.comboBox as any).filteredItems = [filterString];
|
||||
(this.comboBox as any).filteredItems = [
|
||||
{ icon: filterString, keywords: [] },
|
||||
];
|
||||
}
|
||||
} else {
|
||||
(this.comboBox as any).filteredItems = iconItems;
|
||||
|
@ -10,7 +10,7 @@ import {
|
||||
import { customElement, property, state } from "lit/decorators";
|
||||
import { fireEvent } from "../common/dom/fire_event";
|
||||
import { debounce } from "../common/util/debounce";
|
||||
import { CustomIcon, customIconsets } from "../data/custom_iconsets";
|
||||
import { CustomIcon, customIcons } from "../data/custom_icons";
|
||||
import {
|
||||
checkCacheVersion,
|
||||
Chunks,
|
||||
@ -356,7 +356,7 @@ export class HaIcon extends LitElement {
|
||||
|
||||
@state() private _path?: string;
|
||||
|
||||
@state() private _viewBox?;
|
||||
@state() private _viewBox?: string;
|
||||
|
||||
@state() private _legacy = false;
|
||||
|
||||
@ -386,6 +386,7 @@ export class HaIcon extends LitElement {
|
||||
if (!this.icon) {
|
||||
return;
|
||||
}
|
||||
const requestedIcon = this.icon;
|
||||
const [iconPrefix, origIconName] = this.icon.split(":", 2);
|
||||
|
||||
let iconName = origIconName;
|
||||
@ -395,10 +396,10 @@ export class HaIcon extends LitElement {
|
||||
}
|
||||
|
||||
if (!MDI_PREFIXES.includes(iconPrefix)) {
|
||||
if (iconPrefix in customIconsets) {
|
||||
const customIconset = customIconsets[iconPrefix];
|
||||
if (customIconset) {
|
||||
this._setCustomPath(customIconset(iconName));
|
||||
if (iconPrefix in customIcons) {
|
||||
const customIcon = customIcons[iconPrefix];
|
||||
if (customIcon && typeof customIcon.getIcon === "function") {
|
||||
this._setCustomPath(customIcon.getIcon(iconName), requestedIcon);
|
||||
}
|
||||
return;
|
||||
}
|
||||
@ -441,14 +442,16 @@ export class HaIcon extends LitElement {
|
||||
}
|
||||
|
||||
if (databaseIcon) {
|
||||
this._path = databaseIcon;
|
||||
if (this.icon === requestedIcon) {
|
||||
this._path = databaseIcon;
|
||||
}
|
||||
cachedIcons[iconName] = databaseIcon;
|
||||
return;
|
||||
}
|
||||
const chunk = findIconChunk(iconName);
|
||||
|
||||
if (chunk in chunks) {
|
||||
this._setPath(chunks[chunk], iconName);
|
||||
this._setPath(chunks[chunk], iconName, requestedIcon);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -456,19 +459,31 @@ export class HaIcon extends LitElement {
|
||||
response.json()
|
||||
);
|
||||
chunks[chunk] = iconPromise;
|
||||
this._setPath(iconPromise, iconName);
|
||||
this._setPath(iconPromise, iconName, requestedIcon);
|
||||
debouncedWriteCache();
|
||||
}
|
||||
|
||||
private async _setCustomPath(promise: Promise<CustomIcon>) {
|
||||
private async _setCustomPath(
|
||||
promise: Promise<CustomIcon>,
|
||||
requestedIcon: string
|
||||
) {
|
||||
const icon = await promise;
|
||||
if (this.icon !== requestedIcon) {
|
||||
return;
|
||||
}
|
||||
this._path = icon.path;
|
||||
this._viewBox = icon.viewBox;
|
||||
}
|
||||
|
||||
private async _setPath(promise: Promise<Icons>, iconName: string) {
|
||||
private async _setPath(
|
||||
promise: Promise<Icons>,
|
||||
iconName: string,
|
||||
requestedIcon: string
|
||||
) {
|
||||
const iconPack = await promise;
|
||||
this._path = iconPack[iconName];
|
||||
if (this.icon === requestedIcon) {
|
||||
this._path = iconPack[iconName];
|
||||
}
|
||||
cachedIcons[iconName] = iconPack[iconName];
|
||||
}
|
||||
|
||||
|
40
src/data/custom_icons.ts
Normal file
40
src/data/custom_icons.ts
Normal file
@ -0,0 +1,40 @@
|
||||
import { customIconsets } from "./custom_iconsets";
|
||||
|
||||
export interface CustomIcon {
|
||||
path: string;
|
||||
viewBox?: string;
|
||||
}
|
||||
|
||||
export interface CustomIconListItem {
|
||||
name: string;
|
||||
keywords?: string[];
|
||||
}
|
||||
|
||||
export interface CustomIconHelpers {
|
||||
getIcon: (name: string) => Promise<CustomIcon>;
|
||||
getIconList?: () => Promise<CustomIconListItem[]>;
|
||||
}
|
||||
|
||||
export interface CustomIconsWindow {
|
||||
customIcons?: {
|
||||
[key: string]: CustomIconHelpers;
|
||||
};
|
||||
}
|
||||
|
||||
const customIconsWindow = window as CustomIconsWindow;
|
||||
|
||||
if (!("customIcons" in customIconsWindow)) {
|
||||
customIconsWindow.customIcons = {};
|
||||
}
|
||||
|
||||
// Proxy for backward compatibility with icon sets
|
||||
export const customIcons = new Proxy(customIconsWindow.customIcons!, {
|
||||
get: (obj, prop: string) =>
|
||||
obj[prop] ??
|
||||
(customIconsets[prop]
|
||||
? {
|
||||
getIcon: customIconsets[prop],
|
||||
}
|
||||
: undefined),
|
||||
has: (obj, prop: string) => prop in obj || prop in customIconsets,
|
||||
});
|
@ -1,9 +1,6 @@
|
||||
export interface CustomIcon {
|
||||
path: string;
|
||||
viewBox?: string;
|
||||
}
|
||||
import { CustomIcon } from "./custom_icons";
|
||||
|
||||
export interface CustomIconsetsWindow {
|
||||
interface CustomIconsetsWindow {
|
||||
customIconsets?: { [key: string]: (name: string) => Promise<CustomIcon> };
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user