mirror of
https://github.com/home-assistant/frontend.git
synced 2026-02-27 11:57:46 +00:00
Compare commits
6 Commits
ha-input
...
auto-jsdoc
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
75e55d9757 | ||
|
|
58f035b028 | ||
|
|
bf9fec5a81 | ||
|
|
040585f693 | ||
|
|
a6b031358c | ||
|
|
2b0a6d7964 |
@@ -5,6 +5,7 @@ import yaml from "js-yaml";
|
||||
import { marked } from "marked";
|
||||
import path from "path";
|
||||
import paths from "../paths.cjs";
|
||||
import { generateComponentApiMarkdown } from "./gallery/api-docs.js";
|
||||
import "./clean.js";
|
||||
import "./entry-html.js";
|
||||
import "./gather-static.js";
|
||||
@@ -39,11 +40,19 @@ gulp.task("gather-gallery-pages", async function gatherPages() {
|
||||
|
||||
const demoFile = path.resolve(pageDir, `${pageId}.ts`);
|
||||
const descriptionFile = path.resolve(pageDir, `${pageId}.markdown`);
|
||||
const componentFile = path.resolve(
|
||||
"src/components",
|
||||
`${path.basename(pageId)}.ts`
|
||||
);
|
||||
const hasDemo = fs.existsSync(demoFile);
|
||||
let hasDescription = fs.existsSync(descriptionFile);
|
||||
let hasApiDocs = false;
|
||||
let metadata = {};
|
||||
let descriptionContent = "";
|
||||
let apiDocsContent = "";
|
||||
|
||||
if (hasDescription) {
|
||||
let descriptionContent = fs.readFileSync(descriptionFile, "utf-8");
|
||||
descriptionContent = fs.readFileSync(descriptionFile, "utf-8");
|
||||
|
||||
if (descriptionContent.startsWith("---")) {
|
||||
const metadataEnd = descriptionContent.indexOf("---", 3);
|
||||
@@ -52,22 +61,45 @@ gulp.task("gather-gallery-pages", async function gatherPages() {
|
||||
.substring(metadataEnd + 3)
|
||||
.trim();
|
||||
}
|
||||
}
|
||||
|
||||
// If description is just metadata
|
||||
if (descriptionContent === "") {
|
||||
hasDescription = false;
|
||||
} else {
|
||||
descriptionContent = marked(descriptionContent).replace(/`/g, "\\`");
|
||||
fs.mkdirSync(path.resolve(galleryBuild, category), { recursive: true });
|
||||
fs.writeFileSync(
|
||||
path.resolve(galleryBuild, `${pageId}-description.ts`),
|
||||
`
|
||||
import {html} from "lit";
|
||||
export default html\`${descriptionContent}\`
|
||||
`
|
||||
if (fs.existsSync(componentFile)) {
|
||||
// eslint-disable-next-line no-await-in-loop
|
||||
const apiDocsMarkdown = await generateComponentApiMarkdown(componentFile);
|
||||
if (apiDocsMarkdown) {
|
||||
hasApiDocs = true;
|
||||
apiDocsContent = marked(`## API docs\n\n${apiDocsMarkdown}`).replace(
|
||||
/`/g,
|
||||
"\\`"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (descriptionContent === "") {
|
||||
hasDescription = false;
|
||||
} else {
|
||||
descriptionContent = marked(descriptionContent).replace(/`/g, "\\`");
|
||||
fs.mkdirSync(path.resolve(galleryBuild, category), { recursive: true });
|
||||
fs.writeFileSync(
|
||||
path.resolve(galleryBuild, `${pageId}-description.ts`),
|
||||
`
|
||||
import {html} from "lit";
|
||||
export default html\`${descriptionContent}\`
|
||||
`
|
||||
);
|
||||
}
|
||||
|
||||
if (hasApiDocs) {
|
||||
fs.mkdirSync(path.resolve(galleryBuild, category), { recursive: true });
|
||||
fs.writeFileSync(
|
||||
path.resolve(galleryBuild, `${pageId}-api-docs.ts`),
|
||||
`
|
||||
import {html} from "lit";
|
||||
export default html\`${apiDocsContent}\`
|
||||
`
|
||||
);
|
||||
}
|
||||
|
||||
content += ` "${pageId}": {
|
||||
metadata: ${JSON.stringify(metadata)},
|
||||
${
|
||||
@@ -75,6 +107,7 @@ gulp.task("gather-gallery-pages", async function gatherPages() {
|
||||
? `description: () => import("./${pageId}-description").then(m => m.default),`
|
||||
: ""
|
||||
}
|
||||
${hasApiDocs ? `apiDocs: () => import("./${pageId}-api-docs").then(m => m.default),` : ""}
|
||||
${hasDemo ? `demo: () => import("../src/pages/${pageId}")` : ""}
|
||||
|
||||
},\n`;
|
||||
|
||||
292
build-scripts/gulp/gallery/api-docs.js
Normal file
292
build-scripts/gulp/gallery/api-docs.js
Normal file
@@ -0,0 +1,292 @@
|
||||
import { cli as analyzeCustomElements } from "@custom-elements-manifest/analyzer/cli.js";
|
||||
import path from "path";
|
||||
|
||||
const toCamelCase = (value) =>
|
||||
value.replace(/-([a-z])/g, (_match, char) => char.toUpperCase());
|
||||
|
||||
const mdCode = (value) => {
|
||||
if (value === undefined || value === null || value === "") {
|
||||
return "";
|
||||
}
|
||||
|
||||
return `\`${String(value).replace(/`/g, "\\`")}\``;
|
||||
};
|
||||
|
||||
const mdText = (value) =>
|
||||
String(value || "")
|
||||
.replace(/\|/g, "\\|")
|
||||
.replace(/\r?\n+/g, "<br>")
|
||||
.trim();
|
||||
|
||||
const markdownTable = (headers, rows) => {
|
||||
if (!rows.length) {
|
||||
return "";
|
||||
}
|
||||
|
||||
const header = `| ${headers.join(" | ")} |`;
|
||||
const separator = `| ${headers.map(() => "---").join(" | ")} |`;
|
||||
const body = rows.map((row) => `| ${row.join(" | ")} |`).join("\n");
|
||||
|
||||
return `${header}\n${separator}\n${body}`;
|
||||
};
|
||||
|
||||
const mergeAttributesIntoFields = (manifest) => {
|
||||
if (!manifest?.modules) {
|
||||
return manifest;
|
||||
}
|
||||
|
||||
for (const mod of manifest.modules) {
|
||||
if (!mod.declarations) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (const declaration of mod.declarations) {
|
||||
if (!declaration.attributes?.length) {
|
||||
continue;
|
||||
}
|
||||
|
||||
declaration.members = declaration.members || [];
|
||||
|
||||
const memberNames = new Set(
|
||||
declaration.members.map((member) => member.name)
|
||||
);
|
||||
const membersByName = new Map(
|
||||
declaration.members.map((member) => [member.name, member])
|
||||
);
|
||||
|
||||
declaration.attributes = declaration.attributes.map((attribute) => {
|
||||
if (attribute.fieldName) {
|
||||
return attribute;
|
||||
}
|
||||
|
||||
const camelName = toCamelCase(attribute.name);
|
||||
let inferredFieldName;
|
||||
|
||||
if (memberNames.has(camelName)) {
|
||||
inferredFieldName = camelName;
|
||||
} else if (memberNames.has(attribute.name)) {
|
||||
inferredFieldName = attribute.name;
|
||||
}
|
||||
|
||||
return inferredFieldName
|
||||
? { ...attribute, fieldName: inferredFieldName }
|
||||
: attribute;
|
||||
});
|
||||
|
||||
for (const attribute of declaration.attributes) {
|
||||
if (!attribute.fieldName) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const existingMember = membersByName.get(attribute.fieldName);
|
||||
if (existingMember) {
|
||||
if (!existingMember.attribute) {
|
||||
existingMember.attribute = attribute.name;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
const newMember = {
|
||||
kind: "field",
|
||||
name: attribute.fieldName,
|
||||
privacy: "public",
|
||||
type: attribute.type,
|
||||
default: attribute.default,
|
||||
description: attribute.description,
|
||||
attribute: attribute.name,
|
||||
};
|
||||
|
||||
declaration.members.push(newMember);
|
||||
membersByName.set(attribute.fieldName, newMember);
|
||||
memberNames.add(attribute.fieldName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return manifest;
|
||||
};
|
||||
|
||||
const formatType = (type) => {
|
||||
if (!type) {
|
||||
return "";
|
||||
}
|
||||
|
||||
if (typeof type === "string") {
|
||||
return type;
|
||||
}
|
||||
|
||||
if (type.text) {
|
||||
return type.text;
|
||||
}
|
||||
|
||||
return "";
|
||||
};
|
||||
|
||||
const getWebAwesomeSuperclassDocsUrl = (superclass) => {
|
||||
const packageName = superclass?.package || "";
|
||||
|
||||
if (!packageName.startsWith("@home-assistant/webawesome")) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const match = packageName.match(/components\/([^/]+)/);
|
||||
if (match?.[1]) {
|
||||
return `https://webawesome.com/docs/components/${match[1]}`;
|
||||
}
|
||||
|
||||
return "https://webawesome.com/docs/components/";
|
||||
};
|
||||
|
||||
const renderComponentApiMarkdown = (manifest) => {
|
||||
if (!manifest?.modules?.length) {
|
||||
return "";
|
||||
}
|
||||
|
||||
const sections = [];
|
||||
|
||||
for (const mod of manifest.modules) {
|
||||
for (const declaration of mod.declarations || []) {
|
||||
if (declaration.kind !== "class") {
|
||||
continue;
|
||||
}
|
||||
|
||||
const classHeading = declaration.tagName
|
||||
? `### ${mdCode(declaration.tagName)}`
|
||||
: `### ${mdCode(declaration.name)}`;
|
||||
sections.push(classHeading);
|
||||
|
||||
if (declaration.description) {
|
||||
sections.push("#### Description");
|
||||
sections.push(mdText(declaration.description));
|
||||
}
|
||||
|
||||
const properties = (declaration.members || [])
|
||||
.filter(
|
||||
(member) => member.kind === "field" && member.privacy !== "private"
|
||||
)
|
||||
.map((member) => [
|
||||
mdCode(member.name),
|
||||
mdText(member.attribute || ""),
|
||||
mdCode(formatType(member.type) || ""),
|
||||
mdCode(member.default || ""),
|
||||
mdText(member.description || ""),
|
||||
]);
|
||||
|
||||
const propertiesTable = markdownTable(
|
||||
["Name", "Attribute", "Type", "Default", "Description"],
|
||||
properties
|
||||
);
|
||||
if (propertiesTable) {
|
||||
sections.push("#### Properties");
|
||||
sections.push(propertiesTable);
|
||||
}
|
||||
|
||||
const events = (declaration.events || []).map((event) => [
|
||||
mdCode(event.name),
|
||||
mdCode(formatType(event.type) || ""),
|
||||
mdText(event.description || ""),
|
||||
]);
|
||||
const eventsTable = markdownTable(
|
||||
["Name", "Type", "Description"],
|
||||
events
|
||||
);
|
||||
if (eventsTable) {
|
||||
sections.push("#### Events");
|
||||
sections.push(eventsTable);
|
||||
}
|
||||
|
||||
const cssProperties = (declaration.cssProperties || []).map(
|
||||
(property) => [
|
||||
mdCode(property.name),
|
||||
mdCode(property.default || ""),
|
||||
mdText(property.description || ""),
|
||||
]
|
||||
);
|
||||
const cssPropertiesTable = markdownTable(
|
||||
["Name", "Default", "Description"],
|
||||
cssProperties
|
||||
);
|
||||
if (cssPropertiesTable) {
|
||||
sections.push("#### CSS custom properties");
|
||||
sections.push(
|
||||
"[How to use CSS custom properties](https://developer.mozilla.org/docs/Web/CSS/CSS_cascading_variables/Using_CSS_custom_properties)"
|
||||
);
|
||||
sections.push(cssPropertiesTable);
|
||||
}
|
||||
|
||||
const cssParts = (declaration.cssParts || []).map((part) => [
|
||||
mdCode(part.name),
|
||||
mdText(part.description || ""),
|
||||
]);
|
||||
const cssPartsTable = markdownTable(["Name", "Description"], cssParts);
|
||||
if (cssPartsTable) {
|
||||
sections.push("#### CSS shadow parts");
|
||||
sections.push(
|
||||
"[How to style shadow parts with ::part()](https://developer.mozilla.org/docs/Web/CSS/::part)"
|
||||
);
|
||||
sections.push(cssPartsTable);
|
||||
}
|
||||
|
||||
const slots = (declaration.slots || []).map((slot) => [
|
||||
mdCode(slot.name || "(default)"),
|
||||
slot.name ? "no" : "yes",
|
||||
mdText(slot.description || ""),
|
||||
]);
|
||||
const slotsTable = markdownTable(
|
||||
["Name", "Default", "Description"],
|
||||
slots
|
||||
);
|
||||
if (slotsTable) {
|
||||
sections.push("#### Slots");
|
||||
sections.push(slotsTable);
|
||||
}
|
||||
|
||||
sections.push("#### Class");
|
||||
sections.push(
|
||||
markdownTable(
|
||||
["Name", "Tag name"],
|
||||
[[mdCode(declaration.name), mdCode(declaration.tagName || "")]]
|
||||
)
|
||||
);
|
||||
|
||||
if (declaration.superclass?.name) {
|
||||
const docsUrl = getWebAwesomeSuperclassDocsUrl(declaration.superclass);
|
||||
const notes = docsUrl ? `[Web Awesome docs](${docsUrl})` : "";
|
||||
|
||||
sections.push("#### Superclass");
|
||||
sections.push(
|
||||
markdownTable(
|
||||
["Name", "Package", "Docs"],
|
||||
[
|
||||
[
|
||||
mdCode(declaration.superclass.name),
|
||||
mdText(declaration.superclass.package || ""),
|
||||
notes,
|
||||
],
|
||||
]
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return sections.filter(Boolean).join("\n\n").trim();
|
||||
};
|
||||
|
||||
export const generateComponentApiMarkdown = async (componentFile) => {
|
||||
const manifest = await analyzeCustomElements({
|
||||
argv: [
|
||||
"analyze",
|
||||
"--litelement",
|
||||
"--globs",
|
||||
path.relative(process.cwd(), componentFile),
|
||||
"--quiet",
|
||||
],
|
||||
cwd: process.cwd(),
|
||||
noWrite: true,
|
||||
});
|
||||
|
||||
mergeAttributesIntoFields(manifest);
|
||||
return renderComponentApiMarkdown(manifest);
|
||||
};
|
||||
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"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
51
gallery/src/components/page-api-docs.ts
Normal file
51
gallery/src/components/page-api-docs.ts
Normal file
@@ -0,0 +1,51 @@
|
||||
import { css, html, nothing } from "lit";
|
||||
import { customElement, property } from "lit/decorators";
|
||||
import { until } from "lit/directives/until";
|
||||
import { HaMarkdown } from "../../../src/components/ha-markdown";
|
||||
import { PAGES } from "../../build/import-pages";
|
||||
|
||||
@customElement("page-api-docs")
|
||||
class PageApiDocs extends HaMarkdown {
|
||||
@property() public page!: string;
|
||||
|
||||
render() {
|
||||
if (!PAGES[this.page].apiDocs) {
|
||||
return nothing;
|
||||
}
|
||||
|
||||
return html`${until(
|
||||
PAGES[this.page]
|
||||
.apiDocs()
|
||||
.then((content) => html`<div class="root">${content}</div>`),
|
||||
""
|
||||
)}`;
|
||||
}
|
||||
|
||||
static styles = [
|
||||
HaMarkdown.styles,
|
||||
css`
|
||||
:host {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.root {
|
||||
max-width: 800px;
|
||||
margin: 16px auto;
|
||||
}
|
||||
|
||||
.root > *:first-child {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.root > *:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
`,
|
||||
];
|
||||
}
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
"page-api-docs": PageApiDocs;
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,7 @@ import "@material/mwc-drawer";
|
||||
import "@material/mwc-top-app-bar-fixed";
|
||||
import { mdiMenu } from "@mdi/js";
|
||||
import type { PropertyValues } from "lit";
|
||||
import { LitElement, css, html } from "lit";
|
||||
import { LitElement, css, html, nothing } from "lit";
|
||||
import { customElement, query, state } from "lit/decorators";
|
||||
import { dynamicElement } from "../../src/common/dom/dynamic-element-directive";
|
||||
import { HaExpansionPanel } from "../../src/components/ha-expansion-panel";
|
||||
@@ -10,6 +10,7 @@ import "../../src/components/ha-icon-button";
|
||||
import "../../src/managers/notification-manager";
|
||||
import { haStyle } from "../../src/resources/styles";
|
||||
import { PAGES, SIDEBAR } from "../build/import-pages";
|
||||
import "./components/page-api-docs";
|
||||
import "./components/page-description";
|
||||
|
||||
const GITHUB_DEMO_URL =
|
||||
@@ -95,6 +96,9 @@ class HaGallery extends LitElement {
|
||||
`
|
||||
: ""}
|
||||
${dynamicElement(`demo-${this._page.replace("/", "-")}`)}
|
||||
${PAGES[this._page].apiDocs
|
||||
? html`<page-api-docs .page=${this._page}></page-api-docs>`
|
||||
: nothing}
|
||||
</div>
|
||||
<div class="page-footer">
|
||||
<div class="header">Help us to improve our documentation</div>
|
||||
|
||||
@@ -20,7 +20,8 @@
|
||||
"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"
|
||||
},
|
||||
"author": "Paulus Schoutsen <Paulus@PaulusSchoutsen.nl> (http://paulusschoutsen.nl)",
|
||||
"license": "Apache-2.0",
|
||||
@@ -150,6 +151,7 @@
|
||||
"@babel/plugin-transform-runtime": "7.29.0",
|
||||
"@babel/preset-env": "7.29.0",
|
||||
"@bundle-stats/plugin-webpack-filter": "4.21.9",
|
||||
"@custom-elements-manifest/analyzer": "0.11.0",
|
||||
"@lokalise/node-api": "15.6.1",
|
||||
"@octokit/auth-oauth-device": "8.0.3",
|
||||
"@octokit/plugin-retry": "8.0.3",
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user