Compare commits

..

3 Commits

Author SHA1 Message Date
Aidan Timson
fcaabfb326 Use superstruct 2025-08-29 14:34:23 +01:00
Aidan Timson
defc379a92 Max 2025-08-29 14:32:13 +01:00
Aidan Timson
b539ffcc50 Add min/max and step size to volume slider card feature 2025-08-29 14:26:30 +01:00
29 changed files with 506 additions and 410 deletions

View File

@@ -123,7 +123,7 @@
"lit": "3.3.1",
"lit-html": "3.3.1",
"luxon": "3.7.1",
"marked": "16.2.1",
"marked": "16.2.0",
"memoize-one": "6.0.0",
"node-vibrant": "4.0.3",
"object-hash": "3.0.0",
@@ -159,7 +159,7 @@
"@octokit/plugin-retry": "8.0.1",
"@octokit/rest": "22.0.0",
"@rsdoctor/rspack-plugin": "1.2.3",
"@rspack/core": "1.5.1",
"@rspack/core": "1.4.11",
"@rspack/dev-server": "1.1.4",
"@types/babel__plugin-transform-runtime": "7.9.5",
"@types/chromecast-caf-receiver": "6.0.22",

View File

@@ -53,15 +53,9 @@ export class HaMediaSelector extends LitElement {
private _contextEntities: string[] | undefined;
private get _hasAccept(): boolean {
return !!this.selector?.media?.accept?.length;
}
willUpdate(changedProps: PropertyValues<this>) {
if (changedProps.has("context")) {
if (!this._hasAccept) {
this._contextEntities = ensureArray(this.context?.filter_entity);
}
this._contextEntities = ensureArray(this.context?.filter_entity);
}
if (changedProps.has("value")) {
@@ -105,8 +99,10 @@ export class HaMediaSelector extends LitElement {
(stateObj &&
supportsFeature(stateObj, MediaPlayerEntityFeature.BROWSE_MEDIA));
const hasAccept = this.selector?.media?.accept?.length;
return html`
${this._hasAccept ||
${hasAccept ||
(this._contextEntities && this._contextEntities.length <= 1)
? nothing
: html`
@@ -152,7 +148,7 @@ export class HaMediaSelector extends LitElement {
: this.value.metadata?.title || this.value.media_content_id}
@click=${this._pickMedia}
@keydown=${this._handleKeyDown}
class=${this.disabled || (!entityId && !this._hasAccept)
class=${this.disabled || (!entityId && !hasAccept)
? "disabled"
: ""}
>
@@ -219,7 +215,7 @@ export class HaMediaSelector extends LitElement {
private _entityChanged(ev: CustomEvent) {
ev.stopPropagation();
if (!this._hasAccept && this.context?.filter_entity) {
if (this.context?.filter_entity) {
fireEvent(this, "value-changed", {
value: {
media_content_id: "",
@@ -261,7 +257,7 @@ export class HaMediaSelector extends LitElement {
media_content_type: id.media_content_type,
media_content_id: id.media_content_id,
})),
...(!this._hasAccept && this.context?.filter_entity
...(this.context?.filter_entity
? { browse_entity_id: this._getActiveEntityId() }
: {}),
},

View File

@@ -387,18 +387,6 @@ export const normalizeAutomationConfig = <
}
}
// We move all conditions into the action for display
if (config.conditions) {
if (config.actions) {
(config.actions as Action[]).unshift(
...(config.conditions as Condition[])
);
} else {
config.actions = config.conditions;
}
delete config.conditions;
}
return config;
};

View File

@@ -1,7 +1,7 @@
import { mdiDrag, mdiPlus } from "@mdi/js";
import deepClone from "deep-clone-simple";
import type { PropertyValues } from "lit";
import { LitElement, html, nothing } from "lit";
import { LitElement, css, html, nothing } from "lit";
import { customElement, property, queryAll, state } from "lit/decorators";
import { repeat } from "lit/directives/repeat";
import { storage } from "../../../../common/decorators/storage";
@@ -409,7 +409,14 @@ export default class HaAutomationAction extends LitElement {
this._rowSortSelected = undefined;
}
static styles = automationRowsStyles;
static styles = [
automationRowsStyles,
css`
:host([root]) .rows {
padding-right: 8px;
}
`,
];
}
declare global {

View File

@@ -1,7 +1,7 @@
import { mdiDrag, mdiPlus } from "@mdi/js";
import deepClone from "deep-clone-simple";
import type { PropertyValues } from "lit";
import { html, LitElement, nothing } from "lit";
import { css, html, LitElement, nothing } from "lit";
import { customElement, property, queryAll, state } from "lit/decorators";
import { repeat } from "lit/directives/repeat";
import { storage } from "../../../../common/decorators/storage";
@@ -428,7 +428,14 @@ export default class HaAutomationCondition extends LitElement {
this._rowSortSelected = undefined;
}
static styles = automationRowsStyles;
static styles = [
automationRowsStyles,
css`
:host([root]) .rows {
padding-right: 8px;
}
`,
];
}
declare global {

View File

@@ -24,7 +24,6 @@ import type { CSSResultGroup, PropertyValues, TemplateResult } from "lit";
import { css, html, LitElement, nothing } from "lit";
import { property, query, state } from "lit/decorators";
import { classMap } from "lit/directives/class-map";
import { isArray } from "@tsparticles/engine";
import { transform } from "../../../common/decorators/transform";
import { fireEvent } from "../../../common/dom/fire_event";
import { navigate } from "../../../common/navigate";
@@ -44,7 +43,6 @@ import type {
AutomationConfig,
AutomationEntity,
BlueprintAutomationConfig,
Condition,
} from "../../../data/automation";
import {
deleteAutomation,
@@ -1064,28 +1062,8 @@ export class HaAutomationEditor extends PreventUnsavedMixin(
});
}
// Move conditions at top of action to automation condition key
const configToSave = { ...this._config! };
configToSave.conditions = !configToSave.conditions
? []
: isArray(configToSave.conditions)
? [...configToSave.conditions]
: [configToSave.conditions];
configToSave.actions = !configToSave.actions
? []
: isArray(configToSave.actions)
? [...configToSave.actions]
: [configToSave.actions];
while (
configToSave.actions.length > 0 &&
"condition" in configToSave.actions[0]
) {
configToSave.conditions.push(configToSave.actions.shift() as Condition);
}
try {
await saveAutomationConfig(this.hass, id, configToSave);
await saveAutomationConfig(this.hass, id, this._config!);
if (this._entityRegistryUpdate !== undefined) {
let entityId = this._entityId;
@@ -1203,6 +1181,27 @@ export class HaAutomationEditor extends PreventUnsavedMixin(
display: block;
}
:not(.yaml-mode) > .alert-wrapper {
position: sticky;
top: -24px;
margin-top: -24px;
z-index: 1;
width: 100%;
display: flex;
flex-direction: column;
align-items: center;
gap: 8px;
pointer-events: none;
}
:not(.yaml-mode) > .alert-wrapper ha-alert {
background-color: var(--card-background-color);
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
border-radius: var(--ha-border-radius-sm);
margin-bottom: 0;
pointer-events: auto;
}
manual-automation-editor {
max-width: 1540px;
padding: 0 12px;

View File

@@ -23,6 +23,7 @@ import {
extractSearchParam,
removeSearchParam,
} from "../../../common/url/search-params";
import { computeRTL } from "../../../common/util/compute_rtl";
import "../../../components/ha-button";
import "../../../components/ha-fab";
import "../../../components/ha-icon-button";
@@ -45,6 +46,8 @@ import { documentationUrl } from "../../../util/documentation-url";
import { showToast } from "../../../util/toast";
import "./action/ha-automation-action";
import type HaAutomationAction from "./action/ha-automation-action";
import "./condition/ha-automation-condition";
import type HaAutomationCondition from "./condition/ha-automation-condition";
import "./ha-automation-sidebar";
import type HaAutomationSidebar from "./ha-automation-sidebar";
import { showPasteReplaceDialog } from "./paste-replace-dialog/show-dialog-paste-replace";
@@ -90,6 +93,9 @@ export class HaManualAutomationEditor extends LitElement {
@state() private _sidebarConfig?: SidebarConfig;
@query(".content")
private _contentElement?: HTMLDivElement;
@query("ha-automation-sidebar") private _sidebarElement?: HaAutomationSidebar;
private _previousConfig?: ManualAutomationConfig;
@@ -156,6 +162,53 @@ export class HaManualAutomationEditor extends LitElement {
sidebar
></ha-automation-trigger>
<div class="header">
<h2 id="conditions-heading" class="name">
${this.hass.localize(
"ui.panel.config.automation.editor.conditions.header"
)}
<span class="small"
>(${this.hass.localize("ui.common.optional")})</span
>
</h2>
<a
href=${documentationUrl(this.hass, "/docs/automation/condition/")}
target="_blank"
rel="noreferrer"
>
<ha-icon-button
.path=${mdiHelpCircle}
.label=${this.hass.localize(
"ui.panel.config.automation.editor.conditions.learn_more"
)}
></ha-icon-button>
</a>
</div>
${!ensureArray(this.config.conditions)?.length
? html`<p>
${this.hass.localize(
"ui.panel.config.automation.editor.conditions.description",
{ user: this.hass.user?.name || "Alice" }
)}
</p>`
: nothing}
<ha-automation-condition
role="region"
aria-labelledby="conditions-heading"
.conditions=${this.config.conditions || []}
.highlightedConditions=${this._pastedConfig?.conditions || []}
@value-changed=${this._conditionChanged}
.hass=${this.hass}
.disabled=${this.disabled || this.saving}
.narrow=${this.narrow}
@open-sidebar=${this._openSidebar}
@request-close-sidebar=${this._closeSidebar}
@close-sidebar=${this._handleCloseSidebar}
root
sidebar
></ha-automation-condition>
<div class="header">
<h2 id="actions-heading" class="name">
${this.hass.localize(
@@ -207,7 +260,8 @@ export class HaManualAutomationEditor extends LitElement {
return html`
<div
class=${classMap({
"has-sidebar": this._sidebarConfig && !this.narrow,
"split-view": true,
"sidebar-hidden": !this._sidebarConfig,
})}
>
<div class="content-wrapper">
@@ -215,31 +269,31 @@ export class HaManualAutomationEditor extends LitElement {
<slot name="alerts"></slot>
${this._renderContent()}
</div>
<div class="fab-positioner">
<ha-fab
slot="fab"
class=${this.dirty ? "dirty" : ""}
.label=${this.hass.localize("ui.common.save")}
.disabled=${this.saving}
extended
@click=${this._saveAutomation}
>
<ha-svg-icon slot="icon" .path=${mdiContentSave}></ha-svg-icon>
</ha-fab>
</div>
</div>
<div class="sidebar-positioner">
<ha-automation-sidebar
tabindex="-1"
class=${classMap({ hidden: !this._sidebarConfig })}
.isWide=${this.isWide}
.hass=${this.hass}
.narrow=${this.narrow}
.config=${this._sidebarConfig}
@value-changed=${this._sidebarConfigChanged}
.disabled=${this.disabled}
></ha-automation-sidebar>
<ha-fab
slot="fab"
class=${this.dirty ? "dirty" : ""}
.label=${this.hass.localize("ui.common.save")}
.disabled=${this.saving}
extended
@click=${this._saveAutomation}
>
<ha-svg-icon slot="icon" .path=${mdiContentSave}></ha-svg-icon>
</ha-fab>
</div>
<ha-automation-sidebar
tabindex="-1"
class=${classMap({
sidebar: true,
overlay: !this.isWide && !this.narrow,
rtl: computeRTL(this.hass),
})}
.isWide=${this.isWide}
.hass=${this.hass}
.narrow=${this.narrow}
.config=${this._sidebarConfig}
@value-changed=${this._sidebarConfigChanged}
.disabled=${this.disabled}
></ha-automation-sidebar>
</div>
`;
}
@@ -290,6 +344,8 @@ export class HaManualAutomationEditor extends LitElement {
private _handleCloseSidebar() {
this._sidebarConfig = undefined;
// fix content shift when bottom rows are scrolled into view
this._contentElement?.scrollIntoView();
}
private _triggerChanged(ev: CustomEvent): void {
@@ -535,9 +591,9 @@ export class HaManualAutomationEditor extends LitElement {
}
private _getCollapsableElements() {
return this.shadowRoot!.querySelectorAll<HaAutomationAction>(
"ha-automation-action"
);
return this.shadowRoot!.querySelectorAll<
HaAutomationAction | HaAutomationCondition
>("ha-automation-action, ha-automation-condition");
}
public expandAll() {

View File

@@ -69,7 +69,7 @@ export const indentStyle = css`
.selector-row,
:host([indent]) ha-form {
margin-left: 12px;
padding: 12px 0 16px 16px;
padding: 12px 20px 16px 16px;
border-left: 2px solid var(--ha-color-border-neutral-quiet);
border-bottom: 2px solid var(--ha-color-border-neutral-quiet);
border-radius: 0;
@@ -108,59 +108,77 @@ export const saveFabStyles = css`
export const manualEditorStyles = css`
:host {
display: block;
--sidebar-width: 0;
--sidebar-gap: 0;
}
.has-sidebar {
--sidebar-width: min(35vw, 500px);
--sidebar-gap: 16px;
}
.fab-positioner {
.split-view {
display: flex;
justify-content: flex-end;
flex-direction: row;
height: 100%;
position: relative;
gap: 16px;
}
.fab-positioner ha-fab {
position: fixed;
right: unset;
left: unset;
bottom: calc(-80px - var(--safe-area-inset-bottom));
transition: bottom 0.3s;
}
.fab-positioner ha-fab.dirty {
bottom: 16px;
.split-view.sidebar-hidden {
gap: 0;
}
.content-wrapper {
padding-right: calc(var(--sidebar-width) + var(--sidebar-gap));
padding-inline-end: calc(var(--sidebar-width) + var(--sidebar-gap));
padding-inline-start: 0;
position: relative;
flex: 6;
}
.content {
padding-top: 24px;
padding-bottom: 72px;
padding: 32px 16px 64px 0;
height: calc(100vh - 153px);
height: calc(100dvh - 153px);
overflow-y: auto;
overflow-x: hidden;
}
ha-automation-sidebar {
.sidebar {
padding: 12px 0;
flex: 4;
height: calc(100vh - 81px);
height: calc(100dvh - 81px);
width: 40%;
}
.split-view.sidebar-hidden .sidebar {
border-color: transparent;
border-width: 0;
overflow: hidden;
flex: 0;
visibility: hidden;
}
.sidebar.overlay {
position: fixed;
top: calc(var(--header-height) + 16px);
height: calc(-81px + 100dvh);
width: var(--sidebar-width);
display: block;
bottom: 8px;
right: 8px;
height: calc(100% - 70px);
padding: 0;
z-index: 5;
box-shadow: -8px 0 16px rgba(0, 0, 0, 0.2);
}
ha-automation-sidebar.hidden {
display: none;
.sidebar.overlay.rtl {
right: unset;
left: 8px;
}
.sidebar-positioner {
display: flex;
justify-content: flex-end;
@media all and (max-width: 870px) {
.split-view {
gap: 0;
}
.sidebar {
height: 0;
width: 0;
flex: 0;
}
}
.split-view.sidebar-hidden .sidebar.overlay {
width: 0;
}
.description {
margin: 0;
}
@@ -171,6 +189,9 @@ export const manualEditorStyles = css`
export const automationRowsStyles = css`
.rows {
padding: 16px 0 16px 16px;
margin: -16px;
margin-right: -20px;
display: flex;
flex-direction: column;
gap: 16px;

View File

@@ -1,7 +1,7 @@
import { mdiDrag, mdiPlus } from "@mdi/js";
import deepClone from "deep-clone-simple";
import type { PropertyValues } from "lit";
import { html, LitElement, nothing } from "lit";
import { css, html, LitElement, nothing } from "lit";
import { customElement, property, state } from "lit/decorators";
import { repeat } from "lit/directives/repeat";
import { storage } from "../../../../common/decorators/storage";
@@ -368,7 +368,14 @@ export default class HaAutomationTrigger extends LitElement {
this._rowSortSelected = undefined;
}
static styles = automationRowsStyles;
static styles = [
automationRowsStyles,
css`
:host([root]) .rows {
padding-right: 8px;
}
`,
];
}
declare global {

View File

@@ -34,16 +34,6 @@ const UPDATE_THROTTLE_TIME = 10000;
const CORE_SOURCE_ID = "ha";
const CORE_SOURCE_LABEL = "Home Assistant";
const RSSI_COLOR_THRESHOLDS: [number, string][] = [
[-70, "--green-color"], // Excellent: > -70 dBm
[-75, "--lime-color"], // Good: -70 to -75 dBm
[-80, "--yellow-color"], // Okay: -75 to -80 dBm
[-85, "--amber-color"], // Marginal: -80 to -85 dBm
[-90, "--orange-color"], // Weak: -85 to -90 dBm
[-95, "--deep-orange-color"], // Poor: -90 to -95 dBm
[-Infinity, "--red-color"], // Very poor: < -95 dBm
];
@customElement("bluetooth-network-visualization")
export class BluetoothNetworkVisualization extends LitElement {
@property({ attribute: false }) public hass!: HomeAssistant;
@@ -135,16 +125,6 @@ export class BluetoothNetworkVisualization extends LitElement {
`;
}
private _getRssiColorVar = memoizeOne((rssi: number): string => {
for (const [threshold, colorVar] of RSSI_COLOR_THRESHOLDS) {
if (rssi > threshold) {
return colorVar;
}
}
// Fallback (should never reach here)
return "--red-color";
});
private _formatNetworkData = memoizeOne(
(
data: BluetoothDeviceData[],
@@ -226,7 +206,7 @@ export class BluetoothNetworkVisualization extends LitElement {
symbol: "none",
lineStyle: {
width: this._getLineWidth(node.rssi),
color: style.getPropertyValue(this._getRssiColorVar(node.rssi)),
color: style.getPropertyValue("--primary-color"),
},
});
return;
@@ -247,7 +227,7 @@ export class BluetoothNetworkVisualization extends LitElement {
lineStyle: {
width: this._getLineWidth(node.rssi),
color: device
? style.getPropertyValue(this._getRssiColorVar(node.rssi))
? style.getPropertyValue("--primary-color")
: style.getPropertyValue("--disabled-color"),
},
});

View File

@@ -199,10 +199,8 @@ export class HaConfigLovelaceDashboards extends LitElement {
"ui.panel.config.lovelace.dashboards.picker.headers.require_admin"
),
sortable: true,
hidden: narrow,
type: "icon",
minWidth: "120px",
maxWidth: "120px",
hidden: narrow,
template: (dashboard) =>
dashboard.require_admin
? html`<ha-svg-icon .path=${mdiCheck}></ha-svg-icon>`
@@ -212,10 +210,8 @@ export class HaConfigLovelaceDashboards extends LitElement {
title: localize(
"ui.panel.config.lovelace.dashboards.picker.headers.sidebar"
),
hidden: narrow,
type: "icon",
minWidth: "120px",
maxWidth: "120px",
hidden: narrow,
template: (dashboard) =>
dashboard.show_in_sidebar
? html`<ha-svg-icon .path=${mdiCheck}></ha-svg-icon>`

View File

@@ -22,6 +22,7 @@ import {
extractSearchParam,
removeSearchParam,
} from "../../../common/url/search-params";
import { computeRTL } from "../../../common/util/compute_rtl";
import "../../../components/ha-icon-button";
import "../../../components/ha-markdown";
import type { SidebarConfig } from "../../../data/automation";
@@ -198,7 +199,8 @@ export class HaManualScriptEditor extends LitElement {
return html`
<div
class=${classMap({
"has-sidebar": this._sidebarConfig && !this.narrow,
"split-view": true,
"sidebar-hidden": !this._sidebarConfig,
})}
>
<div class="content-wrapper">
@@ -206,33 +208,31 @@ export class HaManualScriptEditor extends LitElement {
<slot name="alerts"></slot>
${this._renderContent()}
</div>
<div class="fab-positioner">
<div class="fab-positioner">
<ha-fab
slot="fab"
class=${this.dirty ? "dirty" : ""}
.label=${this.hass.localize("ui.common.save")}
.disabled=${this.saving}
extended
@click=${this._saveScript}
>
<ha-svg-icon slot="icon" .path=${mdiContentSave}></ha-svg-icon>
</ha-fab>
</div>
</div>
</div>
<div class="sidebar-positioner">
<ha-automation-sidebar
tabindex="-1"
class=${classMap({ hidden: !this._sidebarConfig })}
.narrow=${this.narrow}
.isWide=${this.isWide}
.hass=${this.hass}
.config=${this._sidebarConfig}
@value-changed=${this._sidebarConfigChanged}
.disabled=${this.disabled}
></ha-automation-sidebar>
<ha-fab
slot="fab"
class=${this.dirty ? "dirty" : ""}
.label=${this.hass.localize("ui.common.save")}
.disabled=${this.saving}
extended
@click=${this._saveScript}
>
<ha-svg-icon slot="icon" .path=${mdiContentSave}></ha-svg-icon>
</ha-fab>
</div>
<ha-automation-sidebar
tabindex="-1"
class=${classMap({
sidebar: true,
overlay: !this.isWide,
rtl: computeRTL(this.hass),
})}
.narrow=${this.narrow}
.isWide=${this.isWide}
.hass=${this.hass}
.config=${this._sidebarConfig}
@value-changed=${this._sidebarConfigChanged}
.disabled=${this.disabled}
></ha-automation-sidebar>
</div>
`;
}

View File

@@ -568,10 +568,6 @@ class HaPanelDevState extends LitElement {
margin: 0 8px 16px;
}
ha-expansion-panel p {
padding: 0 8px;
}
.inputs {
width: 100%;
max-width: 800px;
@@ -583,9 +579,8 @@ class HaPanelDevState extends LitElement {
.button-row {
display: flex;
margin: 8px 0;
margin-top: 8px;
align-items: center;
gap: 8px;
}
:host([narrow]) .state-wrapper {

View File

@@ -10,7 +10,7 @@ import {
type MediaPlayerEntity,
} from "../../../data/media-player";
import type { HomeAssistant } from "../../../types";
import type { LovelaceCardFeature } from "../types";
import type { LovelaceCardFeature, LovelaceCardFeatureEditor } from "../types";
import { cardFeatureStyles } from "./common/card-feature-styles";
import type {
LovelaceCardFeatureContext,
@@ -58,6 +58,15 @@ class HuiMediaPlayerVolumeSliderCardFeature
};
}
public static async getConfigElement(): Promise<LovelaceCardFeatureEditor> {
await import(
"../editor/config-elements/hui-media-player-volume-slider-card-feature-editor"
);
return document.createElement(
"hui-media-player-volume-slider-card-feature-editor"
);
}
public setConfig(config: MediaPlayerVolumeSliderCardFeatureConfig): void {
if (!config) {
throw new Error("Invalid configuration");
@@ -84,8 +93,9 @@ class HuiMediaPlayerVolumeSliderCardFeature
return html`
<ha-control-slider
.value=${position}
min="0"
max="100"
.min=${this._config.min ?? 0}
.max=${this._config.max ?? 100}
.step=${this._config.step ?? 1}
.showHandle=${stateActive(this._stateObj)}
.disabled=${!this._stateObj || isUnavailableState(this._stateObj.state)}
@value-changed=${this._valueChanged}

View File

@@ -45,6 +45,9 @@ export interface MediaPlayerPlaybackCardFeatureConfig {
export interface MediaPlayerVolumeSliderCardFeatureConfig {
type: "media-player-volume-slider";
min?: number;
max?: number;
step?: number;
}
export interface FanDirectionCardFeatureConfig {

View File

@@ -126,6 +126,7 @@ const EDITABLES_FEATURE_TYPES = new Set<UiFeatureTypes>([
"fan-preset-modes",
"humidifier-modes",
"lawn-mower-commands",
"media-player-volume-slider",
"numeric-input",
"select-options",
"update-actions",

View File

@@ -0,0 +1,118 @@
import { html, LitElement, nothing } from "lit";
import { customElement, property, state } from "lit/decorators";
import memoizeOne from "memoize-one";
import { assign, assert, number, object, optional } from "superstruct";
import { fireEvent } from "../../../../common/dom/fire_event";
import "../../../../components/ha-form/ha-form";
import type { SchemaUnion } from "../../../../components/ha-form/types";
import type { HomeAssistant } from "../../../../types";
import type { LovelaceCardFeatureEditor } from "../../types";
import type {
MediaPlayerVolumeSliderCardFeatureConfig,
LovelaceCardFeatureContext,
} from "../../card-features/types";
import { baseLovelaceCardConfig } from "../structs/base-card-struct";
const cardConfigStruct = assign(
baseLovelaceCardConfig,
object({
min: optional(number()),
max: optional(number()),
step: optional(number()),
})
);
@customElement("hui-media-player-volume-slider-card-feature-editor")
export class HuiMediaPlayerVolumeSliderCardFeatureEditor
extends LitElement
implements LovelaceCardFeatureEditor
{
@property({ attribute: false }) public hass?: HomeAssistant;
@property({ attribute: false }) public context?: LovelaceCardFeatureContext;
@state() private _config?: MediaPlayerVolumeSliderCardFeatureConfig;
public setConfig(config: MediaPlayerVolumeSliderCardFeatureConfig): void {
assert(config, cardConfigStruct);
this._config = config;
}
private _schema = memoizeOne(
() =>
[
{
name: "min",
selector: {
number: {
min: 0,
max: 100,
mode: "slider",
},
},
},
{
name: "max",
selector: {
number: {
min: 0,
max: 100,
mode: "slider",
},
},
},
{
name: "step",
selector: {
number: {
min: 1,
max: 40,
mode: "slider",
},
},
},
] as const
);
protected render() {
if (!this.hass || !this._config) {
return nothing;
}
const data: MediaPlayerVolumeSliderCardFeatureConfig = {
min: 0,
max: 100,
step: 1,
...this._config,
};
const schema = this._schema();
return html`
<ha-form
.hass=${this.hass}
.data=${data}
.schema=${schema}
.computeLabel=${this._computeLabelCallback}
@value-changed=${this._valueChanged}
></ha-form>
`;
}
private _valueChanged(ev: CustomEvent): void {
fireEvent(this, "config-changed", { config: ev.detail.value });
}
private _computeLabelCallback = (
schema: SchemaUnion<ReturnType<typeof this._schema>>
) =>
this.hass!.localize(
`ui.panel.lovelace.editor.features.types.media-player-volume-slider.${schema.name}`
);
}
declare global {
interface HTMLElementTagNameMap {
"hui-media-player-volume-slider-card-feature-editor": HuiMediaPlayerVolumeSliderCardFeatureEditor;
}
}

View File

@@ -15,6 +15,7 @@ import type { HomeAssistant } from "../../../../../types";
import { supportsAlarmModesCardFeature } from "../../../card-features/hui-alarm-modes-card-feature";
import { supportsCoverOpenCloseCardFeature } from "../../../card-features/hui-cover-open-close-card-feature";
import { supportsFanSpeedCardFeature } from "../../../card-features/hui-fan-speed-card-feature";
import { supportsHistoryChartCardFeature } from "../../../card-features/hui-history-chart-card-feature";
import { supportsLightBrightnessCardFeature } from "../../../card-features/hui-light-brightness-card-feature";
import { supportsLockCommandsCardFeature } from "../../../card-features/hui-lock-commands-card-feature";
import { supportsTargetTemperatureCardFeature } from "../../../card-features/hui-target-temperature-card-feature";
@@ -237,7 +238,12 @@ export const computeAreaTileCardConfig =
let feature: LovelaceCardFeatureConfig | undefined;
if (includeFeature) {
if (supportsLightBrightnessCardFeature(hass, context)) {
if (supportsHistoryChartCardFeature(hass, context)) {
feature = {
type: "history-chart",
hours_to_show: 24,
};
} else if (supportsLightBrightnessCardFeature(hass, context)) {
feature = {
type: "light-brightness",
};

View File

@@ -29,12 +29,8 @@ export class HuiHomeDashboardStrategyEditor
<ha-entities-picker
.hass=${this.hass}
.value=${this._config.favorite_entities || []}
label=${this.hass.localize(
"ui.panel.lovelace.editor.strategy.home.favorite_entities"
)}
placeholder=${this.hass.localize(
"ui.panel.lovelace.editor.strategy.home.add_favorite_entity"
)}
label="Favorite entities"
placeholder="Add favorite entity"
reorder
allow-custom-entity
@value-changed=${this._valueChanged}

View File

@@ -2,7 +2,6 @@ import type {
EntityFilter,
EntityFilterFunc,
} from "../../../../../common/entity/entity_filter";
import type { LocalizeFunc } from "../../../../../common/translations/localize";
export const HOME_SUMMARIES = [
"lights",
@@ -11,16 +10,16 @@ export const HOME_SUMMARIES = [
"media_players",
] as const;
export type HomeSummary = (typeof HOME_SUMMARIES)[number];
export type HomeSummaries = (typeof HOME_SUMMARIES)[number];
export const HOME_SUMMARIES_ICONS: Record<HomeSummary, string> = {
export const HOME_SUMMARIES_ICONS: Record<HomeSummaries, string> = {
lights: "mdi:lamps",
climate: "mdi:home-thermometer",
security: "mdi:security",
media_players: "mdi:multimedia",
};
export const HOME_SUMMARIES_FILTERS: Record<HomeSummary, EntityFilter[]> = {
export const HOME_SUMMARIES_FILTERS: Record<HomeSummaries, EntityFilter[]> = {
lights: [{ domain: "light", entity_category: "none" }],
climate: [
{ domain: "climate", entity_category: "none" },
@@ -91,6 +90,3 @@ export const findEntities = (
return results;
};
export const getSummaryLabel = (localize: LocalizeFunc, summary: HomeSummary) =>
localize(`ui.panel.lovelace.strategy.home.summary_list.${summary}`);

View File

@@ -14,11 +14,10 @@ import type { HeadingCardConfig } from "../../cards/types";
import { computeAreaTileCardConfig } from "../areas/helpers/areas-strategy-helper";
import {
findEntities,
getSummaryLabel,
HOME_SUMMARIES,
HOME_SUMMARIES_FILTERS,
HOME_SUMMARIES_ICONS,
type HomeSummary,
type HomeSummaries,
} from "./helpers/home-summaries";
export interface HomeAreaViewStrategyConfig {
@@ -97,7 +96,7 @@ export class HomeAreaViewStrategy extends ReactiveElement {
acc[summary] = findEntities(areaEntities, filterFunctions);
return acc;
},
{} as Record<HomeSummary, string[]>
{} as Record<HomeSummaries, string[]>
);
const {
@@ -111,11 +110,7 @@ export class HomeAreaViewStrategy extends ReactiveElement {
sections.push({
type: "grid",
cards: [
computeHeadingCard(
getSummaryLabel(hass.localize, "lights"),
HOME_SUMMARIES_ICONS.lights,
"lights"
),
computeHeadingCard("Lights", HOME_SUMMARIES_ICONS.lights, "lights"),
...lights.map(computeTileCard),
],
});
@@ -126,7 +121,7 @@ export class HomeAreaViewStrategy extends ReactiveElement {
type: "grid",
cards: [
computeHeadingCard(
getSummaryLabel(hass.localize, "climate"),
"Climate",
HOME_SUMMARIES_ICONS.climate,
"climate"
),
@@ -140,7 +135,7 @@ export class HomeAreaViewStrategy extends ReactiveElement {
type: "grid",
cards: [
computeHeadingCard(
getSummaryLabel(hass.localize, "security"),
"Security",
HOME_SUMMARIES_ICONS.security,
"security"
),
@@ -154,7 +149,7 @@ export class HomeAreaViewStrategy extends ReactiveElement {
type: "grid",
cards: [
computeHeadingCard(
getSummaryLabel(hass.localize, "media_players"),
"Media players",
HOME_SUMMARIES_ICONS.media_players,
"media-players"
),
@@ -234,11 +229,9 @@ export class HomeAreaViewStrategy extends ReactiveElement {
const device = hass.devices[deviceId];
let heading = "";
if (device) {
heading =
computeDeviceName(device) ||
hass.localize("ui.panel.lovelace.strategy.home.unamed_device");
heading = computeDeviceName(device) || "Unnamed device";
} else {
heading = hass.localize("ui.panel.lovelace.strategy.home.others");
heading = "Others";
}
deviceSections.push({

View File

@@ -12,30 +12,11 @@ import {
} from "../areas/helpers/areas-strategy-helper";
import { getHomeStructure } from "./helpers/home-structure";
import { findEntities, HOME_SUMMARIES_FILTERS } from "./helpers/home-summaries";
import { computeStateName } from "../../../../common/entity/compute_state_name";
import { computeObjectId } from "../../../../common/entity/compute_object_id";
export interface HomeClimateViewStrategyConfig {
type: "home-climate";
}
const createTempHumidBadge = (hass: HomeAssistant, entityId: string) => {
const stateObj = hass.states[entityId];
return {
type: "tile",
entity: entityId,
name: stateObj
? computeStateName(stateObj)
: computeObjectId(entityId).replace(/_/g, " "),
features: [
{
type: "history-chart",
hours_to_show: 3,
},
],
};
};
const processAreasForClimate = (
areaIds: string[],
hass: HomeAssistant,
@@ -65,14 +46,10 @@ const processAreasForClimate = (
});
if (hass.areas[areaId].temperature_entity_id) {
cards.push(
createTempHumidBadge(hass, hass.areas[areaId].temperature_entity_id)
);
cards.push(computeTileCard(hass.areas[areaId].temperature_entity_id));
}
if (hass.areas[areaId].humidity_entity_id) {
cards.push(
createTempHumidBadge(hass, hass.areas[areaId].humidity_entity_id)
);
cards.push(computeTileCard(hass.areas[areaId].humidity_entity_id));
}
for (const entityId of areaEntities) {
@@ -118,10 +95,7 @@ export class HomeClimateViewStrategy extends ReactiveElement {
cards: [
{
type: "heading",
heading:
floorCount > 1
? floor.name
: hass.localize("ui.panel.lovelace.strategy.home.areas"),
heading: floorCount > 1 ? floor.name : "Areas",
},
],
};
@@ -142,10 +116,7 @@ export class HomeClimateViewStrategy extends ReactiveElement {
cards: [
{
type: "heading",
heading:
floorCount > 1
? hass.localize("ui.panel.lovelace.strategy.home.other_areas")
: hass.localize("ui.panel.lovelace.strategy.home.areas"),
heading: floorCount > 1 ? "Other areas" : "Areas",
},
],
};

View File

@@ -6,10 +6,7 @@ import type { LovelaceViewRawConfig } from "../../../../data/lovelace/config/vie
import type { HomeAssistant } from "../../../../types";
import { getAreas } from "../areas/helpers/areas-strategy-helper";
import type { LovelaceStrategyEditor } from "../types";
import {
getSummaryLabel,
HOME_SUMMARIES_ICONS,
} from "./helpers/home-summaries";
import { HOME_SUMMARIES_ICONS } from "./helpers/home-summaries";
import type { HomeAreaViewStrategyConfig } from "./home-area-view-strategy";
import type { HomeMainViewStrategyConfig } from "./home-main-view-strategy";
@@ -63,7 +60,7 @@ export class HomeDashboardStrategy extends ReactiveElement {
});
const lightView = {
title: getSummaryLabel(hass.localize, "lights"),
title: "Lights",
path: "lights",
subview: true,
strategy: {
@@ -73,7 +70,7 @@ export class HomeDashboardStrategy extends ReactiveElement {
} satisfies LovelaceViewRawConfig;
const climateView = {
title: getSummaryLabel(hass.localize, "climate"),
title: "Climate",
path: "climate",
subview: true,
strategy: {
@@ -83,7 +80,7 @@ export class HomeDashboardStrategy extends ReactiveElement {
} satisfies LovelaceViewRawConfig;
const securityView = {
title: getSummaryLabel(hass.localize, "security"),
title: "Security",
path: "security",
subview: true,
strategy: {
@@ -93,7 +90,7 @@ export class HomeDashboardStrategy extends ReactiveElement {
} satisfies LovelaceViewRawConfig;
const mediaPlayersView = {
title: getSummaryLabel(hass.localize, "media_players"),
title: "Media players",
path: "media-players",
subview: true,
strategy: {

View File

@@ -89,10 +89,7 @@ export class HomeLightsViewStrategy extends ReactiveElement {
cards: [
{
type: "heading",
heading:
floorCount > 1
? floor.name
: hass.localize("ui.panel.lovelace.strategy.home.areas"),
heading: floorCount > 1 ? floor.name : "Areas",
},
],
};
@@ -113,10 +110,7 @@ export class HomeLightsViewStrategy extends ReactiveElement {
cards: [
{
type: "heading",
heading:
floorCount > 1
? hass.localize("ui.panel.lovelace.strategy.home.other_areas")
: hass.localize("ui.panel.lovelace.strategy.home.areas"),
heading: floorCount > 1 ? "Other areas" : "Areas",
},
],
};

View File

@@ -15,10 +15,7 @@ import type {
WeatherForecastCardConfig,
} from "../../cards/types";
import { getAreas } from "../areas/helpers/areas-strategy-helper";
import {
getSummaryLabel,
HOME_SUMMARIES_ICONS,
} from "./helpers/home-summaries";
import { HOME_SUMMARIES_ICONS } from "./helpers/home-summaries";
export interface HomeMainViewStrategyConfig {
type: "home-main";
@@ -66,7 +63,7 @@ export class HomeMainViewStrategy extends ReactiveElement {
{
type: "heading",
heading_style: "title",
heading: hass.localize("ui.panel.lovelace.strategy.home.areas"),
heading: "Areas",
},
...areas.map<AreaCardConfig>((area) =>
computeAreaCard(area.area_id, hass)
@@ -111,12 +108,12 @@ export class HomeMainViewStrategy extends ReactiveElement {
cards: [
{
type: "heading",
heading: hass.localize("ui.panel.lovelace.strategy.home.summaries"),
heading: "Summaries",
},
{
type: "button",
icon: HOME_SUMMARIES_ICONS.lights,
name: getSummaryLabel(hass.localize, "lights"),
name: "Lights",
icon_height: "24px",
grid_options: {
rows: 2,
@@ -130,7 +127,7 @@ export class HomeMainViewStrategy extends ReactiveElement {
{
type: "button",
icon: HOME_SUMMARIES_ICONS.climate,
name: getSummaryLabel(hass.localize, "climate"),
name: "Climate",
icon_height: "30px",
grid_options: {
rows: 2,
@@ -144,7 +141,7 @@ export class HomeMainViewStrategy extends ReactiveElement {
{
type: "button",
icon: HOME_SUMMARIES_ICONS.security,
name: getSummaryLabel(hass.localize, "security"),
name: "Security",
icon_height: "30px",
grid_options: {
rows: 2,
@@ -158,7 +155,7 @@ export class HomeMainViewStrategy extends ReactiveElement {
{
type: "button",
icon: HOME_SUMMARIES_ICONS.media_players,
name: getSummaryLabel(hass.localize, "media_players"),
name: "Media Players",
icon_height: "30px",
grid_options: {
rows: 2,
@@ -235,7 +232,7 @@ export class HomeMainViewStrategy extends ReactiveElement {
card: {
type: "markdown",
text_only: true,
content: `## ${hass.localize("ui.panel.lovelace.strategy.home.welcome_user", { user: "{{ user }}" })}`,
content: "## Welcome {{user}}",
} satisfies MarkdownCardConfig,
},
};

View File

@@ -87,10 +87,7 @@ export class HomeMMediaPlayersViewStrategy extends ReactiveElement {
cards: [
{
type: "heading",
heading:
floorCount > 1
? floor.name
: hass.localize("ui.panel.lovelace.strategy.home.areas"),
heading: floorCount > 1 ? floor.name : "Areas",
},
],
};
@@ -111,10 +108,7 @@ export class HomeMMediaPlayersViewStrategy extends ReactiveElement {
cards: [
{
type: "heading",
heading:
floorCount > 1
? hass.localize("ui.panel.lovelace.strategy.home.other_areas")
: hass.localize("ui.panel.lovelace.strategy.home.areas"),
heading: floorCount > 1 ? "Other areas" : "Areas",
},
],
};

View File

@@ -13,8 +13,6 @@ import {
import { getHomeStructure } from "./helpers/home-structure";
import { findEntities, HOME_SUMMARIES_FILTERS } from "./helpers/home-summaries";
import { computeDomain } from "../../../../common/entity/compute_domain";
import { computeStateName } from "../../../../common/entity/compute_state_name";
import { computeObjectId } from "../../../../common/entity/compute_object_id";
export interface HomeSecurityViewStrategyConfig {
type: "home-security";
@@ -27,6 +25,7 @@ const processAreasForSecurity = (
): LovelaceCardConfig[] => {
const cards: LovelaceCardConfig[] = [];
const computeTileCard = computeAreaTileCardConfig(hass, "", false);
const computeTileCardWithFeature = computeAreaTileCardConfig(hass, "", true);
for (const areaId of areaIds) {
const area = hass.areas[areaId];
@@ -49,23 +48,10 @@ const processAreasForSecurity = (
});
for (const entityId of areaEntities) {
const stateObj = hass.states[entityId];
cards.push(
computeDomain(entityId) === "binary_sensor" &&
stateObj?.attributes.device_class === "motion"
? {
type: "tile",
entity: entityId,
name: stateObj
? computeStateName(stateObj)
: computeObjectId(entityId).replace(/_/g, " "),
features: [
{
type: "history-chart",
hours_to_show: 6,
},
],
}
hass.states[entityId]?.attributes.device_class === "motion"
? computeTileCardWithFeature(entityId)
: computeTileCard(entityId)
);
}
@@ -109,10 +95,7 @@ export class HomeSecurityViewStrategy extends ReactiveElement {
cards: [
{
type: "heading",
heading:
floorCount > 1
? floor.name
: hass.localize("ui.panel.lovelace.strategy.home.areas"),
heading: floorCount > 1 ? floor.name : "Areas",
},
],
};
@@ -133,10 +116,7 @@ export class HomeSecurityViewStrategy extends ReactiveElement {
cards: [
{
type: "heading",
heading:
floorCount > 1
? hass.localize("ui.panel.lovelace.strategy.home.other_areas")
: hass.localize("ui.panel.lovelace.strategy.home.areas"),
heading: floorCount > 1 ? "Other areas" : "Areas",
},
],
};

View File

@@ -4109,6 +4109,9 @@
},
"conditions": {
"name": "Conditions",
"header": "And if",
"description": "All conditions added here need to be satisfied for the automation to run. A condition can be satisfied or not at any given time, for example: ''If {user} is home''. You can use building blocks to create more complex conditions.",
"learn_more": "Learn more about conditions",
"add": "Add condition",
"search": "Search condition",
"add_building_block": "Add building block",
@@ -6814,20 +6817,6 @@
},
"other_areas": "Other areas",
"areas": "Areas"
},
"home": {
"summary_list": {
"climate": "Climate",
"lights": "Lights",
"security": "Security",
"media_players": "Media players"
},
"welcome_user": "Welcome {user}",
"summaries": "Summaries",
"areas": "Areas",
"other_areas": "Other areas",
"unamed_device": "Unnamed device",
"others": "Others"
}
},
"cards": {
@@ -7999,7 +7988,10 @@
"label": "Media player playback controls"
},
"media-player-volume-slider": {
"label": "Media player volume slider"
"label": "Media player volume slider",
"min": "Minimum volume",
"max": "Maximum volume",
"step": "Step size"
},
"vacuum-commands": {
"label": "Vacuum commands",
@@ -8187,10 +8179,6 @@
"no_entities": "No entities in this group, the section will not be displayed",
"use_compact_card": "Use compact card",
"use_large_card": "Use large card"
},
"home": {
"favorite_entities": "Favorite entities",
"add_favorite_entity": "Add favorite entity"
}
},
"view": {

178
yarn.lock
View File

@@ -3281,58 +3281,58 @@ __metadata:
languageName: node
linkType: hard
"@module-federation/error-codes@npm:0.18.0":
version: 0.18.0
resolution: "@module-federation/error-codes@npm:0.18.0"
checksum: 10/ccd00f6b2504ec2e685bda6d175ed86df27e21994b36869140a18059595716e9ea7db5d0b516a095891ec9e6c90e702f42a366743df3652bf91ff3bb4f895991
"@module-federation/error-codes@npm:0.17.1":
version: 0.17.1
resolution: "@module-federation/error-codes@npm:0.17.1"
checksum: 10/5f5f02a90a423479c84e4ff4398a3a9e31b66bd545e7c978ecb8a417f33162b86e749356baab14c006e741c9cebae549335a4c99e94ce7ef54210269fdf74f7f
languageName: node
linkType: hard
"@module-federation/runtime-core@npm:0.18.0":
version: 0.18.0
resolution: "@module-federation/runtime-core@npm:0.18.0"
"@module-federation/runtime-core@npm:0.17.1":
version: 0.17.1
resolution: "@module-federation/runtime-core@npm:0.17.1"
dependencies:
"@module-federation/error-codes": "npm:0.18.0"
"@module-federation/sdk": "npm:0.18.0"
checksum: 10/82af795408f2e92bea9c801a2057f1a6ed85eaf131195d5deaa4ef9a6a88db9e2cb851b4416e6e43a841459986b5ebb84e98b4625fb9bbd98cee11929f1ede6b
"@module-federation/error-codes": "npm:0.17.1"
"@module-federation/sdk": "npm:0.17.1"
checksum: 10/b0c945379bde13af84ceb833e3bfe3c8cf11fd265af0ad7640a1506017529458f408a4a3f1bd0f4b5983da71438913d5c25ed25e20908eb1f789bd1483616650
languageName: node
linkType: hard
"@module-federation/runtime-tools@npm:0.18.0":
version: 0.18.0
resolution: "@module-federation/runtime-tools@npm:0.18.0"
"@module-federation/runtime-tools@npm:0.17.1":
version: 0.17.1
resolution: "@module-federation/runtime-tools@npm:0.17.1"
dependencies:
"@module-federation/runtime": "npm:0.18.0"
"@module-federation/webpack-bundler-runtime": "npm:0.18.0"
checksum: 10/c6b1483899865e4c73be0ae77e6e1a5f517798f7ab3b8c6df2bb7ed22463e7a471f68d5f9528b2aff5b45e2db67596805028206f3956aafec5a36dcefb94afd2
"@module-federation/runtime": "npm:0.17.1"
"@module-federation/webpack-bundler-runtime": "npm:0.17.1"
checksum: 10/2e183e357b644dbe015d0e51df3fe601852ca79ffe3a30c582eee7a2050d7600eb3253f5de15e476c60741d0a1dd70add1ade7b5a3537cd2ee12bfee286284ea
languageName: node
linkType: hard
"@module-federation/runtime@npm:0.18.0":
version: 0.18.0
resolution: "@module-federation/runtime@npm:0.18.0"
"@module-federation/runtime@npm:0.17.1":
version: 0.17.1
resolution: "@module-federation/runtime@npm:0.17.1"
dependencies:
"@module-federation/error-codes": "npm:0.18.0"
"@module-federation/runtime-core": "npm:0.18.0"
"@module-federation/sdk": "npm:0.18.0"
checksum: 10/6164597782b21840e3b8f159000338d8e20a817a60909015c11402e9e6442d60d9c3b4b6f25d92d7261011ef1fc0e8caafbb91f25c29b372f28764cbea8ef9eb
"@module-federation/error-codes": "npm:0.17.1"
"@module-federation/runtime-core": "npm:0.17.1"
"@module-federation/sdk": "npm:0.17.1"
checksum: 10/f5405968dff4fa2cf510127701ec1722105f44298fd09eafeecead450b7bb95a05450749157fe2fc39caf6241bec9e45caa9a55375b48e7f195db84799a8df0c
languageName: node
linkType: hard
"@module-federation/sdk@npm:0.18.0":
version: 0.18.0
resolution: "@module-federation/sdk@npm:0.18.0"
checksum: 10/f397dc53c705ad1f1e19530a8ff79116bb5aeeef92a79b3acaaa6140ae4e5784b42e81d1445eabf536c007c9383857f6764506ed725a6352464fe1ce581af89a
"@module-federation/sdk@npm:0.17.1":
version: 0.17.1
resolution: "@module-federation/sdk@npm:0.17.1"
checksum: 10/daaaa49ed900c00a69641130cf673ad5d5b8623d82fb4bd03a67c839a6da760a0a5ae29b836ba66eeb95ee5392e558588ffd987a2c00b05c2b0a7c5039ed042d
languageName: node
linkType: hard
"@module-federation/webpack-bundler-runtime@npm:0.18.0":
version: 0.18.0
resolution: "@module-federation/webpack-bundler-runtime@npm:0.18.0"
"@module-federation/webpack-bundler-runtime@npm:0.17.1":
version: 0.17.1
resolution: "@module-federation/webpack-bundler-runtime@npm:0.17.1"
dependencies:
"@module-federation/runtime": "npm:0.18.0"
"@module-federation/sdk": "npm:0.18.0"
checksum: 10/c80f26e02d497948a0864283bedf13118d5c188ac8165e71edce5da72776091db6da2dc5da5d47a53fbb6914bfbff1ddfce16a6b9c18485a9a41a04bc4060e34
"@module-federation/runtime": "npm:0.17.1"
"@module-federation/sdk": "npm:0.17.1"
checksum: 10/72e5030529dbc53df6271fa78bdb63976d0601fe9fde5105f8a7325e0fa296bc35277b9b084e52995cd314b89e12d33f8b869c1d63a13231c2948d4c741e72fd
languageName: node
linkType: hard
@@ -3990,92 +3990,92 @@ __metadata:
languageName: node
linkType: hard
"@rspack/binding-darwin-arm64@npm:1.5.1":
version: 1.5.1
resolution: "@rspack/binding-darwin-arm64@npm:1.5.1"
"@rspack/binding-darwin-arm64@npm:1.4.11":
version: 1.4.11
resolution: "@rspack/binding-darwin-arm64@npm:1.4.11"
conditions: os=darwin & cpu=arm64
languageName: node
linkType: hard
"@rspack/binding-darwin-x64@npm:1.5.1":
version: 1.5.1
resolution: "@rspack/binding-darwin-x64@npm:1.5.1"
"@rspack/binding-darwin-x64@npm:1.4.11":
version: 1.4.11
resolution: "@rspack/binding-darwin-x64@npm:1.4.11"
conditions: os=darwin & cpu=x64
languageName: node
linkType: hard
"@rspack/binding-linux-arm64-gnu@npm:1.5.1":
version: 1.5.1
resolution: "@rspack/binding-linux-arm64-gnu@npm:1.5.1"
"@rspack/binding-linux-arm64-gnu@npm:1.4.11":
version: 1.4.11
resolution: "@rspack/binding-linux-arm64-gnu@npm:1.4.11"
conditions: os=linux & cpu=arm64 & libc=glibc
languageName: node
linkType: hard
"@rspack/binding-linux-arm64-musl@npm:1.5.1":
version: 1.5.1
resolution: "@rspack/binding-linux-arm64-musl@npm:1.5.1"
"@rspack/binding-linux-arm64-musl@npm:1.4.11":
version: 1.4.11
resolution: "@rspack/binding-linux-arm64-musl@npm:1.4.11"
conditions: os=linux & cpu=arm64 & libc=musl
languageName: node
linkType: hard
"@rspack/binding-linux-x64-gnu@npm:1.5.1":
version: 1.5.1
resolution: "@rspack/binding-linux-x64-gnu@npm:1.5.1"
"@rspack/binding-linux-x64-gnu@npm:1.4.11":
version: 1.4.11
resolution: "@rspack/binding-linux-x64-gnu@npm:1.4.11"
conditions: os=linux & cpu=x64 & libc=glibc
languageName: node
linkType: hard
"@rspack/binding-linux-x64-musl@npm:1.5.1":
version: 1.5.1
resolution: "@rspack/binding-linux-x64-musl@npm:1.5.1"
"@rspack/binding-linux-x64-musl@npm:1.4.11":
version: 1.4.11
resolution: "@rspack/binding-linux-x64-musl@npm:1.4.11"
conditions: os=linux & cpu=x64 & libc=musl
languageName: node
linkType: hard
"@rspack/binding-wasm32-wasi@npm:1.5.1":
version: 1.5.1
resolution: "@rspack/binding-wasm32-wasi@npm:1.5.1"
"@rspack/binding-wasm32-wasi@npm:1.4.11":
version: 1.4.11
resolution: "@rspack/binding-wasm32-wasi@npm:1.4.11"
dependencies:
"@napi-rs/wasm-runtime": "npm:^1.0.1"
conditions: cpu=wasm32
languageName: node
linkType: hard
"@rspack/binding-win32-arm64-msvc@npm:1.5.1":
version: 1.5.1
resolution: "@rspack/binding-win32-arm64-msvc@npm:1.5.1"
"@rspack/binding-win32-arm64-msvc@npm:1.4.11":
version: 1.4.11
resolution: "@rspack/binding-win32-arm64-msvc@npm:1.4.11"
conditions: os=win32 & cpu=arm64
languageName: node
linkType: hard
"@rspack/binding-win32-ia32-msvc@npm:1.5.1":
version: 1.5.1
resolution: "@rspack/binding-win32-ia32-msvc@npm:1.5.1"
"@rspack/binding-win32-ia32-msvc@npm:1.4.11":
version: 1.4.11
resolution: "@rspack/binding-win32-ia32-msvc@npm:1.4.11"
conditions: os=win32 & cpu=ia32
languageName: node
linkType: hard
"@rspack/binding-win32-x64-msvc@npm:1.5.1":
version: 1.5.1
resolution: "@rspack/binding-win32-x64-msvc@npm:1.5.1"
"@rspack/binding-win32-x64-msvc@npm:1.4.11":
version: 1.4.11
resolution: "@rspack/binding-win32-x64-msvc@npm:1.4.11"
conditions: os=win32 & cpu=x64
languageName: node
linkType: hard
"@rspack/binding@npm:1.5.1":
version: 1.5.1
resolution: "@rspack/binding@npm:1.5.1"
"@rspack/binding@npm:1.4.11":
version: 1.4.11
resolution: "@rspack/binding@npm:1.4.11"
dependencies:
"@rspack/binding-darwin-arm64": "npm:1.5.1"
"@rspack/binding-darwin-x64": "npm:1.5.1"
"@rspack/binding-linux-arm64-gnu": "npm:1.5.1"
"@rspack/binding-linux-arm64-musl": "npm:1.5.1"
"@rspack/binding-linux-x64-gnu": "npm:1.5.1"
"@rspack/binding-linux-x64-musl": "npm:1.5.1"
"@rspack/binding-wasm32-wasi": "npm:1.5.1"
"@rspack/binding-win32-arm64-msvc": "npm:1.5.1"
"@rspack/binding-win32-ia32-msvc": "npm:1.5.1"
"@rspack/binding-win32-x64-msvc": "npm:1.5.1"
"@rspack/binding-darwin-arm64": "npm:1.4.11"
"@rspack/binding-darwin-x64": "npm:1.4.11"
"@rspack/binding-linux-arm64-gnu": "npm:1.4.11"
"@rspack/binding-linux-arm64-musl": "npm:1.4.11"
"@rspack/binding-linux-x64-gnu": "npm:1.4.11"
"@rspack/binding-linux-x64-musl": "npm:1.4.11"
"@rspack/binding-wasm32-wasi": "npm:1.4.11"
"@rspack/binding-win32-arm64-msvc": "npm:1.4.11"
"@rspack/binding-win32-ia32-msvc": "npm:1.4.11"
"@rspack/binding-win32-x64-msvc": "npm:1.4.11"
dependenciesMeta:
"@rspack/binding-darwin-arm64":
optional: true
@@ -4097,23 +4097,23 @@ __metadata:
optional: true
"@rspack/binding-win32-x64-msvc":
optional: true
checksum: 10/a6756a35bda55fd9e21b1ce142ca18e228d92832dc213027a19314981f8f12e6510dd862a9724ee96dee61755b3dd30ce73b2bb117d150e9f5ce73ba8fe4b57a
checksum: 10/8bb94774204f41888ff442afec06f019d008abba79964b74d566acf64f7216a148a1842f90c44b3bf680e69b697d8e5cd0f1cca6fd0b8a94df5f97c2a3f05510
languageName: node
linkType: hard
"@rspack/core@npm:1.5.1":
version: 1.5.1
resolution: "@rspack/core@npm:1.5.1"
"@rspack/core@npm:1.4.11":
version: 1.4.11
resolution: "@rspack/core@npm:1.4.11"
dependencies:
"@module-federation/runtime-tools": "npm:0.18.0"
"@rspack/binding": "npm:1.5.1"
"@module-federation/runtime-tools": "npm:0.17.1"
"@rspack/binding": "npm:1.4.11"
"@rspack/lite-tapable": "npm:1.0.1"
peerDependencies:
"@swc/helpers": ">=0.5.1"
peerDependenciesMeta:
"@swc/helpers":
optional: true
checksum: 10/b7a6269d5bdbcad140d172ebe951f4693711573d4f38e4c676c250a9cc6c1bdf602ad5187eeacc07ff12b74d510b746c92e3f112c8ab4dca46846c595d2876b0
checksum: 10/77d463bd90feb2d24f7bc56df198f0b7ad310a9eb676070eac8d78014d151e783943c5b44c64700a51a36708c626a341eeaa9b3287e358616d09dfe25ab04e77
languageName: node
linkType: hard
@@ -9377,7 +9377,7 @@ __metadata:
"@octokit/rest": "npm:22.0.0"
"@replit/codemirror-indentation-markers": "npm:6.5.3"
"@rsdoctor/rspack-plugin": "npm:1.2.3"
"@rspack/core": "npm:1.5.1"
"@rspack/core": "npm:1.4.11"
"@rspack/dev-server": "npm:1.1.4"
"@shoelace-style/shoelace": "npm:2.20.1"
"@swc/helpers": "npm:0.5.17"
@@ -9466,7 +9466,7 @@ __metadata:
lodash.template: "npm:4.5.0"
luxon: "npm:3.7.1"
map-stream: "npm:0.0.7"
marked: "npm:16.2.1"
marked: "npm:16.2.0"
memoize-one: "npm:6.0.0"
node-vibrant: "npm:4.0.3"
object-hash: "npm:3.0.0"
@@ -11137,12 +11137,12 @@ __metadata:
languageName: node
linkType: hard
"marked@npm:16.2.1":
version: 16.2.1
resolution: "marked@npm:16.2.1"
"marked@npm:16.2.0":
version: 16.2.0
resolution: "marked@npm:16.2.0"
bin:
marked: bin/marked.js
checksum: 10/67e911a7dd416869649dee18dc4a9683c0ccd8e72ba0fee3b3f578f857416e69780013e9d63762c600e6f9cf997c5af9fa0507a2053f8e65d39c5459c245c0cd
checksum: 10/0a73dcfbe500514d2f1106da99708beed8a31de586e2826e1aa47ca0e0a4850b1e9598569b09d5366d4f4dee2d279a13f32616ed1ee75c832068eb7dd660f66f
languageName: node
linkType: hard