mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-16 13:56:35 +00:00
View background settings (#23133)
Co-authored-by: karwosts <karwosts@gmail.com> Co-authored-by: Bram Kragten <mail@bramkragten.nl>
This commit is contained in:
parent
53caef8f92
commit
7900eb4054
@ -14,6 +14,7 @@ import "../../../../src/panels/lovelace/views/hui-view";
|
|||||||
import "../../../../src/panels/lovelace/views/hui-view-container";
|
import "../../../../src/panels/lovelace/views/hui-view-container";
|
||||||
import type { HomeAssistant } from "../../../../src/types";
|
import type { HomeAssistant } from "../../../../src/types";
|
||||||
import "./hc-launch-screen";
|
import "./hc-launch-screen";
|
||||||
|
import "../../../../src/panels/lovelace/views/hui-view-background";
|
||||||
|
|
||||||
(window as any).loadCardHelpers = () =>
|
(window as any).loadCardHelpers = () =>
|
||||||
import("../../../../src/panels/lovelace/custom-card-helpers");
|
import("../../../../src/panels/lovelace/custom-card-helpers");
|
||||||
@ -57,11 +58,8 @@ class HcLovelace extends LitElement {
|
|||||||
const background = viewConfig.background || this.lovelaceConfig.background;
|
const background = viewConfig.background || this.lovelaceConfig.background;
|
||||||
|
|
||||||
return html`
|
return html`
|
||||||
<hui-view-container
|
<hui-view-container .hass=${this.hass} .theme=${viewConfig.theme}>
|
||||||
.hass=${this.hass}
|
<hui-view-background .background=${background}> </hui-view-background>
|
||||||
.background=${background}
|
|
||||||
.theme=${viewConfig.theme}
|
|
||||||
>
|
|
||||||
<hui-view
|
<hui-view
|
||||||
.hass=${this.hass}
|
.hass=${this.hass}
|
||||||
.lovelace=${lovelace}
|
.lovelace=${lovelace}
|
||||||
|
98
src/components/ha-selector/ha-selector-button-toggle.ts
Normal file
98
src/components/ha-selector/ha-selector-button-toggle.ts
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
import "@material/mwc-list/mwc-list-item";
|
||||||
|
import { LitElement, css, html } from "lit";
|
||||||
|
import { customElement, property } from "lit/decorators";
|
||||||
|
import { fireEvent } from "../../common/dom/fire_event";
|
||||||
|
import { caseInsensitiveStringCompare } from "../../common/string/compare";
|
||||||
|
import type { ButtonToggleSelector, SelectOption } from "../../data/selector";
|
||||||
|
import type { HomeAssistant, ToggleButton } from "../../types";
|
||||||
|
import "../ha-button-toggle-group";
|
||||||
|
|
||||||
|
@customElement("ha-selector-button_toggle")
|
||||||
|
export class HaButtonToggleSelector extends LitElement {
|
||||||
|
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||||
|
|
||||||
|
@property({ attribute: false }) public selector!: ButtonToggleSelector;
|
||||||
|
|
||||||
|
@property() public value?: string;
|
||||||
|
|
||||||
|
@property() public label?: string;
|
||||||
|
|
||||||
|
@property() public helper?: string;
|
||||||
|
|
||||||
|
@property({ attribute: false })
|
||||||
|
public localizeValue?: (key: string) => string;
|
||||||
|
|
||||||
|
@property({ type: Boolean }) public disabled = false;
|
||||||
|
|
||||||
|
@property({ type: Boolean }) public required = true;
|
||||||
|
|
||||||
|
protected render() {
|
||||||
|
const options =
|
||||||
|
this.selector.button_toggle?.options?.map((option) =>
|
||||||
|
typeof option === "object"
|
||||||
|
? (option as SelectOption)
|
||||||
|
: ({ value: option, label: option } as SelectOption)
|
||||||
|
) || [];
|
||||||
|
|
||||||
|
const translationKey = this.selector.button_toggle?.translation_key;
|
||||||
|
|
||||||
|
if (this.localizeValue && translationKey) {
|
||||||
|
options.forEach((option) => {
|
||||||
|
const localizedLabel = this.localizeValue!(
|
||||||
|
`${translationKey}.options.${option.value}`
|
||||||
|
);
|
||||||
|
if (localizedLabel) {
|
||||||
|
option.label = localizedLabel;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.selector.button_toggle?.sort) {
|
||||||
|
options.sort((a, b) =>
|
||||||
|
caseInsensitiveStringCompare(
|
||||||
|
a.label,
|
||||||
|
b.label,
|
||||||
|
this.hass.locale.language
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const toggleButtons: ToggleButton[] = options.map((item: SelectOption) => ({
|
||||||
|
label: item.label,
|
||||||
|
value: item.value,
|
||||||
|
}));
|
||||||
|
|
||||||
|
return html`
|
||||||
|
${this.label}
|
||||||
|
<ha-button-toggle-group
|
||||||
|
.buttons=${toggleButtons}
|
||||||
|
.active=${this.value}
|
||||||
|
@value-changed=${this._valueChanged}
|
||||||
|
></ha-button-toggle-group>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
private _valueChanged(ev) {
|
||||||
|
ev.stopPropagation();
|
||||||
|
|
||||||
|
const value = ev.detail?.value || ev.target.value;
|
||||||
|
if (this.disabled || value === undefined || value === (this.value ?? "")) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
fireEvent(this, "value-changed", {
|
||||||
|
value: value,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
static styles = css`
|
||||||
|
:host {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
interface HTMLElementTagNameMap {
|
||||||
|
"ha-selector-button_toggle": HaButtonToggleSelector;
|
||||||
|
}
|
||||||
|
}
|
@ -51,6 +51,7 @@ const LOAD_ELEMENTS = {
|
|||||||
icon: () => import("./ha-selector-icon"),
|
icon: () => import("./ha-selector-icon"),
|
||||||
media: () => import("./ha-selector-media"),
|
media: () => import("./ha-selector-media"),
|
||||||
theme: () => import("./ha-selector-theme"),
|
theme: () => import("./ha-selector-theme"),
|
||||||
|
button_toggle: () => import("./ha-selector-button-toggle"),
|
||||||
trigger: () => import("./ha-selector-trigger"),
|
trigger: () => import("./ha-selector-trigger"),
|
||||||
tts: () => import("./ha-selector-tts"),
|
tts: () => import("./ha-selector-tts"),
|
||||||
tts_voice: () => import("./ha-selector-tts-voice"),
|
tts_voice: () => import("./ha-selector-tts-voice"),
|
||||||
|
@ -7,8 +7,22 @@ export interface ShowViewConfig {
|
|||||||
user?: string;
|
user?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface LovelaceViewBackgroundConfig {
|
export interface LovelaceViewBackgroundConfig {
|
||||||
image?: string;
|
image?: string;
|
||||||
|
transparency?: number;
|
||||||
|
size?: "auto" | "cover" | "contain";
|
||||||
|
alignment?:
|
||||||
|
| "top left"
|
||||||
|
| "top center"
|
||||||
|
| "top right"
|
||||||
|
| "center left"
|
||||||
|
| "center"
|
||||||
|
| "center right"
|
||||||
|
| "bottom left"
|
||||||
|
| "bottom center"
|
||||||
|
| "bottom right";
|
||||||
|
repeat?: "repeat" | "no-repeat";
|
||||||
|
attachment?: "scroll" | "fixed";
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface LovelaceBaseViewConfig {
|
export interface LovelaceBaseViewConfig {
|
||||||
|
@ -26,6 +26,7 @@ export type Selector =
|
|||||||
| AreaFilterSelector
|
| AreaFilterSelector
|
||||||
| AttributeSelector
|
| AttributeSelector
|
||||||
| BooleanSelector
|
| BooleanSelector
|
||||||
|
| ButtonToggleSelector
|
||||||
| ColorRGBSelector
|
| ColorRGBSelector
|
||||||
| ColorTempSelector
|
| ColorTempSelector
|
||||||
| ConditionSelector
|
| ConditionSelector
|
||||||
@ -108,6 +109,14 @@ export interface BooleanSelector {
|
|||||||
boolean: {} | null;
|
boolean: {} | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface ButtonToggleSelector {
|
||||||
|
button_toggle: {
|
||||||
|
options: readonly string[] | readonly SelectOption[];
|
||||||
|
translation_key?: string;
|
||||||
|
sort?: boolean;
|
||||||
|
} | null;
|
||||||
|
}
|
||||||
|
|
||||||
export interface ColorRGBSelector {
|
export interface ColorRGBSelector {
|
||||||
// eslint-disable-next-line @typescript-eslint/ban-types
|
// eslint-disable-next-line @typescript-eslint/ban-types
|
||||||
color_rgb: {} | null;
|
color_rgb: {} | null;
|
||||||
|
@ -1,13 +1,14 @@
|
|||||||
import "@material/mwc-list/mwc-list-item";
|
import "@material/mwc-list/mwc-list-item";
|
||||||
import type { CSSResultGroup } from "lit";
|
import type { CSSResultGroup } from "lit";
|
||||||
|
import memoizeOne from "memoize-one";
|
||||||
import { LitElement, css, html, nothing } from "lit";
|
import { LitElement, css, html, nothing } from "lit";
|
||||||
import { customElement, property, state } from "lit/decorators";
|
import { customElement, property, state } from "lit/decorators";
|
||||||
import { fireEvent } from "../../../../common/dom/fire_event";
|
import { fireEvent } from "../../../../common/dom/fire_event";
|
||||||
|
import "../../../../components/ha-form/ha-form";
|
||||||
|
import type { SchemaUnion } from "../../../../components/ha-form/types";
|
||||||
import "../../../../components/ha-selector/ha-selector-image";
|
import "../../../../components/ha-selector/ha-selector-image";
|
||||||
import type { LovelaceViewConfig } from "../../../../data/lovelace/config/view";
|
import type { LovelaceViewConfig } from "../../../../data/lovelace/config/view";
|
||||||
import type { HomeAssistant, ValueChangedEvent } from "../../../../types";
|
import type { HomeAssistant } from "../../../../types";
|
||||||
|
|
||||||
const SELECTOR = { image: { original: true } };
|
|
||||||
|
|
||||||
@customElement("hui-view-background-editor")
|
@customElement("hui-view-background-editor")
|
||||||
export class HuiViewBackgroundEditor extends LitElement {
|
export class HuiViewBackgroundEditor extends LitElement {
|
||||||
@ -19,44 +20,162 @@ export class HuiViewBackgroundEditor extends LitElement {
|
|||||||
this._config = config;
|
this._config = config;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private _localizeValueCallback = (key: string) =>
|
||||||
|
this.hass.localize(key as any);
|
||||||
|
|
||||||
|
private _schema = memoizeOne((showSettings: boolean) => [
|
||||||
|
{
|
||||||
|
name: "image",
|
||||||
|
selector: { image: { original: true } },
|
||||||
|
},
|
||||||
|
...(showSettings
|
||||||
|
? ([
|
||||||
|
{
|
||||||
|
name: "settings",
|
||||||
|
flatten: true,
|
||||||
|
expanded: true,
|
||||||
|
type: "expandable" as const,
|
||||||
|
schema: [
|
||||||
|
{
|
||||||
|
name: "transparency",
|
||||||
|
selector: {
|
||||||
|
number: { min: 1, max: 100, mode: "slider" },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "attachment",
|
||||||
|
selector: {
|
||||||
|
button_toggle: {
|
||||||
|
translation_key:
|
||||||
|
"ui.panel.lovelace.editor.edit_view.background.attachment",
|
||||||
|
options: ["scroll", "fixed"],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "size",
|
||||||
|
selector: {
|
||||||
|
select: {
|
||||||
|
translation_key:
|
||||||
|
"ui.panel.lovelace.editor.edit_view.background.size",
|
||||||
|
options: ["auto", "cover", "contain"],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "alignment",
|
||||||
|
selector: {
|
||||||
|
select: {
|
||||||
|
translation_key:
|
||||||
|
"ui.panel.lovelace.editor.edit_view.background.alignment",
|
||||||
|
options: [
|
||||||
|
"top left",
|
||||||
|
"top center",
|
||||||
|
"top right",
|
||||||
|
"center left",
|
||||||
|
"center",
|
||||||
|
"center right",
|
||||||
|
"bottom left",
|
||||||
|
"bottom center",
|
||||||
|
"bottom right",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "repeat",
|
||||||
|
selector: {
|
||||||
|
select: {
|
||||||
|
translation_key:
|
||||||
|
"ui.panel.lovelace.editor.edit_view.background.repeat",
|
||||||
|
options: ["repeat", "no-repeat"],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
] as const)
|
||||||
|
: []),
|
||||||
|
]);
|
||||||
|
|
||||||
protected render() {
|
protected render() {
|
||||||
if (!this.hass) {
|
if (!this.hass) {
|
||||||
return nothing;
|
return nothing;
|
||||||
}
|
}
|
||||||
|
|
||||||
const background = this._config?.background;
|
let background = this._config?.background;
|
||||||
const backgroundUrl =
|
if (typeof background === "string") {
|
||||||
typeof background === "string"
|
const backgroundUrl = background.match(/url\(['"]?([^'"]+)['"]?\)/)?.[1];
|
||||||
? background.match(/url\(['"]?([^'"]+)['"]?\)/)?.[1]
|
|
||||||
: background?.image;
|
background = {
|
||||||
|
image: backgroundUrl,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
background = {
|
||||||
|
transparency: 100,
|
||||||
|
alignment: "center",
|
||||||
|
size: "auto",
|
||||||
|
repeat: "no-repeat",
|
||||||
|
attachment: "scroll",
|
||||||
|
...background,
|
||||||
|
};
|
||||||
|
|
||||||
return html`
|
return html`
|
||||||
<ha-selector-image
|
<ha-form
|
||||||
.hass=${this.hass}
|
.hass=${this.hass}
|
||||||
.label=${this.hass.localize(
|
.data=${background}
|
||||||
"ui.panel.lovelace.editor.edit_view.background.title"
|
.schema=${this._schema(true)}
|
||||||
)}
|
.computeLabel=${this._computeLabelCallback}
|
||||||
.value=${backgroundUrl}
|
@value-changed=${this._valueChanged}
|
||||||
.selector=${SELECTOR}
|
.localizeValue=${this._localizeValueCallback}
|
||||||
@value-changed=${this._backgroundChanged}
|
></ha-form>
|
||||||
></ha-selector-image>
|
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
private _backgroundChanged(ev: ValueChangedEvent<string | null>) {
|
private _valueChanged(ev: CustomEvent): void {
|
||||||
const backgroundUrl = ev.detail.value;
|
|
||||||
const config = {
|
const config = {
|
||||||
...this._config,
|
...this._config,
|
||||||
background: {
|
background: ev.detail.value,
|
||||||
...(typeof this._config.background === "string"
|
|
||||||
? {}
|
|
||||||
: this._config.background),
|
|
||||||
image: backgroundUrl || undefined,
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
fireEvent(this, "view-config-changed", { config });
|
fireEvent(this, "view-config-changed", { config });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private _computeLabelCallback = (
|
||||||
|
schema: SchemaUnion<ReturnType<typeof this._schema>>
|
||||||
|
) => {
|
||||||
|
switch (schema.name) {
|
||||||
|
case "image":
|
||||||
|
return this.hass.localize(
|
||||||
|
"ui.panel.lovelace.editor.edit_view.background.image"
|
||||||
|
);
|
||||||
|
case "transparency":
|
||||||
|
return this.hass.localize(
|
||||||
|
"ui.panel.lovelace.editor.edit_view.background.transparency"
|
||||||
|
);
|
||||||
|
case "alignment":
|
||||||
|
return this.hass.localize(
|
||||||
|
"ui.panel.lovelace.editor.edit_view.background.alignment.name"
|
||||||
|
);
|
||||||
|
case "size":
|
||||||
|
return this.hass.localize(
|
||||||
|
"ui.panel.lovelace.editor.edit_view.background.size.name"
|
||||||
|
);
|
||||||
|
case "repeat":
|
||||||
|
return this.hass.localize(
|
||||||
|
"ui.panel.lovelace.editor.edit_view.background.repeat.name"
|
||||||
|
);
|
||||||
|
case "attachment":
|
||||||
|
return this.hass.localize(
|
||||||
|
"ui.panel.lovelace.editor.edit_view.background.attachment.name"
|
||||||
|
);
|
||||||
|
default:
|
||||||
|
return this.hass.localize(
|
||||||
|
`ui.panel.lovelace.editor.edit_view.background.${schema.name}`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
static get styles(): CSSResultGroup {
|
static get styles(): CSSResultGroup {
|
||||||
return css`
|
return css`
|
||||||
:host {
|
:host {
|
||||||
|
@ -78,6 +78,7 @@ import type { Lovelace } from "./types";
|
|||||||
import "./views/hui-view";
|
import "./views/hui-view";
|
||||||
import "./views/hui-view-container";
|
import "./views/hui-view-container";
|
||||||
import type { HUIView } from "./views/hui-view";
|
import type { HUIView } from "./views/hui-view";
|
||||||
|
import "./views/hui-view-background";
|
||||||
|
|
||||||
@customElement("hui-root")
|
@customElement("hui-root")
|
||||||
class HUIRoot extends LitElement {
|
class HUIRoot extends LitElement {
|
||||||
@ -469,11 +470,11 @@ class HUIRoot extends LitElement {
|
|||||||
</div>
|
</div>
|
||||||
<hui-view-container
|
<hui-view-container
|
||||||
.hass=${this.hass}
|
.hass=${this.hass}
|
||||||
.background=${background}
|
|
||||||
.theme=${curViewConfig?.theme}
|
.theme=${curViewConfig?.theme}
|
||||||
id="view"
|
id="view"
|
||||||
@ll-rebuild=${this._debouncedConfigChanged}
|
@ll-rebuild=${this._debouncedConfigChanged}
|
||||||
>
|
>
|
||||||
|
<hui-view-background .background=${background}> </hui-view-background>
|
||||||
</hui-view-container>
|
</hui-view-container>
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
|
130
src/panels/lovelace/views/hui-view-background.ts
Normal file
130
src/panels/lovelace/views/hui-view-background.ts
Normal file
@ -0,0 +1,130 @@
|
|||||||
|
import { css, LitElement, nothing } from "lit";
|
||||||
|
import type { CSSResultGroup, PropertyValues } from "lit";
|
||||||
|
import { customElement, property } from "lit/decorators";
|
||||||
|
import type { HomeAssistant } from "../../../types";
|
||||||
|
import type { LovelaceViewBackgroundConfig } from "../../../data/lovelace/config/view";
|
||||||
|
|
||||||
|
@customElement("hui-view-background")
|
||||||
|
export class HUIViewBackground extends LitElement {
|
||||||
|
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||||
|
|
||||||
|
@property({ attribute: false }) background?:
|
||||||
|
| string
|
||||||
|
| LovelaceViewBackgroundConfig
|
||||||
|
| undefined;
|
||||||
|
|
||||||
|
protected render() {
|
||||||
|
return nothing;
|
||||||
|
}
|
||||||
|
|
||||||
|
private _applyTheme() {
|
||||||
|
const computedStyles = getComputedStyle(this);
|
||||||
|
const themeBackground = computedStyles.getPropertyValue(
|
||||||
|
"--lovelace-background"
|
||||||
|
);
|
||||||
|
|
||||||
|
const fixedBackground = this._isFixedBackground(
|
||||||
|
this.background || themeBackground
|
||||||
|
);
|
||||||
|
const viewBackground = this._computeBackgroundProperty(this.background);
|
||||||
|
this.toggleAttribute("fixed-background", fixedBackground);
|
||||||
|
this.style.setProperty("--view-background", viewBackground);
|
||||||
|
|
||||||
|
const viewBackgroundOpacity = this._computeBackgroundOpacityProperty(
|
||||||
|
this.background
|
||||||
|
);
|
||||||
|
this.style.setProperty("--view-background-opacity", viewBackgroundOpacity);
|
||||||
|
}
|
||||||
|
|
||||||
|
private _isFixedBackground(
|
||||||
|
background?: string | LovelaceViewBackgroundConfig
|
||||||
|
) {
|
||||||
|
if (typeof background === "string") {
|
||||||
|
return background.split(" ").includes("fixed");
|
||||||
|
}
|
||||||
|
if (typeof background === "object" && background.attachment === "fixed") {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private _computeBackgroundProperty(
|
||||||
|
background?: string | LovelaceViewBackgroundConfig
|
||||||
|
) {
|
||||||
|
if (typeof background === "object" && background.image) {
|
||||||
|
const size = background.size ?? "auto";
|
||||||
|
const alignment = background.alignment ?? "center";
|
||||||
|
const repeat = background.repeat ?? "no-repeat";
|
||||||
|
return `${alignment} / ${size} ${repeat} url('${background.image}')`;
|
||||||
|
}
|
||||||
|
if (typeof background === "string") {
|
||||||
|
return background;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private _computeBackgroundOpacityProperty(
|
||||||
|
background?: string | LovelaceViewBackgroundConfig
|
||||||
|
) {
|
||||||
|
if (typeof background === "object" && background.image) {
|
||||||
|
if (background.transparency) {
|
||||||
|
return `${background.transparency}%`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected willUpdate(changedProperties: PropertyValues<this>) {
|
||||||
|
super.willUpdate(changedProperties);
|
||||||
|
if (changedProperties.has("hass") && this.hass) {
|
||||||
|
const oldHass = changedProperties.get("hass");
|
||||||
|
if (
|
||||||
|
!oldHass ||
|
||||||
|
this.hass.themes !== oldHass.themes ||
|
||||||
|
this.hass.selectedTheme !== oldHass.selectedTheme
|
||||||
|
) {
|
||||||
|
this._applyTheme();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (changedProperties.has("background")) {
|
||||||
|
this._applyTheme();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static get styles(): CSSResultGroup {
|
||||||
|
return css`
|
||||||
|
/* Fixed background hack for Safari iOS */
|
||||||
|
:host([fixed-background]) {
|
||||||
|
display: block;
|
||||||
|
z-index: -1;
|
||||||
|
position: fixed;
|
||||||
|
background-attachment: scroll !important;
|
||||||
|
}
|
||||||
|
:host(:not([fixed-background])) {
|
||||||
|
z-index: -1;
|
||||||
|
position: absolute;
|
||||||
|
}
|
||||||
|
:host {
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
background: var(
|
||||||
|
--view-background,
|
||||||
|
var(--lovelace-background, var(--primary-background-color))
|
||||||
|
);
|
||||||
|
opacity: var(--view-background-opacity);
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
interface HTMLElementTagNameMap {
|
||||||
|
"hui-view-background": HUIViewBackground;
|
||||||
|
}
|
||||||
|
}
|
@ -45,23 +45,6 @@ class HuiViewContainer extends LitElement {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private _isFixedBackground(background?: BackgroundConfig) {
|
|
||||||
if (typeof background === "string") {
|
|
||||||
return background.split(" ").includes("fixed");
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private _computeBackgroundProperty(background?: BackgroundConfig) {
|
|
||||||
if (typeof background === "object" && background.image) {
|
|
||||||
return `center / cover no-repeat url('${background.image}')`;
|
|
||||||
}
|
|
||||||
if (typeof background === "string") {
|
|
||||||
return background;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected willUpdate(changedProperties: PropertyValues<this>) {
|
protected willUpdate(changedProperties: PropertyValues<this>) {
|
||||||
super.willUpdate(changedProperties);
|
super.willUpdate(changedProperties);
|
||||||
if (changedProperties.has("hass") && this.hass) {
|
if (changedProperties.has("hass") && this.hass) {
|
||||||
@ -76,7 +59,7 @@ class HuiViewContainer extends LitElement {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (changedProperties.has("theme") || changedProperties.has("background")) {
|
if (changedProperties.has("theme")) {
|
||||||
this._applyTheme();
|
this._applyTheme();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -89,18 +72,6 @@ class HuiViewContainer extends LitElement {
|
|||||||
if (this.hass) {
|
if (this.hass) {
|
||||||
applyThemesOnElement(this, this.hass?.themes, this.theme);
|
applyThemesOnElement(this, this.hass?.themes, this.theme);
|
||||||
}
|
}
|
||||||
|
|
||||||
const computedStyles = getComputedStyle(this);
|
|
||||||
const themeBackground = computedStyles.getPropertyValue(
|
|
||||||
"--lovelace-background"
|
|
||||||
);
|
|
||||||
|
|
||||||
const fixedBackground = this._isFixedBackground(
|
|
||||||
this.background || themeBackground
|
|
||||||
);
|
|
||||||
const viewBackground = this._computeBackgroundProperty(this.background);
|
|
||||||
this.toggleAttribute("fixed-background", fixedBackground);
|
|
||||||
this.style.setProperty("--view-background", viewBackground);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static get styles(): CSSResultGroup {
|
static get styles(): CSSResultGroup {
|
||||||
@ -108,30 +79,6 @@ class HuiViewContainer extends LitElement {
|
|||||||
:host {
|
:host {
|
||||||
display: relative;
|
display: relative;
|
||||||
}
|
}
|
||||||
/* Fixed background hack for Safari iOS */
|
|
||||||
:host([fixed-background]) ::slotted(*):before {
|
|
||||||
display: block;
|
|
||||||
content: "";
|
|
||||||
z-index: -1;
|
|
||||||
position: fixed;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
right: 0;
|
|
||||||
bottom: 0;
|
|
||||||
height: 100%;
|
|
||||||
width: 100%;
|
|
||||||
background: var(
|
|
||||||
--view-background,
|
|
||||||
var(--lovelace-background, var(--primary-background-color))
|
|
||||||
);
|
|
||||||
background-attachment: scroll !important;
|
|
||||||
}
|
|
||||||
:host(:not([fixed-background])) {
|
|
||||||
background: var(
|
|
||||||
--view-background,
|
|
||||||
var(--lovelace-background, var(--primary-background-color))
|
|
||||||
);
|
|
||||||
}
|
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5926,7 +5926,45 @@
|
|||||||
"header_name": "{name} View Configuration",
|
"header_name": "{name} View Configuration",
|
||||||
"add": "Add view",
|
"add": "Add view",
|
||||||
"background": {
|
"background": {
|
||||||
"title": "Add a background to the view"
|
"settings": "Background settings",
|
||||||
|
"image": "Background image",
|
||||||
|
"size": {
|
||||||
|
"name": "Background size",
|
||||||
|
"options": {
|
||||||
|
"auto": "Original",
|
||||||
|
"cover": "Fill view",
|
||||||
|
"contain": "Fit view"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"alignment": {
|
||||||
|
"name": "Background alignment",
|
||||||
|
"options": {
|
||||||
|
"top left": "Top left",
|
||||||
|
"top center": "Top center",
|
||||||
|
"top right": "Top right",
|
||||||
|
"center left": "Center left",
|
||||||
|
"center": "Center",
|
||||||
|
"center right": "Center right",
|
||||||
|
"bottom left": "Bottom left",
|
||||||
|
"bottom center": "Bottom center",
|
||||||
|
"bottom right": "Bottom right"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"transparency": "Background transparency",
|
||||||
|
"repeat": {
|
||||||
|
"name": "Background repeat",
|
||||||
|
"options": {
|
||||||
|
"repeat": "Repeat (tile)",
|
||||||
|
"no-repeat": "No repeat"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"attachment": {
|
||||||
|
"name": "Background attachment",
|
||||||
|
"options": {
|
||||||
|
"scroll": "Scroll",
|
||||||
|
"fixed": "Fixed"
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"edit": "Edit view",
|
"edit": "Edit view",
|
||||||
"delete": "Delete view",
|
"delete": "Delete view",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user