Skip to content

Commit d17aa41

Browse files
committed
Merge branch 'dev' into home-dashboard-enable-disable-entities-suggestion
2 parents 9f4ea93 + 4466619 commit d17aa41

41 files changed

Lines changed: 1914 additions & 618 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/release.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ jobs:
3636
python-version: ${{ env.PYTHON_VERSION }}
3737

3838
- name: Verify version
39-
uses: home-assistant/actions/helpers/verify-version@d56d093b9ab8d2105bc0cb6ee9bcc0ef4ec8b96d # master
39+
uses: home-assistant/actions/helpers/verify-version@5752577ea7cc5aefb064b0b21432f18fe4d6ba90 # master
4040

4141
- name: Setup Node
4242
uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
---
2+
title: Textarea
3+
---
4+
5+
# Textarea `<ha-textarea>`
6+
7+
A multiline text input component supporting Home Assistant theming and validation, based on webawesome textarea.
8+
Supports autogrow, hints, validation, and both material and outlined appearances.
9+
10+
## Implementation
11+
12+
### Example usage
13+
14+
```html
15+
<ha-textarea label="Description" value="Hello world"></ha-textarea>
16+
17+
<ha-textarea
18+
label="Notes"
19+
placeholder="Type here..."
20+
resize="auto"
21+
></ha-textarea>
22+
23+
<ha-textarea label="Required field" required></ha-textarea>
24+
25+
<ha-textarea label="Disabled" disabled value="Can't edit this"></ha-textarea>
26+
```
27+
28+
### API
29+
30+
This component is based on the webawesome textarea component.
31+
32+
**Slots**
33+
34+
- `label`: Custom label content. Overrides the `label` property.
35+
- `hint`: Custom hint content. Overrides the `hint` property.
36+
37+
**Properties/Attributes**
38+
39+
| Name | Type | Default | Description |
40+
| ------------------ | -------------------------------------------------------------- | ------- | ------------------------------------------------------------------------ |
41+
| value | String | - | The current value of the textarea. |
42+
| label | String | "" | The textarea's label text. |
43+
| hint | String | "" | The textarea's hint/helper text. |
44+
| placeholder | String | "" | Placeholder text shown when the textarea is empty. |
45+
| rows | Number | 4 | The number of visible text rows. |
46+
| resize | "none"/"vertical"/"horizontal"/"both"/"auto" | "none" | Controls the textarea's resize behavior. |
47+
| readonly | Boolean | false | Makes the textarea readonly. |
48+
| disabled | Boolean | false | Disables the textarea and prevents user interaction. |
49+
| required | Boolean | false | Makes the textarea a required field. |
50+
| auto-validate | Boolean | false | Validates the textarea on blur instead of on form submit. |
51+
| invalid | Boolean | false | Marks the textarea as invalid. |
52+
| validation-message | String | "" | Custom validation message shown when the textarea is invalid. |
53+
| minlength | Number | - | The minimum length of input that will be considered valid. |
54+
| maxlength | Number | - | The maximum length of input that will be considered valid. |
55+
| name | String | - | The name of the textarea, submitted as a name/value pair with form data. |
56+
| autocapitalize | "off"/"none"/"on"/"sentences"/"words"/"characters" | "" | Controls whether and how text input is automatically capitalized. |
57+
| autocomplete | String | - | Indicates whether the browser's autocomplete feature should be used. |
58+
| autofocus | Boolean | false | Automatically focuses the textarea when the page loads. |
59+
| spellcheck | Boolean | true | Enables or disables the browser's spellcheck feature. |
60+
| inputmode | "none"/"text"/"decimal"/"numeric"/"tel"/"search"/"email"/"url" | "" | Hints at the type of data for showing an appropriate virtual keyboard. |
61+
| enterkeyhint | "enter"/"done"/"go"/"next"/"previous"/"search"/"send" | "" | Customizes the label or icon of the Enter key on virtual keyboards. |
62+
63+
#### CSS Parts
64+
65+
- `wa-base` - The underlying wa-textarea base wrapper.
66+
- `wa-hint` - The underlying wa-textarea hint container.
67+
- `wa-textarea` - The underlying wa-textarea textarea element.
68+
69+
**CSS Custom Properties**
70+
71+
- `--ha-textarea-padding-bottom` - Padding below the textarea host.
72+
- `--ha-textarea-max-height` - Maximum height of the textarea when using `resize="auto"`. Defaults to `200px`.
73+
- `--ha-textarea-required-marker` - The marker shown after the label for required fields. Defaults to `"*"`.
Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
import type { TemplateResult } from "lit";
2+
import { css, html, LitElement } from "lit";
3+
import { customElement } from "lit/decorators";
4+
import { applyThemesOnElement } from "../../../../src/common/dom/apply_themes_on_element";
5+
import "../../../../src/components/ha-card";
6+
import "../../../../src/components/ha-textarea";
7+
8+
@customElement("demo-components-ha-textarea")
9+
export class DemoHaTextarea extends LitElement {
10+
protected render(): TemplateResult {
11+
return html`
12+
${["light", "dark"].map(
13+
(mode) => html`
14+
<div class=${mode}>
15+
<ha-card header="ha-textarea in ${mode}">
16+
<div class="card-content">
17+
<h3>Basic</h3>
18+
<div class="row">
19+
<ha-textarea label="Default"></ha-textarea>
20+
<ha-textarea
21+
label="With value"
22+
value="Hello world"
23+
></ha-textarea>
24+
<ha-textarea
25+
label="With placeholder"
26+
placeholder="Type here..."
27+
></ha-textarea>
28+
</div>
29+
30+
<h3>Autogrow</h3>
31+
<div class="row">
32+
<ha-textarea
33+
label="Autogrow empty"
34+
resize="auto"
35+
></ha-textarea>
36+
<ha-textarea
37+
label="Autogrow with value"
38+
resize="auto"
39+
value="This textarea will grow as you type more content into it. Try adding more lines to see the effect."
40+
></ha-textarea>
41+
</div>
42+
43+
<h3>States</h3>
44+
<div class="row">
45+
<ha-textarea
46+
label="Disabled"
47+
disabled
48+
value="Disabled"
49+
></ha-textarea>
50+
<ha-textarea
51+
label="Readonly"
52+
readonly
53+
value="Readonly"
54+
></ha-textarea>
55+
<ha-textarea label="Required" required></ha-textarea>
56+
</div>
57+
<div class="row">
58+
<ha-textarea
59+
label="Invalid"
60+
invalid
61+
validation-message="This field is required"
62+
value=""
63+
></ha-textarea>
64+
<ha-textarea
65+
label="With hint"
66+
hint="Supports Markdown"
67+
></ha-textarea>
68+
<ha-textarea
69+
label="With rows"
70+
.rows=${6}
71+
placeholder="6 rows"
72+
></ha-textarea>
73+
</div>
74+
75+
<h3>No label</h3>
76+
<div class="row">
77+
<ha-textarea
78+
placeholder="No label, just placeholder"
79+
></ha-textarea>
80+
<ha-textarea
81+
resize="auto"
82+
placeholder="No label, autogrow"
83+
></ha-textarea>
84+
</div>
85+
</div>
86+
</ha-card>
87+
</div>
88+
`
89+
)}
90+
`;
91+
}
92+
93+
firstUpdated(changedProps) {
94+
super.firstUpdated(changedProps);
95+
applyThemesOnElement(
96+
this.shadowRoot!.querySelector(".dark"),
97+
{
98+
default_theme: "default",
99+
default_dark_theme: "default",
100+
themes: {},
101+
darkMode: true,
102+
theme: "default",
103+
},
104+
undefined,
105+
undefined,
106+
true
107+
);
108+
}
109+
110+
static styles = css`
111+
:host {
112+
display: flex;
113+
justify-content: center;
114+
}
115+
.dark,
116+
.light {
117+
display: block;
118+
background-color: var(--primary-background-color);
119+
padding: 0 50px;
120+
}
121+
ha-card {
122+
margin: 24px auto;
123+
}
124+
.card-content {
125+
display: flex;
126+
flex-direction: column;
127+
gap: var(--ha-space-2);
128+
}
129+
h3 {
130+
margin: var(--ha-space-4) 0 var(--ha-space-1) 0;
131+
font-size: var(--ha-font-size-l);
132+
font-weight: var(--ha-font-weight-medium);
133+
}
134+
h3:first-child {
135+
margin-top: 0;
136+
}
137+
.row {
138+
display: flex;
139+
gap: var(--ha-space-4);
140+
}
141+
.row > * {
142+
flex: 1;
143+
}
144+
`;
145+
}
146+
147+
declare global {
148+
interface HTMLElementTagNameMap {
149+
"demo-components-ha-textarea": DemoHaTextarea;
150+
}
151+
}

