mirror of
https://github.com/home-assistant/frontend.git
synced 2025-08-20 14:49:27 +00:00
Compare commits
139 Commits
20250509.0
...
auto-jsdoc
Author | SHA1 | Date | |
---|---|---|---|
![]() |
28e3c75ff4 | ||
![]() |
b2ec3c8c37 | ||
![]() |
fe37f8fad5 | ||
![]() |
785929b370 | ||
![]() |
55cf7e635d | ||
![]() |
4b270eb444 | ||
![]() |
d0e55719d1 | ||
![]() |
87f9397643 | ||
![]() |
910e7e10a7 | ||
![]() |
e1b9b47ac7 | ||
![]() |
89e04fcc45 | ||
![]() |
93f2e75fc9 | ||
![]() |
6c671d398f | ||
![]() |
2e5c6a4d3f | ||
![]() |
04e736a51e | ||
![]() |
ec3fdc0ea7 | ||
![]() |
a7a8c25d24 | ||
![]() |
60d457c3d9 | ||
![]() |
a58b1e636d | ||
![]() |
c46368b141 | ||
![]() |
f67e7ae081 | ||
![]() |
0032c5508e | ||
![]() |
036df78de8 | ||
![]() |
617a6ba938 | ||
![]() |
76b9063aec | ||
![]() |
60c1d0a556 | ||
![]() |
193caec2df | ||
![]() |
42c8d132bf | ||
![]() |
0311a7c976 | ||
![]() |
40ffd50b8a | ||
![]() |
334991902a | ||
![]() |
c968266065 | ||
![]() |
d4fc0318f7 | ||
![]() |
8a0d3baf67 | ||
![]() |
8fc55cb6e2 | ||
![]() |
d6ebd9bfc4 | ||
![]() |
15ae37d077 | ||
![]() |
461d5eb687 | ||
![]() |
3058fcad46 | ||
![]() |
06bd1ae4cd | ||
![]() |
00733357a1 | ||
![]() |
665c971822 | ||
![]() |
eff5471dd1 | ||
![]() |
4fba9c3c0a | ||
![]() |
0b32b51e2f | ||
![]() |
6370b0b8e5 | ||
![]() |
681518f443 | ||
![]() |
9f5b89978d | ||
![]() |
130839ee7b | ||
![]() |
ba4ec960c8 | ||
![]() |
6692d9c6aa | ||
![]() |
4d2d94c54f | ||
![]() |
d59c6612c6 | ||
![]() |
498f158253 | ||
![]() |
b8026ccf46 | ||
![]() |
84def48222 | ||
![]() |
cea0ac02fe | ||
![]() |
e1b099e88b | ||
![]() |
d571ef3f18 | ||
![]() |
c8cffef647 | ||
![]() |
6b568307a4 | ||
![]() |
1b501907f1 | ||
![]() |
c7e79998a4 | ||
![]() |
03ccf014d9 | ||
![]() |
ab41bdb87d | ||
![]() |
821a0bc418 | ||
![]() |
6d931b9e37 | ||
![]() |
b823a3b139 | ||
![]() |
47c9a407e6 | ||
![]() |
c0ba48beb6 | ||
![]() |
075e1df204 | ||
![]() |
22c57853b4 | ||
![]() |
fe824062a5 | ||
![]() |
92bf9b4979 | ||
![]() |
ac616a4d3d | ||
![]() |
1aa1bfda2c | ||
![]() |
38a5035d68 | ||
![]() |
042cd0d3a3 | ||
![]() |
00d708fbd4 | ||
![]() |
852278e8aa | ||
![]() |
15dcdffe55 | ||
![]() |
0729aaacb8 | ||
![]() |
92b8cd8f45 | ||
![]() |
ad8d3dd598 | ||
![]() |
d618c25095 | ||
![]() |
83289bdd41 | ||
![]() |
c7882f3926 | ||
![]() |
7434b12d9f | ||
![]() |
9081441d95 | ||
![]() |
d63f610023 | ||
![]() |
e069875432 | ||
![]() |
91026b0986 | ||
![]() |
4ec5fbc9a4 | ||
![]() |
fb3a59272d | ||
![]() |
c49b0803cd | ||
![]() |
9155c85509 | ||
![]() |
9d74cd7561 | ||
![]() |
22ddcca954 | ||
![]() |
8f422357f1 | ||
![]() |
44f5f7bdb5 | ||
![]() |
83819a9be0 | ||
![]() |
3c9dce20e2 | ||
![]() |
a19e7002ea | ||
![]() |
75608db9b8 | ||
![]() |
08f30b714b | ||
![]() |
9983129e26 | ||
![]() |
40fe62c2ec | ||
![]() |
d7660370ab | ||
![]() |
bdad76937e | ||
![]() |
d2822308ec | ||
![]() |
99b94e799d | ||
![]() |
1fb28df1a6 | ||
![]() |
b4e8c56f58 | ||
![]() |
17cc63deba | ||
![]() |
b4f1c8755d | ||
![]() |
b0d4c699db | ||
![]() |
c07bf68161 | ||
![]() |
d1a0eaece5 | ||
![]() |
f608783551 | ||
![]() |
dddba58d38 | ||
![]() |
ebc16d6520 | ||
![]() |
4ed8ecad01 | ||
![]() |
c26fb1713d | ||
![]() |
2b7b17625e | ||
![]() |
cd3e4f55e2 | ||
![]() |
1c12aea8f6 | ||
![]() |
3722f971ca | ||
![]() |
409f665641 | ||
![]() |
5b3b17ef6d | ||
![]() |
05b49e8c80 | ||
![]() |
2dbdbb4b64 | ||
![]() |
a825b632bf | ||
![]() |
f8d706277d | ||
![]() |
221bc732fb | ||
![]() |
055c18463c | ||
![]() |
ddd51ff097 | ||
![]() |
55c75096d0 | ||
![]() |
fd3502f3bc | ||
![]() |
7d6bec01ae |
@@ -1,18 +0,0 @@
|
||||
diff --git a/dist/hls.light.mjs b/dist/hls.light.mjs
|
||||
index eed9d788fafdb159975e1a2eb08ac88ba9c9ac33..ace881935e6665946f1c8110ebd2f739cde4427e 100644
|
||||
--- a/dist/hls.light.mjs
|
||||
+++ b/dist/hls.light.mjs
|
||||
@@ -20523,9 +20523,9 @@ class Hls {
|
||||
}
|
||||
Hls.defaultConfig = void 0;
|
||||
|
||||
-var KeySystemFormats = empty.KeySystemFormats;
|
||||
-var KeySystems = empty.KeySystems;
|
||||
-var SubtitleStreamController = empty.SubtitleStreamController;
|
||||
-var TimelineController = empty.TimelineController;
|
||||
+var KeySystemFormats = empty;
|
||||
+var KeySystems = empty;
|
||||
+var SubtitleStreamController = empty;
|
||||
+var TimelineController = empty;
|
||||
export { AbrController, AttrList, Cues as AudioStreamController, Cues as AudioTrackController, BasePlaylistController, BaseSegment, BaseStreamController, BufferController, Cues as CMCDController, CapLevelController, ChunkMetadata, ContentSteeringController, DateRange, Cues as EMEController, ErrorActionFlags, ErrorController, ErrorDetails, ErrorTypes, Events, FPSController, Fragment, Hls, HlsSkip, HlsUrlParameters, KeySystemFormats, KeySystems, Level, LevelDetails, LevelKey, LoadStats, MetadataSchema, NetworkErrorAction, Part, PlaylistLevelType, SubtitleStreamController, Cues as SubtitleTrackController, TimelineController, Hls as default, getMediaSource, isMSESupported, isSupported };
|
||||
//# sourceMappingURL=hls.light.mjs.map
|
@@ -3,6 +3,9 @@ import { glob } from "glob";
|
||||
import gulp from "gulp";
|
||||
import yaml from "js-yaml";
|
||||
import { marked } from "marked";
|
||||
import ts from "typescript";
|
||||
import { create } from "@custom-elements-manifest/analyzer";
|
||||
import { litPlugin } from "@custom-elements-manifest/analyzer/src/features/framework-plugins/lit/lit.js";
|
||||
import path from "path";
|
||||
import paths from "../paths.cjs";
|
||||
import "./clean.js";
|
||||
@@ -13,6 +16,28 @@ import "./service-worker.js";
|
||||
import "./translations.js";
|
||||
import "./rspack.js";
|
||||
|
||||
gulp.task("generate-component-docs", async function generateComponentDocs() {
|
||||
const filePaths = ["src/components/ha-alert.ts"];
|
||||
|
||||
const modules = await Promise.all(
|
||||
filePaths.map(async (file) => {
|
||||
const filePath = path.resolve(file);
|
||||
console.log(`Reading ${file} -> ${filePath}`);
|
||||
const source = fs.readFileSync(filePath).toString();
|
||||
|
||||
return ts.createSourceFile(file, source, ts.ScriptTarget.ES2015, true);
|
||||
})
|
||||
);
|
||||
|
||||
const manifest = create({
|
||||
modules,
|
||||
plugins: litPlugin(),
|
||||
context: { dev: true },
|
||||
});
|
||||
|
||||
console.log(manifest);
|
||||
});
|
||||
|
||||
gulp.task("gather-gallery-pages", async function gatherPages() {
|
||||
const pageDir = path.resolve(paths.gallery_dir, "src/pages");
|
||||
const files = await glob(path.resolve(pageDir, "**/*"));
|
||||
|
@@ -302,7 +302,7 @@ export class HcConnect extends LitElement {
|
||||
}
|
||||
.error {
|
||||
color: red;
|
||||
font-weight: bold;
|
||||
font-weight: var(--ha-font-weight-bold);
|
||||
}
|
||||
|
||||
.error a {
|
||||
|
@@ -86,7 +86,7 @@ class HcLayout extends LitElement {
|
||||
.card-header {
|
||||
color: var(--ha-card-header-color, var(--primary-text-color));
|
||||
font-family: var(--ha-card-header-font-family, inherit);
|
||||
font-size: var(--ha-card-header-font-size, 24px);
|
||||
font-size: var(--ha-card-header-font-size, var(--ha-font-size-2xl));
|
||||
letter-spacing: -0.012em;
|
||||
line-height: 32px;
|
||||
padding: 24px 16px 16px;
|
||||
@@ -98,7 +98,7 @@ class HcLayout extends LitElement {
|
||||
border-radius: 4px 4px 0 0;
|
||||
}
|
||||
.subtitle {
|
||||
font-size: 14px;
|
||||
font-size: var(--ha-font-size-m);
|
||||
color: var(--secondary-text-color);
|
||||
line-height: initial;
|
||||
}
|
||||
@@ -113,7 +113,7 @@ class HcLayout extends LitElement {
|
||||
}
|
||||
|
||||
:host ::slotted(.section-header) {
|
||||
font-weight: 500;
|
||||
font-weight: var(--ha-font-weight-medium);
|
||||
padding: 4px 16px;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
@@ -135,7 +135,7 @@ class HcLayout extends LitElement {
|
||||
|
||||
.footer {
|
||||
text-align: center;
|
||||
font-size: 12px;
|
||||
font-size: var(--ha-font-size-s);
|
||||
padding: 8px 0 24px;
|
||||
color: var(--secondary-text-color);
|
||||
}
|
||||
|
@@ -29,7 +29,7 @@ class HcLaunchScreen extends LitElement {
|
||||
display: block;
|
||||
height: 100vh;
|
||||
background-color: #f2f4f9;
|
||||
font-size: 24px;
|
||||
font-size: var(--ha-font-size-2xl);
|
||||
}
|
||||
.container {
|
||||
display: flex;
|
||||
|
186
custom-elements.json
Normal file
186
custom-elements.json
Normal file
@@ -0,0 +1,186 @@
|
||||
{
|
||||
"schemaVersion": "1.0.0",
|
||||
"readme": "",
|
||||
"modules": [
|
||||
{
|
||||
"kind": "javascript-module",
|
||||
"path": "src/components/ha-alert.ts",
|
||||
"declarations": [
|
||||
{
|
||||
"kind": "class",
|
||||
"description": "A custom alert component for displaying messages with various alert types.",
|
||||
"name": "HaAlert",
|
||||
"cssProperties": [
|
||||
{
|
||||
"description": "The color used for \"info\" alerts.",
|
||||
"name": "--info-color"
|
||||
},
|
||||
{
|
||||
"description": "The color used for \"warning\" alerts.",
|
||||
"name": "--warning-color"
|
||||
},
|
||||
{
|
||||
"description": "The color used for \"error\" alerts.",
|
||||
"name": "--error-color"
|
||||
},
|
||||
{
|
||||
"description": "The color used for \"success\" alerts.",
|
||||
"name": "--success-color"
|
||||
},
|
||||
{
|
||||
"description": "The primary text color used in the alert.",
|
||||
"name": "--primary-text-color"
|
||||
}
|
||||
],
|
||||
"cssParts": [
|
||||
{
|
||||
"description": "The container for the alert.",
|
||||
"name": "issue-type"
|
||||
},
|
||||
{
|
||||
"description": "The container for the alert icon.",
|
||||
"name": "icon"
|
||||
},
|
||||
{
|
||||
"description": "The container for the alert content.",
|
||||
"name": "content"
|
||||
},
|
||||
{
|
||||
"description": "The container for the alert actions.",
|
||||
"name": "action"
|
||||
},
|
||||
{
|
||||
"description": "The container for the alert title.",
|
||||
"name": "title"
|
||||
}
|
||||
],
|
||||
"slots": [
|
||||
{
|
||||
"description": "The main content of the alert.",
|
||||
"name": ""
|
||||
},
|
||||
{
|
||||
"description": "Slot for providing a custom icon for the alert.",
|
||||
"name": "icon"
|
||||
},
|
||||
{
|
||||
"description": "Slot for providing custom actions or buttons for the alert.",
|
||||
"name": "action"
|
||||
}
|
||||
],
|
||||
"members": [
|
||||
{
|
||||
"kind": "field",
|
||||
"name": "title",
|
||||
"type": {
|
||||
"text": "string"
|
||||
},
|
||||
"privacy": "public",
|
||||
"default": "\"\"",
|
||||
"description": "The title of the alert. Defaults to an empty string.",
|
||||
"attribute": "title"
|
||||
},
|
||||
{
|
||||
"kind": "field",
|
||||
"name": "alertType",
|
||||
"type": {
|
||||
"text": "\"info\" | \"warning\" | \"error\" | \"success\""
|
||||
},
|
||||
"privacy": "public",
|
||||
"default": "\"info\"",
|
||||
"description": "The type of alert to display. Defaults to \"info\". Determines the styling and icon used.",
|
||||
"attribute": "alert-type"
|
||||
},
|
||||
{
|
||||
"kind": "field",
|
||||
"name": "dismissable",
|
||||
"type": {
|
||||
"text": "boolean"
|
||||
},
|
||||
"privacy": "public",
|
||||
"default": "false",
|
||||
"description": "Whether the alert can be dismissed. Defaults to `false`. If `true`, a dismiss button is displayed.",
|
||||
"attribute": "dismissable"
|
||||
},
|
||||
{
|
||||
"kind": "field",
|
||||
"name": "narrow",
|
||||
"type": {
|
||||
"text": "boolean"
|
||||
},
|
||||
"privacy": "public",
|
||||
"default": "false",
|
||||
"description": "Whether the alert should use a narrow layout. Defaults to `false`.",
|
||||
"attribute": "narrow"
|
||||
},
|
||||
{
|
||||
"kind": "method",
|
||||
"name": "_dismissClicked",
|
||||
"privacy": "private"
|
||||
}
|
||||
],
|
||||
"events": [
|
||||
{
|
||||
"description": "Fired when the dismiss button is clicked.",
|
||||
"name": "alert-dismissed-clicked"
|
||||
}
|
||||
],
|
||||
"attributes": [
|
||||
{
|
||||
"name": "title",
|
||||
"type": {
|
||||
"text": "string"
|
||||
},
|
||||
"default": "\"\"",
|
||||
"description": "The title of the alert. Defaults to an empty string.",
|
||||
"fieldName": "title"
|
||||
},
|
||||
{
|
||||
"name": "alert-type",
|
||||
"type": {
|
||||
"text": "\"info\" | \"warning\" | \"error\" | \"success\""
|
||||
},
|
||||
"default": "\"info\"",
|
||||
"description": "The type of alert to display. Defaults to \"info\". Determines the styling and icon used.",
|
||||
"fieldName": "alertType"
|
||||
},
|
||||
{
|
||||
"name": "dismissable",
|
||||
"type": {
|
||||
"text": "boolean"
|
||||
},
|
||||
"default": "false",
|
||||
"description": "Whether the alert can be dismissed. Defaults to `false`. If `true`, a dismiss button is displayed.",
|
||||
"fieldName": "dismissable"
|
||||
},
|
||||
{
|
||||
"name": "narrow",
|
||||
"type": {
|
||||
"text": "boolean"
|
||||
},
|
||||
"default": "false",
|
||||
"description": "Whether the alert should use a narrow layout. Defaults to `false`.",
|
||||
"fieldName": "narrow"
|
||||
}
|
||||
],
|
||||
"superclass": {
|
||||
"name": "LitElement",
|
||||
"package": "lit"
|
||||
},
|
||||
"tagName": "ha-alert",
|
||||
"customElement": true
|
||||
}
|
||||
],
|
||||
"exports": [
|
||||
{
|
||||
"kind": "custom-element-definition",
|
||||
"name": "ha-alert",
|
||||
"declaration": {
|
||||
"name": "HaAlert",
|
||||
"module": "src/components/ha-alert.ts"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
@@ -42,7 +42,7 @@ class PageDescription extends HaMarkdown {
|
||||
padding-bottom: 8px;
|
||||
}
|
||||
.subtitle {
|
||||
font-size: 18px;
|
||||
font-size: var(--ha-font-size-l);
|
||||
line-height: 24px;
|
||||
}
|
||||
.root {
|
||||
|
@@ -34,7 +34,7 @@ class HaDemoOptions extends LitElement {
|
||||
height: 64px;
|
||||
padding: 0 16px;
|
||||
pointer-events: none;
|
||||
font-size: 20px;
|
||||
font-size: var(--ha-font-size-xl);
|
||||
}
|
||||
`,
|
||||
];
|
||||
|
@@ -250,8 +250,8 @@ class HaGallery extends LitElement {
|
||||
}
|
||||
|
||||
.page-footer .header {
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
font-size: var(--ha-font-size-l);
|
||||
font-weight: var(--ha-font-weight-medium);
|
||||
line-height: 28px;
|
||||
text-align: center;
|
||||
}
|
||||
|
@@ -150,7 +150,7 @@ export class DemoHaBarButton extends LitElement {
|
||||
margin: 0;
|
||||
}
|
||||
label {
|
||||
font-weight: 600;
|
||||
font-weight: var(--ha-font-weight-bold);
|
||||
}
|
||||
.custom {
|
||||
--control-button-icon-color: var(--primary-color);
|
||||
|
@@ -86,7 +86,7 @@ export class DemoHarControlNumberButtons extends LitElement {
|
||||
margin: 0;
|
||||
}
|
||||
label {
|
||||
font-weight: 600;
|
||||
font-weight: var(--ha-font-weight-bold);
|
||||
}
|
||||
.custom {
|
||||
color: #2196f3;
|
||||
|
@@ -125,7 +125,7 @@ export class DemoHaControlSelectMenu extends LitElement {
|
||||
margin: 0;
|
||||
}
|
||||
label {
|
||||
font-weight: 600;
|
||||
font-weight: var(--ha-font-weight-bold);
|
||||
}
|
||||
.custom {
|
||||
--control-button-icon-color: var(--primary-color);
|
||||
|
@@ -181,7 +181,7 @@ export class DemoHaControlSelect extends LitElement {
|
||||
margin: 0;
|
||||
}
|
||||
label {
|
||||
font-weight: 600;
|
||||
font-weight: var(--ha-font-weight-bold);
|
||||
}
|
||||
.custom {
|
||||
--mdc-icon-size: 24px;
|
||||
|
@@ -144,7 +144,7 @@ export class DemoHaBarSlider extends LitElement {
|
||||
margin: 0;
|
||||
}
|
||||
label {
|
||||
font-weight: 600;
|
||||
font-weight: var(--ha-font-weight-bold);
|
||||
}
|
||||
.custom {
|
||||
--control-slider-color: #ffcf4c;
|
||||
|
@@ -112,7 +112,7 @@ export class DemoHaControlSwitch extends LitElement {
|
||||
margin: 0;
|
||||
}
|
||||
label {
|
||||
font-weight: 600;
|
||||
font-weight: var(--ha-font-weight-bold);
|
||||
}
|
||||
.custom {
|
||||
--control-switch-on-color: var(--green-color);
|
||||
|
@@ -105,8 +105,8 @@ export class DemoHaHsColorPicker extends LitElement {
|
||||
width: 400px;
|
||||
}
|
||||
.value {
|
||||
font-size: 22px;
|
||||
font-weight: bold;
|
||||
font-size: var(--ha-font-size-xl);
|
||||
font-weight: var(--ha-font-weight-bold);
|
||||
margin: 0 0 12px 0;
|
||||
}
|
||||
`;
|
||||
|
@@ -123,7 +123,7 @@ export class DemoHaSelectBox extends LitElement {
|
||||
margin: 0;
|
||||
}
|
||||
label {
|
||||
font-weight: 600;
|
||||
font-weight: var(--ha-font-weight-bold);
|
||||
margin-bottom: 8px;
|
||||
display: block;
|
||||
}
|
||||
|
@@ -1,6 +1,7 @@
|
||||
import type { TemplateResult } from "lit";
|
||||
import { html, css, LitElement } from "lit";
|
||||
import { css, html, LitElement } from "lit";
|
||||
import { customElement, property } from "lit/decorators";
|
||||
import { applyThemesOnElement } from "../../../../src/common/dom/apply_themes_on_element";
|
||||
import "../../../../src/components/ha-bar";
|
||||
import "../../../../src/components/ha-card";
|
||||
import "../../../../src/components/ha-spinner";
|
||||
@@ -11,29 +12,66 @@ export class DemoHaSpinner extends LitElement {
|
||||
@property({ attribute: false }) hass!: HomeAssistant;
|
||||
|
||||
protected render(): TemplateResult {
|
||||
return html`<ha-card header="Basic spinner">
|
||||
<div class="card-content">
|
||||
<ha-spinner></ha-spinner></div
|
||||
></ha-card>
|
||||
<ha-card header="Different spinner sizes">
|
||||
<div class="card-content">
|
||||
<ha-spinner size="tiny"></ha-spinner>
|
||||
<ha-spinner size="small"></ha-spinner>
|
||||
<ha-spinner size="medium"></ha-spinner>
|
||||
<ha-spinner size="large"></ha-spinner></div
|
||||
></ha-card>
|
||||
<ha-card header="Spinner with an aria-label">
|
||||
<div class="card-content">
|
||||
<ha-spinner aria-label="Doing something..."></ha-spinner>
|
||||
<ha-spinner .ariaLabel=${"Doing something..."}></ha-spinner></div
|
||||
></ha-card>`;
|
||||
return html`
|
||||
${["light", "dark"].map(
|
||||
(mode) => html`
|
||||
<div class=${mode}>
|
||||
<ha-card header="ha-badge ${mode} demo">
|
||||
<div class="card-content">
|
||||
<ha-spinner></ha-spinner>
|
||||
<ha-spinner size="tiny"></ha-spinner>
|
||||
<ha-spinner size="small"></ha-spinner>
|
||||
<ha-spinner size="medium"></ha-spinner>
|
||||
<ha-spinner size="large"></ha-spinner>
|
||||
<ha-spinner aria-label="Doing something..."></ha-spinner>
|
||||
<ha-spinner .ariaLabel=${"Doing something..."}></ha-spinner>
|
||||
</div>
|
||||
</ha-card>
|
||||
</div>
|
||||
`
|
||||
)}
|
||||
`;
|
||||
}
|
||||
|
||||
firstUpdated(changedProps) {
|
||||
super.firstUpdated(changedProps);
|
||||
applyThemesOnElement(
|
||||
this.shadowRoot!.querySelector(".dark"),
|
||||
{
|
||||
default_theme: "default",
|
||||
default_dark_theme: "default",
|
||||
themes: {},
|
||||
darkMode: true,
|
||||
theme: "default",
|
||||
},
|
||||
undefined,
|
||||
undefined,
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
static styles = css`
|
||||
:host {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
.dark,
|
||||
.light {
|
||||
display: block;
|
||||
background-color: var(--primary-background-color);
|
||||
padding: 0 50px;
|
||||
margin: 16px;
|
||||
border-radius: 8px;
|
||||
}
|
||||
ha-card {
|
||||
max-width: 600px;
|
||||
margin: 24px auto;
|
||||
}
|
||||
.card-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
gap: 24px;
|
||||
}
|
||||
`;
|
||||
}
|
||||
|
||||
|
@@ -106,7 +106,7 @@ export class DemoDateTimeDateTimeNumeric extends LitElement {
|
||||
margin: 12px auto;
|
||||
}
|
||||
.header {
|
||||
font-weight: bold;
|
||||
font-weight: var(--ha-font-weight-bold);
|
||||
}
|
||||
.center {
|
||||
text-align: center;
|
||||
|
@@ -106,7 +106,7 @@ export class DemoDateTimeDateTimeSeconds extends LitElement {
|
||||
margin: 12px auto;
|
||||
}
|
||||
.header {
|
||||
font-weight: bold;
|
||||
font-weight: var(--ha-font-weight-bold);
|
||||
}
|
||||
.center {
|
||||
text-align: center;
|
||||
|
@@ -106,7 +106,7 @@ export class DemoDateTimeDateTimeShortYear extends LitElement {
|
||||
margin: 12px auto;
|
||||
}
|
||||
.header {
|
||||
font-weight: bold;
|
||||
font-weight: var(--ha-font-weight-bold);
|
||||
}
|
||||
.center {
|
||||
text-align: center;
|
||||
|
@@ -106,7 +106,7 @@ export class DemoDateTimeDateTimeShort extends LitElement {
|
||||
margin: 12px auto;
|
||||
}
|
||||
.header {
|
||||
font-weight: bold;
|
||||
font-weight: var(--ha-font-weight-bold);
|
||||
}
|
||||
.center {
|
||||
text-align: center;
|
||||
|
@@ -106,7 +106,7 @@ export class DemoDateTimeDateTime extends LitElement {
|
||||
margin: 12px auto;
|
||||
}
|
||||
.header {
|
||||
font-weight: bold;
|
||||
font-weight: var(--ha-font-weight-bold);
|
||||
}
|
||||
.center {
|
||||
text-align: center;
|
||||
|
@@ -92,7 +92,7 @@ export class DemoDateTimeDate extends LitElement {
|
||||
|
||||
static styles = css`
|
||||
.header {
|
||||
font-weight: bold;
|
||||
font-weight: var(--ha-font-weight-bold);
|
||||
}
|
||||
.center {
|
||||
text-align: center;
|
||||
|
@@ -106,7 +106,7 @@ export class DemoDateTimeTimeSeconds extends LitElement {
|
||||
margin: 12px auto;
|
||||
}
|
||||
.header {
|
||||
font-weight: bold;
|
||||
font-weight: var(--ha-font-weight-bold);
|
||||
}
|
||||
.center {
|
||||
text-align: center;
|
||||
|
@@ -106,7 +106,7 @@ export class DemoDateTimeTimeWeekday extends LitElement {
|
||||
margin: 12px auto;
|
||||
}
|
||||
.header {
|
||||
font-weight: bold;
|
||||
font-weight: var(--ha-font-weight-bold);
|
||||
}
|
||||
.center {
|
||||
text-align: center;
|
||||
|
@@ -106,7 +106,7 @@ export class DemoDateTimeTime extends LitElement {
|
||||
margin: 12px auto;
|
||||
}
|
||||
.header {
|
||||
font-weight: bold;
|
||||
font-weight: var(--ha-font-weight-bold);
|
||||
}
|
||||
.center {
|
||||
text-align: center;
|
||||
|
@@ -428,13 +428,13 @@ class HassioAddonConfig extends LitElement {
|
||||
.header h2 {
|
||||
color: var(--ha-card-header-color, var(--primary-text-color));
|
||||
font-family: var(--ha-card-header-font-family, inherit);
|
||||
font-size: var(--ha-card-header-font-size, 24px);
|
||||
font-size: var(--ha-card-header-font-size, var(--ha-font-size-2xl));
|
||||
letter-spacing: -0.012em;
|
||||
line-height: 48px;
|
||||
padding: 12px 16px 16px;
|
||||
display: block;
|
||||
margin-block: 0px;
|
||||
font-weight: normal;
|
||||
font-weight: var(--ha-font-weight-normal);
|
||||
}
|
||||
.card-actions.right {
|
||||
justify-content: flex-end;
|
||||
|
@@ -1280,12 +1280,12 @@ class HassioAddonInfo extends LitElement {
|
||||
padding-left: 8px;
|
||||
padding-inline-start: 8px;
|
||||
padding-inline-end: initial;
|
||||
font-size: 24px;
|
||||
font-size: var(--ha-font-size-2xl);
|
||||
color: var(--ha-card-header-color, var(--primary-text-color));
|
||||
}
|
||||
.addon-version {
|
||||
float: var(--float-end);
|
||||
font-size: 15px;
|
||||
font-size: var(--ha-font-size-l);
|
||||
vertical-align: middle;
|
||||
}
|
||||
.errors {
|
||||
|
@@ -391,7 +391,7 @@ export class HassioBackups extends LitElement {
|
||||
top: -4px;
|
||||
}
|
||||
.selected-txt {
|
||||
font-weight: bold;
|
||||
font-weight: var(--ha-font-weight-bold);
|
||||
padding-left: 16px;
|
||||
padding-inline-start: 16px;
|
||||
padding-inline-end: initial;
|
||||
@@ -401,7 +401,7 @@ export class HassioBackups extends LitElement {
|
||||
margin-top: 20px;
|
||||
}
|
||||
.header-toolbar .selected-txt {
|
||||
font-size: 16px;
|
||||
font-size: var(--ha-font-size-l);
|
||||
}
|
||||
.header-toolbar .header-btns {
|
||||
margin-right: -12px;
|
||||
|
@@ -131,7 +131,7 @@ export class HassioUpdate extends LitElement {
|
||||
}
|
||||
.update-heading {
|
||||
font-size: var(--ha-font-size-l);
|
||||
font-weight: 500;
|
||||
font-weight: var(--ha-font-weight-medium);
|
||||
margin-bottom: 0.5em;
|
||||
color: var(--primary-text-color);
|
||||
}
|
||||
|
@@ -173,7 +173,7 @@ class HassioHardwareDialog extends LitElement {
|
||||
font-family: var(--ha-font-family-code);
|
||||
}
|
||||
code {
|
||||
font-size: 85%;
|
||||
font-size: var(--ha-font-size-s);
|
||||
padding: 0.2em 0.4em;
|
||||
}
|
||||
search-input {
|
||||
|
@@ -1,3 +1,8 @@
|
||||
import {
|
||||
haFontFamilyBody,
|
||||
haFontSmoothing,
|
||||
haMozOsxFontSmoothing,
|
||||
} from "../../src/resources/theme/typography.globals";
|
||||
import "./hassio-main";
|
||||
|
||||
import("../../src/resources/append-ha-style");
|
||||
@@ -5,10 +10,10 @@ import("../../src/resources/append-ha-style");
|
||||
const styleEl = document.createElement("style");
|
||||
styleEl.textContent = `
|
||||
body {
|
||||
font-family: Roboto, sans-serif;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
font-weight: 400;
|
||||
font-family: ${haFontFamilyBody};
|
||||
-moz-osx-font-smoothing: ${haMozOsxFontSmoothing};
|
||||
-webkit-font-smoothing: ${haFontSmoothing};
|
||||
font-weight: var(--ha-font-weight-normal);
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
height: 100vh;
|
||||
|
@@ -340,12 +340,12 @@ class HassioIngressView extends LitElement {
|
||||
.header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-size: 16px;
|
||||
font-size: var(--ha-font-size-l);
|
||||
height: 40px;
|
||||
padding: 0 16px;
|
||||
pointer-events: none;
|
||||
background-color: var(--app-header-background-color);
|
||||
font-weight: 400;
|
||||
font-weight: var(--ha-font-weight-normal);
|
||||
color: var(--app-header-text-color, white);
|
||||
border-bottom: var(--app-header-border-bottom, none);
|
||||
box-sizing: border-box;
|
||||
|
@@ -14,6 +14,7 @@ export const hassioStyle = css`
|
||||
margin-bottom: 8px;
|
||||
font-family: var(--ha-font-family-body);
|
||||
-webkit-font-smoothing: var(--ha-font-smoothing);
|
||||
-moz-osx-font-smoothing: var(--ha-moz-osx-font-smoothing);
|
||||
font-size: var(--ha-font-size-2xl);
|
||||
font-weight: var(--ha-font-weight-normal);
|
||||
line-height: var(--ha-line-height-condensed);
|
||||
|
@@ -4,7 +4,7 @@ export default {
|
||||
"prettier --cache --write",
|
||||
"lit-analyzer --quiet",
|
||||
],
|
||||
"*.{json,css,md,markdown,html,y?aml}": "prettier --cache --write",
|
||||
"*.{json,css,md,markdown,html,ya?ml}": "prettier --cache --write",
|
||||
"translations/*/*.json": (files) =>
|
||||
'printf "%s\n" "Translation files should not be added or modified here. Instead, make the necessary modifications in src/translations/en.json. Other languages are managed externally. Please see https://developers.home-assistant.io/docs/translations/ for details." ' +
|
||||
files.join(" ") +
|
||||
|
58
package.json
58
package.json
@@ -20,13 +20,15 @@
|
||||
"prepack": "pinst --disable",
|
||||
"postpack": "pinst --enable",
|
||||
"test": "vitest run --config test/vitest.config.ts",
|
||||
"test:coverage": "vitest run --config test/vitest.config.ts --coverage"
|
||||
"test:coverage": "vitest run --config test/vitest.config.ts --coverage",
|
||||
"analyze": "cem analyze --litelement --globs \"src/components/ha-alert.ts\" --dev",
|
||||
"doc": "gulp generate-component-docs"
|
||||
},
|
||||
"author": "Paulus Schoutsen <Paulus@PaulusSchoutsen.nl> (http://paulusschoutsen.nl)",
|
||||
"license": "Apache-2.0",
|
||||
"type": "module",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "7.27.0",
|
||||
"@babel/runtime": "7.27.1",
|
||||
"@braintree/sanitize-url": "7.1.1",
|
||||
"@codemirror/autocomplete": "6.18.6",
|
||||
"@codemirror/commands": "6.8.1",
|
||||
@@ -34,7 +36,7 @@
|
||||
"@codemirror/legacy-modes": "6.5.1",
|
||||
"@codemirror/search": "6.5.10",
|
||||
"@codemirror/state": "6.5.2",
|
||||
"@codemirror/view": "6.36.6",
|
||||
"@codemirror/view": "6.36.7",
|
||||
"@egjs/hammerjs": "2.0.17",
|
||||
"@formatjs/intl-datetimeformat": "6.18.0",
|
||||
"@formatjs/intl-displaynames": "6.8.11",
|
||||
@@ -89,17 +91,17 @@
|
||||
"@thomasloven/round-slider": "0.6.0",
|
||||
"@tsparticles/engine": "3.8.1",
|
||||
"@tsparticles/preset-links": "3.2.0",
|
||||
"@vaadin/combo-box": "24.7.4",
|
||||
"@vaadin/vaadin-themable-mixin": "24.7.4",
|
||||
"@vaadin/combo-box": "24.7.5",
|
||||
"@vaadin/vaadin-themable-mixin": "24.7.5",
|
||||
"@vibrant/color": "4.0.0",
|
||||
"@vue/web-component-wrapper": "1.3.0",
|
||||
"@webcomponents/scoped-custom-element-registry": "0.0.10",
|
||||
"@webcomponents/webcomponentsjs": "2.8.0",
|
||||
"app-datepicker": "5.1.1",
|
||||
"barcode-detector": "3.0.1",
|
||||
"barcode-detector": "3.0.4",
|
||||
"color-name": "2.0.0",
|
||||
"comlink": "4.4.2",
|
||||
"core-js": "3.41.0",
|
||||
"core-js": "3.42.0",
|
||||
"cropperjs": "1.6.2",
|
||||
"date-fns": "4.1.0",
|
||||
"date-fns-tz": "3.2.0",
|
||||
@@ -111,9 +113,9 @@
|
||||
"fuse.js": "7.1.0",
|
||||
"google-timezones-json": "1.2.0",
|
||||
"gulp-zopfli-green": "6.0.2",
|
||||
"hls.js": "patch:hls.js@npm%3A1.5.7#~/.yarn/patches/hls.js-npm-1.5.7-f5bbd3d060.patch",
|
||||
"hls.js": "1.6.2",
|
||||
"home-assistant-js-websocket": "9.5.0",
|
||||
"idb-keyval": "6.2.1",
|
||||
"idb-keyval": "6.2.2",
|
||||
"intl-messageformat": "10.7.16",
|
||||
"js-yaml": "4.1.0",
|
||||
"leaflet": "1.9.4",
|
||||
@@ -131,7 +133,7 @@
|
||||
"qrcode": "1.5.4",
|
||||
"roboto-fontface": "0.10.0",
|
||||
"rrule": "2.8.1",
|
||||
"sortablejs": "patch:sortablejs@npm%3A1.15.3#~/.yarn/patches/sortablejs-npm-1.15.3-3235a8f83b.patch",
|
||||
"sortablejs": "patch:sortablejs@npm%3A1.15.6#~/.yarn/patches/sortablejs-npm-1.15.6-3235a8f83b.patch",
|
||||
"stacktrace-js": "2.0.2",
|
||||
"superstruct": "2.0.2",
|
||||
"tinykeys": "3.0.0",
|
||||
@@ -150,18 +152,20 @@
|
||||
"xss": "1.0.15"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "7.26.10",
|
||||
"@babel/core": "7.27.1",
|
||||
"@babel/helper-define-polyfill-provider": "0.6.4",
|
||||
"@babel/plugin-transform-runtime": "7.26.10",
|
||||
"@babel/preset-env": "7.26.9",
|
||||
"@bundle-stats/plugin-webpack-filter": "4.19.1",
|
||||
"@lokalise/node-api": "14.4.0",
|
||||
"@babel/plugin-transform-runtime": "7.27.1",
|
||||
"@babel/preset-env": "7.27.2",
|
||||
"@bundle-stats/plugin-webpack-filter": "4.20.1",
|
||||
"@custom-elements-manifest/analyzer": "0.10.4",
|
||||
"@custom-elements-manifest/to-markdown": "0.1.0",
|
||||
"@lokalise/node-api": "14.7.0",
|
||||
"@octokit/auth-oauth-device": "7.1.5",
|
||||
"@octokit/plugin-retry": "7.2.1",
|
||||
"@octokit/rest": "21.1.1",
|
||||
"@rsdoctor/rspack-plugin": "1.0.2",
|
||||
"@rspack/cli": "1.3.7",
|
||||
"@rspack/core": "1.3.7",
|
||||
"@rsdoctor/rspack-plugin": "1.1.2",
|
||||
"@rspack/cli": "1.3.9",
|
||||
"@rspack/core": "1.3.9",
|
||||
"@types/babel__plugin-transform-runtime": "7.9.5",
|
||||
"@types/chromecast-caf-receiver": "6.0.21",
|
||||
"@types/chromecast-caf-sender": "1.0.11",
|
||||
@@ -170,7 +174,7 @@
|
||||
"@types/html-minifier-terser": "7.0.2",
|
||||
"@types/js-yaml": "4.0.9",
|
||||
"@types/leaflet": "1.9.17",
|
||||
"@types/leaflet-draw": "1.0.11",
|
||||
"@types/leaflet-draw": "1.0.12",
|
||||
"@types/leaflet.markercluster": "1.5.5",
|
||||
"@types/lodash.merge": "4.6.9",
|
||||
"@types/luxon": "3.6.2",
|
||||
@@ -180,20 +184,20 @@
|
||||
"@types/tar": "6.1.13",
|
||||
"@types/ua-parser-js": "0.7.39",
|
||||
"@types/webspeechapi": "0.0.29",
|
||||
"@vitest/coverage-v8": "3.1.2",
|
||||
"@vitest/coverage-v8": "3.1.3",
|
||||
"babel-loader": "10.0.0",
|
||||
"babel-plugin-template-html-minifier": "4.1.0",
|
||||
"browserslist-useragent-regexp": "4.1.3",
|
||||
"del": "8.0.0",
|
||||
"eslint": "9.25.1",
|
||||
"eslint": "9.26.0",
|
||||
"eslint-config-airbnb-base": "15.0.0",
|
||||
"eslint-config-prettier": "10.1.2",
|
||||
"eslint-config-prettier": "10.1.5",
|
||||
"eslint-import-resolver-webpack": "0.13.10",
|
||||
"eslint-plugin-import": "2.31.0",
|
||||
"eslint-plugin-lit": "2.1.1",
|
||||
"eslint-plugin-lit-a11y": "4.1.4",
|
||||
"eslint-plugin-unused-imports": "4.1.4",
|
||||
"eslint-plugin-wc": "3.0.0",
|
||||
"eslint-plugin-wc": "3.0.1",
|
||||
"fancy-log": "2.0.0",
|
||||
"fs-extra": "11.3.0",
|
||||
"glob": "11.0.2",
|
||||
@@ -205,7 +209,7 @@
|
||||
"husky": "9.1.7",
|
||||
"jsdom": "26.1.0",
|
||||
"jszip": "3.10.1",
|
||||
"lint-staged": "15.5.1",
|
||||
"lint-staged": "15.5.2",
|
||||
"lit-analyzer": "2.0.3",
|
||||
"lodash.merge": "4.6.2",
|
||||
"lodash.template": "4.5.0",
|
||||
@@ -219,9 +223,9 @@
|
||||
"terser-webpack-plugin": "5.3.14",
|
||||
"ts-lit-plugin": "2.0.2",
|
||||
"typescript": "5.8.3",
|
||||
"typescript-eslint": "8.31.0",
|
||||
"typescript-eslint": "8.32.0",
|
||||
"vite-tsconfig-paths": "5.1.4",
|
||||
"vitest": "3.1.2",
|
||||
"vitest": "3.1.3",
|
||||
"webpack-stats-plugin": "1.1.3",
|
||||
"webpackbar": "7.0.0",
|
||||
"workbox-build": "patch:workbox-build@npm%3A7.1.1#~/.yarn/patches/workbox-build-npm-7.1.1-a854f3faae.patch"
|
||||
@@ -233,7 +237,7 @@
|
||||
"clean-css": "5.3.3",
|
||||
"@lit/reactive-element": "2.1.0",
|
||||
"@fullcalendar/daygrid": "6.1.17",
|
||||
"globals": "16.0.0",
|
||||
"globals": "16.1.0",
|
||||
"tslib": "2.8.1",
|
||||
"@material/mwc-list@^0.27.0": "patch:@material/mwc-list@npm%3A0.27.0#~/.yarn/patches/@material-mwc-list-npm-0.27.0-5344fc9de4.patch"
|
||||
},
|
||||
|
@@ -1,13 +1,13 @@
|
||||
<svg width="94" height="72" viewBox="0 0 94 72" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M76.9105 39.4999C77.739 39.4999 78.4105 38.8283 78.4105 37.9999C78.4105 37.1715 77.739 36.4999 76.9105 36.4999V39.4999ZM37.5 39.4999L76.9105 39.4999V36.4999L37.5 36.4999L37.5 39.4999Z" fill="#00AFFF" fill-opacity="0.3"/>
|
||||
<path d="M76.9105 39.4999C77.739 39.4999 78.4105 38.8284 78.4105 37.9999C78.4105 37.1715 77.739 36.4999 76.9105 36.4999V39.4999ZM37.5 37.9999L37.5 39.4999L76.9105 39.4999V37.9999V36.4999L37.5 36.4999L37.5 37.9999Z" fill="#00AFFF" fill-opacity="0.3"/>
|
||||
<path d="M30.8239 22.3365L38.8239 38.8365L30.3239 50.3365" stroke="black" stroke-opacity="0.12" stroke-width="3" stroke-linecap="round"/>
|
||||
<mask id="mask0_1110_23734" style="mask-type:alpha" maskUnits="userSpaceOnUse" x="30" y="27" width="18" height="18">
|
||||
<mask id="mask0_2_779" style="mask-type:alpha" maskUnits="userSpaceOnUse" x="30" y="27" width="18" height="18">
|
||||
<path d="M45.75 42.075C45.75 42.4462 45.4462 42.75 45.075 42.75H32.925C32.5538 42.75 32.25 42.4462 32.25 42.075V36.675C32.25 36.3037 32.4649 35.7851 32.7276 35.5224L38.5224 29.7275C38.7851 29.4649 39.2143 29.4649 39.477 29.7275L45.2724 35.523C45.5351 35.7857 45.75 36.3043 45.75 36.6755V42.075Z" fill="black"/>
|
||||
</mask>
|
||||
<g mask="url(#mask0_1110_23734)">
|
||||
<rect x="30" y="27" width="18" height="18" fill="#212121"/>
|
||||
<g mask="url(#mask0_2_779)">
|
||||
<rect x="30" y="27" width="18" height="18" fill="#00AFFF"/>
|
||||
</g>
|
||||
<path d="M82 37.9999C82 36.343 83.3431 34.9999 85 34.9999C86.6569 34.9999 88 36.343 88 37.9999C88 39.6567 86.6569 40.9999 85 40.9999C83.3431 40.9999 82 39.6567 82 37.9999Z" stroke="#00AFFF" stroke-width="2"/>
|
||||
<path d="M85 34.9999C86.6569 34.9999 88 36.343 88 37.9999C88 39.6567 86.6569 40.9999 85 40.9999C83.3431 40.9999 82 39.6567 82 37.9999C82 36.343 83.3431 34.9999 85 34.9999Z" stroke="#00AFFF" stroke-width="2"/>
|
||||
<rect x="23" y="11" width="8" height="8" rx="4" fill="black" fill-opacity="0.32"/>
|
||||
<rect x="22" y="52" width="8" height="8" rx="4" fill="black" fill-opacity="0.32"/>
|
||||
<path d="M21.5715 19.5C17.4983 23.801 15 29.6087 15 36C15 41.9085 17.1351 47.3183 20.6759 51.5" stroke="black" stroke-opacity="0.12" stroke-width="3" stroke-linecap="round"/>
|
||||
|
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.6 KiB |
@@ -1,19 +1,19 @@
|
||||
<svg width="94" height="72" viewBox="0 0 94 72" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M63.1358 38.5084C63.9608 38.4334 64.5688 37.7037 64.4938 36.8787C64.4188 36.0537 63.6892 35.4457 62.8642 35.5207L63.1358 38.5084ZM46.6358 40.0084L63.1358 38.5084L62.8642 35.5207L46.3642 37.0207L46.6358 40.0084Z" fill="#00AFFF" fill-opacity="0.3"/>
|
||||
<path d="M38.5 22L45.9722 37.4115C46.2967 38.0807 46.223 38.8747 45.781 39.4728L38 50" stroke="#00AFFF" stroke-opacity="0.3" stroke-width="3" stroke-linecap="round" stroke-linejoin="bevel"/>
|
||||
<circle cx="47" cy="36" r="34" fill="white"/>
|
||||
<circle cx="47" cy="36" r="33.5" stroke="black" stroke-opacity="0.12"/>
|
||||
<path d="M41.8777 12.5216C43.4905 12.1798 45.1631 12 46.8777 12C58.2401 12 67.7582 19.8959 70.2445 30.5M40 59C42.1788 59.6506 44.4874 60 46.8777 60C56.9498 60 65.5728 53.7955 69.1332 45" stroke="#00AFFF" stroke-opacity="0.3" stroke-width="3" stroke-linecap="round" stroke-linejoin="bevel"/>
|
||||
<path d="M38.5 22L45.9722 37.4115C46.2967 38.0807 46.223 38.8747 45.781 39.4728L38 50" stroke="#00AFFF" stroke-opacity="0.3" stroke-width="3" stroke-linecap="round" stroke-linejoin="bevel"/>
|
||||
<mask id="mask0_1110_23775" style="mask-type:alpha" maskUnits="userSpaceOnUse" x="38" y="27" width="18" height="18">
|
||||
<path d="M53.75 42.075C53.75 42.4462 53.4462 42.75 53.075 42.75H40.925C40.5538 42.75 40.25 42.4462 40.25 42.075V36.675C40.25 36.3037 40.4649 35.7851 40.7276 35.5224L46.5224 29.7275C46.7851 29.4649 47.2143 29.4649 47.477 29.7275L53.2724 35.523C53.5351 35.7857 53.75 36.3043 53.75 36.6755V42.075Z" fill="black"/>
|
||||
<path d="M55.1358 38.5084C55.9608 38.4334 56.5688 37.7038 56.4938 36.8788C56.4188 36.0538 55.6892 35.4457 54.8642 35.5207L55.1358 38.5084ZM38.5 38.5146L38.6358 40.0084L55.1358 38.5084L55 37.0146L54.8642 35.5207L38.3642 37.0207L38.5 38.5146Z" fill="#00AFFF" fill-opacity="0.3"/>
|
||||
<path d="M30.5 22L37.9722 37.4115C38.2967 38.0807 38.223 38.8747 37.781 39.4728L30 50" stroke="#00AFFF" stroke-opacity="0.3" stroke-width="3" stroke-linecap="round" stroke-linejoin="bevel"/>
|
||||
<circle cx="39" cy="36" r="34" fill="white"/>
|
||||
<circle cx="39" cy="36" r="33.5" stroke="black" stroke-opacity="0.12"/>
|
||||
<path d="M33.8777 12.5216C35.4905 12.1798 37.1631 12 38.8777 12C50.2401 12 59.7582 19.8959 62.2445 30.5M32 59C34.1788 59.6506 36.4874 60 38.8777 60C48.9498 60 57.5728 53.7955 61.1332 45" stroke="#00AFFF" stroke-opacity="0.3" stroke-width="3" stroke-linecap="round" stroke-linejoin="bevel"/>
|
||||
<path d="M30.5 22L37.9722 37.4115C38.2967 38.0807 38.223 38.8747 37.781 39.4728L30 50" stroke="#00AFFF" stroke-opacity="0.3" stroke-width="3" stroke-linecap="round" stroke-linejoin="bevel"/>
|
||||
<mask id="mask0_2_810" style="mask-type:alpha" maskUnits="userSpaceOnUse" x="30" y="27" width="18" height="18">
|
||||
<path d="M45.75 42.075C45.75 42.4462 45.4463 42.75 45.075 42.75H32.925C32.5538 42.75 32.25 42.4462 32.25 42.075V36.675C32.25 36.3037 32.4649 35.7851 32.7276 35.5224L38.5224 29.7275C38.7851 29.4649 39.2143 29.4649 39.477 29.7275L45.2724 35.523C45.5351 35.7857 45.75 36.3043 45.75 36.6755V42.075Z" fill="black"/>
|
||||
</mask>
|
||||
<g mask="url(#mask0_1110_23775)">
|
||||
<rect x="38" y="27" width="18" height="18" fill="#212121"/>
|
||||
<g mask="url(#mask0_2_810)">
|
||||
<rect x="30" y="27" width="18" height="18" fill="#00AFFF"/>
|
||||
</g>
|
||||
<path d="M63.5 39.4999C64.3284 39.4999 65 38.8283 65 37.9999C65 37.1715 64.3284 36.4999 63.5 36.4999L63.5 39.4999ZM49.5 39.4999L63.5 39.4999L63.5 36.4999L49.5 36.4999L49.5 39.4999Z" fill="#00AFFF" fill-opacity="0.3"/>
|
||||
<rect x="31" y="11" width="8" height="8" rx="4" fill="#00AFFF" fill-opacity="0.6"/>
|
||||
<rect x="30" y="52" width="8" height="8" rx="4" fill="#00AFFF" fill-opacity="0.6"/>
|
||||
<path d="M29.5715 19.5C25.4983 23.801 23 29.6087 23 36C23 41.9085 25.1351 47.3183 28.6759 51.5" stroke="#00AFFF" stroke-opacity="0.3" stroke-width="3" stroke-linecap="round" stroke-linejoin="bevel"/>
|
||||
<path d="M68 37.9999C68 36.343 69.3431 34.9999 71 34.9999C72.6569 34.9999 74 36.343 74 37.9999C74 39.6567 72.6569 40.9999 71 40.9999C69.3431 40.9999 68 39.6567 68 37.9999Z" stroke="#00AFFF" stroke-width="2"/>
|
||||
<path d="M55.5 39.4999C56.3284 39.4999 57 38.8283 57 37.9999C57 37.1715 56.3284 36.4999 55.5 36.4999L55.5 39.4999ZM41.5 37.9999L41.5 39.4999L55.5 39.4999L55.5 37.9999L55.5 36.4999L41.5 36.4999L41.5 37.9999Z" fill="#00AFFF" fill-opacity="0.3"/>
|
||||
<rect x="23" y="11" width="8" height="8" rx="4" fill="#00AFFF" fill-opacity="0.6"/>
|
||||
<rect x="22" y="52" width="8" height="8" rx="4" fill="#00AFFF" fill-opacity="0.6"/>
|
||||
<path d="M21.5715 19.5C17.4983 23.801 15 29.6087 15 36C15 41.9085 17.1351 47.3183 20.6759 51.5" stroke="#00AFFF" stroke-opacity="0.3" stroke-width="3" stroke-linecap="round" stroke-linejoin="bevel"/>
|
||||
<path d="M63 34.9999C64.6569 34.9999 66 36.343 66 37.9999C66 39.6567 64.6569 40.9999 63 40.9999C61.3431 40.9999 60 39.6567 60 37.9999C60 36.343 61.3431 34.9999 63 34.9999Z" stroke="#00AFFF" stroke-width="2"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 2.5 KiB |
@@ -1,19 +1,18 @@
|
||||
<svg width="94" height="72" viewBox="0 0 94 72" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M63.1358 38.5084C63.9608 38.4334 64.5688 37.7037 64.4938 36.8787C64.4188 36.0537 63.6892 35.4457 62.8642 35.5207L63.1358 38.5084ZM46.6358 40.0084L63.1358 38.5084L62.8642 35.5207L46.3642 37.0207L46.6358 40.0084Z" fill="#00AFFF" fill-opacity="0.3"/>
|
||||
<path d="M38.5 22L45.9722 37.4115C46.2967 38.0807 46.223 38.8747 45.781 39.4728L38 50" stroke="#00AFFF" stroke-opacity="0.3" stroke-width="3" stroke-linecap="round" stroke-linejoin="bevel"/>
|
||||
<circle cx="47" cy="36" r="34" fill="#1C1C1C"/>
|
||||
<circle cx="47" cy="36" r="33.5" stroke="white" stroke-opacity="0.24"/>
|
||||
<path d="M41.8777 12.5216C43.4905 12.1798 45.1631 12 46.8777 12C58.2401 12 67.7582 19.8959 70.2445 30.5M40 59C42.1788 59.6506 44.4874 60 46.8777 60C56.9498 60 65.5728 53.7955 69.1332 45" stroke="#00AFFF" stroke-opacity="0.3" stroke-width="3" stroke-linecap="round" stroke-linejoin="bevel"/>
|
||||
<path d="M38.5 22L45.9722 37.4115C46.2967 38.0807 46.223 38.8747 45.781 39.4728L38 50" stroke="#00AFFF" stroke-opacity="0.3" stroke-width="3" stroke-linecap="round" stroke-linejoin="bevel"/>
|
||||
<mask id="mask0_1180_4965" style="mask-type:alpha" maskUnits="userSpaceOnUse" x="38" y="27" width="18" height="18">
|
||||
<path d="M53.75 42.075C53.75 42.4462 53.4462 42.75 53.075 42.75H40.925C40.5538 42.75 40.25 42.4462 40.25 42.075V36.675C40.25 36.3037 40.4649 35.7851 40.7276 35.5224L46.5224 29.7275C46.7851 29.4649 47.2143 29.4649 47.477 29.7275L53.2724 35.523C53.5351 35.7857 53.75 36.3043 53.75 36.6755V42.075Z" fill="black"/>
|
||||
<path d="M55.1358 38.5084C55.9608 38.4334 56.5688 37.7038 56.4938 36.8788C56.4188 36.0538 55.6892 35.4457 54.8642 35.5207L55.1358 38.5084ZM38.5 38.5146L38.6358 40.0084L55.1358 38.5084L55 37.0146L54.8642 35.5207L38.3642 37.0207L38.5 38.5146Z" fill="#00AFFF" fill-opacity="0.3"/>
|
||||
<path d="M30.5 22L37.9722 37.4115C38.2967 38.0807 38.223 38.8747 37.781 39.4728L30 50" stroke="#00AFFF" stroke-opacity="0.3" stroke-width="3" stroke-linecap="round" stroke-linejoin="bevel"/>
|
||||
<circle cx="39" cy="36" r="33.5" stroke="white" stroke-opacity="0.24"/>
|
||||
<path d="M33.8777 12.5216C35.4905 12.1798 37.1631 12 38.8777 12C50.2401 12 59.7582 19.8959 62.2445 30.5M32 59C34.1788 59.6506 36.4874 60 38.8777 60C48.9498 60 57.5728 53.7955 61.1332 45" stroke="#00AFFF" stroke-opacity="0.3" stroke-width="3" stroke-linecap="round" stroke-linejoin="bevel"/>
|
||||
<path d="M30.5 22L37.9722 37.4115C38.2967 38.0807 38.223 38.8747 37.781 39.4728L30 50" stroke="#00AFFF" stroke-opacity="0.3" stroke-width="3" stroke-linecap="round" stroke-linejoin="bevel"/>
|
||||
<mask id="mask0_2_810" style="mask-type:alpha" maskUnits="userSpaceOnUse" x="30" y="27" width="18" height="18">
|
||||
<path d="M45.75 42.075C45.75 42.4462 45.4463 42.75 45.075 42.75H32.925C32.5538 42.75 32.25 42.4462 32.25 42.075V36.675C32.25 36.3037 32.4649 35.7851 32.7276 35.5224L38.5224 29.7275C38.7851 29.4649 39.2143 29.4649 39.477 29.7275L45.2724 35.523C45.5351 35.7857 45.75 36.3043 45.75 36.6755V42.075Z" fill="black"/>
|
||||
</mask>
|
||||
<g mask="url(#mask0_1180_4965)">
|
||||
<rect x="38" y="27" width="18" height="18" fill="#00AFFF"/>
|
||||
<g mask="url(#mask0_2_810)">
|
||||
<rect x="30" y="27" width="18" height="18" fill="#00AFFF"/>
|
||||
</g>
|
||||
<path d="M63.5 39.4999C64.3284 39.4999 65 38.8283 65 37.9999C65 37.1715 64.3284 36.4999 63.5 36.4999L63.5 39.4999ZM49.5 39.4999L63.5 39.4999L63.5 36.4999L49.5 36.4999L49.5 39.4999Z" fill="#00AFFF" fill-opacity="0.3"/>
|
||||
<rect x="31" y="11" width="8" height="8" rx="4" fill="#00AFFF" fill-opacity="0.6"/>
|
||||
<rect x="30" y="52" width="8" height="8" rx="4" fill="#00AFFF" fill-opacity="0.6"/>
|
||||
<path d="M29.5715 19.5C25.4983 23.801 23 29.6087 23 36C23 41.9085 25.1351 47.3183 28.6759 51.5" stroke="#00AFFF" stroke-opacity="0.3" stroke-width="3" stroke-linecap="round" stroke-linejoin="bevel"/>
|
||||
<path d="M68 37.9999C68 36.343 69.3431 34.9999 71 34.9999C72.6569 34.9999 74 36.343 74 37.9999C74 39.6567 72.6569 40.9999 71 40.9999C69.3431 40.9999 68 39.6567 68 37.9999Z" stroke="#00AFFF" stroke-width="2"/>
|
||||
<path d="M55.5 39.4999C56.3284 39.4999 57 38.8283 57 37.9999C57 37.1715 56.3284 36.4999 55.5 36.4999L55.5 39.4999ZM41.5 37.9999L41.5 39.4999L55.5 39.4999L55.5 37.9999L55.5 36.4999L41.5 36.4999L41.5 37.9999Z" fill="#00AFFF" fill-opacity="0.3"/>
|
||||
<rect x="23" y="11" width="8" height="8" rx="4" fill="#00AFFF" fill-opacity="0.6"/>
|
||||
<rect x="22" y="52" width="8" height="8" rx="4" fill="#00AFFF" fill-opacity="0.6"/>
|
||||
<path d="M21.5715 19.5C17.4983 23.801 15 29.6087 15 36C15 41.9085 17.1351 47.3183 20.6759 51.5" stroke="#00AFFF" stroke-opacity="0.3" stroke-width="3" stroke-linecap="round" stroke-linejoin="bevel"/>
|
||||
<path d="M63 34.9999C64.6569 34.9999 66 36.343 66 37.9999C66 39.6567 64.6569 40.9999 63 40.9999C61.3431 40.9999 60 39.6567 60 37.9999C60 36.343 61.3431 34.9999 63 34.9999Z" stroke="#00AFFF" stroke-width="2"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 2.4 KiB |
@@ -93,7 +93,7 @@ export class HaAuthorize extends litLocalizeLiteMixin(LitElement) {
|
||||
background-color: var(--primary-background-color, #fafafa);
|
||||
}
|
||||
p {
|
||||
font-size: 14px;
|
||||
font-size: var(--ha-font-size-m);
|
||||
line-height: 20px;
|
||||
}
|
||||
.card-content {
|
||||
@@ -151,8 +151,8 @@ export class HaAuthorize extends litLocalizeLiteMixin(LitElement) {
|
||||
margin-inline-start: initial;
|
||||
}
|
||||
h1 {
|
||||
font-size: 28px;
|
||||
font-weight: 400;
|
||||
font-size: var(--ha-font-size-3xl);
|
||||
font-weight: var(--ha-font-weight-normal);
|
||||
margin-top: 16px;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
@@ -57,8 +57,8 @@ export class HaPickAuthProvider extends LitElement {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
text-align: center;
|
||||
font-size: 14px;
|
||||
font-weight: 400;
|
||||
font-size: var(--ha-font-size-m);
|
||||
font-weight: var(--ha-font-weight-normal);
|
||||
line-height: 20px;
|
||||
}
|
||||
h3:before {
|
||||
|
@@ -9,6 +9,7 @@ import type { LitElement } from "lit";
|
||||
*/
|
||||
export interface DragScrollControllerConfig {
|
||||
selector: string;
|
||||
enabled?: boolean;
|
||||
}
|
||||
|
||||
export class DragScrollController implements ReactiveController {
|
||||
@@ -28,19 +29,47 @@ export class DragScrollController implements ReactiveController {
|
||||
|
||||
private _scrollContainer?: HTMLElement | null;
|
||||
|
||||
private _enabled = true;
|
||||
|
||||
public get enabled(): boolean {
|
||||
return this._enabled;
|
||||
}
|
||||
|
||||
public set enabled(value: boolean) {
|
||||
if (value === this._enabled) {
|
||||
return;
|
||||
}
|
||||
this._enabled = value;
|
||||
if (this._enabled) {
|
||||
this._attach();
|
||||
} else {
|
||||
this._detach();
|
||||
}
|
||||
this._host.requestUpdate();
|
||||
}
|
||||
|
||||
constructor(
|
||||
host: ReactiveControllerHost & LitElement,
|
||||
{ selector }: DragScrollControllerConfig
|
||||
{ selector, enabled }: DragScrollControllerConfig
|
||||
) {
|
||||
this._selector = selector;
|
||||
this._host = host;
|
||||
this.enabled = enabled ?? true;
|
||||
host.addController(this);
|
||||
}
|
||||
|
||||
hostUpdated() {
|
||||
if (this._scrollContainer) {
|
||||
if (!this.enabled || this._scrollContainer) {
|
||||
return;
|
||||
}
|
||||
this._attach();
|
||||
}
|
||||
|
||||
hostDisconnected() {
|
||||
this._detach();
|
||||
}
|
||||
|
||||
private _attach() {
|
||||
this._scrollContainer = this._host.renderRoot?.querySelector(
|
||||
this._selector
|
||||
);
|
||||
@@ -49,9 +78,18 @@ export class DragScrollController implements ReactiveController {
|
||||
}
|
||||
}
|
||||
|
||||
hostDisconnected() {
|
||||
private _detach() {
|
||||
window.removeEventListener("mousemove", this._mouseMove);
|
||||
window.removeEventListener("mouseup", this._mouseUp);
|
||||
if (this._scrollContainer) {
|
||||
this._scrollContainer.removeEventListener("mousedown", this._mouseDown);
|
||||
this._scrollContainer = undefined;
|
||||
}
|
||||
this.scrolled = false;
|
||||
this.scrolling = false;
|
||||
this.mouseIsDown = false;
|
||||
this.scrollStartX = 0;
|
||||
this.scrollLeft = 0;
|
||||
}
|
||||
|
||||
private _mouseDown = (event: MouseEvent) => {
|
||||
|
@@ -1,6 +1,5 @@
|
||||
import type { UnsubscribeFunc } from "home-assistant-js-websocket";
|
||||
import { ReactiveElement } from "lit";
|
||||
import type { InternalPropertyDeclaration } from "lit/decorators";
|
||||
import type { ReactiveElement } from "lit";
|
||||
|
||||
type Callback = (oldValue: any, newValue: any) => void;
|
||||
|
||||
@@ -108,7 +107,6 @@ export function storage(options: {
|
||||
storage?: "localStorage" | "sessionStorage";
|
||||
subscribe?: boolean;
|
||||
state?: boolean;
|
||||
stateOptions?: InternalPropertyDeclaration;
|
||||
serializer?: (value: any) => any;
|
||||
deserializer?: (value: any) => any;
|
||||
}) {
|
||||
@@ -174,7 +172,7 @@ export function storage(options: {
|
||||
performUpdate.call(this);
|
||||
};
|
||||
|
||||
if (options.state && options.subscribe) {
|
||||
if (options.subscribe) {
|
||||
const connectedCallback = proto.connectedCallback;
|
||||
const disconnectedCallback = proto.disconnectedCallback;
|
||||
|
||||
@@ -192,12 +190,6 @@ export function storage(options: {
|
||||
el.__unbsubLocalStorage = undefined;
|
||||
};
|
||||
}
|
||||
if (options.state) {
|
||||
ReactiveElement.createProperty(propertyKey, {
|
||||
noAccessor: true,
|
||||
...options.stateOptions,
|
||||
});
|
||||
}
|
||||
|
||||
const descriptor = Object.getOwnPropertyDescriptor(proto, propertyKey);
|
||||
let newDescriptor: PropertyDescriptor;
|
||||
|
@@ -1,10 +1,4 @@
|
||||
import {
|
||||
ReactiveElement,
|
||||
type PropertyDeclaration,
|
||||
type PropertyValues,
|
||||
} from "lit";
|
||||
import { shallowEqual } from "../util/shallow-equal";
|
||||
|
||||
import type { ReactiveElement, PropertyValues } from "lit";
|
||||
/**
|
||||
* Transform function type.
|
||||
*/
|
||||
@@ -23,7 +17,6 @@ type ReactiveTransformElement = ReactiveElement & {
|
||||
export function transform<T, V>(config: {
|
||||
transformer: Transformer<T, V>;
|
||||
watch?: PropertyKey[];
|
||||
propertyOptions?: PropertyDeclaration;
|
||||
}) {
|
||||
return <ElemClass extends ReactiveElement>(
|
||||
proto: ElemClass,
|
||||
@@ -84,11 +77,6 @@ export function transform<T, V>(config: {
|
||||
curWatch.add(propertyKey);
|
||||
});
|
||||
}
|
||||
ReactiveElement.createProperty(propertyKey, {
|
||||
noAccessor: true,
|
||||
hasChanged: (v: any, o: any) => !shallowEqual(v, o),
|
||||
...config.propertyOptions,
|
||||
});
|
||||
|
||||
const descriptor = Object.getOwnPropertyDescriptor(proto, propertyKey);
|
||||
let newDescriptor: PropertyDescriptor;
|
||||
|
@@ -1,5 +1,11 @@
|
||||
export const canOverrideAlphanumericInput = (composedPath: EventTarget[]) => {
|
||||
if (composedPath.some((el) => "tagName" in el && el.tagName === "HA-MENU")) {
|
||||
if (
|
||||
composedPath.some(
|
||||
(el) =>
|
||||
"tagName" in el &&
|
||||
(el.tagName === "HA-MENU" || el.tagName === "HA-CODE-EDITOR")
|
||||
)
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@@ -2,7 +2,7 @@ import type { CSSResult } from "lit";
|
||||
|
||||
const _extractCssVars = (
|
||||
cssString: string,
|
||||
condition: (string) => boolean = () => true
|
||||
condition: (string: string) => boolean = () => true
|
||||
) => {
|
||||
const variables: Record<string, string> = {};
|
||||
|
||||
|
@@ -600,12 +600,32 @@ export class HaChartBase extends LitElement {
|
||||
}
|
||||
|
||||
private _getSeries() {
|
||||
if (!Array.isArray(this.data)) {
|
||||
return this.data;
|
||||
}
|
||||
return this.data.filter(
|
||||
const series = ensureArray(this.data).filter(
|
||||
(d) => !this._hiddenDatasets.has(String(d.name ?? d.id))
|
||||
);
|
||||
const yAxis = (this.options?.yAxis?.[0] ?? this.options?.yAxis) as
|
||||
| YAXisOption
|
||||
| undefined;
|
||||
if (yAxis?.type === "log") {
|
||||
// set <=0 values to null so they render as gaps on a log graph
|
||||
return series.map((d) =>
|
||||
d.type === "line"
|
||||
? {
|
||||
...d,
|
||||
data: d.data?.map((v) =>
|
||||
Array.isArray(v)
|
||||
? [
|
||||
v[0],
|
||||
typeof v[1] !== "number" || v[1] > 0 ? v[1] : null,
|
||||
...v.slice(2),
|
||||
]
|
||||
: v
|
||||
),
|
||||
}
|
||||
: d
|
||||
);
|
||||
}
|
||||
return series;
|
||||
}
|
||||
|
||||
private _getDefaultHeight() {
|
||||
@@ -719,7 +739,7 @@ export class HaChartBase extends LitElement {
|
||||
max-height: 60%;
|
||||
overflow-y: auto;
|
||||
padding: 12px 0 0;
|
||||
font-size: 12px;
|
||||
font-size: var(--ha-font-size-s);
|
||||
color: var(--primary-text-color);
|
||||
}
|
||||
.chart-legend ul {
|
||||
|
@@ -105,10 +105,41 @@ export class HaSankeyChart extends LitElement {
|
||||
|
||||
private _createData = memoizeOne((data: SankeyChartData, width = 0) => {
|
||||
const filteredNodes = data.nodes.filter((n) => n.value > 0);
|
||||
const indexes = [...new Set(filteredNodes.map((n) => n.index))];
|
||||
const indexes = [...new Set(filteredNodes.map((n) => n.index))].sort();
|
||||
const depthMap = new Map<number, number>();
|
||||
indexes.sort().forEach((index, i) => {
|
||||
const sections: Node[][] = [];
|
||||
indexes.forEach((index, i) => {
|
||||
depthMap.set(index, i);
|
||||
const nodesWithIndex = filteredNodes.filter((n) => n.index === index);
|
||||
if (nodesWithIndex.length > 0) {
|
||||
sections.push(
|
||||
sections.length > 0
|
||||
? nodesWithIndex.sort((a, b) => {
|
||||
// sort by the order of their parents in the previous section with orphans at the end
|
||||
const aParentIndex = this._findParentIndex(
|
||||
a.id,
|
||||
data.links,
|
||||
sections
|
||||
);
|
||||
const bParentIndex = this._findParentIndex(
|
||||
b.id,
|
||||
data.links,
|
||||
sections
|
||||
);
|
||||
if (aParentIndex === bParentIndex) {
|
||||
return 0;
|
||||
}
|
||||
if (aParentIndex === -1) {
|
||||
return 1;
|
||||
}
|
||||
if (bParentIndex === -1) {
|
||||
return -1;
|
||||
}
|
||||
return aParentIndex - bParentIndex;
|
||||
})
|
||||
: nodesWithIndex
|
||||
);
|
||||
}
|
||||
});
|
||||
const links = this._processLinks(filteredNodes, data.links);
|
||||
const sectionWidth = width / indexes.length;
|
||||
@@ -117,7 +148,7 @@ export class HaSankeyChart extends LitElement {
|
||||
return {
|
||||
id: "sankey",
|
||||
type: "sankey",
|
||||
nodes: filteredNodes.map((node) => ({
|
||||
nodes: sections.flat().map((node) => ({
|
||||
id: node.id,
|
||||
value: node.value,
|
||||
itemStyle: {
|
||||
@@ -227,6 +258,23 @@ export class HaSankeyChart extends LitElement {
|
||||
return links;
|
||||
}
|
||||
|
||||
private _findParentIndex(id: string, links: Link[], sections: Node[][]) {
|
||||
const parent = links.find((l) => l.target === id)?.source;
|
||||
if (!parent) {
|
||||
return -1;
|
||||
}
|
||||
let offset = 0;
|
||||
for (let i = sections.length - 1; i >= 0; i--) {
|
||||
const section = sections[i];
|
||||
const index = section.findIndex((n) => n.id === parent);
|
||||
if (index !== -1) {
|
||||
return offset + index;
|
||||
}
|
||||
offset += section.length;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static styles = css`
|
||||
:host {
|
||||
display: block;
|
||||
|
@@ -60,7 +60,7 @@ export class HaAssistChip extends AssistChip {
|
||||
opacity: var(--ha-assist-chip-active-container-opacity);
|
||||
}
|
||||
.label {
|
||||
font-family: Roboto, sans-serif;
|
||||
font-family: var(--ha-font-family-body);
|
||||
}
|
||||
`,
|
||||
];
|
||||
|
@@ -164,6 +164,8 @@ export class HaDataTable extends LitElement {
|
||||
|
||||
@state() private _collapsedGroups: string[] = [];
|
||||
|
||||
@state() private _lastSelectedRowId: string | null = null;
|
||||
|
||||
private _checkableRowsCount?: number;
|
||||
|
||||
private _checkedRows: string[] = [];
|
||||
@@ -187,6 +189,7 @@ export class HaDataTable extends LitElement {
|
||||
|
||||
public clearSelection(): void {
|
||||
this._checkedRows = [];
|
||||
this._lastSelectedRowId = null;
|
||||
this._checkedRowsChanged();
|
||||
}
|
||||
|
||||
@@ -194,6 +197,7 @@ export class HaDataTable extends LitElement {
|
||||
this._checkedRows = this._filteredData
|
||||
.filter((data) => data.selectable !== false)
|
||||
.map((data) => data[this.id]);
|
||||
this._lastSelectedRowId = null;
|
||||
this._checkedRowsChanged();
|
||||
}
|
||||
|
||||
@@ -207,6 +211,7 @@ export class HaDataTable extends LitElement {
|
||||
this._checkedRows.push(id);
|
||||
}
|
||||
});
|
||||
this._lastSelectedRowId = null;
|
||||
this._checkedRowsChanged();
|
||||
}
|
||||
|
||||
@@ -217,6 +222,7 @@ export class HaDataTable extends LitElement {
|
||||
this._checkedRows.splice(index, 1);
|
||||
}
|
||||
});
|
||||
this._lastSelectedRowId = null;
|
||||
this._checkedRowsChanged();
|
||||
}
|
||||
|
||||
@@ -261,6 +267,7 @@ export class HaDataTable extends LitElement {
|
||||
if (this.columns[columnId].direction) {
|
||||
this.sortDirection = this.columns[columnId].direction!;
|
||||
this.sortColumn = columnId;
|
||||
this._lastSelectedRowId = null;
|
||||
|
||||
fireEvent(this, "sorting-changed", {
|
||||
column: columnId,
|
||||
@@ -286,6 +293,7 @@ export class HaDataTable extends LitElement {
|
||||
|
||||
if (properties.has("filter")) {
|
||||
this._debounceSearch(this.filter);
|
||||
this._lastSelectedRowId = null;
|
||||
}
|
||||
|
||||
if (properties.has("data")) {
|
||||
@@ -296,9 +304,11 @@ export class HaDataTable extends LitElement {
|
||||
|
||||
if (!this.hasUpdated && this.initialCollapsedGroups) {
|
||||
this._collapsedGroups = this.initialCollapsedGroups;
|
||||
this._lastSelectedRowId = null;
|
||||
fireEvent(this, "collapsed-changed", { value: this._collapsedGroups });
|
||||
} else if (properties.has("groupColumn")) {
|
||||
this._collapsedGroups = [];
|
||||
this._lastSelectedRowId = null;
|
||||
fireEvent(this, "collapsed-changed", { value: this._collapsedGroups });
|
||||
}
|
||||
|
||||
@@ -312,6 +322,14 @@ export class HaDataTable extends LitElement {
|
||||
this._sortFilterData();
|
||||
}
|
||||
|
||||
if (
|
||||
properties.has("_filter") ||
|
||||
properties.has("sortColumn") ||
|
||||
properties.has("sortDirection")
|
||||
) {
|
||||
this._lastSelectedRowId = null;
|
||||
}
|
||||
|
||||
if (properties.has("selectable") || properties.has("hiddenColumns")) {
|
||||
this._filteredData = [...this._filteredData];
|
||||
}
|
||||
@@ -542,7 +560,7 @@ export class HaDataTable extends LitElement {
|
||||
>
|
||||
<ha-checkbox
|
||||
class="mdc-data-table__row-checkbox"
|
||||
@change=${this._handleRowCheckboxClick}
|
||||
@click=${this._handleRowCheckboxClicked}
|
||||
.rowId=${row[this.id]}
|
||||
.disabled=${row.selectable === false}
|
||||
.checked=${this._checkedRows.includes(String(row[this.id]))}
|
||||
@@ -603,7 +621,7 @@ export class HaDataTable extends LitElement {
|
||||
.map(
|
||||
([key2, column2], i) =>
|
||||
html`${i !== 0
|
||||
? " ⸱ "
|
||||
? " · "
|
||||
: nothing}${column2.template
|
||||
? column2.template(row)
|
||||
: row[key2]}`
|
||||
@@ -724,6 +742,7 @@ export class HaDataTable extends LitElement {
|
||||
Object.entries(sorted).forEach(([groupName, rows]) => {
|
||||
groupedItems.push({
|
||||
append: true,
|
||||
selectable: false,
|
||||
content: html`<div
|
||||
class="mdc-data-table__cell group-header"
|
||||
role="cell"
|
||||
@@ -750,7 +769,7 @@ export class HaDataTable extends LitElement {
|
||||
}
|
||||
|
||||
if (appendRow) {
|
||||
items.push({ append: true, content: appendRow });
|
||||
items.push({ append: true, selectable: false, content: appendRow });
|
||||
}
|
||||
|
||||
if (hasFab) {
|
||||
@@ -800,23 +819,84 @@ export class HaDataTable extends LitElement {
|
||||
this._checkedRows = [];
|
||||
this._checkedRowsChanged();
|
||||
}
|
||||
this._lastSelectedRowId = null;
|
||||
}
|
||||
|
||||
private _handleRowCheckboxClick = (ev: Event) => {
|
||||
private _handleRowCheckboxClicked = (ev: Event) => {
|
||||
const checkbox = ev.currentTarget as HaCheckbox;
|
||||
const rowId = (checkbox as any).rowId;
|
||||
|
||||
if (checkbox.checked) {
|
||||
if (this._checkedRows.includes(rowId)) {
|
||||
return;
|
||||
const groupedData = this._groupData(
|
||||
this._filteredData,
|
||||
this.localizeFunc || this.hass.localize,
|
||||
this.appendRow,
|
||||
this.hasFab,
|
||||
this.groupColumn,
|
||||
this.groupOrder,
|
||||
this._collapsedGroups
|
||||
);
|
||||
|
||||
if (
|
||||
groupedData.find((data) => data[this.id] === rowId)?.selectable === false
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
const rowIndex = groupedData.findIndex((data) => data[this.id] === rowId);
|
||||
|
||||
if (
|
||||
ev instanceof MouseEvent &&
|
||||
ev.shiftKey &&
|
||||
this._lastSelectedRowId !== null
|
||||
) {
|
||||
const lastSelectedRowIndex = groupedData.findIndex(
|
||||
(data) => data[this.id] === this._lastSelectedRowId
|
||||
);
|
||||
|
||||
if (lastSelectedRowIndex > -1 && rowIndex > -1) {
|
||||
this._checkedRows = [
|
||||
...this._checkedRows,
|
||||
...this._selectRange(groupedData, lastSelectedRowIndex, rowIndex),
|
||||
];
|
||||
}
|
||||
} else if (!checkbox.checked) {
|
||||
if (!this._checkedRows.includes(rowId)) {
|
||||
this._checkedRows = [...this._checkedRows, rowId];
|
||||
}
|
||||
this._checkedRows = [...this._checkedRows, rowId];
|
||||
} else {
|
||||
this._checkedRows = this._checkedRows.filter((row) => row !== rowId);
|
||||
}
|
||||
|
||||
if (rowIndex > -1) {
|
||||
this._lastSelectedRowId = rowId;
|
||||
}
|
||||
this._checkedRowsChanged();
|
||||
};
|
||||
|
||||
private _selectRange(
|
||||
groupedData: DataTableRowData[],
|
||||
startIndex: number,
|
||||
endIndex: number
|
||||
) {
|
||||
const start = Math.min(startIndex, endIndex);
|
||||
const end = Math.max(startIndex, endIndex);
|
||||
|
||||
const checkedRows: string[] = [];
|
||||
|
||||
for (let i = start; i <= end; i++) {
|
||||
const row = groupedData[i];
|
||||
if (
|
||||
row &&
|
||||
row.selectable !== false &&
|
||||
!this._checkedRows.includes(row[this.id])
|
||||
) {
|
||||
checkedRows.push(row[this.id]);
|
||||
}
|
||||
}
|
||||
|
||||
return checkedRows;
|
||||
}
|
||||
|
||||
private _handleRowClick = (ev: Event) => {
|
||||
if (
|
||||
ev
|
||||
@@ -858,6 +938,7 @@ export class HaDataTable extends LitElement {
|
||||
if (this.filter) {
|
||||
return;
|
||||
}
|
||||
this._lastSelectedRowId = null;
|
||||
this._debounceSearch(ev.detail.value);
|
||||
}
|
||||
|
||||
@@ -894,11 +975,13 @@ export class HaDataTable extends LitElement {
|
||||
} else {
|
||||
this._collapsedGroups = [...this._collapsedGroups, groupName];
|
||||
}
|
||||
this._lastSelectedRowId = null;
|
||||
fireEvent(this, "collapsed-changed", { value: this._collapsedGroups });
|
||||
};
|
||||
|
||||
public expandAllGroups() {
|
||||
this._collapsedGroups = [];
|
||||
this._lastSelectedRowId = null;
|
||||
fireEvent(this, "collapsed-changed", { value: this._collapsedGroups });
|
||||
}
|
||||
|
||||
@@ -916,6 +999,7 @@ export class HaDataTable extends LitElement {
|
||||
delete grouped.undefined;
|
||||
}
|
||||
this._collapsedGroups = Object.keys(grouped);
|
||||
this._lastSelectedRowId = null;
|
||||
fireEvent(this, "collapsed-changed", { value: this._collapsedGroups });
|
||||
}
|
||||
|
||||
@@ -928,12 +1012,12 @@ export class HaDataTable extends LitElement {
|
||||
height: 100%;
|
||||
}
|
||||
.mdc-data-table__content {
|
||||
font-family: Roboto, sans-serif;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
font-family: var(--ha-font-family-body);
|
||||
-moz-osx-font-smoothing: var(--ha-moz-osx-font-smoothing);
|
||||
-webkit-font-smoothing: var(--ha-font-smoothing);
|
||||
font-size: 0.875rem;
|
||||
line-height: 1.25rem;
|
||||
font-weight: 400;
|
||||
font-weight: var(--ha-font-weight-normal);
|
||||
letter-spacing: 0.0178571429em;
|
||||
text-decoration: inherit;
|
||||
text-transform: inherit;
|
||||
@@ -1048,12 +1132,12 @@ export class HaDataTable extends LitElement {
|
||||
}
|
||||
|
||||
.mdc-data-table__cell {
|
||||
font-family: Roboto, sans-serif;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
font-family: var(--ha-font-family-body);
|
||||
-moz-osx-font-smoothing: var(--ha-moz-osx-font-smoothing);
|
||||
-webkit-font-smoothing: var(--ha-font-smoothing);
|
||||
font-size: 0.875rem;
|
||||
line-height: 1.25rem;
|
||||
font-weight: 400;
|
||||
font-weight: var(--ha-font-weight-normal);
|
||||
letter-spacing: 0.0178571429em;
|
||||
text-decoration: inherit;
|
||||
text-transform: inherit;
|
||||
@@ -1170,12 +1254,12 @@ export class HaDataTable extends LitElement {
|
||||
}
|
||||
|
||||
.mdc-data-table__header-cell {
|
||||
font-family: Roboto, sans-serif;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
font-family: var(--ha-font-family-body);
|
||||
-moz-osx-font-smoothing: var(--ha-moz-osx-font-smoothing);
|
||||
-webkit-font-smoothing: var(--ha-font-smoothing);
|
||||
font-size: 0.875rem;
|
||||
line-height: 1.375rem;
|
||||
font-weight: 500;
|
||||
font-weight: var(--ha-font-weight-medium);
|
||||
letter-spacing: 0.0071428571em;
|
||||
text-decoration: inherit;
|
||||
text-transform: inherit;
|
||||
@@ -1199,7 +1283,7 @@ export class HaDataTable extends LitElement {
|
||||
padding-inline-start: 12px;
|
||||
padding-inline-end: initial;
|
||||
width: 100%;
|
||||
font-weight: 500;
|
||||
font-weight: var(--ha-font-weight-medium);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
|
@@ -73,16 +73,20 @@ class HaEntityAttributePicker extends LitElement {
|
||||
return nothing;
|
||||
}
|
||||
|
||||
const stateObj = this.hass.states[this.entityId!] as HassEntity | undefined;
|
||||
|
||||
return html`
|
||||
<ha-combo-box
|
||||
.hass=${this.hass}
|
||||
.value=${this.value
|
||||
? computeAttributeNameDisplay(
|
||||
this.hass.localize,
|
||||
this.hass.states[this.entityId!],
|
||||
this.hass.entities,
|
||||
this.value
|
||||
)
|
||||
? stateObj
|
||||
? computeAttributeNameDisplay(
|
||||
this.hass.localize,
|
||||
stateObj,
|
||||
this.hass.entities,
|
||||
this.value
|
||||
)
|
||||
: this.value
|
||||
: ""}
|
||||
.autofocus=${this.autofocus}
|
||||
.label=${this.label ??
|
||||
|
@@ -5,7 +5,6 @@ import type { HassEntity } from "home-assistant-js-websocket";
|
||||
import type { PropertyValues, TemplateResult } from "lit";
|
||||
import { html, LitElement, nothing } from "lit";
|
||||
import { customElement, property, query, state } from "lit/decorators";
|
||||
import { styleMap } from "lit/directives/style-map";
|
||||
import memoizeOne from "memoize-one";
|
||||
import { fireEvent } from "../../common/dom/fire_event";
|
||||
import { computeAreaName } from "../../common/entity/compute_area_name";
|
||||
@@ -30,28 +29,17 @@ import "../ha-icon-button";
|
||||
import "../ha-svg-icon";
|
||||
import "./state-badge";
|
||||
|
||||
const FAKE_ENTITY: HassEntity = {
|
||||
entity_id: "",
|
||||
state: "",
|
||||
last_changed: "",
|
||||
last_updated: "",
|
||||
context: { id: "", user_id: null, parent_id: null },
|
||||
attributes: {},
|
||||
};
|
||||
|
||||
interface EntityComboBoxItem extends HassEntity {
|
||||
interface EntityComboBoxItem {
|
||||
// Force empty label to always display empty value by default in the search field
|
||||
id: string;
|
||||
label: "";
|
||||
primary: string;
|
||||
secondary?: string;
|
||||
translated_domain?: string;
|
||||
show_entity_id?: boolean;
|
||||
entity_name?: string;
|
||||
area_name?: string;
|
||||
device_name?: string;
|
||||
friendly_name?: string;
|
||||
domain_name?: string;
|
||||
search_labels?: string[];
|
||||
sorting_label?: string;
|
||||
icon_path?: string;
|
||||
stateObj?: HassEntity;
|
||||
}
|
||||
|
||||
export type HaEntityComboBoxEntityFilterFunc = (entity: HassEntity) => boolean;
|
||||
@@ -59,22 +47,6 @@ export type HaEntityComboBoxEntityFilterFunc = (entity: HassEntity) => boolean;
|
||||
const CREATE_ID = "___create-new-entity___";
|
||||
const NO_ENTITIES_ID = "___no-entities___";
|
||||
|
||||
const DOMAIN_STYLE = styleMap({
|
||||
fontSize: "var(--ha-font-size-s)",
|
||||
fontWeight: "var(--ha-font-weight-normal)",
|
||||
lineHeight: "var(--ha-line-height-normal)",
|
||||
alignSelf: "flex-end",
|
||||
maxWidth: "30%",
|
||||
textOverflow: "ellipsis",
|
||||
overflow: "hidden",
|
||||
whiteSpace: "nowrap",
|
||||
});
|
||||
|
||||
const ENTITY_ID_STYLE = styleMap({
|
||||
fontFamily: "var(--code-font-family, monospace)",
|
||||
fontSize: "var(--ha-font-size-xs)",
|
||||
});
|
||||
|
||||
@customElement("ha-entity-combo-box")
|
||||
export class HaEntityComboBox extends LitElement {
|
||||
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||
@@ -177,33 +149,43 @@ export class HaEntityComboBox extends LitElement {
|
||||
private _rowRenderer: ComboBoxLitRenderer<EntityComboBoxItem> = (
|
||||
item,
|
||||
{ index }
|
||||
) => html`
|
||||
<ha-combo-box-item type="button" compact .borderTop=${index !== 0}>
|
||||
${item.icon_path
|
||||
? html`<ha-svg-icon slot="start" .path=${item.icon_path}></ha-svg-icon>`
|
||||
: html`
|
||||
<state-badge
|
||||
slot="start"
|
||||
.stateObj=${item}
|
||||
.hass=${this.hass}
|
||||
></state-badge>
|
||||
`}
|
||||
<span slot="headline">${item.primary}</span>
|
||||
${item.secondary
|
||||
? html`<span slot="supporting-text">${item.secondary}</span>`
|
||||
: nothing}
|
||||
${item.entity_id && item.show_entity_id
|
||||
? html`<span slot="supporting-text" style=${ENTITY_ID_STYLE}
|
||||
>${item.entity_id}</span
|
||||
>`
|
||||
: nothing}
|
||||
${item.translated_domain && !item.show_entity_id
|
||||
? html`<div slot="trailing-supporting-text" style=${DOMAIN_STYLE}>
|
||||
${item.translated_domain}
|
||||
</div>`
|
||||
: nothing}
|
||||
</ha-combo-box-item>
|
||||
`;
|
||||
) => {
|
||||
const showEntityId = this.hass.userData?.showEntityIdPicker;
|
||||
|
||||
return html`
|
||||
<ha-combo-box-item type="button" compact .borderTop=${index !== 0}>
|
||||
${item.icon_path
|
||||
? html`
|
||||
<ha-svg-icon slot="start" .path=${item.icon_path}></ha-svg-icon>
|
||||
`
|
||||
: html`
|
||||
<state-badge
|
||||
slot="start"
|
||||
.stateObj=${item.stateObj}
|
||||
.hass=${this.hass}
|
||||
></state-badge>
|
||||
`}
|
||||
<span slot="headline">${item.primary}</span>
|
||||
${item.secondary
|
||||
? html`<span slot="supporting-text">${item.secondary}</span>`
|
||||
: nothing}
|
||||
${item.stateObj && showEntityId
|
||||
? html`
|
||||
<span slot="supporting-text" class="code">
|
||||
${item.stateObj.entity_id}
|
||||
</span>
|
||||
`
|
||||
: nothing}
|
||||
${item.domain_name && !showEntityId
|
||||
? html`
|
||||
<div slot="trailing-supporting-text" class="domain">
|
||||
${item.domain_name}
|
||||
</div>
|
||||
`
|
||||
: nothing}
|
||||
</ha-combo-box-item>
|
||||
`;
|
||||
};
|
||||
|
||||
private _getItems = memoizeOne(
|
||||
(
|
||||
@@ -218,7 +200,7 @@ export class HaEntityComboBox extends LitElement {
|
||||
excludeEntities: this["excludeEntities"],
|
||||
createDomains: this["createDomains"]
|
||||
): EntityComboBoxItem[] => {
|
||||
let states: EntityComboBoxItem[] = [];
|
||||
let items: EntityComboBoxItem[] = [];
|
||||
|
||||
let entityIds = Object.keys(hass.states);
|
||||
|
||||
@@ -236,9 +218,8 @@ export class HaEntityComboBox extends LitElement {
|
||||
);
|
||||
|
||||
return {
|
||||
...FAKE_ENTITY,
|
||||
id: CREATE_ID + domain,
|
||||
label: "",
|
||||
entity_id: CREATE_ID + domain,
|
||||
primary: primary,
|
||||
secondary: this.hass.localize(
|
||||
"ui.components.entity.entity-picker.new_entity"
|
||||
@@ -251,9 +232,8 @@ export class HaEntityComboBox extends LitElement {
|
||||
if (!entityIds.length) {
|
||||
return [
|
||||
{
|
||||
...FAKE_ENTITY,
|
||||
id: NO_ENTITIES_ID,
|
||||
label: "",
|
||||
entity_id: NO_ENTITIES_ID,
|
||||
primary: this.hass!.localize(
|
||||
"ui.components.entity.entity-picker.no_entities"
|
||||
),
|
||||
@@ -289,7 +269,7 @@ export class HaEntityComboBox extends LitElement {
|
||||
|
||||
const isRTL = computeRTL(this.hass);
|
||||
|
||||
states = entityIds
|
||||
items = entityIds
|
||||
.map<EntityComboBoxItem>((entityId) => {
|
||||
const stateObj = hass!.states[entityId];
|
||||
|
||||
@@ -300,30 +280,32 @@ export class HaEntityComboBox extends LitElement {
|
||||
const deviceName = device ? computeDeviceName(device) : undefined;
|
||||
const areaName = area ? computeAreaName(area) : undefined;
|
||||
|
||||
const domainName = domainToName(
|
||||
this.hass.localize,
|
||||
computeDomain(entityId)
|
||||
);
|
||||
|
||||
const primary = entityName || deviceName || entityId;
|
||||
const secondary = [areaName, entityName ? deviceName : undefined]
|
||||
.filter(Boolean)
|
||||
.join(isRTL ? " ◂ " : " ▸ ");
|
||||
|
||||
const translatedDomain = domainToName(
|
||||
this.hass.localize,
|
||||
computeDomain(entityId)
|
||||
);
|
||||
|
||||
return {
|
||||
...hass!.states[entityId],
|
||||
id: entityId,
|
||||
label: "",
|
||||
primary: primary,
|
||||
secondary:
|
||||
secondary ||
|
||||
this.hass.localize("ui.components.device-picker.no_area"),
|
||||
translated_domain: translatedDomain,
|
||||
sorting_label: [deviceName, entityName].filter(Boolean).join("-"),
|
||||
entity_name: entityName || deviceName,
|
||||
area_name: areaName,
|
||||
device_name: deviceName,
|
||||
friendly_name: friendlyName,
|
||||
show_entity_id: hass.userData?.showEntityIdPicker,
|
||||
secondary: secondary,
|
||||
domain_name: domainName,
|
||||
sorting_label: [deviceName, entityName].filter(Boolean).join("_"),
|
||||
search_labels: [
|
||||
entityName,
|
||||
deviceName,
|
||||
areaName,
|
||||
domainName,
|
||||
friendlyName,
|
||||
entityId,
|
||||
].filter(Boolean) as string[],
|
||||
stateObj: stateObj,
|
||||
};
|
||||
})
|
||||
.sort((entityA, entityB) =>
|
||||
@@ -335,41 +317,43 @@ export class HaEntityComboBox extends LitElement {
|
||||
);
|
||||
|
||||
if (includeDeviceClasses) {
|
||||
states = states.filter(
|
||||
(stateObj) =>
|
||||
items = items.filter(
|
||||
(item) =>
|
||||
// We always want to include the entity of the current value
|
||||
stateObj.entity_id === this.value ||
|
||||
(stateObj.attributes.device_class &&
|
||||
includeDeviceClasses.includes(stateObj.attributes.device_class))
|
||||
item.id === this.value ||
|
||||
(item.stateObj?.attributes.device_class &&
|
||||
includeDeviceClasses.includes(
|
||||
item.stateObj.attributes.device_class
|
||||
))
|
||||
);
|
||||
}
|
||||
|
||||
if (includeUnitOfMeasurement) {
|
||||
states = states.filter(
|
||||
(stateObj) =>
|
||||
items = items.filter(
|
||||
(item) =>
|
||||
// We always want to include the entity of the current value
|
||||
stateObj.entity_id === this.value ||
|
||||
(stateObj.attributes.unit_of_measurement &&
|
||||
item.id === this.value ||
|
||||
(item.stateObj?.attributes.unit_of_measurement &&
|
||||
includeUnitOfMeasurement.includes(
|
||||
stateObj.attributes.unit_of_measurement
|
||||
item.stateObj.attributes.unit_of_measurement
|
||||
))
|
||||
);
|
||||
}
|
||||
|
||||
if (entityFilter) {
|
||||
states = states.filter(
|
||||
(stateObj) =>
|
||||
items = items.filter(
|
||||
(item) =>
|
||||
// We always want to include the entity of the current value
|
||||
stateObj.entity_id === this.value || entityFilter!(stateObj)
|
||||
item.id === this.value ||
|
||||
(item.stateObj && entityFilter!(item.stateObj))
|
||||
);
|
||||
}
|
||||
|
||||
if (!states.length) {
|
||||
if (!items.length) {
|
||||
return [
|
||||
{
|
||||
...FAKE_ENTITY,
|
||||
id: NO_ENTITIES_ID,
|
||||
label: "",
|
||||
entity_id: NO_ENTITIES_ID,
|
||||
primary: this.hass!.localize(
|
||||
"ui.components.entity.entity-picker.no_match"
|
||||
),
|
||||
@@ -380,10 +364,10 @@ export class HaEntityComboBox extends LitElement {
|
||||
}
|
||||
|
||||
if (createItems?.length) {
|
||||
states.push(...createItems);
|
||||
items.push(...createItems);
|
||||
}
|
||||
|
||||
return states;
|
||||
return items;
|
||||
}
|
||||
);
|
||||
|
||||
@@ -426,7 +410,9 @@ export class HaEntityComboBox extends LitElement {
|
||||
protected render(): TemplateResult {
|
||||
return html`
|
||||
<ha-combo-box
|
||||
item-value-path="entity_id"
|
||||
item-id-path="id"
|
||||
item-value-path="id"
|
||||
item-label-path="label"
|
||||
.hass=${this.hass}
|
||||
.value=${this._value}
|
||||
.label=${this.label === undefined
|
||||
@@ -478,17 +464,7 @@ export class HaEntityComboBox extends LitElement {
|
||||
}
|
||||
|
||||
private _fuseIndex = memoizeOne((states: EntityComboBoxItem[]) =>
|
||||
Fuse.createIndex(
|
||||
[
|
||||
"entity_name",
|
||||
"device_name",
|
||||
"area_name",
|
||||
"translated_domain",
|
||||
"friendly_name", // for backwards compatibility
|
||||
"entity_id", // for technical search
|
||||
],
|
||||
states
|
||||
)
|
||||
Fuse.createIndex(["search_labels"], states)
|
||||
);
|
||||
|
||||
private _filterChanged(ev: CustomEvent): void {
|
||||
@@ -505,9 +481,8 @@ export class HaEntityComboBox extends LitElement {
|
||||
if (results.length === 0) {
|
||||
target.filteredItems = [
|
||||
{
|
||||
...FAKE_ENTITY,
|
||||
id: NO_ENTITIES_ID,
|
||||
label: "",
|
||||
entity_id: NO_ENTITIES_ID,
|
||||
primary: this.hass!.localize(
|
||||
"ui.components.entity.entity-picker.no_match"
|
||||
),
|
||||
|
@@ -1,6 +1,13 @@
|
||||
import { mdiClose, mdiMenuDown, mdiShape } from "@mdi/js";
|
||||
import type { ComboBoxLightOpenedChangedEvent } from "@vaadin/combo-box/vaadin-combo-box-light";
|
||||
import { css, html, LitElement, nothing, type CSSResultGroup } from "lit";
|
||||
import {
|
||||
css,
|
||||
html,
|
||||
LitElement,
|
||||
nothing,
|
||||
type CSSResultGroup,
|
||||
type PropertyValues,
|
||||
} from "lit";
|
||||
import { customElement, property, query, state } from "lit/decorators";
|
||||
import { fireEvent } from "../../common/dom/fire_event";
|
||||
import { stopPropagation } from "../../common/dom/stop_propagation";
|
||||
@@ -106,6 +113,12 @@ export class HaEntityPicker extends LitElement {
|
||||
|
||||
@state() private _opened = false;
|
||||
|
||||
protected firstUpdated(changedProperties: PropertyValues): void {
|
||||
super.firstUpdated(changedProperties);
|
||||
// Load title translations so it is available when the combo-box opens
|
||||
this.hass.loadBackendTranslation("title");
|
||||
}
|
||||
|
||||
private _renderContent() {
|
||||
const entityId = this.value || "";
|
||||
|
||||
@@ -162,10 +175,7 @@ export class HaEntityPicker extends LitElement {
|
||||
slot="start"
|
||||
></state-badge>
|
||||
<span slot="headline">${primary}</span>
|
||||
<span slot="supporting-text">
|
||||
${secondary ||
|
||||
this.hass.localize("ui.components.device-picker.no_area")}
|
||||
</span>
|
||||
<span slot="supporting-text">${secondary}</span>
|
||||
${showClearIcon
|
||||
? html`<ha-icon-button
|
||||
class="clear"
|
||||
|
@@ -267,7 +267,7 @@ export class HaStateLabelBadge extends LitElement {
|
||||
cursor: pointer;
|
||||
}
|
||||
.big {
|
||||
font-size: 70%;
|
||||
font-size: var(--ha-font-size-xs);
|
||||
}
|
||||
ha-label-badge {
|
||||
--ha-label-badge-color: var(--label-badge-red);
|
||||
|
@@ -1,11 +1,10 @@
|
||||
import { mdiChartLine, mdiShape } from "@mdi/js";
|
||||
import { mdiChartLine, mdiHelpCircle, mdiShape } from "@mdi/js";
|
||||
import type { ComboBoxLitRenderer } from "@vaadin/combo-box/lit";
|
||||
import Fuse from "fuse.js";
|
||||
import type { HassEntity } from "home-assistant-js-websocket";
|
||||
import type { PropertyValues, TemplateResult } from "lit";
|
||||
import { html, LitElement, nothing } from "lit";
|
||||
import { customElement, property, query, state } from "lit/decorators";
|
||||
import { styleMap } from "lit/directives/style-map";
|
||||
import memoizeOne from "memoize-one";
|
||||
import { ensureArray } from "../../common/array/ensure-array";
|
||||
import { fireEvent } from "../../common/dom/fire_event";
|
||||
@@ -26,31 +25,27 @@ import type { HaComboBox } from "../ha-combo-box";
|
||||
import "../ha-combo-box-item";
|
||||
import "../ha-svg-icon";
|
||||
import "./state-badge";
|
||||
import { documentationUrl } from "../../util/documentation-url";
|
||||
|
||||
type StatisticItemType = "entity" | "external" | "no_state";
|
||||
|
||||
interface StatisticItem {
|
||||
// Force empty label to always display empty value by default in the search field
|
||||
id: string;
|
||||
statistic_id?: string;
|
||||
label: "";
|
||||
primary: string;
|
||||
secondary?: string;
|
||||
show_entity_id?: boolean;
|
||||
entity_name?: string;
|
||||
area_name?: string;
|
||||
device_name?: string;
|
||||
friendly_name?: string;
|
||||
search_labels?: string[];
|
||||
sorting_label?: string;
|
||||
state?: HassEntity;
|
||||
icon_path?: string;
|
||||
type?: StatisticItemType;
|
||||
iconPath?: string;
|
||||
stateObj?: HassEntity;
|
||||
}
|
||||
|
||||
const TYPE_ORDER = ["entity", "external", "no_state"] as StatisticItemType[];
|
||||
const MISSING_ID = "___missing-entity___";
|
||||
|
||||
const ENTITY_ID_STYLE = styleMap({
|
||||
fontFamily: "var(--code-font-family, monospace)",
|
||||
fontSize: "11px",
|
||||
});
|
||||
const TYPE_ORDER = ["entity", "external", "no_state"] as StatisticItemType[];
|
||||
|
||||
@customElement("ha-statistic-combo-box")
|
||||
export class HaStatisticComboBox extends LitElement {
|
||||
@@ -131,37 +126,39 @@ export class HaStatisticComboBox extends LitElement {
|
||||
private _rowRenderer: ComboBoxLitRenderer<StatisticItem> = (
|
||||
item,
|
||||
{ index }
|
||||
) => html`
|
||||
<ha-combo-box-item type="button" compact .borderTop=${index !== 0}>
|
||||
${!item.state
|
||||
? html`
|
||||
<ha-svg-icon
|
||||
style="margin: 0 4px"
|
||||
slot="start"
|
||||
.path=${item.iconPath}
|
||||
></ha-svg-icon>
|
||||
`
|
||||
: html`
|
||||
<state-badge
|
||||
slot="start"
|
||||
.stateObj=${item.state}
|
||||
.hass=${this.hass}
|
||||
></state-badge>
|
||||
`}
|
||||
|
||||
<span slot="headline">${item.primary} </span>
|
||||
${item.secondary
|
||||
? html`<span slot="supporting-text">${item.secondary}</span>`
|
||||
: nothing}
|
||||
${item.id && item.show_entity_id
|
||||
? html`
|
||||
<span slot="supporting-text" style=${ENTITY_ID_STYLE}>
|
||||
${item.id}
|
||||
</span>
|
||||
`
|
||||
: nothing}
|
||||
</ha-combo-box-item>
|
||||
`;
|
||||
) => {
|
||||
const showEntityId = this.hass.userData?.showEntityIdPicker;
|
||||
return html`
|
||||
<ha-combo-box-item type="button" compact .borderTop=${index !== 0}>
|
||||
${item.icon_path
|
||||
? html`
|
||||
<ha-svg-icon
|
||||
style="margin: 0 4px"
|
||||
slot="start"
|
||||
.path=${item.icon_path}
|
||||
></ha-svg-icon>
|
||||
`
|
||||
: item.stateObj
|
||||
? html`
|
||||
<state-badge
|
||||
slot="start"
|
||||
.stateObj=${item.stateObj}
|
||||
.hass=${this.hass}
|
||||
></state-badge>
|
||||
`
|
||||
: nothing}
|
||||
<span slot="headline">${item.primary} </span>
|
||||
${item.secondary
|
||||
? html`<span slot="supporting-text">${item.secondary}</span>`
|
||||
: nothing}
|
||||
${item.id && showEntityId
|
||||
? html`<span slot="supporting-text" class="code">
|
||||
${item.statistic_id}
|
||||
</span>`
|
||||
: nothing}
|
||||
</ha-combo-box-item>
|
||||
`;
|
||||
};
|
||||
|
||||
private _getItems = memoizeOne(
|
||||
(
|
||||
@@ -249,19 +246,22 @@ export class HaStatisticComboBox extends LitElement {
|
||||
label: "",
|
||||
type,
|
||||
sorting_label: label,
|
||||
iconPath: mdiShape,
|
||||
search_labels: [label, id],
|
||||
icon_path: mdiShape,
|
||||
});
|
||||
} else if (type === "external") {
|
||||
const domain = id.split(":")[0];
|
||||
const domainName = domainToName(this.hass.localize, domain);
|
||||
output.push({
|
||||
id,
|
||||
statistic_id: id,
|
||||
primary: label,
|
||||
secondary: domainName,
|
||||
label: "",
|
||||
type,
|
||||
sorting_label: label,
|
||||
iconPath: mdiChartLine,
|
||||
search_labels: [label, domainName, id],
|
||||
icon_path: mdiChartLine,
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -283,17 +283,20 @@ export class HaStatisticComboBox extends LitElement {
|
||||
|
||||
output.push({
|
||||
id,
|
||||
statistic_id: id,
|
||||
label: "",
|
||||
primary,
|
||||
secondary,
|
||||
label: "",
|
||||
state: stateObj,
|
||||
stateObj: stateObj,
|
||||
type: "entity",
|
||||
sorting_label: [deviceName, entityName].join("_"),
|
||||
entity_name: entityName || deviceName,
|
||||
area_name: areaName,
|
||||
device_name: deviceName,
|
||||
friendly_name: friendlyName,
|
||||
show_entity_id: hass.userData?.showEntityIdPicker,
|
||||
search_labels: [
|
||||
entityName,
|
||||
deviceName,
|
||||
areaName,
|
||||
friendlyName,
|
||||
id,
|
||||
].filter(Boolean) as string[],
|
||||
});
|
||||
});
|
||||
|
||||
@@ -323,11 +326,12 @@ export class HaStatisticComboBox extends LitElement {
|
||||
}
|
||||
|
||||
output.push({
|
||||
id: "__missing",
|
||||
id: MISSING_ID,
|
||||
primary: this.hass.localize(
|
||||
"ui.components.statistic-picker.missing_entity"
|
||||
),
|
||||
label: "",
|
||||
icon_path: mdiHelpCircle,
|
||||
});
|
||||
|
||||
return output;
|
||||
@@ -392,6 +396,9 @@ export class HaStatisticComboBox extends LitElement {
|
||||
|
||||
return html`
|
||||
<ha-combo-box
|
||||
item-id-path="id"
|
||||
item-value-path="id"
|
||||
item-label-path="label"
|
||||
.hass=${this.hass}
|
||||
.label=${this.label === undefined && this.hass
|
||||
? this.hass.localize("ui.components.statistic-picker.statistic")
|
||||
@@ -401,9 +408,6 @@ export class HaStatisticComboBox extends LitElement {
|
||||
.disabled=${this.disabled}
|
||||
.allowCustomValue=${this.allowCustomEntity}
|
||||
.filteredItems=${this._items}
|
||||
item-value-path="id"
|
||||
item-id-path="id"
|
||||
item-label-path="label"
|
||||
@opened-changed=${this._openedChanged}
|
||||
@value-changed=${this._statisticChanged}
|
||||
@filter-changed=${this._filterChanged}
|
||||
@@ -422,8 +426,12 @@ export class HaStatisticComboBox extends LitElement {
|
||||
private _statisticChanged(ev: ValueChangedEvent<string>) {
|
||||
ev.stopPropagation();
|
||||
let newValue = ev.detail.value;
|
||||
if (newValue === "__missing") {
|
||||
if (newValue === MISSING_ID) {
|
||||
newValue = "";
|
||||
window.open(
|
||||
documentationUrl(this.hass, this.helpMissingEntityUrl),
|
||||
"_blank"
|
||||
);
|
||||
}
|
||||
|
||||
if (newValue !== this._value) {
|
||||
@@ -436,16 +444,7 @@ export class HaStatisticComboBox extends LitElement {
|
||||
}
|
||||
|
||||
private _fuseIndex = memoizeOne((states: StatisticItem[]) =>
|
||||
Fuse.createIndex(
|
||||
[
|
||||
"entity_name",
|
||||
"device_name",
|
||||
"area_name",
|
||||
"friendly_name", // for backwards compatibility
|
||||
"id", // for technical search
|
||||
],
|
||||
states
|
||||
)
|
||||
Fuse.createIndex(["search_labels"], states)
|
||||
);
|
||||
|
||||
private _filterChanged(ev: CustomEvent): void {
|
||||
|
@@ -25,6 +25,36 @@ declare global {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A custom alert component for displaying messages with various alert types.
|
||||
*
|
||||
* @element ha-alert
|
||||
*
|
||||
* @property {string} title - The title of the alert. Defaults to an empty string.
|
||||
* @property {"info" | "warning" | "error" | "success"} alertType - The type of alert to display.
|
||||
* Defaults to "info". Determines the styling and icon used.
|
||||
* @property {boolean} dismissable - Whether the alert can be dismissed. Defaults to `false`.
|
||||
* If `true`, a dismiss button is displayed.
|
||||
* @property {boolean} narrow - Whether the alert should use a narrow layout. Defaults to `false`.
|
||||
*
|
||||
* @slot - The main content of the alert.
|
||||
* @slot icon - Slot for providing a custom icon for the alert.
|
||||
* @slot action - Slot for providing custom actions or buttons for the alert.
|
||||
*
|
||||
* @fires alert-dismissed-clicked - Fired when the dismiss button is clicked.
|
||||
*
|
||||
* @csspart issue-type - The container for the alert.
|
||||
* @csspart icon - The container for the alert icon.
|
||||
* @csspart content - The container for the alert content.
|
||||
* @csspart action - The container for the alert actions.
|
||||
* @csspart title - The container for the alert title.
|
||||
*
|
||||
* @cssprop --info-color - The color used for "info" alerts.
|
||||
* @cssprop --warning-color - The color used for "warning" alerts.
|
||||
* @cssprop --error-color - The color used for "error" alerts.
|
||||
* @cssprop --success-color - The color used for "success" alerts.
|
||||
* @cssprop --primary-text-color - The primary text color used in the alert.
|
||||
*/
|
||||
@customElement("ha-alert")
|
||||
class HaAlert extends LitElement {
|
||||
// eslint-disable-next-line lit/no-native-attributes
|
||||
@@ -35,7 +65,7 @@ class HaAlert extends LitElement {
|
||||
| "warning"
|
||||
| "error"
|
||||
| "success" = "info";
|
||||
|
||||
|
||||
@property({ type: Boolean }) public dismissable = false;
|
||||
|
||||
@property({ type: Boolean }) public narrow = false;
|
||||
@@ -129,7 +159,7 @@ class HaAlert extends LitElement {
|
||||
}
|
||||
.title {
|
||||
margin-top: 2px;
|
||||
font-weight: bold;
|
||||
font-weight: var(--ha-font-weight-bold);
|
||||
}
|
||||
.action mwc-button,
|
||||
.action ha-icon-button {
|
||||
|
@@ -56,7 +56,7 @@ export class HaAnsiToHtml extends LitElement {
|
||||
overflow-wrap: break-word;
|
||||
}
|
||||
.bold {
|
||||
font-weight: bold;
|
||||
font-weight: var(--ha-font-weight-bold);
|
||||
}
|
||||
.italic {
|
||||
font-style: italic;
|
||||
|
@@ -595,7 +595,7 @@ export class HaAssistChat extends LitElement {
|
||||
}
|
||||
.message {
|
||||
white-space: pre-line;
|
||||
font-size: 18px;
|
||||
font-size: var(--ha-font-size-l);
|
||||
clear: both;
|
||||
margin: 8px 0;
|
||||
padding: 8px;
|
||||
@@ -604,7 +604,7 @@ export class HaAssistChat extends LitElement {
|
||||
|
||||
@media all and (max-width: 450px), all and (max-height: 500px) {
|
||||
.message {
|
||||
font-size: 16px;
|
||||
font-size: var(--ha-font-size-l);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -95,9 +95,9 @@ export class HaBadge extends LitElement {
|
||||
text-align: center;
|
||||
}
|
||||
.label {
|
||||
font-size: 10px;
|
||||
font-size: var(--ha-font-size-xs);
|
||||
font-style: normal;
|
||||
font-weight: 500;
|
||||
font-weight: var(--ha-font-weight-medium);
|
||||
line-height: 10px;
|
||||
letter-spacing: 0.1px;
|
||||
color: var(--secondary-text-color);
|
||||
@@ -105,7 +105,7 @@ export class HaBadge extends LitElement {
|
||||
.content {
|
||||
font-size: var(--ha-badge-font-size, var(--ha-font-size-s));
|
||||
font-style: normal;
|
||||
font-weight: 500;
|
||||
font-weight: var(--ha-font-weight-medium);
|
||||
line-height: 16px;
|
||||
letter-spacing: 0.1px;
|
||||
color: var(--primary-text-color);
|
||||
|
@@ -381,15 +381,18 @@ export class HaBaseTimeInput extends LitElement {
|
||||
border-bottom-width: 1px;
|
||||
}
|
||||
label {
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: var(--ha-moz-osx-font-smoothing);
|
||||
-webkit-font-smoothing: var(--ha-font-smoothing);
|
||||
font-family: var(
|
||||
--mdc-typography-body2-font-family,
|
||||
var(--mdc-typography-font-family, Roboto, sans-serif)
|
||||
var(--mdc-typography-font-family, var(--ha-font-family-body))
|
||||
);
|
||||
font-size: var(--mdc-typography-body2-font-size, 0.875rem);
|
||||
font-size: var(--mdc-typography-body2-font-size, var(--ha-font-size-s));
|
||||
line-height: var(--mdc-typography-body2-line-height, 1.25rem);
|
||||
font-weight: var(--mdc-typography-body2-font-weight, 400);
|
||||
font-weight: var(
|
||||
--mdc-typography-body2-font-weight,
|
||||
var(--ha-font-weight-normal)
|
||||
);
|
||||
letter-spacing: var(
|
||||
--mdc-typography-body2-letter-spacing,
|
||||
0.0178571429em
|
||||
|
@@ -41,14 +41,14 @@ export class HaCard extends LitElement {
|
||||
:host ::slotted(.card-header) {
|
||||
color: var(--ha-card-header-color, var(--primary-text-color));
|
||||
font-family: var(--ha-card-header-font-family, inherit);
|
||||
font-size: var(--ha-card-header-font-size, 24px);
|
||||
font-size: var(--ha-card-header-font-size, var(--ha-font-size-2xl));
|
||||
letter-spacing: -0.012em;
|
||||
line-height: 48px;
|
||||
padding: 12px 16px 16px;
|
||||
display: block;
|
||||
margin-block-start: 0px;
|
||||
margin-block-end: 0px;
|
||||
font-weight: normal;
|
||||
font-weight: var(--ha-font-weight-normal);
|
||||
}
|
||||
|
||||
:host ::slotted(.card-content:not(:first-child)),
|
||||
|
@@ -154,7 +154,7 @@ class HaClimateState extends LitElement {
|
||||
}
|
||||
|
||||
.state-label {
|
||||
font-weight: bold;
|
||||
font-weight: var(--ha-font-weight-bold);
|
||||
}
|
||||
|
||||
.unit {
|
||||
|
@@ -22,12 +22,12 @@ export class HaComboBoxItem extends HaMdListItem {
|
||||
}
|
||||
[slot="headline"] {
|
||||
line-height: 22px;
|
||||
font-size: 14px;
|
||||
font-size: var(--ha-font-size-m);
|
||||
white-space: nowrap;
|
||||
}
|
||||
[slot="supporting-text"] {
|
||||
line-height: 18px;
|
||||
font-size: 12px;
|
||||
font-size: var(--ha-font-size-s);
|
||||
white-space: nowrap;
|
||||
}
|
||||
::slotted(state-badge),
|
||||
@@ -35,6 +35,20 @@ export class HaComboBoxItem extends HaMdListItem {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
}
|
||||
::slotted(.code) {
|
||||
font-family: var(--ha-font-family-code);
|
||||
font-size: var(--ha-font-size-xs);
|
||||
}
|
||||
::slotted(.domain) {
|
||||
font-size: var(--ha-font-size-s);
|
||||
font-weight: var(--ha-font-weight-normal);
|
||||
line-height: var(--ha-line-height-normal);
|
||||
align-self: flex-end;
|
||||
max-width: 30%;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
}
|
||||
`,
|
||||
];
|
||||
}
|
||||
|
@@ -58,8 +58,8 @@ export class HaControlButton extends LitElement {
|
||||
padding: var(--control-button-padding);
|
||||
box-sizing: border-box;
|
||||
line-height: inherit;
|
||||
font-family: Roboto;
|
||||
font-weight: 500;
|
||||
font-family: var(--ha-font-family-body);
|
||||
font-weight: var(--ha-font-weight-medium);
|
||||
outline: none;
|
||||
overflow: hidden;
|
||||
background: none;
|
||||
|
@@ -194,7 +194,7 @@ export class HaControlNumberButton extends LitElement {
|
||||
color: var(--primary-text-color);
|
||||
-webkit-tap-highlight-color: transparent;
|
||||
font-style: normal;
|
||||
font-weight: 500;
|
||||
font-weight: var(--ha-font-weight-medium);
|
||||
transition: color 180ms ease-in-out;
|
||||
}
|
||||
:host([disabled]) {
|
||||
|
@@ -179,7 +179,7 @@ export class HaControlSelectMenu extends SelectBase {
|
||||
--control-select-menu-padding: 6px 10px;
|
||||
--mdc-icon-size: 20px;
|
||||
--ha-ripple-color: var(--secondary-text-color);
|
||||
font-size: 14px;
|
||||
font-size: var(--ha-font-size-m);
|
||||
line-height: 1.4;
|
||||
width: auto;
|
||||
color: var(--primary-text-color);
|
||||
@@ -208,7 +208,7 @@ export class HaControlSelectMenu extends SelectBase {
|
||||
width: 100%;
|
||||
user-select: none;
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-weight: var(--ha-font-weight-normal);
|
||||
letter-spacing: 0.25px;
|
||||
}
|
||||
.content {
|
||||
|
@@ -207,7 +207,7 @@ export class HaControlSelect extends LitElement {
|
||||
outline: none;
|
||||
transition: box-shadow 180ms ease-in-out;
|
||||
font-style: normal;
|
||||
font-weight: 500;
|
||||
font-weight: var(--ha-font-weight-medium);
|
||||
color: var(--primary-text-color);
|
||||
user-select: none;
|
||||
-webkit-tap-highlight-color: transparent;
|
||||
|
@@ -368,7 +368,7 @@ export class HaControlSlider extends LitElement {
|
||||
--control-slider-background-opacity: 0.2;
|
||||
--control-slider-thickness: 40px;
|
||||
--control-slider-border-radius: 10px;
|
||||
--control-slider-tooltip-font-size: 14px;
|
||||
--control-slider-tooltip-font-size: var(--ha-font-size-m);
|
||||
height: var(--control-slider-thickness);
|
||||
width: 100%;
|
||||
border-radius: var(--control-slider-border-radius);
|
||||
|
@@ -53,12 +53,12 @@ export class HaDialogHeader extends LitElement {
|
||||
white-space: nowrap;
|
||||
}
|
||||
.header-title {
|
||||
font-size: 22px;
|
||||
font-size: var(--ha-font-size-xl);
|
||||
line-height: 28px;
|
||||
font-weight: 400;
|
||||
font-weight: var(--ha-font-weight-normal);
|
||||
}
|
||||
.header-subtitle {
|
||||
font-size: 14px;
|
||||
font-size: var(--ha-font-size-m);
|
||||
line-height: 20px;
|
||||
color: var(--secondary-text-color);
|
||||
}
|
||||
|
@@ -85,12 +85,12 @@ export class HaDialog extends DialogBase {
|
||||
var(--dialog-backdrop-filter, none)
|
||||
);
|
||||
--mdc-dialog-box-shadow: var(--dialog-box-shadow, none);
|
||||
--mdc-typography-headline6-font-weight: 400;
|
||||
--mdc-typography-headline6-font-weight: var(--ha-font-weight-normal);
|
||||
--mdc-typography-headline6-font-size: 1.574rem;
|
||||
}
|
||||
.mdc-dialog__actions {
|
||||
justify-content: var(--justify-action-buttons, flex-end);
|
||||
padding-bottom: max(env(safe-area-inset-bottom), 24px);
|
||||
padding: 12px 24px max(env(safe-area-inset-bottom), 12px) 24px;
|
||||
}
|
||||
.mdc-dialog__actions span:nth-child(1) {
|
||||
flex: var(--secondary-action-button-flex, unset);
|
||||
@@ -107,9 +107,6 @@ export class HaDialog extends DialogBase {
|
||||
.mdc-dialog__title:has(span) {
|
||||
padding: 12px 12px 0;
|
||||
}
|
||||
.mdc-dialog__actions {
|
||||
padding: 12px 24px 12px 24px;
|
||||
}
|
||||
.mdc-dialog__title::before {
|
||||
content: unset;
|
||||
}
|
||||
|
@@ -188,7 +188,7 @@ export class HaExpansionPanel extends LitElement {
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
overflow: hidden;
|
||||
font-weight: 500;
|
||||
font-weight: var(--ha-font-weight-medium);
|
||||
outline: none;
|
||||
}
|
||||
#summary.noCollapse {
|
||||
@@ -218,7 +218,7 @@ export class HaExpansionPanel extends LitElement {
|
||||
.secondary {
|
||||
display: block;
|
||||
color: var(--secondary-text-color);
|
||||
font-size: 12px;
|
||||
font-size: var(--ha-font-size-s);
|
||||
}
|
||||
`;
|
||||
}
|
||||
|
@@ -294,7 +294,7 @@ export class HaFileUpload extends LitElement {
|
||||
}
|
||||
.supports {
|
||||
color: var(--secondary-text-color);
|
||||
font-size: 12px;
|
||||
font-size: var(--ha-font-size-s);
|
||||
}
|
||||
:host([disabled]) .secondary {
|
||||
color: var(--disabled-text-color);
|
||||
@@ -324,7 +324,7 @@ export class HaFileUpload extends LitElement {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.header {
|
||||
font-weight: 500;
|
||||
font-weight: var(--ha-font-weight-medium);
|
||||
}
|
||||
.progress {
|
||||
color: var(--secondary-text-color);
|
||||
@@ -333,7 +333,7 @@ export class HaFileUpload extends LitElement {
|
||||
background: none;
|
||||
border: none;
|
||||
padding: 0;
|
||||
font-size: 14px;
|
||||
font-size: var(--ha-font-size-m);
|
||||
color: var(--primary-color);
|
||||
text-decoration: underline;
|
||||
cursor: pointer;
|
||||
|
@@ -208,8 +208,8 @@ export class HaFilterBlueprints extends LitElement {
|
||||
min-width: 16px;
|
||||
box-sizing: border-box;
|
||||
border-radius: 50%;
|
||||
font-weight: 400;
|
||||
font-size: 11px;
|
||||
font-size: var(--ha-font-size-xs);
|
||||
font-weight: var(--ha-font-weight-normal);
|
||||
background-color: var(--primary-color);
|
||||
line-height: 16px;
|
||||
text-align: center;
|
||||
|
@@ -303,8 +303,8 @@ export class HaFilterCategories extends SubscribeMixin(LitElement) {
|
||||
min-width: 16px;
|
||||
box-sizing: border-box;
|
||||
border-radius: 50%;
|
||||
font-weight: 400;
|
||||
font-size: 11px;
|
||||
font-size: var(--ha-font-size-xs);
|
||||
font-weight: var(--ha-font-weight-normal);
|
||||
background-color: var(--primary-color);
|
||||
line-height: 16px;
|
||||
text-align: center;
|
||||
|
@@ -232,8 +232,8 @@ export class HaFilterDevices extends LitElement {
|
||||
min-width: 16px;
|
||||
box-sizing: border-box;
|
||||
border-radius: 50%;
|
||||
font-weight: 400;
|
||||
font-size: 11px;
|
||||
font-size: var(--ha-font-size-xs);
|
||||
font-weight: var(--ha-font-weight-normal);
|
||||
background-color: var(--primary-color);
|
||||
line-height: 16px;
|
||||
text-align: center;
|
||||
|
@@ -189,8 +189,8 @@ export class HaFilterDomains extends LitElement {
|
||||
min-width: 16px;
|
||||
box-sizing: border-box;
|
||||
border-radius: 50%;
|
||||
font-weight: 400;
|
||||
font-size: 11px;
|
||||
font-size: var(--ha-font-size-xs);
|
||||
font-weight: var(--ha-font-weight-normal);
|
||||
background-color: var(--primary-color);
|
||||
line-height: 16px;
|
||||
text-align: center;
|
||||
|
@@ -246,8 +246,8 @@ export class HaFilterEntities extends LitElement {
|
||||
min-width: 16px;
|
||||
box-sizing: border-box;
|
||||
border-radius: 50%;
|
||||
font-weight: 400;
|
||||
font-size: 11px;
|
||||
font-size: var(--ha-font-size-xs);
|
||||
font-weight: var(--ha-font-weight-normal);
|
||||
background-color: var(--primary-color);
|
||||
line-height: 16px;
|
||||
text-align: center;
|
||||
|
@@ -303,8 +303,8 @@ export class HaFilterFloorAreas extends LitElement {
|
||||
min-width: 16px;
|
||||
box-sizing: border-box;
|
||||
border-radius: 50%;
|
||||
font-weight: 400;
|
||||
font-size: 11px;
|
||||
font-size: var(--ha-font-size-xs);
|
||||
font-weight: var(--ha-font-weight-normal);
|
||||
background-color: var(--primary-color);
|
||||
line-height: 16px;
|
||||
text-align: center;
|
||||
|
@@ -195,8 +195,8 @@ export class HaFilterIntegrations extends LitElement {
|
||||
min-width: 16px;
|
||||
box-sizing: border-box;
|
||||
border-radius: 50%;
|
||||
font-weight: 400;
|
||||
font-size: 11px;
|
||||
font-size: var(--ha-font-size-xs);
|
||||
font-weight: var(--ha-font-weight-normal);
|
||||
background-color: var(--primary-color);
|
||||
line-height: 16px;
|
||||
text-align: center;
|
||||
|
@@ -233,8 +233,8 @@ export class HaFilterLabels extends SubscribeMixin(LitElement) {
|
||||
min-width: 16px;
|
||||
box-sizing: border-box;
|
||||
border-radius: 50%;
|
||||
font-weight: 400;
|
||||
font-size: 11px;
|
||||
font-size: var(--ha-font-size-xs);
|
||||
font-weight: var(--ha-font-weight-normal);
|
||||
background-color: var(--primary-color);
|
||||
line-height: 16px;
|
||||
text-align: center;
|
||||
|
@@ -177,8 +177,8 @@ export class HaFilterStates extends LitElement {
|
||||
min-width: 16px;
|
||||
box-sizing: border-box;
|
||||
border-radius: 50%;
|
||||
font-weight: 400;
|
||||
font-size: 11px;
|
||||
font-size: var(--ha-font-size-xs);
|
||||
font-weight: var(--ha-font-weight-normal);
|
||||
background-color: var(--primary-color);
|
||||
line-height: 16px;
|
||||
text-align: center;
|
||||
|
@@ -71,7 +71,10 @@ export class HaFormBoolean extends LitElement implements HaFormElement {
|
||||
box-sizing: border-box;
|
||||
color: var(--secondary-text-color);
|
||||
font-size: 0.875rem;
|
||||
font-weight: var(--mdc-typography-body2-font-weight, 400);
|
||||
font-weight: var(
|
||||
--mdc-typography-body2-font-weight,
|
||||
var(--ha-font-weight-normal)
|
||||
);
|
||||
}
|
||||
`;
|
||||
}
|
||||
|
@@ -20,7 +20,7 @@ export class HaFormConstant extends LitElement implements HaFormElement {
|
||||
display: block;
|
||||
}
|
||||
.label {
|
||||
font-weight: 500;
|
||||
font-weight: var(--ha-font-weight-medium);
|
||||
}
|
||||
`;
|
||||
}
|
||||
|
@@ -46,7 +46,7 @@ export class HaHeaderBar extends LitElement {
|
||||
flex: none;
|
||||
}
|
||||
.mdc-top-app-bar__title {
|
||||
font-size: 20px;
|
||||
font-size: var(--ha-font-size-xl);
|
||||
padding-inline-start: 24px;
|
||||
padding-inline-end: initial;
|
||||
}
|
||||
|
@@ -34,7 +34,7 @@ export class HaBadge extends LitElement {
|
||||
align-items: center;
|
||||
gap: 3px;
|
||||
color: var(--ha-heading-badge-text-color, var(--secondary-text-color));
|
||||
font-size: var(--ha-heading-badge-font-size, 14px);
|
||||
font-size: var(--ha-heading-badge-font-size, var(--ha-font-size-m));
|
||||
font-weight: var(--ha-heading-badge-font-weight, 400);
|
||||
line-height: var(--ha-heading-badge-line-height, 20px);
|
||||
letter-spacing: 0.1px;
|
||||
|
@@ -103,7 +103,7 @@ class HaHumidifierState extends LitElement {
|
||||
}
|
||||
|
||||
.state-label {
|
||||
font-weight: bold;
|
||||
font-weight: var(--ha-font-weight-bold);
|
||||
}
|
||||
|
||||
.unit {
|
||||
|
@@ -91,7 +91,7 @@ class HaLabelBadge extends LitElement {
|
||||
color: var(--ha-label-badge-label-color, white);
|
||||
border-radius: 1em;
|
||||
padding: 9% 16% 8% 16%; /* mostly apitalized text, not much descenders => bit more top margin */
|
||||
font-weight: 500;
|
||||
font-weight: var(--ha-font-weight-medium);
|
||||
overflow: hidden;
|
||||
text-transform: uppercase;
|
||||
text-overflow: ellipsis;
|
||||
@@ -102,7 +102,10 @@ class HaLabelBadge extends LitElement {
|
||||
margin-top: 1em;
|
||||
font-size: var(--ha-label-badge-title-font-size, 0.9em);
|
||||
width: var(--ha-label-badge-title-width, 5em);
|
||||
font-weight: var(--ha-label-badge-title-font-weight, 400);
|
||||
font-weight: var(
|
||||
--ha-label-badge-title-font-weight,
|
||||
var(--ha-font-weight-normal)
|
||||
);
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
line-height: normal;
|
||||
|
@@ -32,8 +32,8 @@ class HaLabel extends LitElement {
|
||||
display: inline-flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
font-size: 12px;
|
||||
font-weight: 500;
|
||||
font-size: var(--ha-font-size-s);
|
||||
font-weight: var(--ha-font-weight-medium);
|
||||
line-height: 16px;
|
||||
letter-spacing: 0.1px;
|
||||
vertical-align: middle;
|
||||
|
@@ -30,8 +30,9 @@ class HaLabeledSlider extends LitElement {
|
||||
@property({ type: Number }) public value?: number;
|
||||
|
||||
protected render() {
|
||||
const title = this._getTitle();
|
||||
return html`
|
||||
<div class="title">${this._getTitle()}</div>
|
||||
${title ? html`<div class="title">${title}</div>` : nothing}
|
||||
<div class="extra-container"><slot name="extra"></slot></div>
|
||||
<div class="slider-container">
|
||||
${this.icon ? html`<ha-icon icon=${this.icon}></ha-icon>` : nothing}
|
||||
@@ -73,17 +74,20 @@ class HaLabeledSlider extends LitElement {
|
||||
|
||||
.slider-container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
ha-icon {
|
||||
margin-top: 8px;
|
||||
color: var(--secondary-text-color);
|
||||
}
|
||||
|
||||
ha-slider {
|
||||
display: flex;
|
||||
flex-grow: 1;
|
||||
align-items: center;
|
||||
background-image: var(--ha-slider-background);
|
||||
border-radius: 4px;
|
||||
height: 32px;
|
||||
}
|
||||
`;
|
||||
}
|
||||
|
@@ -102,7 +102,7 @@ export class HaLanguagePicker extends LitElement {
|
||||
localeChanged
|
||||
) {
|
||||
this._select.layoutOptions();
|
||||
if (this._select.value !== this.value) {
|
||||
if (!this.disabled && this._select.value !== this.value) {
|
||||
fireEvent(this, "value-changed", { value: this._select.value });
|
||||
}
|
||||
if (!this.value) {
|
||||
@@ -141,7 +141,10 @@ export class HaLanguagePicker extends LitElement {
|
||||
);
|
||||
|
||||
const value =
|
||||
this.value ?? (this.required ? languageOptions[0]?.value : this.value);
|
||||
this.value ??
|
||||
(this.required && !this.disabled
|
||||
? languageOptions[0]?.value
|
||||
: this.value);
|
||||
|
||||
return html`
|
||||
<ha-select
|
||||
@@ -182,7 +185,7 @@ export class HaLanguagePicker extends LitElement {
|
||||
|
||||
private _changed(ev): void {
|
||||
const target = ev.target as HaSelect;
|
||||
if (target.value === "" || target.value === this.value) {
|
||||
if (this.disabled || target.value === "" || target.value === this.value) {
|
||||
return;
|
||||
}
|
||||
this.value = target.value;
|
||||
|
@@ -64,7 +64,7 @@ export class HaMarkdown extends LitElement {
|
||||
color: var(--markdown-svg-color, none);
|
||||
}
|
||||
code {
|
||||
font-size: 85%;
|
||||
font-size: var(--ha-font-size-s);
|
||||
padding: 0.2em 0.4em;
|
||||
}
|
||||
pre code {
|
||||
@@ -85,8 +85,8 @@ export class HaMarkdown extends LitElement {
|
||||
line-height: initial;
|
||||
}
|
||||
h2 {
|
||||
font-size: 1.5em;
|
||||
font-weight: bold;
|
||||
font-size: var(--ha-font-size-xl);
|
||||
font-weight: var(--ha-font-weight-bold);
|
||||
}
|
||||
hr {
|
||||
border-color: var(--divider-color);
|
||||
|
@@ -6,6 +6,13 @@ import { customElement } from "lit/decorators";
|
||||
|
||||
@customElement("ha-outlined-icon-button")
|
||||
export class HaOutlinedIconButton extends IconButton {
|
||||
protected override getRenderClasses() {
|
||||
return {
|
||||
...super.getRenderClasses(),
|
||||
outlined: true,
|
||||
};
|
||||
}
|
||||
|
||||
static override styles = [
|
||||
css`
|
||||
.icon-button {
|
||||
|
@@ -37,7 +37,7 @@ export class HaOutlinedTextField extends OutlinedTextField {
|
||||
--mdc-icon-size: var(--md-input-chip-icon-size, 18px);
|
||||
}
|
||||
.input {
|
||||
font-family: Roboto, sans-serif;
|
||||
font-family: var(--ha-font-family-body);
|
||||
}
|
||||
`,
|
||||
];
|
||||
|
@@ -154,8 +154,8 @@ export class HaSelectBox extends LitElement {
|
||||
}
|
||||
.option .content .text .label {
|
||||
color: var(--primary-text-color);
|
||||
font-size: 14px;
|
||||
font-weight: 400;
|
||||
font-size: var(--ha-font-size-m);
|
||||
font-weight: var(--ha-font-weight-normal);
|
||||
line-height: 20px;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
@@ -164,7 +164,7 @@ export class HaSelectBox extends LitElement {
|
||||
.option .content .text .description {
|
||||
color: var(--secondary-text-color);
|
||||
font-size: 13px;
|
||||
font-weight: 400;
|
||||
font-weight: var(--ha-font-weight-normal);
|
||||
line-height: 16px;
|
||||
}
|
||||
img {
|
||||
|
@@ -45,7 +45,7 @@ export class HaActionSelector extends LitElement {
|
||||
label {
|
||||
display: block;
|
||||
margin-bottom: 4px;
|
||||
font-weight: 500;
|
||||
font-weight: var(--ha-font-weight-medium);
|
||||
}
|
||||
`;
|
||||
}
|
||||
|
@@ -62,7 +62,10 @@ export class HaBooleanSelector extends LitElement {
|
||||
box-sizing: border-box;
|
||||
color: var(--secondary-text-color);
|
||||
font-size: 0.875rem;
|
||||
font-weight: var(--mdc-typography-body2-font-weight, 400);
|
||||
font-weight: var(
|
||||
--mdc-typography-body2-font-weight,
|
||||
var(--ha-font-weight-normal)
|
||||
);
|
||||
}
|
||||
`;
|
||||
}
|
||||
|
@@ -36,7 +36,7 @@ export class HaConditionSelector extends LitElement {
|
||||
label {
|
||||
display: block;
|
||||
margin-bottom: 4px;
|
||||
font-weight: 500;
|
||||
font-weight: var(--ha-font-weight-medium);
|
||||
}
|
||||
`;
|
||||
}
|
||||
|
@@ -11,6 +11,7 @@ import type { SchemaUnion } from "../ha-form/types";
|
||||
import type { MarkerLocation } from "../map/ha-locations-editor";
|
||||
import "../map/ha-locations-editor";
|
||||
import "../ha-form/ha-form";
|
||||
import type { LocalizeFunc } from "../../common/translations/localize";
|
||||
|
||||
@customElement("ha-selector-location")
|
||||
export class HaLocationSelector extends LitElement {
|
||||
@@ -27,7 +28,7 @@ export class HaLocationSelector extends LitElement {
|
||||
@property({ type: Boolean, reflect: true }) public disabled = false;
|
||||
|
||||
private _schema = memoizeOne(
|
||||
(radius?: boolean, radius_readonly?: boolean) =>
|
||||
(localize: LocalizeFunc, radius?: boolean, radius_readonly?: boolean) =>
|
||||
[
|
||||
{
|
||||
name: "",
|
||||
@@ -36,12 +37,12 @@ export class HaLocationSelector extends LitElement {
|
||||
{
|
||||
name: "latitude",
|
||||
required: true,
|
||||
selector: { number: { step: "any" } },
|
||||
selector: { number: { step: "any", unit_of_measurement: "°" } },
|
||||
},
|
||||
{
|
||||
name: "longitude",
|
||||
required: true,
|
||||
selector: { number: { step: "any" } },
|
||||
selector: { number: { step: "any", unit_of_measurement: "°" } },
|
||||
},
|
||||
],
|
||||
},
|
||||
@@ -52,7 +53,16 @@ export class HaLocationSelector extends LitElement {
|
||||
required: true,
|
||||
default: 1000,
|
||||
disabled: !!radius_readonly,
|
||||
selector: { number: { min: 0, step: 1, mode: "box" } as const },
|
||||
selector: {
|
||||
number: {
|
||||
min: 0,
|
||||
step: 1,
|
||||
mode: "box",
|
||||
unit_of_measurement: localize(
|
||||
"ui.components.selectors.location.radius_meters"
|
||||
),
|
||||
} as const,
|
||||
},
|
||||
} as const,
|
||||
]
|
||||
: []),
|
||||
@@ -84,6 +94,7 @@ export class HaLocationSelector extends LitElement {
|
||||
<ha-form
|
||||
.hass=${this.hass}
|
||||
.schema=${this._schema(
|
||||
this.hass.localize,
|
||||
this.selector.location?.radius,
|
||||
this.selector.location?.radius_readonly
|
||||
)}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user