Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions src/data/helpers_crud.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@ import {
fetchInputButton,
updateInputButton,
} from "./input_button";
import {
deleteInputColor,
fetchInputColor,
updateInputColor,
} from "./input_color";
import {
deleteInputDateTime,
fetchInputDateTime,
Expand Down Expand Up @@ -39,6 +44,11 @@ export const HELPERS_CRUD = {
update: updateInputButton,
delete: deleteInputButton,
},
input_color: {
fetch: fetchInputColor,
update: updateInputColor,
delete: deleteInputColor,
},
input_text: {
fetch: fetchInputText,
update: updateInputText,
Expand Down
47 changes: 47 additions & 0 deletions src/data/input_color.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import type { HomeAssistant } from "../types";

export interface InputColor {
id: string;
name: string;
icon?: string;
initial_color?: string;
initial_kelvin?: number;
initial_brightness?: number;
}

export interface InputColorMutableParams {
name: string;
icon?: string;
initial_color?: string;
initial_kelvin?: number;
initial_brightness?: number;
}

export const fetchInputColor = (hass: HomeAssistant) =>
hass.callWS<InputColor[]>({ type: "input_color/list" });

export const createInputColor = (
hass: HomeAssistant,
values: InputColorMutableParams
) =>
hass.callWS<InputColor>({
type: "input_color/create",
...values,
});

export const updateInputColor = (
hass: HomeAssistant,
id: string,
updates: Partial<InputColorMutableParams>
) =>
hass.callWS<InputColor>({
type: "input_color/update",
input_color_id: id,
...updates,
});

export const deleteInputColor = (hass: HomeAssistant, id: string) =>
hass.callWS({
type: "input_color/delete",
input_color_id: id,
});
3 changes: 3 additions & 0 deletions src/panels/config/helpers/const.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { arrayLiteralIncludes } from "../../../common/array/literal-includes";
import type { Counter } from "../../../data/counter";
import type { InputBoolean } from "../../../data/input_boolean";
import type { InputButton } from "../../../data/input_button";
import type { InputColor } from "../../../data/input_color";
import type { InputDateTime } from "../../../data/input_datetime";
import type { InputNumber } from "../../../data/input_number";
import type { InputSelect } from "../../../data/input_select";
Expand All @@ -12,6 +13,7 @@ import type { Timer } from "../../../data/timer";
export const HELPER_DOMAINS = [
"input_boolean",
"input_button",
"input_color",
"input_text",
"input_number",
"input_datetime",
Expand All @@ -27,6 +29,7 @@ export const isHelperDomain = arrayLiteralIncludes(HELPER_DOMAINS);
export type Helper =
| InputBoolean
| InputButton
| InputColor
| InputText
| InputNumber
| InputSelect
Expand Down
6 changes: 6 additions & 0 deletions src/panels/config/helpers/dialog-helper-detail.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import { getConfigFlowHandlers } from "../../../data/config_flow";
import { createCounter } from "../../../data/counter";
import { createInputBoolean } from "../../../data/input_boolean";
import { createInputButton } from "../../../data/input_button";
import { createInputColor } from "../../../data/input_color";
import { createInputDateTime } from "../../../data/input_datetime";
import { createInputNumber } from "../../../data/input_number";
import { createInputSelect } from "../../../data/input_select";
Expand Down Expand Up @@ -69,6 +70,11 @@ const HELPERS: HelperCreators = {
create: createInputButton,
import: () => import("./forms/ha-input_button-form"),
},
input_color: {
create: createInputColor,
import: () => import("./forms/ha-input_color-form"),
alias: ["color", "palette"],
},
input_text: {
create: createInputText,
import: () => import("./forms/ha-input_text-form"),
Expand Down
234 changes: 234 additions & 0 deletions src/panels/config/helpers/forms/ha-input_color-form.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,234 @@
import type { CSSResultGroup } from "lit";
import { css, html, LitElement, nothing } from "lit";
import { customElement, property, query, state } from "lit/decorators";
import { fireEvent } from "../../../../common/dom/fire_event";
import "../../../../components/ha-icon-picker";
import "../../../../components/input/ha-input";
import "../../../../components/radio/ha-radio-group";
import type { HaRadioGroup } from "../../../../components/radio/ha-radio-group";
import "../../../../components/radio/ha-radio-option";
import type { InputColor } from "../../../../data/input_color";
import { haStyle } from "../../../../resources/styles";
import type { HomeAssistant } from "../../../../types";

const DEFAULT_HEX = "#ffffff";
const DEFAULT_KELVIN = 4000;

@customElement("ha-input_color-form")
class HaInputColorForm extends LitElement {
@property({ attribute: false }) public hass!: HomeAssistant;

@property({ type: Boolean }) public new = false;

@property({ type: Boolean }) public disabled = false;

private _item?: Partial<InputColor>;

@state() private _name!: string;

@state() private _icon!: string;

// eslint-disable-next-line: variable-name
@state() private _initial_color?: string;

// eslint-disable-next-line: variable-name
@state() private _initial_kelvin?: number;

// eslint-disable-next-line: variable-name
@state() private _initial_brightness?: number;

@state() private _mode: "color" | "white" = "color";

@query("[dialogInitialFocus]") private _focusElement?: HTMLElement;

set item(item: InputColor) {
this._item = item ?? {};
this._name = item?.name || "";
this._icon = item?.icon || "";
this._initial_color = item?.initial_color || DEFAULT_HEX;
this._initial_kelvin = item?.initial_kelvin || DEFAULT_KELVIN;
this._initial_brightness = item?.initial_brightness;
this._mode = item?.initial_kelvin !== undefined ? "white" : "color";
}

public focus() {
this.updateComplete.then(() => this._focusElement?.focus());
}

protected render() {
if (!this.hass) {
return nothing;
}

return html`
<div class="form">
<ha-input
.value=${this._name}
.configValue=${"name"}
@input=${this._valueChanged}
.label=${this.hass.localize(
"ui.dialogs.helper_settings.generic.name"
)}
auto-validate
required
.validationMessage=${this.hass.localize(
"ui.dialogs.helper_settings.required_error_msg"
)}
dialogInitialFocus
.disabled=${this.disabled}
></ha-input>
<ha-icon-picker
.hass=${this.hass}
.value=${this._icon}
.configValue=${"icon"}
@value-changed=${this._valueChanged}
.label=${this.hass.localize(
"ui.dialogs.helper_settings.generic.icon"
)}
.disabled=${this.disabled}
></ha-icon-picker>
<ha-radio-group
orientation="horizontal"
class="mode"
.label=${this.hass.localize(
"ui.dialogs.helper_settings.input_color.mode"
)}
.value=${this._mode}
.disabled=${this.disabled}
name="mode"
@change=${this._modeChanged}
>
<ha-radio-option value="color">
${this.hass.localize("ui.dialogs.helper_settings.input_color.color")}
</ha-radio-option>
<ha-radio-option value="white">
${this.hass.localize("ui.dialogs.helper_settings.input_color.white")}
</ha-radio-option>
</ha-radio-group>
${
this._mode === "white"
? html`<ha-input
.value=${
this._initial_kelvin !== undefined
? String(this._initial_kelvin)
: ""
}
.configValue=${"initial_kelvin"}
type="number"
min="1000"
max="20000"
step="50"
@input=${this._valueChanged}
.label=${this.hass.localize(
"ui.dialogs.helper_settings.input_color.initial_kelvin"
)}
.disabled=${this.disabled}
></ha-input>`
: html`<ha-input
.value=${this._initial_color || DEFAULT_HEX}
.configValue=${"initial_color"}
type="color"
@input=${this._valueChanged}
.label=${this.hass.localize(
"ui.dialogs.helper_settings.input_color.initial_color"
)}
.disabled=${this.disabled}
></ha-input>`
}
<ha-input
.value=${
this._initial_brightness !== undefined
? String(this._initial_brightness)
: ""
}
.configValue=${"initial_brightness"}
type="number"
min="0"
max="255"
step="1"
@input=${this._valueChanged}
.label=${this.hass.localize(
"ui.dialogs.helper_settings.input_color.initial_brightness"
)}
.disabled=${this.disabled}
></ha-input>
</div>
`;
}

private _modeChanged(ev: Event) {
const mode = (ev.currentTarget as HaRadioGroup).value as "color" | "white";
this._mode = mode;
const newValue = { ...this._item };
if (mode === "white") {
delete newValue.initial_color;
newValue.initial_kelvin = this._initial_kelvin || DEFAULT_KELVIN;
} else {
delete newValue.initial_kelvin;
newValue.initial_color = this._initial_color || DEFAULT_HEX;
}
fireEvent(this, "value-changed", { value: newValue });
}

private _valueChanged(ev: CustomEvent) {
if (!this.new && !this._item) {
return;
}
ev.stopPropagation();
const target = ev.target as any;
const configValue = target.configValue;
const value =
target.type === "number"
? target.value === ""
? undefined
: Number(target.value)
: ev.detail?.value || target.value;

if (this[`_${configValue}`] === value) {
return;
}

const newValue = { ...this._item };
if (value === undefined || value === "") {
delete newValue[configValue];
} else {
newValue[configValue] = value;
}

if (configValue === "initial_color") {
delete newValue.initial_kelvin;
} else if (configValue === "initial_kelvin") {
delete newValue.initial_color;
}

fireEvent(this, "value-changed", { value: newValue });
}

static get styles(): CSSResultGroup {
return [
haStyle,
css`
.form {
color: var(--primary-text-color);
}
ha-input {
--ha-input-padding-bottom: 0;
}
ha-icon-picker,
ha-input:not([required]) {
display: block;
margin-bottom: var(--ha-space-5);
}
.mode {
margin-bottom: var(--ha-space-4);
}
`,
];
}
}

declare global {
interface HTMLElementTagNameMap {
"ha-input_color-form": HaInputColorForm;
}
}
9 changes: 9 additions & 0 deletions src/translations/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -2135,6 +2135,14 @@
"step": "Step size",
"unit_of_measurement": "Unit of measurement"
},
"input_color": {
"mode": "Initial value type",
"color": "Color",
"white": "White",
"initial_color": "Initial color",
"initial_kelvin": "Initial color temperature",
"initial_brightness": "Initial brightness"
},
"input_select": {
"options": "Options",
"add_option": "[%key:ui::panel::config::automation::editor::actions::type::choose::add_option%]",
Expand Down Expand Up @@ -4347,6 +4355,7 @@
"types": {
"input_text": "Text",
"input_number": "Number",
"input_color": "Color",
"input_select": "Dropdown",
"input_boolean": "Toggle",
"input_button": "Button",
Expand Down