package.json

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434
"@codemirror/legacy-modes": "6.5.2",
3535
"@codemirror/search": "6.6.0",
3636
"@codemirror/state": "6.6.0",
37-
"@codemirror/view": "6.40.0",
37+
"@codemirror/view": "6.41.0",
3838
"@date-fns/tz": "1.4.1",
3939
"@egjs/hammerjs": "2.0.17",
4040
"@formatjs/intl-datetimeformat": "7.3.1",
@@ -73,23 +73,21 @@
7373
"@material/mwc-radio": "0.27.0",
7474
"@material/mwc-select": "0.27.0",
7575
"@material/mwc-switch": "0.27.0",
76-
"@material/mwc-textarea": "0.27.0",
77-
"@material/mwc-textfield": "0.27.0",
7876
"@material/mwc-top-app-bar": "0.27.0",
7977
"@material/mwc-top-app-bar-fixed": "0.27.0",
8078
"@material/top-app-bar": "=14.0.0-canary.53b3cad2f.0",
8179
"@material/web": "2.4.1",
8280
"@mdi/js": "7.4.47",
8381
"@mdi/svg": "7.4.47",
8482
"@replit/codemirror-indentation-markers": "6.5.3",
85-
"@swc/helpers": "0.5.20",
83+
"@swc/helpers": "0.5.21",
8684
"@thomasloven/round-slider": "0.6.0",
8785
"@tsparticles/engine": "3.9.1",
8886
"@tsparticles/preset-links": "3.2.0",
8987
"@vibrant/color": "4.0.4",
9088
"@webcomponents/scoped-custom-element-registry": "0.0.10",
9189
"@webcomponents/webcomponentsjs": "2.8.0",
92-
"barcode-detector": "3.1.1",
90+
"barcode-detector": "3.1.2",
9391
"cally": "0.9.2",
9492
"color-name": "2.1.0",
9593
"comlink": "4.4.2",
@@ -102,7 +100,7 @@
102100
"dialog-polyfill": "0.5.6",
103101
"echarts": "6.0.0",
104102
"element-internals-polyfill": "3.0.2",
105-
"fuse.js": "7.1.0",
103+
"fuse.js": "7.2.0",
106104
"google-timezones-json": "1.2.0",
107105
"gulp-zopfli-green": "7.0.0",
108106
"hls.js": "1.6.15",
@@ -177,7 +175,7 @@
177175
"eslint": "9.39.4",
178176
"eslint-config-airbnb-base": "15.0.0",
179177
"eslint-config-prettier": "10.1.8",
180-
"eslint-import-resolver-webpack": "0.13.10",
178+
"eslint-import-resolver-webpack": "0.13.11",
181179
"eslint-plugin-import": "2.32.0",
182180
"eslint-plugin-lit": "2.2.1",
183181
"eslint-plugin-lit-a11y": "5.1.1",

