-
-
+
+
+ ${this._options.length
+ ? repeat(
+ this._options,
+ (option) => option,
+ (option, index) => html`
+
+
- ${option}
-
-
+
+
+ `
+ )
+ : html`
+
+ ${this.hass!.localize(
+ "ui.dialogs.helper_settings.input_select.no_options"
+ )}
- `
- )
- : html`
-
- ${this.hass!.localize(
- "ui.dialogs.helper_settings.input_select.no_options"
- )}
-
- `}
-
+ `}
+
+
;
- private _sortable?: SortableInstance;
-
- @query("#unchecked") private _uncheckedContainer?: HTMLElement;
-
connectedCallback(): void {
super.connectedCallback();
if (this.hasUpdated) {
@@ -264,9 +258,15 @@ export class HuiTodoListCard extends LitElement implements LovelaceCard {
`
: nothing}
-
- ${this._renderItems(uncheckedItems, unavailable)}
- `
+
+
+ ${this._renderItems(uncheckedItems, unavailable)}
+
+ `
: html`
${this.hass.localize(
"ui.panel.lovelace.cards.todo-list.no_unchecked_items"
@@ -553,43 +553,12 @@ export class HuiTodoListCard extends LitElement implements LovelaceCard {
private async _toggleReorder() {
this._reordering = !this._reordering;
- await this.updateComplete;
- if (this._reordering) {
- this._createSortable();
- } else {
- this._sortable?.destroy();
- this._sortable = undefined;
- }
}
- private async _createSortable() {
- const Sortable = (await import("../../../resources/sortable")).default;
- this._sortable = new Sortable(this._uncheckedContainer!, {
- animation: 150,
- fallbackClass: "sortable-fallback",
- dataIdAttr: "item-id",
- handle: "ha-svg-icon",
- onChoose: (evt: SortableEvent) => {
- (evt.item as any).placeholder =
- document.createComment("sort-placeholder");
- evt.item.after((evt.item as any).placeholder);
- },
- onEnd: (evt: SortableEvent) => {
- // put back in original location
- if ((evt.item as any).placeholder) {
- (evt.item as any).placeholder.replaceWith(evt.item);
- delete (evt.item as any).placeholder;
- }
- if (evt.newIndex === undefined || evt.oldIndex === undefined) {
- return;
- }
- // Since this is `onEnd` event, it's possible that
- // an item was dragged away and was put back to its original position.
- if (evt.oldIndex !== evt.newIndex) {
- this._moveItem(evt.oldIndex, evt.newIndex);
- }
- },
- });
+ private async _itemMoved(ev: CustomEvent) {
+ ev.stopPropagation();
+ const { oldIndex, newIndex } = ev.detail;
+ this._moveItem(oldIndex, newIndex);
}
private async _moveItem(oldIndex: number, newIndex: number) {
@@ -621,165 +590,162 @@ export class HuiTodoListCard extends LitElement implements LovelaceCard {
}
static get styles(): CSSResultGroup {
- return [
- sortableStyles,
- css`
- ha-card {
- height: 100%;
- box-sizing: border-box;
- }
+ return css`
+ ha-card {
+ height: 100%;
+ box-sizing: border-box;
+ }
- .has-header {
- padding-top: 0;
- }
+ .has-header {
+ padding-top: 0;
+ }
- .addRow {
- padding: 16px;
- padding-bottom: 0;
- position: relative;
- }
+ .addRow {
+ padding: 16px;
+ padding-bottom: 0;
+ position: relative;
+ }
- .addRow ha-icon-button {
- position: absolute;
- right: 16px;
- inset-inline-start: initial;
- inset-inline-end: 16px;
- }
+ .addRow ha-icon-button {
+ position: absolute;
+ right: 16px;
+ inset-inline-start: initial;
+ inset-inline-end: 16px;
+ }
- .addRow,
- .header {
- display: flex;
- flex-direction: row;
- align-items: center;
- }
+ .addRow,
+ .header {
+ display: flex;
+ flex-direction: row;
+ align-items: center;
+ }
- .header {
- padding-left: 30px;
- padding-right: 16px;
- padding-inline-start: 30px;
- padding-inline-end: 16px;
- margin-top: 8px;
- justify-content: space-between;
- direction: var(--direction);
- }
+ .header {
+ padding-left: 30px;
+ padding-right: 16px;
+ padding-inline-start: 30px;
+ padding-inline-end: 16px;
+ margin-top: 8px;
+ justify-content: space-between;
+ direction: var(--direction);
+ }
- .header span {
- color: var(--primary-text-color);
- font-weight: 500;
- }
+ .header span {
+ color: var(--primary-text-color);
+ font-weight: 500;
+ }
- .empty {
- padding: 16px 32px;
- }
+ .empty {
+ padding: 16px 32px;
+ }
- .item {
- margin-top: 8px;
- }
+ .item {
+ margin-top: 8px;
+ }
- ha-check-list-item {
- --mdc-list-item-meta-size: 56px;
- min-height: 56px;
- height: auto;
- }
+ ha-check-list-item {
+ --mdc-list-item-meta-size: 56px;
+ min-height: 56px;
+ height: auto;
+ }
- ha-check-list-item.multiline {
- align-items: flex-start;
- --check-list-item-graphic-margin-top: 8px;
- }
+ ha-check-list-item.multiline {
+ align-items: flex-start;
+ --check-list-item-graphic-margin-top: 8px;
+ }
- .row {
- display: flex;
- justify-content: space-between;
- }
+ .row {
+ display: flex;
+ justify-content: space-between;
+ }
- .multiline .column {
- display: flex;
- flex-direction: column;
- margin-top: 18px;
- margin-bottom: 12px;
- }
+ .multiline .column {
+ display: flex;
+ flex-direction: column;
+ margin-top: 18px;
+ margin-bottom: 12px;
+ }
- .completed .summary {
- text-decoration: line-through;
- }
+ .completed .summary {
+ text-decoration: line-through;
+ }
- .description,
- .due {
- font-size: 12px;
- color: var(--secondary-text-color);
- }
+ .description,
+ .due {
+ font-size: 12px;
+ color: var(--secondary-text-color);
+ }
- .description {
- white-space: initial;
- overflow: hidden;
- display: -webkit-box;
- -webkit-line-clamp: 3;
- line-clamp: 3;
- -webkit-box-orient: vertical;
- }
+ .description {
+ white-space: initial;
+ overflow: hidden;
+ display: -webkit-box;
+ -webkit-line-clamp: 3;
+ line-clamp: 3;
+ -webkit-box-orient: vertical;
+ }
- .description p {
- margin: 0;
- }
+ .description p {
+ margin: 0;
+ }
- .description a {
- color: var(--primary-color);
- }
+ .description a {
+ color: var(--primary-color);
+ }
- .due {
- display: flex;
- align-items: center;
- }
+ .due {
+ display: flex;
+ align-items: center;
+ }
- .due ha-svg-icon {
- margin-right: 4px;
- --mdc-icon-size: 14px;
- }
+ .due ha-svg-icon {
+ margin-right: 4px;
+ --mdc-icon-size: 14px;
+ }
- .due.overdue {
- color: var(--warning-color);
- }
+ .due.overdue {
+ color: var(--warning-color);
+ }
- .completed .due.overdue {
- color: var(--secondary-text-color);
- }
+ .completed .due.overdue {
+ color: var(--secondary-text-color);
+ }
- .handle {
- cursor: move; /* fallback if grab cursor is unsupported */
- cursor: grab;
- height: 24px;
- padding: 16px 4px;
- }
+ .handle {
+ cursor: move; /* fallback if grab cursor is unsupported */
+ cursor: grab;
+ height: 24px;
+ padding: 16px 4px;
+ }
- .deleteItemButton {
- position: relative;
- left: 8px;
- }
+ .deleteItemButton {
+ position: relative;
+ left: 8px;
+ }
- ha-textfield {
- flex-grow: 1;
- }
+ ha-textfield {
+ flex-grow: 1;
+ }
- .divider {
- height: 1px;
- background-color: var(--divider-color);
- margin: 10px 0;
- }
+ .divider {
+ height: 1px;
+ background-color: var(--divider-color);
+ margin: 10px 0;
+ }
- .clearall {
- cursor: pointer;
- }
+ .clearall {
+ cursor: pointer;
+ }
- .todoList {
- display: block;
- padding: 8px;
- }
+ .todoList {
+ display: block;
+ padding: 8px;
+ }
- .warning {
- color: var(--error-color);
- }
- `,
- ];
+ .warning {
+ color: var(--error-color);
+ }
+ `;
}
}
diff --git a/src/panels/lovelace/components/hui-entity-editor.ts b/src/panels/lovelace/components/hui-entity-editor.ts
index 22ac4f8aa0..0af08f1180 100644
--- a/src/panels/lovelace/components/hui-entity-editor.ts
+++ b/src/panels/lovelace/components/hui-entity-editor.ts
@@ -2,7 +2,6 @@ import { mdiDrag } from "@mdi/js";
import { css, CSSResultGroup, html, LitElement, nothing } from "lit";
import { customElement, property } from "lit/decorators";
import { repeat } from "lit/directives/repeat";
-import type { SortableEvent } from "sortablejs";
import { fireEvent } from "../../../common/dom/fire_event";
import "../../../components/entity/ha-entity-picker";
import type {
@@ -10,8 +9,7 @@ import type {
HaEntityPickerEntityFilterFunc,
} from "../../../components/entity/ha-entity-picker";
import "../../../components/ha-icon-button";
-import { sortableStyles } from "../../../resources/ha-sortable-style";
-import type { SortableInstance } from "../../../resources/sortable";
+import "../../../components/ha-sortable";
import { HomeAssistant } from "../../../types";
import { EntityConfig } from "../entity-rows/types";
@@ -27,13 +25,6 @@ export class HuiEntityEditor extends LitElement {
private _entityKeys = new WeakMap();
- private _sortable?: SortableInstance;
-
- public disconnectedCallback() {
- super.disconnectedCallback();
- this._destroySortable();
- }
-
private _getKey(action: EntityConfig) {
if (!this._entityKeys.has(action)) {
this._entityKeys.set(action, Math.random().toString());
@@ -55,27 +46,29 @@ export class HuiEntityEditor extends LitElement {
this.hass!.localize("ui.panel.lovelace.editor.card.config.required") +
")"}
-
- ${repeat(
- this.entities,
- (entityConf) => this._getKey(entityConf),
- (entityConf, index) => html`
-
-
-
+
+
+ ${repeat(
+ this.entities,
+ (entityConf) => this._getKey(entityConf),
+ (entityConf, index) => html`
+
-
-
- `
- )}
-
+ `
+ )}
+
+
{
- (evt.item as any).placeholder =
- document.createComment("sort-placeholder");
- evt.item.after((evt.item as any).placeholder);
- },
- onEnd: (evt: SortableEvent) => {
- // put back in original location
- if ((evt.item as any).placeholder) {
- (evt.item as any).placeholder.replaceWith(evt.item);
- delete (evt.item as any).placeholder;
- }
- this._entityMoved(evt);
- },
- }
- );
- }
-
- private _destroySortable() {
- this._sortable?.destroy();
- this._sortable = undefined;
- }
-
private async _addEntity(ev: CustomEvent): Promise {
const value = ev.detail.value;
if (value === "") {
@@ -132,14 +90,13 @@ export class HuiEntityEditor extends LitElement {
fireEvent(this, "entities-changed", { entities: newConfigEntities });
}
- private _entityMoved(ev: SortableEvent): void {
- if (ev.oldIndex === ev.newIndex) {
- return;
- }
+ private _entityMoved(ev: CustomEvent): void {
+ ev.stopPropagation();
+ const { oldIndex, newIndex } = ev.detail;
const newEntities = this.entities!.concat();
- newEntities.splice(ev.newIndex!, 0, newEntities.splice(ev.oldIndex!, 1)[0]);
+ newEntities.splice(newIndex, 0, newEntities.splice(oldIndex, 1)[0]);
fireEvent(this, "entities-changed", { entities: newEntities });
}
@@ -162,39 +119,36 @@ export class HuiEntityEditor extends LitElement {
}
static get styles(): CSSResultGroup {
- return [
- sortableStyles,
- css`
- ha-entity-picker {
- margin-top: 8px;
- }
- .add-entity {
- display: block;
- margin-left: 31px;
- margin-inline-start: 31px;
- margin-inline-end: initial;
- direction: var(--direction);
- }
- .entity {
- display: flex;
- align-items: center;
- }
- .entity .handle {
- padding-right: 8px;
- cursor: move; /* fallback if grab cursor is unsupported */
- cursor: grab;
- padding-inline-end: 8px;
- padding-inline-start: initial;
- direction: var(--direction);
- }
- .entity .handle > * {
- pointer-events: none;
- }
- .entity ha-entity-picker {
- flex-grow: 1;
- }
- `,
- ];
+ return css`
+ ha-entity-picker {
+ margin-top: 8px;
+ }
+ .add-entity {
+ display: block;
+ margin-left: 31px;
+ margin-inline-start: 31px;
+ margin-inline-end: initial;
+ direction: var(--direction);
+ }
+ .entity {
+ display: flex;
+ align-items: center;
+ }
+ .entity .handle {
+ padding-right: 8px;
+ cursor: move; /* fallback if grab cursor is unsupported */
+ cursor: grab;
+ padding-inline-end: 8px;
+ padding-inline-start: initial;
+ direction: var(--direction);
+ }
+ .entity .handle > * {
+ pointer-events: none;
+ }
+ .entity ha-entity-picker {
+ flex-grow: 1;
+ }
+ `;
}
}
diff --git a/src/panels/lovelace/editor/config-elements/hui-card-features-editor.ts b/src/panels/lovelace/editor/config-elements/hui-card-features-editor.ts
index 8693be890d..d8fe23d0a7 100644
--- a/src/panels/lovelace/editor/config-elements/hui-card-features-editor.ts
+++ b/src/panels/lovelace/editor/config-elements/hui-card-features-editor.ts
@@ -3,13 +3,13 @@ import { HassEntity } from "home-assistant-js-websocket";
import { CSSResultGroup, LitElement, css, html, nothing } from "lit";
import { customElement, property } from "lit/decorators";
import { repeat } from "lit/directives/repeat";
-import type { SortableEvent } from "sortablejs";
import { fireEvent } from "../../../../common/dom/fire_event";
import { stopPropagation } from "../../../../common/dom/stop_propagation";
import "../../../../components/entity/ha-entity-picker";
import "../../../../components/ha-button";
import "../../../../components/ha-icon-button";
import "../../../../components/ha-list-item";
+import "../../../../components/ha-sortable";
import "../../../../components/ha-svg-icon";
import {
CUSTOM_TYPE_PREFIX,
@@ -18,8 +18,6 @@ import {
isCustomType,
stripCustomPrefix,
} from "../../../../data/lovelace_custom_cards";
-import { sortableStyles } from "../../../../resources/ha-sortable-style";
-import type { SortableInstance } from "../../../../resources/sortable";
import { HomeAssistant } from "../../../../types";
import { supportsAlarmModesCardFeature } from "../../card-features/hui-alarm-modes-card-feature";
import { supportsClimateFanModesCardFeature } from "../../card-features/hui-climate-fan-modes-card-feature";
@@ -39,11 +37,11 @@ import { supportsNumericInputCardFeature } from "../../card-features/hui-numeric
import { supportsSelectOptionsCardFeature } from "../../card-features/hui-select-options-card-feature";
import { supportsTargetHumidityCardFeature } from "../../card-features/hui-target-humidity-card-feature";
import { supportsTargetTemperatureCardFeature } from "../../card-features/hui-target-temperature-card-feature";
+import { supportsUpdateActionsCardFeature } from "../../card-features/hui-update-actions-card-feature";
import { supportsVacuumCommandsCardFeature } from "../../card-features/hui-vacuum-commands-card-feature";
import { supportsWaterHeaterOperationModesCardFeature } from "../../card-features/hui-water-heater-operation-modes-card-feature";
import { LovelaceCardFeatureConfig } from "../../card-features/types";
import { getCardFeatureElementClass } from "../../create-element/create-card-feature-element";
-import { supportsUpdateActionsCardFeature } from "../../card-features/hui-update-actions-card-feature";
export type FeatureType = LovelaceCardFeatureConfig["type"];
type SupportsFeature = (stateObj: HassEntity) => boolean;
@@ -149,13 +147,6 @@ export class HuiCardFeaturesEditor extends LitElement {
private _featuresKeys = new WeakMap();
- private _sortable?: SortableInstance;
-
- public disconnectedCallback() {
- super.disconnectedCallback();
- this._destroySortable();
- }
-
private _supportsFeatureType(type: string): boolean {
if (!this.stateObj) return false;
@@ -205,10 +196,6 @@ export class HuiCardFeaturesEditor extends LitElement {
return this._featuresKeys.get(feature)!;
}
- protected firstUpdated() {
- this._createSortable();
- }
-
private _getSupportedFeaturesType() {
const featuresTypes = UI_FEATURE_TYPES.filter(
(type) => !this.featuresTypes || this.featuresTypes.includes(type)
@@ -249,61 +236,66 @@ export class HuiCardFeaturesEditor extends LitElement {
`
: nothing}
-
- ${repeat(
- this.features,
- (featureConf) => this._getKey(featureConf),
- (featureConf, index) => {
- const type = featureConf.type;
- const supported = this._supportsFeatureType(type);
- const editable = this._isFeatureTypeEditable(type);
- return html`
-
-
-
-
-
-
-
${this._getFeatureTypeLabel(type)}
- ${this.stateObj && !supported
- ? html`
-
- ${this.hass!.localize(
- "ui.panel.lovelace.editor.features.not_compatible"
- )}
-
- `
- : nothing}
+
+
+ ${repeat(
+ this.features,
+ (featureConf) => this._getKey(featureConf),
+ (featureConf, index) => {
+ const type = featureConf.type;
+ const supported = this._supportsFeatureType(type);
+ const editable = this._isFeatureTypeEditable(type);
+ return html`
+
+
+
+
+
+ ${this._getFeatureTypeLabel(type)}
+ ${this.stateObj && !supported
+ ? html`
+
+ ${this.hass!.localize(
+ "ui.panel.lovelace.editor.features.not_compatible"
+ )}
+
+ `
+ : nothing}
+
+
+ ${editable
+ ? html`
+
+ `
+ : nothing}
+
- ${editable
- ? html`
-
- `
- : nothing}
-
-
- `;
- }
- )}
-
+ `;
+ }
+ )}
+
+
${supportedFeaturesType.length > 0
? html`
{
- (evt.item as any).placeholder =
- document.createComment("sort-placeholder");
- evt.item.after((evt.item as any).placeholder);
- },
- onEnd: (evt: SortableEvent) => {
- // put back in original location
- if ((evt.item as any).placeholder) {
- (evt.item as any).placeholder.replaceWith(evt.item);
- delete (evt.item as any).placeholder;
- }
- this._rowMoved(evt);
- },
- }
- );
- }
-
- private _destroySortable() {
- this._sortable?.destroy();
- this._sortable = undefined;
- }
-
private async _addFeature(ev: CustomEvent): Promise {
const index = ev.detail.index as number;
@@ -395,14 +357,13 @@ export class HuiCardFeaturesEditor extends LitElement {
fireEvent(this, "features-changed", { features: newConfigFeature });
}
- private _rowMoved(ev: SortableEvent): void {
- if (ev.oldIndex === ev.newIndex) {
- return;
- }
+ private _featureMoved(ev: CustomEvent): void {
+ ev.stopPropagation();
+ const { oldIndex, newIndex } = ev.detail;
const newFeatures = this.features!.concat();
- newFeatures.splice(ev.newIndex!, 0, newFeatures.splice(ev.oldIndex!, 1)[0]);
+ newFeatures.splice(newIndex, 0, newFeatures.splice(oldIndex, 1)[0]);
fireEvent(this, "features-changed", { features: newFeatures });
}
@@ -428,79 +389,76 @@ export class HuiCardFeaturesEditor extends LitElement {
}
static get styles(): CSSResultGroup {
- return [
- sortableStyles,
- css`
- :host {
- display: flex !important;
- flex-direction: column;
- }
- .content {
- padding: 12px;
- }
- ha-expansion-panel {
- display: block;
- --expansion-panel-content-padding: 0;
- border-radius: 6px;
- }
- h3 {
- margin: 0;
- font-size: inherit;
- font-weight: inherit;
- }
- ha-svg-icon,
- ha-icon {
- color: var(--secondary-text-color);
- }
- ha-button-menu {
- margin-top: 8px;
- }
- .feature {
- display: flex;
- align-items: center;
- }
- .feature .handle {
- padding-right: 8px;
- cursor: move; /* fallback if grab cursor is unsupported */
- cursor: grab;
- padding-inline-end: 8px;
- padding-inline-start: initial;
- direction: var(--direction);
- }
- .feature .handle > * {
- pointer-events: none;
- }
+ return css`
+ :host {
+ display: flex !important;
+ flex-direction: column;
+ }
+ .content {
+ padding: 12px;
+ }
+ ha-expansion-panel {
+ display: block;
+ --expansion-panel-content-padding: 0;
+ border-radius: 6px;
+ }
+ h3 {
+ margin: 0;
+ font-size: inherit;
+ font-weight: inherit;
+ }
+ ha-svg-icon,
+ ha-icon {
+ color: var(--secondary-text-color);
+ }
+ ha-button-menu {
+ margin-top: 8px;
+ }
+ .feature {
+ display: flex;
+ align-items: center;
+ }
+ .feature .handle {
+ cursor: move; /* fallback if grab cursor is unsupported */
+ cursor: grab;
+ padding-right: 8px;
+ padding-inline-end: 8px;
+ padding-inline-start: initial;
+ direction: var(--direction);
+ }
+ .feature .handle > * {
+ pointer-events: none;
+ }
- .feature-content {
- height: 60px;
- font-size: 16px;
- display: flex;
- align-items: center;
- justify-content: space-between;
- flex-grow: 1;
- }
+ .feature-content {
+ height: 60px;
+ font-size: 16px;
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ flex-grow: 1;
+ }
- .feature-content div {
- display: flex;
- flex-direction: column;
- }
+ .feature-content div {
+ display: flex;
+ flex-direction: column;
+ }
- .remove-icon,
- .edit-icon {
- --mdc-icon-button-size: 36px;
- color: var(--secondary-text-color);
- }
+ .remove-icon,
+ .edit-icon {
+ --mdc-icon-button-size: 36px;
+ color: var(--secondary-text-color);
+ }
- .secondary {
- font-size: 12px;
- color: var(--secondary-text-color);
- }
+ .secondary {
+ font-size: 12px;
+ color: var(--secondary-text-color);
+ }
- li[divider] {
- border-bottom-color: var(--divider-color);
- }
- `,
- ];
+ li[divider] {
+ border-bottom-color: var(--divider-color);
+ }
+ `;
}
}
diff --git a/src/panels/lovelace/editor/hui-entities-card-row-editor.ts b/src/panels/lovelace/editor/hui-entities-card-row-editor.ts
index 231305a1a3..58891055fc 100644
--- a/src/panels/lovelace/editor/hui-entities-card-row-editor.ts
+++ b/src/panels/lovelace/editor/hui-entities-card-row-editor.ts
@@ -1,15 +1,13 @@
import { mdiClose, mdiDrag, mdiPencil } from "@mdi/js";
-import { css, CSSResultGroup, html, LitElement, nothing } from "lit";
+import { CSSResultGroup, LitElement, css, html, nothing } from "lit";
import { customElement, property } from "lit/decorators";
import { repeat } from "lit/directives/repeat";
-import type { SortableEvent } from "sortablejs";
import { fireEvent } from "../../../common/dom/fire_event";
import "../../../components/entity/ha-entity-picker";
import type { HaEntityPicker } from "../../../components/entity/ha-entity-picker";
import "../../../components/ha-icon-button";
+import "../../../components/ha-sortable";
import "../../../components/ha-svg-icon";
-import { sortableStyles } from "../../../resources/ha-sortable-style";
-import type { SortableInstance } from "../../../resources/sortable";
import { HomeAssistant } from "../../../types";
import { EntityConfig, LovelaceRowConfig } from "../entity-rows/types";
@@ -31,13 +29,6 @@ export class HuiEntitiesCardRowEditor extends LitElement {
private _entityKeys = new WeakMap();
- private _sortable?: SortableInstance;
-
- public disconnectedCallback() {
- super.disconnectedCallback();
- this._destroySortable();
- }
-
private _getKey(action: LovelaceRowConfig) {
if (!this._entityKeys.has(action)) {
this._entityKeys.set(action, Math.random().toString());
@@ -60,64 +51,66 @@ export class HuiEntitiesCardRowEditor extends LitElement {
"ui.panel.lovelace.editor.card.config.required"
)})`}
-
- ${repeat(
- this.entities,
- (entityConf) => this._getKey(entityConf),
- (entityConf, index) => html`
-
-
-
-
- ${entityConf.type
- ? html`
-
-
-
- ${this.hass!.localize(
- `ui.panel.lovelace.editor.card.entities.entity_row.${entityConf.type}`
- )}
-
-
${this.hass!.localize(
- "ui.panel.lovelace.editor.card.entities.edit_special_row"
- )}
+
+
+ ${repeat(
+ this.entities,
+ (entityConf) => this._getKey(entityConf),
+ (entityConf, index) => html`
+
+
+
+
+ ${entityConf.type
+ ? html`
+
+
+
+ ${this.hass!.localize(
+ `ui.panel.lovelace.editor.card.entities.entity_row.${entityConf.type}`
+ )}
+
+ ${this.hass!.localize(
+ "ui.panel.lovelace.editor.card.entities.edit_special_row"
+ )}
+
-
- `
- : html`
-
- `}
-
-
-
- `
- )}
-
+ `
+ : html`
+
+ `}
+
+
+
+ `
+ )}
+
+
{
- (evt.item as any).placeholder =
- document.createComment("sort-placeholder");
- evt.item.after((evt.item as any).placeholder);
- },
- onEnd: (evt: SortableEvent) => {
- // put back in original location
- if ((evt.item as any).placeholder) {
- (evt.item as any).placeholder.replaceWith(evt.item);
- delete (evt.item as any).placeholder;
- }
- this._rowMoved(evt);
- },
- }
- );
- }
-
- private _destroySortable() {
- this._sortable?.destroy();
- this._sortable = undefined;
- }
-
private async _addEntity(ev: CustomEvent): Promise {
const value = ev.detail.value;
if (value === "") {
@@ -172,14 +131,13 @@ export class HuiEntitiesCardRowEditor extends LitElement {
fireEvent(this, "entities-changed", { entities: newConfigEntities });
}
- private _rowMoved(ev: SortableEvent): void {
- if (ev.oldIndex === ev.newIndex) {
- return;
- }
+ private _rowMoved(ev: CustomEvent): void {
+ ev.stopPropagation();
+ const { oldIndex, newIndex } = ev.detail;
const newEntities = this.entities!.concat();
- newEntities.splice(ev.newIndex!, 0, newEntities.splice(ev.oldIndex!, 1)[0]);
+ newEntities.splice(newIndex, 0, newEntities.splice(oldIndex, 1)[0]);
fireEvent(this, "entities-changed", { entities: newEntities });
}
@@ -222,67 +180,64 @@ export class HuiEntitiesCardRowEditor extends LitElement {
}
static get styles(): CSSResultGroup {
- return [
- sortableStyles,
- css`
- ha-entity-picker {
- margin-top: 8px;
- }
- .add-entity {
- display: block;
- margin-left: 31px;
- margin-right: 71px;
- margin-inline-start: 31px;
- margin-inline-end: 71px;
- direction: var(--direction);
- }
- .entity {
- display: flex;
- align-items: center;
- }
+ return css`
+ ha-entity-picker {
+ margin-top: 8px;
+ }
+ .add-entity {
+ display: block;
+ margin-left: 31px;
+ margin-right: 71px;
+ margin-inline-start: 31px;
+ margin-inline-end: 71px;
+ direction: var(--direction);
+ }
+ .entity {
+ display: flex;
+ align-items: center;
+ }
- .entity .handle {
- padding-right: 8px;
- cursor: move; /* fallback if grab cursor is unsupported */
- cursor: grab;
- padding-inline-end: 8px;
- padding-inline-start: initial;
- direction: var(--direction);
- }
- .entity .handle > * {
- pointer-events: none;
- }
+ .entity .handle {
+ padding-right: 8px;
+ cursor: move; /* fallback if grab cursor is unsupported */
+ cursor: grab;
+ padding-inline-end: 8px;
+ padding-inline-start: initial;
+ direction: var(--direction);
+ }
+ .entity .handle > * {
+ pointer-events: none;
+ }
- .entity ha-entity-picker {
- flex-grow: 1;
- }
+ .entity ha-entity-picker {
+ flex-grow: 1;
+ }
- .special-row {
- height: 60px;
- font-size: 16px;
- display: flex;
- align-items: center;
- justify-content: space-between;
- flex-grow: 1;
- }
+ .special-row {
+ height: 60px;
+ font-size: 16px;
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ flex-grow: 1;
+ }
- .special-row div {
- display: flex;
- flex-direction: column;
- }
+ .special-row div {
+ display: flex;
+ flex-direction: column;
+ }
- .remove-icon,
- .edit-icon {
- --mdc-icon-button-size: 36px;
- color: var(--secondary-text-color);
- }
+ .remove-icon,
+ .edit-icon {
+ --mdc-icon-button-size: 36px;
+ color: var(--secondary-text-color);
+ }
- .secondary {
- font-size: 12px;
- color: var(--secondary-text-color);
- }
- `,
- ];
+ .secondary {
+ font-size: 12px;
+ color: var(--secondary-text-color);
+ }
+ `;
}
}
diff --git a/src/resources/ha-sortable-style.ts b/src/resources/ha-sidebar-edit-style.ts
similarity index 74%
rename from src/resources/ha-sortable-style.ts
rename to src/resources/ha-sidebar-edit-style.ts
index a1fcfe9209..50bf37c756 100644
--- a/src/resources/ha-sortable-style.ts
+++ b/src/resources/ha-sidebar-edit-style.ts
@@ -1,7 +1,7 @@
import { css } from "lit";
-export const sortableStyles = css`
- #sortable a:nth-of-type(2n) paper-icon-item {
+export const sidebarEditStyle = css`
+ .reorder-list a:nth-of-type(2n) paper-icon-item {
animation-name: keyframes1;
animation-iteration-count: infinite;
transform-origin: 50% 10%;
@@ -9,7 +9,7 @@ export const sortableStyles = css`
animation-duration: 0.25s;
}
- #sortable a:nth-of-type(2n-1) paper-icon-item {
+ .reorder-list a:nth-of-type(2n-1) paper-icon-item {
animation-name: keyframes2;
animation-iteration-count: infinite;
animation-direction: alternate;
@@ -18,12 +18,12 @@ export const sortableStyles = css`
animation-duration: 0.33s;
}
- #sortable a {
+ .reorder-list a {
height: 48px;
display: flex;
}
- #sortable {
+ .reorder-list {
outline: none;
display: block !important;
}
@@ -32,26 +32,6 @@ export const sortableStyles = css`
display: flex !important;
}
- .sortable-fallback {
- display: none;
- opacity: 0;
- }
-
- .sortable-ghost {
- border: 2px solid var(--primary-color);
- background: rgba(var(--rgb-primary-color), 0.25);
- border-radius: 4px;
- opacity: 0.4;
- }
-
- .sortable-drag {
- border-radius: 4px;
- opacity: 1;
- background: var(--card-background-color);
- box-shadow: 0px 4px 8px 3px #00000026;
- cursor: grabbing;
- }
-
@keyframes keyframes1 {
0% {
transform: rotate(-1deg);