Tile card editor improvements (#24373)
* Add selector support * Feedbacks * Use select box fields in tile card editor
@ -0,0 +1,7 @@
|
||||
<svg width="94" height="40" viewBox="0 0 94 40" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect width="94" height="40" rx="8" fill="white"/>
|
||||
<rect x="0.5" y="0.5" width="93" height="39" rx="7.5" stroke="black" stroke-opacity="0.12"/>
|
||||
<circle cx="20" cy="20" r="12" fill="black" fill-opacity="0.12"/>
|
||||
<path d="M40 14C40 10.6863 42.6863 8 46 8H65C68.3137 8 71 10.6863 71 14C71 17.3137 68.3137 20 65 20H46C42.6863 20 40 17.3137 40 14Z" fill="black" fill-opacity="0.32"/>
|
||||
<path d="M40 28C40 25.7909 41.7909 24 44 24H77C79.2091 24 81 25.7909 81 28C81 30.2091 79.2091 32 77 32H44C41.7909 32 40 30.2091 40 28Z" fill="black" fill-opacity="0.32"/>
|
||||
</svg>
|
After Width: | Height: | Size: 652 B |
@ -0,0 +1,7 @@
|
||||
<svg width="94" height="40" viewBox="0 0 94 40" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect width="94" height="40" rx="8" fill="black"/>
|
||||
<rect x="0.5" y="0.5" width="93" height="39" rx="7.5" stroke="white" stroke-opacity="0.24"/>
|
||||
<circle cx="20" cy="20" r="12" fill="white" fill-opacity="0.24"/>
|
||||
<path d="M40 14C40 10.6863 42.6863 8 46 8H65C68.3137 8 71 10.6863 71 14C71 17.3137 68.3137 20 65 20H46C42.6863 20 40 17.3137 40 14Z" fill="white" fill-opacity="0.48"/>
|
||||
<path d="M40 28C40 25.7909 41.7909 24 44 24H77C79.2091 24 81 25.7909 81 28C81 30.2091 79.2091 32 77 32H44C41.7909 32 40 30.2091 40 28Z" fill="white" fill-opacity="0.48"/>
|
||||
</svg>
|
After Width: | Height: | Size: 652 B |
@ -0,0 +1,7 @@
|
||||
<svg width="94" height="72" viewBox="0 0 94 72" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect width="94" height="72" rx="8" fill="white"/>
|
||||
<rect x="0.5" y="0.5" width="93" height="71" rx="7.5" stroke="black" stroke-opacity="0.12"/>
|
||||
<circle cx="47" cy="20" r="12" fill="black" fill-opacity="0.12"/>
|
||||
<path d="M31.5 46C31.5 42.6863 34.1863 40 37.5 40H56.5C59.8137 40 62.5 42.6863 62.5 46C62.5 49.3137 59.8137 52 56.5 52H37.5C34.1863 52 31.5 49.3137 31.5 46Z" fill="black" fill-opacity="0.32"/>
|
||||
<path d="M26.5 60C26.5 57.7909 28.2909 56 30.5 56H63.5C65.7091 56 67.5 57.7909 67.5 60C67.5 62.2091 65.7091 64 63.5 64H30.5C28.2909 64 26.5 62.2091 26.5 60Z" fill="black" fill-opacity="0.32"/>
|
||||
</svg>
|
After Width: | Height: | Size: 699 B |
@ -0,0 +1,7 @@
|
||||
<svg width="94" height="72" viewBox="0 0 94 72" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect width="94" height="72" rx="8" fill="black"/>
|
||||
<rect x="0.5" y="0.5" width="93" height="71" rx="7.5" stroke="white" stroke-opacity="0.24"/>
|
||||
<circle cx="47" cy="20" r="12" fill="white" fill-opacity="0.24"/>
|
||||
<path d="M31.5 46C31.5 42.6863 34.1863 40 37.5 40H56.5C59.8137 40 62.5 42.6863 62.5 46C62.5 49.3137 59.8137 52 56.5 52H37.5C34.1863 52 31.5 49.3137 31.5 46Z" fill="white" fill-opacity="0.48"/>
|
||||
<path d="M26.5 60C26.5 57.7909 28.2909 56 30.5 56H63.5C65.7091 56 67.5 57.7909 67.5 60C67.5 62.2091 65.7091 64 63.5 64H30.5C28.2909 64 26.5 62.2091 26.5 60Z" fill="white" fill-opacity="0.48"/>
|
||||
</svg>
|
After Width: | Height: | Size: 699 B |
@ -0,0 +1,6 @@
|
||||
<svg width="94" height="48" viewBox="0 0 94 48" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect width="94" height="48" rx="8" fill="white"/>
|
||||
<rect x="0.5" y="0.5" width="93" height="47" rx="7.5" stroke="black" stroke-opacity="0.12"/>
|
||||
<rect x="8" y="8" width="78" height="12" rx="3" fill="black" fill-opacity="0.12"/>
|
||||
<rect x="8" y="28" width="78" height="12" rx="3" fill="black" fill-opacity="0.32"/>
|
||||
</svg>
|
After Width: | Height: | Size: 414 B |
@ -0,0 +1,6 @@
|
||||
<svg width="94" height="48" viewBox="0 0 94 48" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect width="94" height="48" rx="8" fill="black"/>
|
||||
<rect x="0.5" y="0.5" width="93" height="47" rx="7.5" stroke="white" stroke-opacity="0.24"/>
|
||||
<rect x="8" y="8" width="78" height="12" rx="3" fill="white" fill-opacity="0.24"/>
|
||||
<rect x="8" y="28" width="78" height="12" rx="3" fill="white" fill-opacity="0.48"/>
|
||||
</svg>
|
After Width: | Height: | Size: 414 B |
@ -0,0 +1,6 @@
|
||||
<svg width="94" height="28" viewBox="0 0 94 28" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect width="94" height="28" rx="8" fill="white"/>
|
||||
<rect x="0.5" y="0.5" width="93" height="27" rx="7.5" stroke="black" stroke-opacity="0.12"/>
|
||||
<rect x="8" y="8" width="35" height="12" rx="3" fill="black" fill-opacity="0.12"/>
|
||||
<rect x="51" y="8" width="35" height="12" rx="3" fill="black" fill-opacity="0.32"/>
|
||||
</svg>
|
After Width: | Height: | Size: 414 B |
@ -0,0 +1,6 @@
|
||||
<svg width="94" height="28" viewBox="0 0 94 28" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect width="94" height="28" rx="8" fill="black"/>
|
||||
<rect x="0.5" y="0.5" width="93" height="27" rx="7.5" stroke="white" stroke-opacity="0.24"/>
|
||||
<rect x="8" y="8" width="35" height="12" rx="3" fill="white" fill-opacity="0.24"/>
|
||||
<rect x="51" y="8" width="35" height="12" rx="3" fill="white" fill-opacity="0.48"/>
|
||||
</svg>
|
After Width: | Height: | Size: 414 B |
@ -115,7 +115,7 @@ export class HuiTileCardEditor
|
||||
localize: LocalizeFunc,
|
||||
entityId: string | undefined,
|
||||
hideState: boolean,
|
||||
vertical: boolean,
|
||||
isDark: boolean,
|
||||
displayActions: AdvancedActions[] = []
|
||||
) =>
|
||||
[
|
||||
@ -175,41 +175,20 @@ export class HuiTileCardEditor
|
||||
] as const satisfies readonly HaFormSchema[])
|
||||
: []),
|
||||
{
|
||||
name: "",
|
||||
type: "grid",
|
||||
schema: [
|
||||
{
|
||||
name: "content_layout",
|
||||
required: true,
|
||||
selector: {
|
||||
select: {
|
||||
mode: "dropdown",
|
||||
options: ["horizontal", "vertical"].map((value) => ({
|
||||
label: localize(
|
||||
`ui.panel.lovelace.editor.card.tile.content_layout_options.${value}`
|
||||
),
|
||||
value,
|
||||
})),
|
||||
},
|
||||
},
|
||||
name: "content_layout",
|
||||
required: true,
|
||||
selector: {
|
||||
select: {
|
||||
mode: "box",
|
||||
options: ["horizontal", "vertical"].map((value) => ({
|
||||
label: localize(
|
||||
`ui.panel.lovelace.editor.card.tile.content_layout_options.${value}`
|
||||
),
|
||||
value,
|
||||
image: `/static/images/form/tile_content_layout_${value}${isDark ? "_dark" : ""}.svg`,
|
||||
})),
|
||||
},
|
||||
{
|
||||
name: "features_position",
|
||||
required: true,
|
||||
selector: {
|
||||
select: {
|
||||
mode: "dropdown",
|
||||
options: ["bottom", "inline"].map((value) => ({
|
||||
label: localize(
|
||||
`ui.panel.lovelace.editor.card.tile.features_position_options.${value}`
|
||||
),
|
||||
value,
|
||||
disabled: vertical && value === "inline",
|
||||
})),
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
@ -250,6 +229,29 @@ export class HuiTileCardEditor
|
||||
] as const satisfies readonly HaFormSchema[]
|
||||
);
|
||||
|
||||
private _featuresSchema = memoizeOne(
|
||||
(localize: LocalizeFunc, vertical: boolean, isDark: boolean) =>
|
||||
[
|
||||
{
|
||||
name: "features_position",
|
||||
required: true,
|
||||
selector: {
|
||||
select: {
|
||||
mode: "box",
|
||||
options: ["bottom", "inline"].map((value) => ({
|
||||
label: localize(
|
||||
`ui.panel.lovelace.editor.card.tile.features_position_options.${value}`
|
||||
),
|
||||
value,
|
||||
image: `/static/images/form/tile_features_position_${value}${isDark ? "_dark" : ""}.svg`,
|
||||
disabled: vertical && value === "inline",
|
||||
})),
|
||||
},
|
||||
},
|
||||
},
|
||||
] as const satisfies readonly HaFormSchema[]
|
||||
);
|
||||
|
||||
protected render() {
|
||||
if (!this.hass || !this._config) {
|
||||
return nothing;
|
||||
@ -262,10 +264,16 @@ export class HuiTileCardEditor
|
||||
this.hass.localize,
|
||||
entityId,
|
||||
this._config.hide_state ?? false,
|
||||
this._config.vertical ?? false,
|
||||
this.hass.themes.darkMode,
|
||||
this._displayActions
|
||||
);
|
||||
|
||||
const featuresSchema = this._featuresSchema(
|
||||
this.hass.localize,
|
||||
this._config.vertical ?? false,
|
||||
this.hass.themes.darkMode
|
||||
);
|
||||
|
||||
const data = {
|
||||
...this._config,
|
||||
content_layout: this._config.vertical ? "vertical" : "horizontal",
|
||||
@ -293,6 +301,15 @@ export class HuiTileCardEditor
|
||||
)}
|
||||
</h3>
|
||||
<div class="content">
|
||||
<ha-form
|
||||
class="features-form"
|
||||
.hass=${this.hass}
|
||||
.data=${data}
|
||||
.schema=${featuresSchema}
|
||||
.computeLabel=${this._computeLabelCallback}
|
||||
.computeHelper=${this._computeHelperCallback}
|
||||
@value-changed=${this._valueChanged}
|
||||
></ha-form>
|
||||
<hui-card-features-editor
|
||||
.hass=${this.hass}
|
||||
.stateObj=${stateObj}
|
||||
@ -381,7 +398,9 @@ export class HuiTileCardEditor
|
||||
}
|
||||
|
||||
private _computeLabelCallback = (
|
||||
schema: SchemaUnion<ReturnType<typeof this._schema>>
|
||||
schema:
|
||||
| SchemaUnion<ReturnType<typeof this._schema>>
|
||||
| SchemaUnion<ReturnType<typeof this._featuresSchema>>
|
||||
) => {
|
||||
switch (schema.name) {
|
||||
case "color":
|
||||
@ -405,13 +424,22 @@ export class HuiTileCardEditor
|
||||
};
|
||||
|
||||
private _computeHelperCallback = (
|
||||
schema: SchemaUnion<ReturnType<typeof this._schema>>
|
||||
schema:
|
||||
| SchemaUnion<ReturnType<typeof this._schema>>
|
||||
| SchemaUnion<ReturnType<typeof this._featuresSchema>>
|
||||
) => {
|
||||
switch (schema.name) {
|
||||
case "color":
|
||||
return this.hass!.localize(
|
||||
`ui.panel.lovelace.editor.card.tile.${schema.name}_helper`
|
||||
);
|
||||
case "features_position":
|
||||
if (this._config?.vertical) {
|
||||
return this.hass!.localize(
|
||||
`ui.panel.lovelace.editor.card.tile.${schema.name}_helper_vertical`
|
||||
);
|
||||
}
|
||||
return undefined;
|
||||
default:
|
||||
return undefined;
|
||||
}
|
||||
|
@ -7158,6 +7158,7 @@
|
||||
"bottom": "Bottom",
|
||||
"inline": "Inline"
|
||||
},
|
||||
"features_position_helper_vertical": "Always displayed at the bottom if the content layout is vertical",
|
||||
"content_layout": "Content layout",
|
||||
"content_layout_options": {
|
||||
"horizontal": "Horizontal",
|
||||
|