src/common/datetime/calc_date_range.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ export type DateRange =
2727
| "this_year"
2828
| "now-7d"
2929
| "now-30d"
30+
| "now-365d"
3031
| "now-12m"
3132
| "now-1h"
3233
| "now-12h"
@@ -102,6 +103,11 @@ export const calcDateRange = (
102103
),
103104
calcDate(today, endOfMonth, locale, hassConfig),
104105
];
106+
case "now-365d":
107+
return [
108+
calcDate(today, subDays, locale, hassConfig, 365),
109+
calcDate(today, subDays, locale, hassConfig, 0),
110+
];
105111
case "now-1h":
106112
return [
107113
calcDate(today, subHours, locale, hassConfig, 1),

src/components/date-picker/ha-date-range-picker.ts

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,8 @@ export class HaDateRangePicker extends LitElement {
133133
${!this.minimal
134134
? html`<ha-textarea
135135
id="field"
136-
mobile-multiline
136+
rows="1"
137+
resize="auto"
137138
@click=${this._openPicker}
138139
@keydown=${this._handleKeydown}
139140
.value=${(isThisYear(this.startDate)
@@ -336,14 +337,7 @@ export class HaDateRangePicker extends LitElement {
336337
private _setTextareaFocusStyle(focused: boolean) {
337338
const textarea = this.renderRoot.querySelector("ha-textarea");
338339
if (textarea) {
339-
const foundation = (textarea as any).mdcFoundation;
340-
if (foundation) {
341-
if (focused) {
342-
foundation.activateFocus();
343-
} else {
344-
foundation.deactivateFocus();
345-
}
346-
}
340+
textarea.setFocused(focused);
347341
}
348342
}
349343

src/components/ha-gauge.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,7 @@ export class HaGauge extends LitElement {
171171
? svg`
172172
<path
173173
class="needle"
174-
d="M -36,-2 L -44,-1 A 1,1,0,0,0,-44,1 L -36,2 A 2,2,0,0,0,-36,-2 Z"
174+
d="M -34,-3 L -48,-1 A 1,1,0,0,0,-48,1 L -34,3 A 2,2,0,0,0,-34,-3 Z"
175175
176176
style=${styleMap({ transform: `rotate(${this._angle}deg)` })}
177177
/>
@@ -243,19 +243,19 @@ export class HaGauge extends LitElement {
243243
.levels-base {
244244
fill: none;
245245
stroke: var(--primary-background-color);
246-
stroke-width: 6;
246+
stroke-width: 12;
247247
stroke-linecap: butt;
248248
}
249249
250250
.level {
251251
fill: none;
252-
stroke-width: 6;
252+
stroke-width: 12;
253253
stroke-linecap: butt;
254254
}
255255
256256
.value {
257257
fill: none;
258-
stroke-width: 6;
258+
stroke-width: 12;
259259
stroke: var(--gauge-color);
260260
stroke-linecap: butt;
261261
transition: stroke-dashoffset 1s ease 0s;

src/components/ha-selector/ha-selector-text.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -65,15 +65,14 @@ export class HaTextSelector extends LitElement {
6565
.label=${this.label}
6666
.placeholder=${this.placeholder}
6767
.value=${this.value || ""}
68-
.helper=${this.helper}
69-
helperPersistent
68+
.hint=${this.helper}
7069
.disabled=${this.disabled}
7170
@input=${this._handleChange}
7271
autocapitalize="none"
7372
.autocomplete=${this.selector.text?.autocomplete}
7473
spellcheck="false"
7574
.required=${this.required}
76-
autogrow
75+
resize="auto"
7776
></ha-textarea>`;
7877
}
7978
return html`<ha-input

0 commit comments

Comments
 (0)