Compare commits

..

579 Commits

Author SHA1 Message Date
ildar170975 73a1ce90c3 Data tables: do not show "Assistants" column in "secondary" when narrow (#29120)
fix a column for "narrow"
2026-01-22 09:37:03 +02:00
uptimeZERO_ ea1b7b9dec Media player fixes (#29075)
* aligning ui of dialog and media bar

* refactored media progress logic to be reusable

* updating track times to be consistent with music assistant

* WIP aligning volume slider with music assistant

* migrating to ha-dropdown

* showing volume tooltip on touch devices

* Fixed volume slider going to 100 randomly

* Added scrolling support

* Refactored volume control logic
2026-01-21 20:28:32 +01:00
Paul Bottein fd506d4d72 Add assign area shortcut to home panel (#29082)
* Add assign area shortcut to home panel

* Set empty state for empty other devices page
2026-01-21 17:11:23 +01:00
karwosts a3be09018c Fix add entry button for integrations (#29106) 2026-01-21 16:13:03 +02:00
Wendelin 3364d4f578 Migrate button-menu components to dropdown in 7 files (#29105)
Migrate button-menu components to dropdown in various editors
2026-01-21 15:12:15 +02:00
Paul Bottein 1f04379974 Add button to heading card (#28991)
* Add heading badge button

* Fix look and feel

* Improve editor

* Prettier
2026-01-21 11:38:48 +01:00
Kristel e060c179f6 Refactor ha-automation-picker _applyFilters (#29055) 2026-01-21 10:56:01 +01:00
Wendelin 54b72ce2b8 Migrate button-menu to ha-dropdown 8 files (#29102) 2026-01-21 09:35:25 +00:00
Aidan Timson 5795b8787d Allow helpers area id to fallback to device area if not set (#29093) 2026-01-21 10:22:38 +01:00
Paulus Schoutsen ec742d3342 App store link app panel 2 (#29100)
* Revert "App store to link to app panel"

This reverts commit 415319f69e.

* App store to link to app panel
2026-01-21 06:04:45 +01:00
renovate[bot] e4d6f3c9d7 Update dependency tar to v7.5.3 [SECURITY] (#29045)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-01-20 17:12:23 +00:00
Paul Bottein 2d496afdbc Add discovered devices to add integration dialog (#29092) 2026-01-20 14:28:29 +00:00
Wendelin 681b60614f Migrate button-menu to ha-dropdown in 9 files (#29089)
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-20 14:20:29 +00:00
Petar Petrov 1654a67d30 Refactor area control picker into a separate component (#29080) 2026-01-20 15:04:20 +01:00
renovate[bot] 8f00494d53 Update dependency rspack-manifest-plugin to v5.2.1 (#29091)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-01-20 15:31:53 +02:00
Joost Lekkerkerker d9c7c0422b Allow the main entry type button to be translatable (#28721)
Co-authored-by: Simon Lamon <32477463+silamon@users.noreply.github.com>
2026-01-20 14:25:48 +01:00
Aidan Timson 2d24447c3c Rename Add-ons to Apps in more areas (#29076)
* Remove add-ons mention in agents file

* Rename user facing form and selector name

* Everything else

* Update more

* Update more

* Update more

* Update more

* Update key

* Update key

* Update keys

* Use translation

* More changes

* Update key

* Backward / Forward compat

* Drop "the"

Co-authored-by: Norbert Rittel <norbert@rittel.de>

---------

Co-authored-by: Norbert Rittel <norbert@rittel.de>
2026-01-20 13:39:30 +02:00
Paul Bottein 3b8d485ec6 Update log icons (#29084) 2026-01-20 11:40:03 +01:00
Wendelin 4e4a00e3e9 Migrate ha-button-menu to ha-dropdown in 6 files (#29072)
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-20 09:29:29 +00:00
Paul Bottein 14f7328f92 Add context to group more info (#29077)
* Add area context in more info group

* Use entity name instead of entry

* Remove filter
2026-01-20 10:26:03 +02:00
Paul Bottein c5ad074dfb Create reusable ha tile container component. (#29038)
* Create reusable component for tile based card

* Fix icon interaction

* Add icon and iconPath props

* Migrate discovered devices card

* Refactor

* Share card style
2026-01-20 08:49:10 +02:00
Paulus Schoutsen 07aa8706ce App store to link to app panel (#29079) 2026-01-20 06:11:56 +01:00
TheJulianJES 1665fa3775 Fix Z-Wave dashboard picker showing disabled config entries (#29078)
* Fix Z-Wave dashboard picker showing disabled config entries

* Fix Z-Wave dashboard picker showing ignored discoveries
2026-01-19 20:08:44 +01:00
Aidan Timson 3be6a87658 Bring scene editor in line with automations and scripts (#29002)
Co-authored-by: Wendelin <12148533+wendevlin@users.noreply.github.com>
2026-01-19 16:49:54 +01:00
ildar170975 9092de5c28 Entity card: add support of actions (#28949) 2026-01-19 15:13:36 +01:00
Petar Petrov e0fc661920 Allow specific entity controls in Area card (#29025)
Co-authored-by: Wendelin <12148533+wendevlin@users.noreply.github.com>
2026-01-19 14:44:10 +01:00
JLo aaad8e5434 Add distribution card (#28886)
* Add horizontal stacked bar card

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>

* Refactor to use ha-segmented-bar component

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>

* Fix spacing when heading is empty

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>

* Rename card from horizontal-stacked-bar to distribution

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>

* Fix remaining translation references

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>

* Add fixed row setting to prevent layout issues

* Add spacing between bar and legend

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>

* PR review changes

* Improve accessibility and performance

---------

Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
Co-authored-by: Petar Petrov <MindFreeze@users.noreply.github.com>
2026-01-19 12:46:14 +00:00
Jan Layola 35c668744a Update ha-base-time-input to accept decimal input for seconds (#29058)
* Update ha-base-time-input to accept decimal input for seconds

* Add support for decimal values in time formatting ha-base-time-input
2026-01-19 14:28:08 +02:00
Wendelin 081b0a0222 Migrate ha-button-menu to ha-dropdown in 8 files (#29070)
Migrates the following files from ha-button-menu to ha-dropdown component:
- ha-config-backup-details.ts
- ha-config-areas-dashboard.ts
- ha-config-dashboard.ts
- ha-panel-history.ts
- ha-scene-editor.ts
- ha-config-integrations-dashboard.ts
- thread-config-panel.ts
- ha-panel-developer-tools.ts

Changes:
- Replace ha-button-menu with ha-dropdown
- Replace ha-list-item with ha-dropdown-item
- Change @action event handlers to @wa-select
- Change slot="graphic" to slot="icon" for icons
- Update event handlers from index-based to value-based selection
- Replace <li divider role="separator"> with <wa-divider>
- Update CSS selectors from ha-button-menu to ha-dropdown
- Use type="checkbox" for checkbox dropdown items in integrations dashboard
- Remove unused li[role="separator"] CSS styles

Contributes to #26537

Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-19 13:11:29 +02:00
Paulus Schoutsen 829cd96e9b Add apps panel as built-in panel (#28245)
* Add apps panel as built-in panel

* Fix missing translation

* Address cursor comment

* Another cursor fix

* One more cursor fix

* Address PR review comments: localize error messages, fix deprecated method, use spacing tokens (#28246)

* Initial plan

* Address PR review comments: localize error messages, replace substr with substring, use spacing tokens

Co-authored-by: balloob <1444314+balloob@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: balloob <1444314+balloob@users.noreply.github.com>

* Cursor fix

* Cursor: use willUpdate

* prettier

* Cursor: fix translation placeholder swap

* Apply suggestions from code review

Co-authored-by: Petar Petrov <MindFreeze@users.noreply.github.com>

* Cursor: clearTimeout

* Cursor: fix race condition

* Update src/translations/en.json

Co-authored-by: Norbert Rittel <norbert@rittel.de>

* Apply spacing tokens

---------

Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com>
Co-authored-by: balloob <1444314+balloob@users.noreply.github.com>
Co-authored-by: Petar Petrov <MindFreeze@users.noreply.github.com>
Co-authored-by: Norbert Rittel <norbert@rittel.de>
2026-01-19 13:08:15 +02:00
Paulus Schoutsen c404e66ee5 Add new app panel (#28214)
* Add ingress panel to Home Assistant

* Better wait until app loaded logic

* Cleaner slug extraction

* Support HA-aware apps integrating more tightly

* Add new file too

* Memoize

* Cursor: use clearTimeout

* Cursor: fix race conditions

* Claude: fixes

* Cursor: fix issues

* Rename hideToolbar to kioskMode

* Hook kiosk mode into native kiosk mode

* Update src/data/route.ts

* Move computeRouteTail to common URL module

* dry refactor

---------

Co-authored-by: Petar Petrov <MindFreeze@users.noreply.github.com>
2026-01-19 13:08:07 +02:00
Aidan Timson d47d3f9694 Create shared ai task metadata suggestion task (#29012)
Co-authored-by: Wendelin <12148533+wendevlin@users.noreply.github.com>
2026-01-19 09:42:36 +01:00
dependabot[bot] 622df52167 Bump actions/cache from 5.0.1 to 5.0.2 (#29068)
Bumps [actions/cache](https://github.com/actions/cache) from 5.0.1 to 5.0.2.
- [Release notes](https://github.com/actions/cache/releases)
- [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md)
- [Commits](https://github.com/actions/cache/compare/9255dc7a253b0ccc959486e2bca901246202afeb...8b402f58fbc84540c8b491a91e594a4576fec3d7)

---
updated-dependencies:
- dependency-name: actions/cache
  dependency-version: 5.0.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-01-19 09:44:26 +02:00
dependabot[bot] 20345c3771 Bump actions/setup-node from 6.1.0 to 6.2.0 (#29067)
Bumps [actions/setup-node](https://github.com/actions/setup-node) from 6.1.0 to 6.2.0.
- [Release notes](https://github.com/actions/setup-node/releases)
- [Commits](https://github.com/actions/setup-node/compare/395ad3262231945c25e8478fd5baf05154b1d79f...6044e13b5dc448c55e2357c09f80417699197238)

---
updated-dependencies:
- dependency-name: actions/setup-node
  dependency-version: 6.2.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-01-19 09:44:01 +02:00
dependabot[bot] fc7468a43b Bump github/codeql-action from 4.31.9 to 4.31.10 (#29069)
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 4.31.9 to 4.31.10.
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/github/codeql-action/compare/5d4e8d1aca955e8d8589aabd499c5cae939e33c7...cdefb33c0f6224e58673d9004f47f7cb3e328b89)

---
updated-dependencies:
- dependency-name: github/codeql-action
  dependency-version: 4.31.10
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-01-19 09:43:43 +02:00
renovate[bot] c8ab65cde9 Lock file maintenance (#29065)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-01-19 08:01:36 +02:00
Kristel 001ade24ea Reuse <voice-assistant-brand-icon> (#29046) 2026-01-18 23:55:53 +01:00
karwosts f987cfe91e Use water-heater operation_mode icon translations (#29051) 2026-01-18 23:31:11 +01:00
renovate[bot] 0bc0acebe0 Update formatjs monorepo (#29062)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-01-18 23:30:07 +01:00
renovate[bot] 2087efca51 Update dependency prettier to v3.8.0 (#29049)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-01-18 09:57:51 +01:00
renovate[bot] 16a4a07080 Update dependency @rsdoctor/rspack-plugin to v1.5.0 (#29044)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-01-17 13:26:05 +01:00
renovate[bot] 58eefcb216 Update CodeMirror (#29043)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-01-17 13:24:01 +01:00
Wendelin 92a36ac687 Migrate ha-button-menu to ha-dropdown in logs and forms (#29036)
Migrate four components from ha-button-menu to ha-dropdown:
- error-log-card: overflow menu with log view switching
- system-log-card: overflow menu for full logs
- ha-filter-categories: category edit/delete actions
- ha-form-optional_actions: add interaction dropdown

Changes:
- Replace ha-button-menu with ha-dropdown
- Replace ha-list-item with ha-dropdown-item
- Update event handlers from @action to @wa-select
- Use value-based selection instead of index-based
- Add proper accessibility labels to trigger buttons

Part of #26537

Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-16 19:27:14 +01:00
Wendelin 8221ca8971 Add artifact upload step for frontend build in CI workflow (#29034) 2026-01-16 17:30:37 +01:00
Paul Bottein 8f69cbb6c1 Add discovered devices card (#29035) 2026-01-16 17:25:08 +01:00
renovate[bot] 4c111e1a7d Update dependency @codemirror/search to v6.6.0 (#29029)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-01-16 15:17:31 +02:00
Aidan Timson af8659d8ed Migrate automation/script dialogs to ha-wa-dialog (#29030)
* Migrate dialog-automation-save to ha-wa-dialog

* Migrate dialog-automation-mode to ha-wa-dialog

* Migrate dialog-paste-replace to ha-wa-dialog

* Migrate dialog-new-automation to ha-wa-dialog

* Migrate ha-device-automation-dialog to ha-wa-dialog
2026-01-16 13:23:56 +02:00
renovate[bot] c9e1c9e0a3 Update dependency ua-parser-js to v2.0.8 (#29028)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-01-16 10:14:57 +00:00
renovate[bot] 9d15499953 Update dependency @rspack/core to v1.7.2 (#29027)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-01-16 10:03:25 +00:00
Wendelin 7d54dd4940 Fix shortcuts ctrl translation (#29024)
* fix: update localization for CTRL key in shortcuts dialog

* fix: update search label in translations for improved clarity
2026-01-16 11:09:34 +02:00
renovate[bot] 8ef717df6e Update dependency typescript-eslint to v8.53.0 (#29019)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-01-16 11:08:06 +02:00
renovate[bot] 7b4a7403c8 Update babel monorepo to v7.28.6 (#29018)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-01-16 11:07:40 +02:00
ildar170975 22b7c52828 "Voice assistant" column in tables: standardize (#28889)
Co-authored-by: Wendelin <12148533+wendevlin@users.noreply.github.com>
2026-01-16 09:10:02 +01:00
Remy Sharp 04dbeb5e84 Fixed dark mode hidden text in debug assistant (#29021)
Co-authored-by: Wendelin <w@pe8.at>
2026-01-16 08:33:45 +01:00
Simon Lamon db5f823b6b Remove twine and introduce trusted publishing (#27110)
* Remove twine and introduce trusted publishing

* Update release.yaml
2026-01-15 22:50:52 -05:00
uptimeZERO_ 1d241aa49a Truncate long menu item labels in the sidebar (#29005) 2026-01-15 15:41:48 +00:00
Pegasus fece231faf fix: restrict to exact match for data table (#28853) 2026-01-15 15:50:15 +01:00
Aidan Timson fffb3c3a28 Migrate category dialogs to ha-wa-dialog (#29009) 2026-01-15 15:32:43 +01:00
renovate[bot] fe14d436ff Update vitest monorepo to v4.0.17 (#29007)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-01-15 15:46:10 +02:00
Petar Petrov 42e02be928 Add subpage titles in for config panel pages (#28990)
Co-authored-by: Wendelin <12148533+wendevlin@users.noreply.github.com>
2026-01-15 12:48:33 +01:00
Aydar Gumerbaev 6213b6cd2a Always use fallback for brands URL (#28994) 2026-01-15 11:42:17 +00:00
Aidan Timson cd75c55392 Entity context: voice assistants expose entities (#28992)
* Entity context: voice assistants expose entities

* Load virtualiser

* Refactor filter entities, reduce duplicate renders

* Fix logic
2026-01-15 13:09:38 +02:00
Marcin Bauer ca325020d7 Add Labs feature note to automation element picker (#28874)
Co-authored-by: Wendelin <w@pe8.at>
Co-authored-by: Wendelin <12148533+wendevlin@users.noreply.github.com>
2026-01-15 11:09:11 +00:00
Jeremy Cook 6250402661 Fix vertical-align in markdown tables with presentation role (#29001) 2026-01-15 11:48:43 +01:00
Amit Finkelstein 0bfca79851 Stop dropdown select events from bubbling in automation rows (#28985) 2026-01-15 11:22:23 +01:00
Wendelin 49bddf6139 Automation add TCA: fix: prevent multiple dialog closures by tracking closing state (#28978) 2026-01-15 08:50:55 +01:00
Wendelin 0daf94e98f Quick bar: new design and area search (#28678)
* Add "Commands" title to quick bar translations in English

* Enhance QuickBar dialog handling and localize commands title

* add nav icons

* Add icons and styles and separate navigation from commands

* handle non admin

* Add areas

* Fix import and shortcuts

* Restructure

* remove area sort

* move keys

* area search keys review

* Fix adaptive dialog slots without header

* Design review

* Review marcin

* Fix safe area bottom

* Fix ios focus

* Make it clearable

---------

Co-authored-by: Simon Lamon <32477463+silamon@users.noreply.github.com>
2026-01-15 09:45:57 +02:00
uptimeZERO_ 00a3237611 Persist theme settings to user profile and allow migration (#28965)
* Moved theme functionality and persistence target

* fixed type mismatch

* using SubscribeMixin

* returning no-op unsub to handle rejection path

* added notification if theme save fails

* using hass instead of state

* renamed theme variable for clarity

* Added toast if theme pref is unavailable

* Always saving theme to localStorage

* Removing localStorage fallback

* Updating local cache when new theme comes from core
2026-01-15 09:40:43 +02:00
StormDev 53deb3f419 Removed uneccessary import in landing-page-network.ts (#29000)
* Removed uneccessary console on landing-page-networks.ts

* Uneccessary import removed in landing-page-networks.ts
2026-01-15 07:26:50 +00:00
Pegasus 6c1c7cead3 Fixes duplicate "Device info" section name when viewing Matter devices. (#28984)
ha-device-info-matter: rename 'Device info' to 'Matter info'

Fixes duplicate "Device info" section name when viewing Matter devices.
The nested expansion panel now displays "Matter info" consistent with
other integrations (e.g., ZHA uses "Zigbee info", Z-Wave uses "Z-Wave info").

Also adds a gallery demo for testing the component.
2026-01-15 09:18:21 +02:00
Jason Madigan f8d65cc0ec Make entities on the energy now sankey graph clickable (#28998)
* enhancement: make entities on the energy now sankey graph clickable to show details

Signed-off-by: Jason Madigan <jason@jasonmadigan.com>

* add a test

Signed-off-by: Jason Madigan <jason@jasonmadigan.com>

* format

---------

Signed-off-by: Jason Madigan <jason@jasonmadigan.com>
Co-authored-by: Petar Petrov <MindFreeze@users.noreply.github.com>
2026-01-15 06:44:03 +00:00
Paul Bottein 5be7bad176 Allow to add context to tile card secondary line (#28995) 2026-01-14 19:48:27 +01:00
Paul Bottein 0a54a93a39 Use tabs for bluetooth panel (#28824)
Co-authored-by: Petar Petrov <MindFreeze@users.noreply.github.com>
2026-01-14 14:38:10 +01:00
Petar Petrov 156583aff1 Include the area when duplicating a scene from the scene dashboard (#28955) 2026-01-14 12:28:05 +01:00
Aidan Timson 7572257821 Match expose config dashboard for assistants columns (#28956) 2026-01-14 11:43:56 +01:00
Pegasus 4703cf802f Change border-quiet token values from 80 to 90 (#28976) 2026-01-14 09:28:32 +00:00
ildar170975 55c2315329 ha-label-picker: remove valueRenderer (#28975) 2026-01-14 10:15:39 +01:00
Wendelin 7d7e95ac55 Improve device automation UI (#28967)
* Improve device automation rows

* Improve device automation type picker

* Update src/panels/config/automation/condition/ha-automation-condition-row.ts

---------

Co-authored-by: Petar Petrov <MindFreeze@users.noreply.github.com>
2026-01-14 07:06:56 +00:00
ildar170975 6d7694caff ha-label-picker, ha-category-picker: fix icon for "no items available" (#28973)
* remove NO_LABELS

* remove NO_CATEGORIES

* reverted removed icon
2026-01-14 08:42:24 +02:00
calm d7b6243698 Fix tree view heading overlapping Show more button (#28872) (#28968) 2026-01-13 18:34:39 +01:00
calm 73feef9e92 Remove box-shadow from automation dialog "Show more" button (#28945) (#28960) 2026-01-13 17:31:55 +01:00
renovate[bot] 453a546574 Update Node.js to v24.13.0 (#28963)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-01-13 15:16:03 +00:00
Petar Petrov 52c0e6f1f5 Respect user-configured grid options for fixed_rows/fixed_columns cards (#28961) 2026-01-13 16:24:25 +02:00
Aidan Timson 444f8d87b3 Ignore all node_modules, not just from root dir (#28959) 2026-01-13 13:51:54 +01:00
Pegasus 57a586c3a7 fix: update the z-index of search button mainly for yaml mode (#28878) 2026-01-13 13:41:53 +01:00
Pegasus 1975265e6b Update the Select Option type from any to string per documentation (#28954) 2026-01-13 10:44:02 +01:00
Wendelin 66e6cb8dbc Fix category-picker unknown check (#28957) 2026-01-13 09:39:05 +00:00
Petar Petrov 9ce9d254f8 Picture elements position by click (#28597) 2026-01-13 10:01:07 +01:00
ildar170975 1beca4bfa6 ha-data-table: issues with "numeric" column (#28916)
Co-authored-by: uptimeZERO_ <pavilionsahota@gmail.com>
2026-01-13 08:38:15 +00:00
Kristel 82ab29cfc5 Add "Voice assistant" filter to helpers, automations, scenes and scripts pages (#28914) 2026-01-13 08:29:28 +00:00
Simon Lamon 3579c66f71 Update dropdown adjustments (#28294) 2026-01-13 08:54:17 +01:00
ildar170975 c042a8e310 ha-sidebar: remove scrollIntoViewIfNeeded() (#28938)
remove scrollIntoViewIfNeeded()
2026-01-13 07:23:20 +01:00
renovate[bot] 8d2794a4ee Update dependency vite-tsconfig-paths to v6.0.4 (#28952)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-01-13 07:15:15 +01:00
Paul Bottein 50be1d9345 Use action button text name for empty state card (#28948) 2026-01-12 17:42:01 +01:00
Petar Petrov c551bf03b6 Sanitize names in history card and map card (#28947) 2026-01-12 15:28:32 +00:00
Paul Bottein cd062293fc Add config to empty state card and use it in area empty page (#28946)
* Add config to empty state card and use it in area empty page

* Remove old translations
2026-01-12 16:58:59 +02:00
TheJulianJES e89ea47d3a Add Matter status to config dashboard (#28825)
Co-authored-by: Norbert Rittel <norbert@rittel.de>
Co-authored-by: Bram Kragten <mail@bramkragten.nl>
2026-01-12 15:45:18 +01:00
SmartCoder 2cd209a6a4 Fixed modal visibility issue in settings -> areas -> edit room (#28907)
* Fixed modal visibility issue in settings -> areas -> edit room

* converting both components to use ha-wa-dialog

* removed z-index from ha-wa-dialog

* fixed hardcoded .open in media browser dialog and remove unnecessary z-index CSS variables
2026-01-12 15:07:56 +02:00
Marcin Bauer 9bbc761736 Fix: Allow dismissing add integration and helper dialogs with escape/click (#28944)
* refactor: polish automation dialog UI and component styles

* Revert "Merge pull request #1 from marcinbauer85/fix/ui-polish-automation-dialog"

This reverts commit c2c47197e2, reversing
changes made to 49bed5e6a6.

* Fix: Allow dismissing add integration and helper dialogs

* Apply suggestions from code review

Co-authored-by: Wendelin <12148533+wendevlin@users.noreply.github.com>

---------

Co-authored-by: Petar Petrov <MindFreeze@users.noreply.github.com>
Co-authored-by: Wendelin <12148533+wendevlin@users.noreply.github.com>
2026-01-12 13:39:16 +01:00
Daniel O'Connor 9097faa04b Config > Helpers > Add loading filter state from URL (#28924) 2026-01-12 13:38:04 +01:00
SmartCoder fcf844cf1a Fix issue #28896: "Last 12 months" in the Datetime Picker selects last year (#28902)
Summary of the fix:
The Problem:
now-12m was selecting the calendar year (Jan 1st to Dec 31st) instead of the last 12 months from now
It used startOfMonth and endOfMonth, which snap to month boundaries
The Solution:
Changed to match the now-7d and now-30d pattern
Now uses subMonths(today, 12) for start and subMonths(today, 0) (which equals today) for end
This gives exactly the last 12 months (365/366 days) ending at the current time
The Fix:
// Before (WRONG):calcDate(subMonths(today, 12), startOfMonth, ...)  // Jan 1st of 12 months agocalcDate(subMonths(today, 1), endOfMonth, ...)     // Dec 31st of last month// After (CORRECT):calcDate(today, subMonths, hass.locale, hass.config, 12)  // 12 months ago from nowcalcDate(today, subMonths, hass.locale, hass.config, 0)   // now
2026-01-12 11:53:08 +00:00
dcapslock 8808c31e98 Fix ha-card styling of .card-content when not first element but not following .card-header (#28935) 2026-01-12 12:41:14 +01:00
Michael e0a9f5a08a Show also not installable updates on update overview page (#28717)
* add "show not installable option" to update page

* split updates by install feature and show always

* fix

* fix "no update" panel

* use `nothing` instead of empty string

* re-add `outlined` to ha-card

* keep title, use different for not-installable updates
2026-01-12 13:18:53 +02:00
Petar Petrov 56d71c8e54 Use temp & humidity data from attributes in Area card (#28530)
* Use temp & humidity data from attributes in Area card

* Avoid duplicate sensor readings by tracking devices contributing values
2026-01-12 12:01:12 +01:00
karwosts 125ab4c671 Update energy summary visibility condition (#28913)
* Update energy summary visibility condition

* add grid power as special case

* Always show summary when you have powersource
2026-01-12 12:42:16 +02:00
Eduardo Tsen 8014216c45 Fix ha-entity-toggle not restoring old state on exception (#28915) 2026-01-12 10:28:23 +00:00
ildar170975 55ba331489 developer-tools-statistics: alignment for "fix" column (#28942) 2026-01-12 11:25:44 +01:00
karwosts ad2ff672b0 Add configurable confirmation title & button text (#28931) 2026-01-12 10:19:09 +00:00
JLo 00907ecd17 Add area and device context to media player join dialog (#28926)
* Add area and device context to media player join dialog

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>

* Add memoization to avoid recomputing display data

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-12 11:08:44 +01:00
Petar Petrov 07d8219136 Add ES5-compatible keyed directive implementation (#28941) 2026-01-12 10:50:38 +01:00
Eduardo Tsen f37241c84c Fix hui-select-entity-row restoring old state (#28918) 2026-01-12 09:43:31 +00:00
SmartCoder 65d046132d Updated entity name to friendly name (#28928) 2026-01-12 10:14:23 +01:00
Simon Lamon 122cf40092 Don't close dialog upon tooltip close (#28927) 2026-01-11 20:23:42 -05:00
SmartCoder 28ed5c86c7 Fix automation row menu icon being pushed off-screen on mobile (#28893)
When entity names are too long, the header text would push the three-dot menu icon off the right edge of the screen, making it inaccessible. This fix ensures the menu icon remains visible by:

- Adding min-width: 0 to the header slot to allow proper flexbox shrinking and text wrapping

- Adding flex-shrink: 0 to the icons container to prevent it from being compressed

The fix uses standard flexbox properties that work universally across all screen sizes, ensuring the menu icon stays visible on both mobile and desktop views.
2026-01-10 15:58:28 +01:00
Kristel 1f99c3d895 Add Voice assistants filter to Entities page (#28854)
* create Assistants filter

* render logo and name

* make the Voice assistants filter work

* integrate cloudStatus

* code clean-up

* remove cloudStatus

* bugfix

* remove console log

* remove cloudstatus

* set ha-list clientHeight to 49px
2026-01-10 12:57:33 +01:00
LG-ThinQ-Integration f2293713de Add target_humidity_step to humidifier (#28005)
Co-authored-by: yunseon.park <yunseon.park@lge.com>
2026-01-10 10:12:55 +01:00
Brendan Annable b3f202400c Fix timer restore bug (#28898) 2026-01-10 09:51:19 +01:00
ildar170975 010d87bd0d ha-dialog-automation-save: small improvements & fixes (#28561)
* explictly set line-height for "helper" element

* move "description" to bottom, css tweaks

* revert

* revert, make a helper persistent
2026-01-10 09:40:10 +01:00
karwosts b403b8f09e Implement allow_negative for duration selector (#28909) 2026-01-10 08:58:14 +01:00
karwosts b9a3dc795b Duration selector: migrate legacy duration formats (#28880) 2026-01-09 20:30:09 +01:00
Bram Kragten 35dbfdebcf Add support for choose selector to initial form data (#28876)
* Add support for choose selector to initial form data

* Update compute-initial-ha-form-data.ts
2026-01-09 19:57:32 +01:00
renovate[bot] c5e5fb3ace Update formatjs monorepo (#28905)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-01-09 17:41:54 +00:00
Yosi Levy e649472b20 Arrow fixes in media browser (#28890) 2026-01-09 18:31:25 +01:00
Yosi Levy 3cbb24a4c5 Fix for volume scroll in media player (#28891) 2026-01-09 18:30:45 +01:00
renovate[bot] f92608a9d3 Update dependency @codemirror/view to v6.39.9 (#28903)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-01-09 18:23:11 +01:00
renovate[bot] 6591cdc5c1 Update dependency @rspack/core to v1.7.1 (#28892)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-01-09 18:22:51 +01:00
renovate[bot] 0ae1ac367d Update dependency lit-html to v3.3.2 (#28762)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-01-09 08:32:27 +02:00
renovate[bot] 6d3a1b93e1 Update dependency lit to v3.3.2 (#28761)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-01-08 21:03:20 +01:00
renovate[bot] 6d7b22a21c Update dependency typescript-eslint to v8.52.0 (#28879)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-01-08 20:54:45 +01:00
Petar Petrov 784ee22623 Removes duplicate closing tag in ha-auth-form-string (#28883) 2026-01-08 20:53:55 +01:00
Aidan Timson c03654ef8e Fix wa dialog esc behaviour when preventing scrim closure (#28875)
* Fix wa dialog esc behaviour when preventing scrim closure

* Use wa-hide event to prevend closure
2026-01-08 17:10:53 +00:00
Pegasus 826cb3117d Fix: update the id, pan id to capitalize (#28873)
fix: update the id, pan id to capitalize
2026-01-08 12:26:49 +00:00
Aidan Timson f77fa26ffe Fix type error for calendar card (#28869) 2026-01-08 12:57:46 +02:00
Bram Kragten 35e30f9184 Fix color palette creation (#28867) 2026-01-08 10:14:03 +00:00
DAccord 7dd3ade678 Handling empty history (#28852)
Co-authored-by: DAccord <11232265+DAccord@users.noreply.github.com>
2026-01-08 09:58:38 +00:00
karwosts 6d1e15d11a Add a devtools event listener filter (#28849) 2026-01-08 10:58:24 +01:00
Timothy f5b33922ff Move companion app settings to a dedicated section in the settings (#28830) 2026-01-08 10:36:50 +01:00
dcapslock ceb7baf851 Fix choose selector active_choice when card editor config changes (#28858) 2026-01-08 10:20:42 +01:00
ildar170975 d195fd3244 Views: allow showing both icon & text title (#28690) 2026-01-07 19:03:48 +00:00
renovate[bot] 231cd632d6 Update dependency @bundle-stats/plugin-webpack-filter to v4.21.8 (#28846)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-01-07 17:23:37 +01:00
Wendelin 82d72ea39c Fix logs provider picker mobile width (#28847) 2026-01-07 16:30:49 +01:00
Wendelin 022bebb14f Throttle unknown value checks in ha-generic-picker (#28842) 2026-01-07 16:14:33 +01:00
Paul Bottein 0981ae1b4a Prefill the field with current value when editing a custom text item (#28840) 2026-01-07 15:42:47 +01:00
Paul Bottein 9608824a28 Remove ha-combo-box-textfield (#28841) 2026-01-07 15:39:58 +01:00
Marcin Bauer 33d215533e Add Shift+/ shortcut to shortcuts dialog and use Unicode command character (#28838)
* refactor: polish automation dialog UI and component styles

* Revert "Merge pull request #1 from marcinbauer85/fix/ui-polish-automation-dialog"

This reverts commit c2c47197e2, reversing
changes made to 49bed5e6a6.

* Add shortcuts dialog shortcut and use Unicode command character

* Update shortcut description text
2026-01-07 14:17:18 +00:00
Paul Bottein 5c503ecac0 Reduce shadow effect for scrollable fade mixin (#28832) 2026-01-07 14:16:41 +00:00
Wendelin d114693fed Improve device picker performance (#28835) 2026-01-07 14:28:18 +01:00
Kristel 7a8cb80413 Add Voice assistant column to data tables (#28785)
* added Voice assistant column to data tables

* remove commented code

* fix column settings

* code review changes

* reuse voice-assistants-expose-assistant-icon

* refactor getEntityVoiceAssistantsKeys

* fix column width

* Apply suggestion from @MindFreeze

---------

Co-authored-by: Petar Petrov <MindFreeze@users.noreply.github.com>
2026-01-07 13:15:01 +00:00
Marcin Bauer f5cd234c4b Refactor: Polish automation dialog UI and component styles (#28831)
* refactor: polish automation dialog UI and component styles

* Update ha-automation-row-targets.ts

- added borders to main automation list chips
2026-01-07 09:27:01 +00:00
karwosts 49bed5e6a6 Standardize all energy period calculations (#28827) 2026-01-07 08:46:54 +02:00
Bram Kragten b84a51235d Prevent showing error during loading of statistics picker (#28823) 2026-01-06 17:40:53 +01:00
Bram Kragten 602d6a2337 Use target selector to filter references entities (#28822)
* Use target selector to filter references entities

* Update ha-selector-state.ts
2026-01-06 16:16:23 +01:00
Matthias Alphart 6e614cd3f2 Explicitly set ha-wa-dialog content color (#28821) 2026-01-06 16:00:15 +01:00
Paulus Schoutsen 6793edd68b Bluetooth panel to support multi adapter (#28763)
* Support multiple adapters in bluetooth panel

* Move connection allocations up

* Make it tabs

* Add icons

* Revert "Add icons"

This reverts commit e338b6e578.

* Revert "Make it tabs"

This reverts commit d1b19d5c3e.

* Fix scanner matching and no active connection slot support

* Update src/panels/config/integrations/integration-panels/bluetooth/bluetooth-config-dashboard.ts

---------

Co-authored-by: Paul Bottein <paul.bottein@gmail.com>
Co-authored-by: J. Nick Koston <nick@koston.org>
Co-authored-by: Petar Petrov <MindFreeze@users.noreply.github.com>
2026-01-06 16:46:43 +02:00
Bram Kragten ad6e3267c3 Fix translation loading of choose selector (#28817) 2026-01-06 14:24:19 +01:00
Bram Kragten f941117ca4 Remove iOS focus handling from dialogs (#28818) 2026-01-06 13:45:21 +01:00
Bram Kragten aef0bf03e3 Use single path for thread icon, add KNX, simplify (#28819)
* Use single path for thread icon, simplify

* Add custom path for KNX
2026-01-06 12:43:05 +00:00
Simon Lamon f22f6b74db Remove used from energy usage header (#28775)
* Remove used

* Update src/translations/en.json

---------

Co-authored-by: Petar Petrov <MindFreeze@users.noreply.github.com>
2026-01-06 11:37:27 +00:00
Aidan Timson 913c4ae24e Remove duplicate custom items, remove "no matching ..." when allow-custom-value set (#28801)
* Remove duplicate custom items, allow default from picker

* Memoize

* Memoize

* Memoize func

* Don't show no matching item when custom value is allowed

* Remove no items found label now unused

* Cleanup unused translations

* Restore used value

* Remove no items found label now unused

* Remove redundant comment

* Remove searchFn

* Ensure custom value isnt identical

* Fix duplicated value

* Fix duplicated value

* Use additional items for entity state content

* Fix duplicate values

---------

Co-authored-by: Paul Bottein <paul.bottein@gmail.com>
2026-01-06 11:16:54 +01:00
Matthias Alphart 4b7b5fa21a Replace unload event handler for custom panels with pagehide (#28781)
* Replace `unload` event handler for custom panels

* Handle restore from bfcache

---------

Co-authored-by: Petar Petrov <MindFreeze@users.noreply.github.com>
2026-01-06 09:07:52 +00:00
Norbert Rittel bf6887541b Capitalize counter button labels (#28814)
Capitalized counter button labels
2026-01-06 08:47:51 +02:00
karwosts 26da9f3a37 Fix statistic-graph-card cutoff w/ energy date picker (#28810)
* Fix statistics-graph energy-date mode end-time with 5min statistics

* don't modify date/hour for 5minute graph

* suggestedMax use period instead of days

* go back to string types
2026-01-05 17:28:15 +02:00
Aidan Timson d48520efdf Add option for any state and show translated label for entity state values (#28803)
* Add option for any state

* Use translated labels for value
2026-01-05 16:55:23 +02:00
Aidan Timson d462356122 Reapply "Migrate dialog-device-registry-detail to ha-wa-dialog (#27668)" (#28804)
* Reapply "Migrate dialog-device-registry-detail to ha-wa-dialog (#27668)" (#27716)

This reverts commit 5f75fc5bcb.

* Apply suggestion from @MindFreeze

---------

Co-authored-by: Petar Petrov <MindFreeze@users.noreply.github.com>
2026-01-05 11:51:12 +00:00
Copilot 9a5cdb0a99 Display template targets with neutral badge instead of "Unknown area" error (#28799)
* Initial plan

* Add template target display with neutral badge

- Import mdiCodeBraces icon and isTemplate function
- Check if target ID is a template before checking if it exists
- Display grey {} icon with "Template" text for templated targets
- Add "template" translation key to target_summary
- Prevents misleading red "Unknown area" badge for template targets

Co-authored-by: piitaya <5878303+piitaya@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: piitaya <5878303+piitaya@users.noreply.github.com>
2026-01-05 12:44:58 +01:00
Paul Bottein eaf012d5ff Show close button when zwave firmware update is finished (#28805) 2026-01-05 13:42:55 +02:00
Paul Bottein 19934dad72 Remove custom value for unknown icon in icon picker (#28800) 2026-01-05 10:57:09 +00:00
Paul Bottein 6194f73442 Use regular item for bottom padding in combobox (#28798) 2026-01-05 11:40:54 +01:00
Paul Bottein dbc880fe35 Add warning about running tsc with file arguments (#28797)
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-05 10:08:21 +00:00
karwosts be4e46a3c6 Fix statistic names w/ energy_date_selection (#28787) 2026-01-05 09:51:49 +02:00
renovate[bot] 2fce89a689 Update dependency globals to v17 (#28789)
* Update dependency globals to v17

* Add global definitions for audioWorklet in ESLint configuration

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Petar Petrov <MindFreeze@users.noreply.github.com>
2026-01-05 07:11:10 +00:00
renovate[bot] 81d21b0907 Update formatjs monorepo (#28793)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-01-05 09:04:20 +02:00
dependabot[bot] 65381b1dc5 Bump relative-ci/agent-action from 3.2.1 to 3.2.2 (#28792)
Bumps [relative-ci/agent-action](https://github.com/relative-ci/agent-action) from 3.2.1 to 3.2.2.
- [Release notes](https://github.com/relative-ci/agent-action/releases)
- [Commits](https://github.com/relative-ci/agent-action/compare/c45aaa919ef85620af54242a241ac17a8fa35983...3c681926017930047fc03acaa35cd6a44efcbfc3)

---
updated-dependencies:
- dependency-name: relative-ci/agent-action
  dependency-version: 3.2.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-01-05 08:51:48 +02:00
Norbert Rittel 7cbede2f6e A few small spelling fixes in user-facing strings (#28786)
- use correct spelling for "Wi-Fi" trademark
- capitalize "PIN" as abbreviation
- fix spelling of "set up" as verb
- fix sentence-casing
2026-01-04 18:07:40 +01:00
renovate[bot] 0a13dddaea Update dependency @rspack/core to v1.7.0 (#28774)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-01-04 09:12:12 +00:00
renovate[bot] 662be980e8 Update dependency @rspack/dev-server to v1.1.5 (#28773)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-01-04 10:03:10 +01:00
renovate[bot] 209abf466d Update dependency @codemirror/view to v6.39.8 (#28759)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-01-02 19:29:57 +01:00
Simon Lamon db9a3bd562 Fix matter translations (#28752) 2026-01-02 11:22:45 +01:00
Paulus Schoutsen 36ecaa6610 Add config entry picker for Z-Wave JS panel (#28741) 2026-01-02 11:20:42 +01:00
Simon Lamon 4f46d0f4a3 Make cancel a secondary action in blueprint import (#28754) 2026-01-02 11:18:37 +01:00
Paulus Schoutsen 42ad47649d Verify bluetooth config entries exist before showing entry (#28745) 2026-01-02 11:18:02 +01:00
dependabot[bot] c62ee6e692 Bump qs from 6.14.0 to 6.14.1 (#28760)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-01-02 11:16:37 +01:00
Simon Lamon b38c8d7d5f Revert lit update (#28751) 2026-01-02 11:13:09 +01:00
renovate[bot] 83bcc39d5f Update dependency typescript-eslint to v8.51.0 (#28756) 2026-01-02 09:54:41 +01:00
Paulus Schoutsen 8d317d1e2c Hide dashboard controls in kiosk mode (#28742) 2026-01-01 00:36:49 +01:00
Simon Lamon 9acad2e83c Provide kioskmode in demo (#28739) 2025-12-30 22:45:01 +01:00
ildar170975 9099c5a92c Map card editor: add a basic sub-element editor (#28687)
* add subelement editor

* explicit type convertion

* test

* test

* test

* test

* prettier
2025-12-30 20:18:57 +01:00
Paulus Schoutsen 60c4d60d66 Protocol link updates (#28736)
* Update icons Thread & Insteon

* Remove matter link

* Remove back path from ZHA

* Fix ZHA dashboard config entry
2025-12-30 19:54:48 +01:00
sebcaps e8a4cde643 Add energy percentage usage on pie chart view. (#28733)
* showPercent

* unnecessary change
2025-12-30 19:54:35 +01:00
renovate[bot] 148eab31b6 Update dependency jsdom to v27.4.0 (#28726)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-12-29 19:18:29 +01:00
Franck Nijhof 9f7683021e Bumped version to 20251229.0 2025-12-29 12:41:19 +00:00
Franck Nijhof 549bd25f5c Merge branch 'master' into dev 2025-12-29 12:38:44 +00:00
Paulus Schoutsen eb74dd541a Show the protocols on the top level of the config section (#28448) 2025-12-29 11:52:20 +01:00
Paulus Schoutsen 4c84c7b54f Add kiosk mode foundation (#28714)
* Add kiosk mode foundation

* last file too
2025-12-29 11:24:24 +01:00
renovate[bot] 3a8f964ebd Update formatjs monorepo (#28724)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-12-29 05:21:27 +00:00
Christopher Nethercott 211ddcf7a4 Developer Tools: Update both event fire and event listen when clicked. (#28646)
Set the event listen event to one clicked when it isn't currently listening to an event.
2025-12-28 20:40:45 +01:00
renovate[bot] 021e5f5ce0 Update dependency @swc/helpers to v0.5.18 (#28722)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-12-28 19:03:16 +01:00
Paulus Schoutsen 4398e2d6c2 Remove snow flakes from hot path (#28716) 2025-12-27 20:28:58 +01:00
renovate[bot] e95af3c661 Update dependency @codemirror/view to v6.39.7 (#28713)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-12-27 19:17:06 +01:00
renovate[bot] 53af746466 Update dependency @lit-labs/observers to v2.1.0 (#28712)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-12-27 05:51:28 +00:00
renovate[bot] 18103c0e36 Update dependency lit-html to v3.3.2 (#28710)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-12-27 05:51:18 +00:00
renovate[bot] d6d235d032 Update dependency @lit-labs/motion to v1.1.0 (#28711)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-12-27 06:41:31 +01:00
renovate[bot] 3761dec700 Update dependency lit to v3.3.2 (#28709)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-12-27 06:40:45 +01:00
renovate[bot] 606fa41e6e Update dependency @lit/reactive-element to v2.1.2 (#28708)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-12-27 06:40:32 +01:00
renovate[bot] 0ee37e9544 Update formatjs monorepo (#28706)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-12-26 20:48:03 +01:00
renovate[bot] b0027b8c18 Update formatjs monorepo (#28704)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-12-26 16:32:59 +01:00
renovate[bot] a397368e02 Update dependency @codemirror/view to v6.39.6 (#28702)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-12-26 14:15:09 +00:00
Joep Meindertsma cac89e94df Add history link to statistics graph card (#28500) 2025-12-26 14:06:31 +00:00
Aidan Timson cc2e001990 Migrate area and cropper dialogs to ha-wa-dialog (#28608)
* Migrate area dialog to ha-wa-dialog

* Migrate cropper dialog to wa
2025-12-26 11:40:41 +01:00
renovate[bot] b1e2724aca Update dependency @rsdoctor/rspack-plugin to v1.4.0 (#28701)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-12-26 10:34:35 +00:00
ildar170975 5a60750841 ha-labels-picker: add a check for undefined label (#28686)
* add a check for undefined label

* simplify fix
2025-12-26 11:24:09 +01:00
ildar170975 94c180d64b state-badge element in Picture elements card: allow to set a "name" option (#28689)
* add "name" to StateBadgeElementConfig

* pass "name" to ha-state-label-badge

* add "name" field
2025-12-26 11:16:31 +01:00
ildar170975 6121f425c4 "Devices" & "Voice assistants expose": fix sort for "-" values (#28692)
* fix sorting for "-" values

* fix sorting for "-" values
2025-12-26 11:06:18 +01:00
renovate[bot] 91028fd0dd Update dependency typescript-eslint to v8.50.1 (#28698)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-12-26 11:05:21 +01:00
renovate[bot] 082a2c08b9 Update fullcalendar monorepo to v6.1.20 (#28700)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-12-26 11:05:15 +01:00
renovate[bot] d447dad28d Update CodeMirror (#28697)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-12-25 18:08:10 +01:00
renovate[bot] 4358ccdff8 Update CodeMirror (#28693)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-12-25 17:35:28 +02:00
Bram Kragten 8f7dd9b0ef Fix navigation in supervisor panel (#28683) 2025-12-24 13:32:30 +01:00
Paul Bottein 52db6a16d1 Add other devices view to home dashboard (#28097)
Co-authored-by: Bram Kragten <mail@bramkragten.nl>
2025-12-24 09:38:47 +00:00
karwosts ba213bf11c Don't set history redraw timer when not connected (#28679) 2025-12-24 10:08:35 +01:00
karwosts 5dea6b2c89 Fix a crash when clearing energy statistic (#28680) 2025-12-23 18:38:14 +01:00
Wendelin 97d51094df Add iOS-specific autofocus handling in HaWaDialog (#28607) 2025-12-23 14:43:03 +01:00
Wendelin 0904a1116c Language picker: add search fallback to en (#27818) 2025-12-23 14:41:30 +01:00
Wendelin 282458e645 Automation editor target in row improve configEntry subscription (#28662) 2025-12-23 14:40:55 +01:00
Paul Bottein 063c2d776a Improve new color picker (#28663)
Co-authored-by: Wendelin <12148533+wendevlin@users.noreply.github.com>
2025-12-23 10:36:00 +00:00
Aidan Timson 97e0bc8080 Show icons for ha-tab in desktop views (#28508)
Add icons to tabs
2025-12-22 21:18:54 +01:00
renovate[bot] 21e2c676b8 Update dependency @lokalise/node-api to v15.6.0 (#28668)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-12-22 20:50:46 +01:00
Paul Bottein 214b8cd5c7 Put favorite at the top for home dashboard (#28665) 2025-12-22 20:50:22 +01:00
renovate[bot] 3bd5481274 Update formatjs monorepo (#28667)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-12-22 20:39:18 +01:00
Wendelin ac63f991b2 Use generic-picker for log provider select (#28664)
Use generic-picker for log provider switcher
2025-12-22 18:56:22 +01:00
renovate[bot] 97e9129832 Update dependency sinon to v21.0.1 (#28666)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-12-22 18:02:51 +01:00
dependabot[bot] 704887999b Bump github/codeql-action from 4.31.8 to 4.31.9 (#28659)
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 4.31.8 to 4.31.9.
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/github/codeql-action/compare/1b168cd39490f61582a9beae412bb7057a6b2c4e...5d4e8d1aca955e8d8589aabd499c5cae939e33c7)

---
updated-dependencies:
- dependency-name: github/codeql-action
  dependency-version: 4.31.9
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-12-22 12:19:52 +01:00
ndrwrbgs 3194fe9a30 Add back button to history when coming from history-card title link (#28649) 2025-12-22 09:38:16 +01:00
ndrwrbgs 5ce7308194 Change 'Weekdays' to 'Days of the Week' (#28656) 2025-12-21 21:28:46 +01:00
renovate[bot] f9a9cf0ba0 Update dependency fs-extra to v11.3.3 (#28657)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-12-21 21:24:12 +01:00
renovate[bot] bf90c6829f Update dependency @lokalise/node-api to v15.5.0 (#28653)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-12-21 21:23:57 +01:00
karwosts 36d4097ff8 Add select-all to media management dialog, design update, migrate to wa (#28595)
* Add select-all to media management dialog, design update

* Update src/components/media-player/dialog-media-manage.ts

Co-authored-by: Petar Petrov <MindFreeze@users.noreply.github.com>

* remove old styles

* css

---------

Co-authored-by: Petar Petrov <MindFreeze@users.noreply.github.com>
2025-12-21 21:22:40 +02:00
Aidan Timson 92bf8c3d47 Add missing close icon in adaptive dialog mode (#28461)
* Add missing close icon in adaptive dialog mode

* No need for default text

* Restore
2025-12-21 14:53:10 +00:00
renovate[bot] 4251f3468b Update dependency vite-tsconfig-paths to v6.0.3 (#28652)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-12-21 14:54:09 +01:00
karwosts a6869e7c14 Use-top-label for statistic picker (#28639) 2025-12-20 18:25:42 +01:00
renovate[bot] bd46c358fb Update dependency @codemirror/commands to v6.10.1 (#28642)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-12-20 10:59:12 +00:00
renovate[bot] 30b8ea1ae8 Update dependency @rspack/core to v1.6.8 (#28643)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-12-20 11:53:48 +01:00
renovate[bot] a24dacf50d Update formatjs monorepo (#28641)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-12-20 11:53:03 +01:00
renovate[bot] 7cbd07e33e Update dependency vite-tsconfig-paths to v6.0.2 (#28640)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-12-20 08:57:07 +01:00
renovate[bot] c72ad83532 Lock file maintenance (#28621)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-12-19 19:11:00 +00:00
renovate[bot] f2aba45dfe Update formatjs monorepo (major) (#28619)
* Update formatjs monorepo

* Add compiler paths

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Simon Lamon <32477463+silamon@users.noreply.github.com>
2025-12-19 18:58:38 +00:00
Bram Kragten 639c2ce077 Add choose selector (#28624)
* Add choose selector

* add support for translation

* pass required

* Add to gallery
2025-12-19 19:52:31 +01:00
renovate[bot] 1bddc02ae0 Update dependency @formatjs/intl-durationformat to v0.8.1 (#28617)
* Update dependency @formatjs/intl-durationformat to v0.8.1

* Add compiler path for polyfill

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Simon Lamon <32477463+silamon@users.noreply.github.com>
2025-12-19 18:33:11 +00:00
Simon ebea5176e2 Add npmMinimalAgeGate to .yarnrc.yml (#28638) 2025-12-19 17:53:57 +00:00
Petar Petrov 39f550cf9f Fix datetime handling in energy charts (#28345)
* Fix datetime handling in energy charts

* PR comment

* Add detailedDailyData parameter to getSuggestedMax and update getCommonOptions

* refactor

---------

Co-authored-by: Bram Kragten <mail@bramkragten.nl>
2025-12-19 18:47:18 +01:00
Paul Bottein cdcbd00a92 Remove ha-space-0 (#28635)
* Remove ha-space-0

* Update src/components/ha-sidebar.ts

Co-authored-by: Aidan Timson <aidan@timmo.dev>

* Fix variable inside calc

* Replace for variables

---------

Co-authored-by: Aidan Timson <aidan@timmo.dev>
2025-12-19 17:12:28 +01:00
Bram Kragten 5b0bd9d577 Merge branch 'rc' 2025-12-19 17:05:32 +01:00
Bram Kragten d839152fd1 Bumped version to 20251203.3 2025-12-19 17:05:16 +01:00
Petar Petrov 407cb79805 Fix power sources graph ordering with multiple sources (#28549) 2025-12-19 17:04:50 +01:00
karwosts 7817ebe983 Home strategy: don't link non-admin to config pages (#28512) 2025-12-19 17:04:49 +01:00
Wendelin 7e58cedd49 Fix ha-toast z-index (#28491) 2025-12-19 17:04:48 +01:00
Wendelin 06334a039c Fix automation add TCA search icons (#28490)
Fix automation add TCA seach icons
2025-12-19 17:04:47 +01:00
Silas Krause 6e5853a1c0 Support legacy table styles in markdown (#28488)
* Remove unnecessary assist styles

* Fix list styles

* Remove table styles for role="presentation"
2025-12-19 17:04:46 +01:00
Wendelin f4f4520773 Fix target picker area in history/activity (#28474)
* Add max target picker width for history and activity

* Fix target picker  area selection in history and activity
2025-12-19 17:04:45 +01:00
karwosts 94453dfba5 Fix markdown card image sizing (#28449) 2025-12-19 17:04:44 +01:00
renovate[bot] 86cd0e81ad Update vitest monorepo to v4.0.16 (#28636)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-12-19 15:56:52 +00:00
Aidan Timson 6efe444af3 Use space tokens in more info dialog area (#28627)
Co-authored-by: Wendelin <12148533+wendevlin@users.noreply.github.com>
2025-12-19 16:12:32 +01:00
Wendelin 09c9665b2f Remove ha-combo-box and vaadin dependencies (#28632) 2025-12-19 15:11:17 +01:00
Paul Bottein 23e394fec9 Always add favorite heading for home overview (#28629) 2025-12-19 11:35:44 +00:00
Wendelin 4b02a11634 Migrate ha-selector-select to use ha-generic-picker component (#28614) 2025-12-19 10:06:20 +00:00
Aidan Timson ed9c00cab5 Migrate entity state picker to generic picker (#28613)
Co-authored-by: Wendelin <12148533+wendevlin@users.noreply.github.com>
2025-12-19 10:52:39 +01:00
Aidan Timson eaa1fb4107 Add space tokens to developer tools (#28626) 2025-12-19 09:33:53 +00:00
Aidan Timson c0a49b3d0b Migrate floor dialog to webawesome (#28606) 2025-12-19 10:21:55 +01:00
karwosts a7a00228a2 Add a debug tool to capture an entity diagnostic details (#28615) 2025-12-19 09:18:13 +00:00
renovate[bot] c85f7a71b2 Update dependency @rsdoctor/rspack-plugin to v1.3.16 (#28623)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-12-19 09:11:31 +00:00
renovate[bot] c95e914219 Update dependency @types/chromecast-caf-receiver to v6.0.25 (#27189)
* Update dependency @types/chromecast-caf-receiver to v6.0.25

* Fix typings

* Fix messageType type json

* Fix FMP4

* Add doc link

* Fix FMP4

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Paul Bottein <paul.bottein@gmail.com>
2025-12-19 10:53:48 +02:00
ildar170975 362a0b96ab ha-labels-picker: remove margin-bottom for ha-chip-set (#28559) 2025-12-19 08:55:21 +01:00
Jan Layola ef984fc438 Trim whitespace from 2FA input before validation (#28616) 2025-12-19 08:48:11 +01:00
renovate[bot] ce9bbc9972 Update dependency typescript-eslint to v8.50.0 (#28618)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-12-18 19:19:20 +01:00
Aidan Timson a3921f0559 Migrate entity state content picker to generic picker (#28612)
* Migrate entity state content picker to generic picker

* Use similar primary/secondary as name picker

* Remove redundant func

* Memoize func

* Add custom value label

* Format

* Remove

* Remove renderer, use better translation

* Format

* Cleanup import

* Remove search labels where unused

* Merge
2025-12-18 19:12:03 +01:00
Aidan Timson f8ec5d27a4 Migrate entity attribute picker to generic picker (#28611)
Co-authored-by: Wendelin <12148533+wendevlin@users.noreply.github.com>
2025-12-18 17:03:21 +01:00
Wendelin d679916fa5 Migrate domain selection to use generic picker component (#28605)
* Migrate domain selection to use generic picker component

* Remove unused CSS, add margins

* Space tokens

* Fix validation

---------

Co-authored-by: Aidan Timson <aidan@timmo.dev>
2025-12-18 13:39:16 +00:00
Aidan Timson 96be4768d3 Migrate entity name picker to generic picker (#28604)
Co-authored-by: Wendelin <12148533+wendevlin@users.noreply.github.com>
2025-12-18 14:31:29 +01:00
Aidan Timson 6ff3b9f761 Migrate new label dialog to ha-wa-dialog (#28586) 2025-12-18 13:22:07 +01:00
Joakim Plate 9026009842 Let event domain expose attributes in gui (#28486) 2025-12-18 12:43:48 +01:00
Aidan Timson 54398a4784 Fix entity settings row sizing (#28585) 2025-12-18 12:42:29 +01:00
Wendelin fa3cc970ec Migrate Z-Wave JS node configuration to use generic picker component (#28603) 2025-12-18 13:30:24 +02:00
Aidan Timson 1cf0560003 Migrate color picker to generic picker (#28598) 2025-12-18 11:23:25 +01:00
Wendelin 2a4ac15987 Generic-picker: Implement allowCustomValue (#28572)
* Introduce allowCustomValue and remove usage

* Review

* Fix secondary title
2025-12-18 12:19:57 +02:00
Aidan Timson f264eebe49 Remove unused prop in target picker (#28601) 2025-12-18 10:14:42 +00:00
Aidan Timson dae27e091f Migrate config entry picker to new picker syntax (#28600) 2025-12-18 10:10:55 +00:00
Aidan Timson 7ca681e417 Refactor generic pickers (#28570) 2025-12-18 10:53:50 +01:00
ndrwrbgs 1adfe63322 Add media query for prefers-reduced-motion in dialog styles (#28593)
Co-authored-by: ndrwrbgs <10776890+ndrwrbgs@users.noreply.github.com>
Co-authored-by: Wendelin <12148533+wendevlin@users.noreply.github.com>
2025-12-18 08:18:19 +00:00
Wendelin 119a505a0d Add iOS focus element messaging for ha-generic-picker component (#28569) 2025-12-18 09:18:01 +01:00
renovate[bot] 1f8403f6c1 Update dependency vite-tsconfig-paths to v6 (#28596)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-12-18 09:19:09 +02:00
Wendelin 7dd7309a47 Migrate addon-picker to generic-picker (#28567) 2025-12-17 16:33:41 +00:00
Wendelin 736afe2530 Migrate config-entry-picker to generic-picker (#28568)
* Use generic-picker for config-entry-picker

* Apply suggestion from @MindFreeze

Co-authored-by: Petar Petrov <MindFreeze@users.noreply.github.com>

* Apply suggestion from @MindFreeze

Co-authored-by: Petar Petrov <MindFreeze@users.noreply.github.com>

---------

Co-authored-by: Petar Petrov <MindFreeze@users.noreply.github.com>
2025-12-17 13:49:23 +02:00
Paul Bottein 92980dfddf Show summaries at top on mobile, sidebar on desktop (#28573)
* Use weather tile card and energy summary in home dashboard

* Only use sidebar on desktop

* Hide sidebar on mobile

* Rename widget to summaries

* Improve commonly used

* Feedbacks

* Use key instead of section
2025-12-17 11:45:27 +02:00
karwosts 9f3d6e1fea fix read-only fields in config flow expandables (#28579)
* fix read-only fields in config flow expandables

* types

---------

Co-authored-by: Petar Petrov <MindFreeze@users.noreply.github.com>
2025-12-17 07:29:56 +00:00
ildar170975 9e9adfcc90 ha-data-table: add ellipsis for ".secondary" (#28577)
add ellipsis for ".secondary"
2025-12-17 06:41:07 +01:00
karwosts 9b6ebdfcc0 device selector - add missing disabled & helper (#28576)
* device selector - add missing disabled & helper

* more
2025-12-17 06:39:50 +01:00
Aidan Timson 88faedba65 Migrate ha-icon-picker to generic picker (#27677) 2025-12-16 15:14:44 +00:00
Aidan Timson b125cd5f3e Migrate hui-dialog-select-dashboard to ha-wa-dialog (#28456) 2025-12-16 13:47:50 +01:00
Aidan Timson 3425837de3 Switch energy now chart to watts, format values to W, kW etc (#28555)
* Switch energy now chart to watts

* Add kW

* Scale formatted value based on powers of 1000

1000 W -> 1 kW
W → kW → MW → GW → TW

* Explainers

* Use 3 dp for kW+ and 0 for W

* Add non-integer test
2025-12-16 14:33:45 +02:00
Paul Bottein 24a797e46a Improve shadow and border for energy date picker (#28566)
* Improve shadow and border for energy date picker

* Use variable

* Fix z-index

* Fix margin

* Improve mobile margin
2025-12-16 14:05:47 +02:00
Copilot 4a486ff28b Add fallback for empty cards in sections view (#28565)
* Initial plan

* Add edit-mode class to container in hui-grid-section to enable minimum card height

Co-authored-by: piitaya <5878303+piitaya@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: piitaya <5878303+piitaya@users.noreply.github.com>
2025-12-16 10:17:28 +00:00
Clément Notin 6be390a07e Add ignoreLocation option to fuseMultiTerm config (#28557) 2025-12-16 09:44:33 +01:00
Wendelin c93942919b Automation editor show targets within rows (#28510)
* Automation editor show targets within rows

* review

* Fix expandable row icons

* Use state icon instead of state-badge

* Fix target wrap

* Use default font weight for automation rows

* Remove comma from targets in row
2025-12-16 09:42:38 +02:00
ildar170975 ca06269a91 Entity card: remove whitespaces in span (#28562) 2025-12-16 08:18:13 +01:00
ildar170975 b3d7c0b6dc Helpers table: show dashes in "Area" column (#28563) 2025-12-16 08:16:15 +01:00
Paul Bottein e709703f79 Wait for translations before showing home and domain dashboards (#28556) 2025-12-16 08:11:15 +01:00
renovate[bot] fd42614a23 Update dependency eslint to v9.39.2 (#28560)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-12-16 08:41:38 +02:00
Petar Petrov 4050dd0384 Fixed period selector for energy dashboard (#28458)
* Sticky period selector for energy dashboard

* Blur view when date picker is open

* move to hui-root via slot

* fix scrollbar

* Use dialog backdrop and define default

* Set energy selector position to fixed

* format

---------

Co-authored-by: Paul Bottein <paul.bottein@gmail.com>
2025-12-15 18:21:46 +01:00
Petar Petrov 9996b1bfea Fix inability to leave scene creation page without saving (#28546) 2025-12-15 16:59:57 +01:00
Petar Petrov 8092340d2a Fix min max issues in statistics chart (#28493) 2025-12-15 15:54:47 +01:00
Petar Petrov 443e205395 Fix power sources graph ordering with multiple sources (#28549) 2025-12-15 15:52:59 +01:00
Wendelin 8c5d0c4b80 Use ha-state-icon for add from target entity icon (#28551) 2025-12-15 15:51:17 +01:00
Paul Bottein 3005f12ef5 Restore navigation header for home, light, security and climate dashboards (#28552) 2025-12-15 15:44:51 +01:00
Petar Petrov 3bcf530200 Storage space breakdown chart (#28311)
Co-authored-by: Aidan Timson <aidan@timmo.dev>
Co-authored-by: Wendelin <12148533+wendevlin@users.noreply.github.com>
2025-12-15 15:10:35 +01:00
ildar170975 af2fa98666 ha-map: add a variable for marker size (#28536)
* use a new variable for width & height

* use a new variable for width & height

* fix styles & creation of marker

* iconSize -> markerIconSize (for zones)

* Apply suggestion from @MindFreeze

Co-authored-by: Petar Petrov <MindFreeze@users.noreply.github.com>

* format

---------

Co-authored-by: Petar Petrov <MindFreeze@users.noreply.github.com>
2025-12-15 13:01:27 +00:00
renovate[bot] 8f335668db Update Node.js to v24 (#27687)
* Update Node.js to v24

* fix test

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Petar Petrov <MindFreeze@users.noreply.github.com>
2025-12-15 14:56:48 +02:00
Aidan Timson 51acd271ea Add duplicate voice assistant action (#28511) 2025-12-15 13:12:57 +01:00
dependabot[bot] 830e9b5089 Bump dessant/lock-threads from 5.0.1 to 6.0.0 (#28545)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-12-15 11:12:59 +00:00
dependabot[bot] b13cb84baf Bump actions/upload-artifact from 5.0.0 to 6.0.0 (#28542)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-12-15 11:12:33 +00:00
renovate[bot] f8df7f37ea Update dependency @codemirror/view to v6.39.4 (#28548)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-12-15 12:32:35 +02:00
Aidan Timson 54e4f4e60a Attempt to ensure view transitions are always ran (#28547) 2025-12-15 11:24:50 +01:00
ildar170975 81cb483163 Generic picker: show a label for area, category, language (#28236)
Co-authored-by: Aidan Timson <aidan@timmo.dev>
2025-12-15 08:54:12 +00:00
dependabot[bot] eb5b14ea00 Bump actions/cache from 4.3.0 to 5.0.1 (#28543)
Bumps [actions/cache](https://github.com/actions/cache) from 4.3.0 to 5.0.1.
- [Release notes](https://github.com/actions/cache/releases)
- [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md)
- [Commits](https://github.com/actions/cache/compare/0057852bfaa89a56745cba8c7296529d2fc39830...9255dc7a253b0ccc959486e2bca901246202afeb)

---
updated-dependencies:
- dependency-name: actions/cache
  dependency-version: 5.0.1
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-12-15 08:20:03 +02:00
renovate[bot] b221fbb387 Update dependency @rsdoctor/rspack-plugin to v1.3.15 (#28541)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-12-15 06:11:43 +00:00
dependabot[bot] 3033bfb1fb Bump github/codeql-action from 4.31.7 to 4.31.8 (#28544)
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 4.31.7 to 4.31.8.
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/github/codeql-action/compare/cf1bb45a277cb3c205638b2cd5c984db1c46a412...1b168cd39490f61582a9beae412bb7057a6b2c4e)

---
updated-dependencies:
- dependency-name: github/codeql-action
  dependency-version: 4.31.8
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-12-15 08:11:38 +02:00
karwosts 8db967eb2f Fix navigate action after confirm (#28535)
Fix navigate on confirm
2025-12-15 08:11:20 +02:00
renovate[bot] 10af86cc02 Update dependency terser-webpack-plugin to v5.3.16 (#28537)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-12-15 08:03:40 +02:00
renovate[bot] dfc7116819 Update dependency @codemirror/view to v6.39.3 (#28533)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-12-14 15:56:09 +01:00
ildar170975 685c642bfc hui-map-card: add firstUpdated() with _getMapEntities() (#28526)
add firstUpdated() with _getMapEntities()
2025-12-13 17:15:57 +02:00
renovate[bot] 2e547937b8 Update dependency @rsdoctor/rspack-plugin to v1.3.13 (#28532)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-12-13 16:32:52 +02:00
Michael Bisbjerg e3e01c327a Fix trace download truncation with Jinja comments (#28519) 2025-12-13 09:50:42 +02:00
renovate[bot] abd706fed0 Update dependency @codemirror/view to v6.39.2 (#28522)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-12-13 07:59:22 +01:00
renovate[bot] 3bd45dd29b Update dependency ua-parser-js to v2.0.7 (#28516)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-12-12 15:34:04 +01:00
renovate[bot] 206f067d2b Update dependency @rspack/core to v1.6.7 (#28518)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-12-12 15:31:53 +01:00
renovate[bot] caefa7530a Update dependency @codemirror/view to v6.39.1 (#28520)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-12-12 15:31:26 +01:00
Aidan Timson de142e33a1 Use entity picker for heading card entities editor (#28463)
* Use entity picker for heading card entities editor

* Use space tokens

* Pass index

* Lint

* Set undefined

* Iterate

* Spread

* Fixes

* Fixes
2025-12-12 09:30:07 +02:00
karwosts 5d4c3ebfcd Home strategy: don't link non-admin to config pages (#28512) 2025-12-12 07:23:37 +01:00
renovate[bot] eb910c5ac5 Update dependency typescript-eslint to v8.49.0 (#28515)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-12-12 07:23:10 +01:00
renovate[bot] 72726a2e0f Update dependency @codemirror/view to v6.39.0 (#28514)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-12-12 07:22:53 +01:00
Aidan Timson 253b49871e Allow deletion of disabled helper entities via overflow menu (#28498)
* Allow deletion of disabled entities

* Still check if editable
2025-12-11 16:12:33 +02:00
Aidan Timson 6306890922 Add entities to device page overflow menu (#28497) 2025-12-11 16:07:04 +02:00
renovate[bot] fee16ed4e4 Update dependency jsdom to v27.3.0 (#28504)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-12-11 16:01:40 +02:00
karwosts 055f6c82fb Fix labels in entity picker create entity (#28503) 2025-12-11 15:55:15 +02:00
Paul Bottein 0c1627c69a Fix area and floor picker search (#28494) 2025-12-11 14:16:17 +02:00
Aidan Timson 780c03ece8 Add .cursor to gitignore (#28496) 2025-12-11 14:14:27 +02:00
Silas Krause 62dc66abd8 Support legacy table styles in markdown (#28488)
* Remove unnecessary assist styles

* Fix list styles

* Remove table styles for role="presentation"
2025-12-11 14:10:26 +02:00
Wendelin 08aaee754e Fix automation add TCA search icons (#28490)
Fix automation add TCA seach icons
2025-12-11 13:48:41 +02:00
Aidan Timson bba400443e Fix mobile touch edit card click after saving card (#28484) 2025-12-11 10:17:52 +01:00
Wendelin a7a937e197 Fix ha-toast z-index (#28491) 2025-12-11 09:14:12 +00:00
karwosts 2a97913520 Pass hass to ha-yaml-editors (and others) (#28485) 2025-12-11 08:31:42 +01:00
Wendelin 9f16ce7341 Fix picker initial sort and reorganize picker data (#28476) 2025-12-11 08:28:45 +01:00
Aidan Timson 3e20e9b388 Wait for custom dashboards to load in profile settings before rendering select (#28482)
Wait for custom dashboards to load before rendering select
2025-12-10 18:06:42 +01:00
Wendelin 6891eb9ff8 Fix target picker area in history/activity (#28474)
* Add max target picker width for history and activity

* Fix target picker  area selection in history and activity
2025-12-10 17:59:35 +02:00
Wendelin f649b3783d fix service-picker search keys (#28481)
Update SEARCH_KEYS to include search_labels prefix for consistency
2025-12-10 16:59:23 +01:00
Wendelin c46f67d572 Fix automation add tca item search (#28483) 2025-12-10 15:34:52 +00:00
Wendelin 86acfa67dd Add unchecked icon support to ha-dropdown-item component (#28299) 2025-12-10 16:08:45 +01:00
dcapslock 3c5c19270f Allow for badges to be connectedWhileHidden and for hui-badge to respond to badge-visibility-changed event (#28399)
* Allow for badges to be connectedWhileHidden and for hui-badge to respond to badge-visibility-changed event

* Update after environment prettier update
2025-12-10 15:23:53 +01:00
karwosts 6db7817032 Hide energy usage chips when no title is set (#28464) 2025-12-10 10:16:34 +02:00
Aidan Timson 05ca8253f0 Update HaGenericPicker unknown value check to handle null and empty strings (#28462) 2025-12-09 15:53:28 +01:00
Aidan Timson 071161e82d Add area to helpers table (#28460) 2025-12-09 14:05:54 +00:00
Wendelin 9cd38c7128 Multi term search sort by search score (#28353) 2025-12-09 14:48:57 +01:00
Wendelin 6322c19a45 Generic picker warn unknown selected item (#28372)
* Add unknown item text localization to various pickers

* Review
2025-12-09 14:24:30 +02:00
karwosts 74b51b77fe Fix markdown card image sizing (#28449) 2025-12-09 13:15:12 +01:00
Wendelin b80481b53e Generic picker: scroll to selected value on open (#28457) 2025-12-09 12:27:56 +01:00
Aidan Timson 2ce1eaf8c6 Revert "Add basic view transitions between tab UIs (#28374)" (#28451) 2025-12-09 13:18:51 +02:00
Aidan Timson 4030ce3f88 Migrate dialog-upload-backup to ha-wa-dialog (#28444)
* Migrate dialog-upload-backup.ts from ha-md-dialog to ha-wa-dialog

* Remove custom css, space tokens

* Restore
2025-12-09 09:32:28 +02:00
Aidan Timson 41cabde393 Migrate dialog-download-decrypted-backup to ha-wa-dialog (#28442)
* Migrate dialog-download-decrypted-backup.ts from ha-md-dialog to ha-wa-dialog

* Fixes from other migrations
2025-12-09 09:28:44 +02:00
Aidan Timson 47d1fdf673 Migrate change/show backup encryption key to ha-wa-dialog (#28428)
* Migrate dialog-change-backup-encryption-key.ts from ha-md-dialog to ha-wa-dialog

* Remove open render nothing, remove custom css size

* Migrate show backup key

* Apply suggestion from @MindFreeze

---------

Co-authored-by: Petar Petrov <MindFreeze@users.noreply.github.com>
2025-12-09 07:24:43 +00:00
Aidan Timson e59e83fffe Migrate dialog-areas-floors-order to ha-wa-dialog (#28424)
* Migrate dialog-areas-floors-order.ts from ha-md-dialog to ha-wa-dialog

* Fix saving

* Remove render nothing if dialog false

* Remove custom width
2025-12-09 09:12:29 +02:00
Aidan Timson b896b78876 Migrate labs dialogs to ha-wa-dialog (#28429)
* Migrate dialog-labs-preview-feature-enable.ts from ha-md-dialog to ha-wa-dialog

* Migrate dialog-labs-progress.ts from ha-md-dialog to ha-wa-dialog

* Restore

* Remove use of slots

* Fix

* Remove header
2025-12-09 08:55:28 +02:00
Copilot 6e180c9fb4 Migrate ha-button-menu to ha-dropdown in 3 files (#28337)
* Initial plan

* Migrate ha-button-menu to ha-dropdown in 3 files

- Migrate ha-config-logs.ts: Replace ha-button-menu with ha-dropdown for log provider selection
- Migrate ha-qr-scanner.ts: Replace ha-button-menu with ha-dropdown for camera selection
- Migrate ha-data-table-labels.ts: Replace ha-button-menu with ha-dropdown for overflow labels

Following the migration pattern from PR #28293

Co-authored-by: wendevlin <12148533+wendevlin@users.noreply.github.com>

* Fix ha-data-table-labels migration to use proper @wa-select pattern

- Add HaDropdownItem type import
- Use @wa-show instead of @click for menu opening
- Use @wa-select for item selection with proper event handler
- Update comment to reference ha-dropdown instead of ha-button-menu

Co-authored-by: wendevlin <12148533+wendevlin@users.noreply.github.com>

* Fixes

* Remove unused code

* Remove unused styles

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: wendevlin <12148533+wendevlin@users.noreply.github.com>
Co-authored-by: Wendelin <w@pe8.at>
2025-12-08 21:30:35 +01:00
Paul Bottein 0ce0247a2c 20251203.2 (#28443) 2025-12-08 17:30:04 +01:00
Paul Bottein ce8cabbad9 Bumped version to 20251203.2 2025-12-08 17:29:01 +01:00
karwosts 0802841606 More unsafe description_placeholders fixes (#28416) 2025-12-08 17:28:52 +01:00
Nils Schönwald cb93e1b741 Update snowflake to 6 sides (#28406) 2025-12-08 17:28:51 +01:00
dcapslock 30c383a2fc Energy strategies to refresh energy collection which allows to be used in custom dashboards (#28400)
* Energy strategies to refresh energy collection which allows to be used in custom dashboards

* Update src/panels/energy/strategies/energy-overview-view-strategy.ts

Co-authored-by: Petar Petrov <MindFreeze@users.noreply.github.com>

* Only refresh if no prefs

---------

Co-authored-by: Petar Petrov <MindFreeze@users.noreply.github.com>
2025-12-08 17:28:50 +01:00
karwosts 73ee235fef Fix for undefined description_placeholders (#28395)
Another fix for undefined description_placeholders
2025-12-08 17:28:49 +01:00
Aidan Timson b50daecdec Create an adaptive dialog and bottom sheet component, migrate restart (#28344)
* Create a switchable dialog and bottom sheet component

* Migrate dialog restart

* Fix close action

* Docstring

* Rename type

* Rename func

* Document

* Remove flex, use flex

* Cleanup docstring

* Update bodyScrolled

* Cleanup

* Remove

* Rename to ha-adaptive-dialog

* Cleanup

* Format

* Fix forwarding of slots

* Fix style

* listenMediaQuery, simplify and remove double scroll handling

* Add slotted footer to bottom sheet for compat

* Add block-mode-change to stop mode switches for forms etc.

* Document block-mode-change

* Update gallery

* Fix gallery doc for wa-dialog (caught by agent review)

* Update src/components/ha-adaptive-dialog.ts

Co-authored-by: Petar Petrov <MindFreeze@users.noreply.github.com>

* Cleanup

---------

Co-authored-by: Petar Petrov <MindFreeze@users.noreply.github.com>
2025-12-08 17:32:31 +02:00
Aidan Timson f5bd0816a8 Fix more info entity settings bottom fade (#28437)
* Use space tokens

* Fix settings bottom fade issue

* Space token

* Restore
2025-12-08 16:05:49 +02:00
Aidan Timson b6d1e65044 Migrate dialog-edit-sidebar to ha-wa-dialog, fix dialog padding (#28426)
* Migrate dialog-edit-sidebar.ts from ha-md-dialog to ha-wa-dialog

* Format

* Fix wa dialog padding impl

* Remove custom size

* Use space tokens

* Remove render nothing

* Fix default top padding
2025-12-08 14:47:10 +02:00
Aidan Timson e2312e52e3 Remove z-index from scrollable fades (#28434) 2025-12-08 14:33:30 +02:00
renovate[bot] 46a6da33d9 Update dependency terser-webpack-plugin to v5.3.15 (#28436)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-12-08 14:32:39 +02:00
Aidan Timson e7b0b9a090 Add basic view transitions between tab UIs (#28374)
* Add basic view transitions between tab UIs

* Remove debug

* Add to debug navigation action
2025-12-08 14:22:05 +02:00
Petar Petrov 63ffc3b7f9 Restrict row resizing for stack and entities cards (#28422)
* Restrict row resizing for stack and entities cards

* Fix disabled state for grid layout slider
2025-12-08 12:53:37 +02:00
Nils Schönwald ebfceae38c Update snowflake to 6 sides (#28406) 2025-12-08 09:16:55 +00:00
Aidan Timson cccfc1716b Add scrollable fade mixin to bottom sheet, picker combo box (#28347)
* Add scrollable fade mixin to ha-bottom-sheet

* Wrap picker combobox (used inside of sheet with virtualizer)
2025-12-08 08:58:19 +02:00
dcapslock 6abf0dfcb9 Energy strategies to refresh energy collection which allows to be used in custom dashboards (#28400)
* Energy strategies to refresh energy collection which allows to be used in custom dashboards

* Update src/panels/energy/strategies/energy-overview-view-strategy.ts

Co-authored-by: Petar Petrov <MindFreeze@users.noreply.github.com>

* Only refresh if no prefs

---------

Co-authored-by: Petar Petrov <MindFreeze@users.noreply.github.com>
2025-12-08 08:17:19 +02:00
dependabot[bot] 9d2404763f Bump home-assistant/wheels from 2025.11.0 to 2025.12.0 (#28421)
Bumps [home-assistant/wheels](https://github.com/home-assistant/wheels) from 2025.11.0 to 2025.12.0.
- [Release notes](https://github.com/home-assistant/wheels/releases)
- [Commits](https://github.com/home-assistant/wheels/compare/2025.11.0...2025.12.0)

---
updated-dependencies:
- dependency-name: home-assistant/wheels
  dependency-version: 2025.12.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-12-08 06:11:02 +00:00
dependabot[bot] 6c84c9b44e Bump github/codeql-action from 4.31.5 to 4.31.7 (#28417)
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 4.31.5 to 4.31.7.
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/github/codeql-action/compare/fdbfb4d2750291e159f0156def62b853c2798ca2...cf1bb45a277cb3c205638b2cd5c984db1c46a412)

---
updated-dependencies:
- dependency-name: github/codeql-action
  dependency-version: 4.31.7
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-12-08 06:10:48 +00:00
dependabot[bot] edb2172bdd Bump actions/checkout from 6.0.0 to 6.0.1 (#28419)
Bumps [actions/checkout](https://github.com/actions/checkout) from 6.0.0 to 6.0.1.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/1af3b93b6815bc44a9784bd300feb67ff0d1eeb3...8e8c483db84b4bee98b60c0593521ed34d9990e8)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: 6.0.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-12-08 06:10:44 +00:00
dependabot[bot] 067e7645ac Bump actions/stale from 10.1.0 to 10.1.1 (#28420)
Bumps [actions/stale](https://github.com/actions/stale) from 10.1.0 to 10.1.1.
- [Release notes](https://github.com/actions/stale/releases)
- [Changelog](https://github.com/actions/stale/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/stale/compare/5f858e3efba33a5ca4407a664cc011ad407f2008...997185467fa4f803885201cee163a9f38240193d)

---
updated-dependencies:
- dependency-name: actions/stale
  dependency-version: 10.1.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-12-08 06:10:35 +00:00
dependabot[bot] c3e4af3db8 Bump actions/setup-node from 6.0.0 to 6.1.0 (#28418)
Bumps [actions/setup-node](https://github.com/actions/setup-node) from 6.0.0 to 6.1.0.
- [Release notes](https://github.com/actions/setup-node/releases)
- [Commits](https://github.com/actions/setup-node/compare/2028fbc5c25fe9cf00d9f06a71cc4710d4507903...395ad3262231945c25e8478fd5baf05154b1d79f)

---
updated-dependencies:
- dependency-name: actions/setup-node
  dependency-version: 6.1.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-12-08 06:10:25 +00:00
karwosts f44be2d3b9 More unsafe description_placeholders fixes (#28416) 2025-12-08 08:05:35 +02:00
karwosts cff7ed9b05 Fix for undefined description_placeholders (#28395)
Another fix for undefined description_placeholders
2025-12-07 09:21:08 +02:00
Norbert Rittel c4e5f1dba6 Fix wording for use with both energy and power sensors (#28392) 2025-12-06 13:41:56 +00:00
Bram Kragten d1011d691f Handle search params changed after first updated for dashboards and … (#28375)
handle search params changed after first updated for dashboards and integrations
2025-12-06 13:45:44 +02:00
renovate[bot] 7dda8c36bc Update dependency prettier to v3.7.4 (#28388)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-12-06 09:32:57 +01:00
Paul Bottein 31603ea7b2 20251203.1 (#28383) 2025-12-05 20:53:17 +01:00
Paul Bottein 17c1043cfc Bumped version to 20251203.1 2025-12-05 20:51:48 +01:00
Timothy da255dce40 Add add to button in more info topbar for non admin users (#28365) 2025-12-05 20:51:20 +01:00
Paul Bottein 0c68072f8f Use non-admin endpoint to subscribe to one lab feature (#28352) 2025-12-05 20:51:19 +01:00
Petar Petrov d197fd8f76 Fix calendar card not showing different colors for multiple calendars (#28338) 2025-12-05 20:51:18 +01:00
Paul Bottein a961a87872 Move reorder areas and floors to floor overflow (#28335) 2025-12-05 20:51:17 +01:00
Petar Petrov cc96c707b9 Fix markdown sections and styling (#28333) 2025-12-05 20:51:16 +01:00
Petar Petrov 4b73713f2a Fix gauge severity using entity state instead of attribute value (#28331) 2025-12-05 20:51:15 +01:00
Petar Petrov c001102f15 Append current state to power-sources-graph (#28330) 2025-12-05 20:51:14 +01:00
Preet Patel c1e5e0bfcb Fix energy dashboard redirect for device-consumption-only configs (#28322)
When users configure energy with only device consumption (no
grid/solar/battery/gas/water sources), the dashboard would redirect
to /config/energy instead of displaying. This occurred because
_generateLovelaceConfig() returned an empty views array.

The fix adds hasDeviceConsumption check and includes ENERGY_VIEW
when device consumption is configured, since energy-view-strategy
already supports device consumption cards.
2025-12-05 20:51:13 +01:00
Bram Kragten a1412e90fd Add more info to the energy demo (#28316)
* Add more info to the energy demo

* Also add battery power
2025-12-05 20:51:12 +01:00
Petar Petrov f6f40c1679 Always show energy-sources-table in overview (#28315) 2025-12-05 20:48:59 +01:00
renovate[bot] 45b2376616 Update vitest monorepo to v4.0.15 (#28379)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-12-05 17:51:51 +01:00
Paul Bottein 2f70a82d02 Use non-admin endpoint to subscribe to one lab feature (#28352) 2025-12-05 17:34:22 +01:00
Aidan Timson 00868b2450 Add scrollable fade to more info dialog (#28314)
* Add scrollable fade to more info dialog

* Introduce scroll threshold (default 4px, more info 24px)

* Docstrings

* Remove getter for numeric values in mixin

* Update src/dialogs/more-info/ha-more-info-dialog.ts

Co-authored-by: Wendelin <12148533+wendevlin@users.noreply.github.com>

* Fix lint

---------

Co-authored-by: Wendelin <12148533+wendevlin@users.noreply.github.com>
2025-12-05 15:43:47 +01:00
Timothy e573a726aa Add add to button in more info topbar for non admin users (#28365) 2025-12-05 15:05:50 +01:00
Petar Petrov ef82bc2abb Fix calendar card not showing different colors for multiple calendars (#28338) 2025-12-05 13:39:51 +01:00
renovate[bot] 92e3864f63 Update dependency typescript-eslint to v8.48.1 (#28371)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-12-05 13:17:53 +01:00
renovate[bot] a4af975bb3 Update dependency @rspack/core to v1.6.6 (#28370)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-12-05 13:17:47 +01:00
Aidan Timson 025ffd7b56 Revert "Fix underflowing text in ha-settings-row (#28339)" (#28369) 2025-12-05 11:50:37 +00:00
Jan-Philipp Benecke 3ea4a28931 Fix underflowing text in ha-settings-row (#28339) 2025-12-05 09:08:42 +00:00
Benjamin 3b092b834e Filter out hidden entities in map configuration (#28320) 2025-12-05 08:44:07 +01:00
Aidan Timson ed8ccbe12c Add scrollable fade mixin to ha-wa-dialog (#28346) 2025-12-05 08:43:43 +01:00
karwosts 420f88f73a Fix incorrect water & gas price hints (#28357)
* Fix incorrect water price hint

* Gas
2025-12-05 08:44:23 +02:00
karwosts 086aa5fa28 Delete stop response variable on empty (#28362) 2025-12-05 08:38:39 +02:00
renovate[bot] cca4cc512b Update dependency @rsdoctor/rspack-plugin to v1.3.12 (#28350)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-12-04 14:54:27 +00:00
Petar Petrov 8eb65f327a Append current state to power-sources-graph (#28330) 2025-12-04 10:18:48 +01:00
Petar Petrov f3495feacb Fix markdown sections and styling (#28333) 2025-12-04 10:15:11 +01:00
Petar Petrov 2161bcfa3f Fix gauge severity using entity state instead of attribute value (#28331) 2025-12-04 10:13:41 +01:00
Paul Bottein 1400398422 Move reorder areas and floors to floor overflow (#28335) 2025-12-04 10:58:27 +02:00
Preet Patel 506d466c03 Fix energy dashboard redirect for device-consumption-only configs (#28322)
When users configure energy with only device consumption (no
grid/solar/battery/gas/water sources), the dashboard would redirect
to /config/energy instead of displaying. This occurred because
_generateLovelaceConfig() returned an empty views array.

The fix adds hasDeviceConsumption check and includes ENERGY_VIEW
when device consumption is configured, since energy-view-strategy
already supports device consumption cards.
2025-12-04 06:38:43 +00:00
Bram Kragten 46735c72ed Add more info to the energy demo (#28316)
* Add more info to the energy demo

* Also add battery power
2025-12-03 20:46:59 +01:00
Copilot c43d41053b Migrate ha-button-menu to ha-dropdown in 4 files (#28300)
Co-authored-by: wendevlin <12148533+wendevlin@users.noreply.github.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: Wendelin <w@pe8.at>
Co-authored-by: uptimeZERO_ <pavilionsahota@gmail.com>
2025-12-03 16:43:07 +00:00
Petar Petrov 844d53a0ba Always show energy-sources-table in overview (#28315) 2025-12-03 17:18:07 +01:00
Bram Kragten d77bebe96b Bumped version to 20251203.0 2025-12-03 15:38:49 +01:00
Bram Kragten 1260af0b45 Fix add matter device my link (#28313) 2025-12-03 15:36:05 +01:00
Petar Petrov 1d37eec411 Fix label filter losing selections when searching (#28312) 2025-12-03 15:36:04 +01:00
Bram Kragten 5a52f83358 Fix sticky headers in TCA dialog when target is selected (#28310) 2025-12-03 15:36:03 +01:00
Aidan Timson 60724eb952 Add subscribeLabFeature function (#28309)
* Add subscribe to lab feature function

* Add docstrings to exported functions
2025-12-03 15:36:02 +01:00
Aidan Timson de5778079e Add small rotation to snowflakes (#28308) 2025-12-03 15:36:01 +01:00
Wendelin f3710650f2 Hide disabled devices in automation target tree (#28307) 2025-12-03 15:36:00 +01:00
Paul Bottein feb35dbc4f Use svg for snowflakes (#28306) 2025-12-03 15:35:59 +01:00
Paul Bottein ee9e101fa6 Rename unassigned areas to other areas (#28305) 2025-12-03 15:35:58 +01:00
Paul Bottein 24b16360a6 Use core area sorting everywhere (#28304) 2025-12-03 15:35:57 +01:00
Wendelin 109c81a00d Revert "Migrate updates dropdown to ha-dropdown" (#28303)
Revert "Migrate updates dropdown to ha-dropdown (#28039)"

This reverts commit ba9bab38c9.
2025-12-03 15:35:56 +01:00
Wendelin eaa1ddbf61 Fix filtering of floors in getAreasAndFloorsItems function (#28302) 2025-12-03 15:35:55 +01:00
Paul Bottein b11cb57a1e Always set ha-wa-dialog position to fixed (#28301) 2025-12-03 15:35:55 +01:00
Petar Petrov 87b5f58779 Add Y-axis label formatter to energy charts (#28298) 2025-12-03 15:35:53 +01:00
Petar Petrov 8dac53c672 Fix binary sensor history timeline not rendering properly (#28297) 2025-12-03 15:35:52 +01:00
Petar Petrov d0966bf35a Hide empty System message in assist debug view (#28296) 2025-12-03 15:35:51 +01:00
Paul Bottein 6ba4fc0808 Handle not existing panels in dashboard config (#28292) 2025-12-03 15:35:50 +01:00
ildar170975 bd582ff816 computeLovelaceEntityName(): allow "number" names to be processed (#28231)
* allow "number" names to be processed

* Apply suggestion from @MindFreeze

---------

Co-authored-by: Petar Petrov <MindFreeze@users.noreply.github.com>
2025-12-03 15:35:49 +01:00
Bram Kragten 1c8b78eae9 Bumped version to 20251203.0 2025-12-03 15:31:03 +01:00
Bram Kragten a918e878fa Fix add matter device my link (#28313) 2025-12-03 15:30:26 +01:00
Petar Petrov ebc354bf55 Fix label filter losing selections when searching (#28312) 2025-12-03 15:29:48 +01:00
Wendelin 98a1f5ca3a Use ha-dropdown for automations/scripts (#28293)
Co-authored-by: uptimeZERO_ <pavilionsahota@gmail.com>
2025-12-03 13:33:48 +00:00
Bram Kragten 48015ab312 Fix sticky headers in TCA dialog when target is selected (#28310) 2025-12-03 14:24:29 +01:00
Aidan Timson 09515b1937 Add subscribeLabFeature function (#28309)
* Add subscribe to lab feature function

* Add docstrings to exported functions
2025-12-03 14:16:09 +01:00
Aidan Timson 5a40627676 Add small rotation to snowflakes (#28308) 2025-12-03 14:12:08 +01:00
Wendelin cd34447603 Hide disabled devices in automation target tree (#28307) 2025-12-03 14:02:25 +01:00
Paul Bottein 803fabbf64 Use svg for snowflakes (#28306) 2025-12-03 11:46:07 +00:00
Paul Bottein 78c4dc48d0 Rename unassigned areas to other areas (#28305) 2025-12-03 12:42:14 +01:00
Paul Bottein 147600ea43 Use core area sorting everywhere (#28304) 2025-12-03 12:28:55 +01:00
Wendelin 2f91f0dd15 Revert "Migrate updates dropdown to ha-dropdown" (#28303)
Revert "Migrate updates dropdown to ha-dropdown (#28039)"

This reverts commit ba9bab38c9.
2025-12-03 12:27:39 +01:00
ildar170975 3fa330acfb computeLovelaceEntityName(): allow "number" names to be processed (#28231)
* allow "number" names to be processed

* Apply suggestion from @MindFreeze

---------

Co-authored-by: Petar Petrov <MindFreeze@users.noreply.github.com>
2025-12-03 10:40:29 +00:00
Paul Bottein e0a6b671ce Always set ha-wa-dialog position to fixed (#28301) 2025-12-03 10:11:54 +00:00
Wendelin d6edd150a8 Fix filtering of floors in getAreasAndFloorsItems function (#28302) 2025-12-03 10:45:18 +01:00
Petar Petrov 2c00889921 Add Y-axis label formatter to energy charts (#28298) 2025-12-03 10:33:00 +01:00
Petar Petrov 0447d87f18 Hide empty System message in assist debug view (#28296) 2025-12-03 10:29:07 +01:00
Petar Petrov d7e18b0520 Fix binary sensor history timeline not rendering properly (#28297) 2025-12-03 10:18:32 +01:00
Luca Félix e7254b1587 feat: round_temperature on weather forecast card (#28103)
* feat: round_temperature on weather forecast card

* fix: use round util function

* refactor: applied comments from review
2025-12-03 10:02:25 +02:00
renovate[bot] 8681a7d450 Update dependency prettier to v3.7.3 (#28295)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-12-03 07:19:24 +01:00
Paul Bottein fff12acb6b Handle not existing panels in dashboard config (#28292) 2025-12-02 17:23:09 +01:00
Bram Kragten d34bf83da0 Bumped version to 20251202.0 2025-12-02 16:02:32 +01:00
Wendelin b0cfb31bf3 Automation add TCA: fix narrow subtitles & icons (#28291) 2025-12-02 16:02:25 +01:00
Wendelin 6c39e5d2c5 Use history to manage back button click in automations add TCA (#28289) 2025-12-02 16:02:24 +01:00
Paul Bottein 7b51e71092 Only show current weather in home overview (#28288) 2025-12-02 16:02:23 +01:00
Paul Bottein 8a82483685 Fix container alignment in section view (#28287) 2025-12-02 16:02:23 +01:00
Bram Kragten bb691fa7a2 fix paste in add tca dialog (#28286) 2025-12-02 16:02:22 +01:00
Petar Petrov 2232db9c0f Update Energy dashboard layout (#28283) 2025-12-02 16:02:21 +01:00
Petar Petrov 5375665dc6 Fix index value for grid return in power sankey card (#28281) 2025-12-02 16:02:20 +01:00
Silas Krause 480122f40a Revert custom markdown styles (#28277) 2025-12-02 16:02:18 +01:00
karwosts ee5c54030a Safer lookup of description_placeholders when service is invalid (#28273) 2025-12-02 16:02:17 +01:00
Paul Bottein b73f50e864 Add dialog to reorder areas and floors (#28272) 2025-12-02 16:02:16 +01:00
eringerli b9836073b7 fix stacking of multiple power sources (#28243) 2025-12-02 16:02:15 +01:00
Petar Petrov 3d327ed628 Update Energy dashboard layout (#28283) 2025-12-02 16:01:17 +01:00
Wendelin 0d51648de1 Use history to manage back button click in automations add TCA (#28289) 2025-12-02 15:43:13 +01:00
Wendelin c5642c15b8 Automation add TCA: fix narrow subtitles & icons (#28291) 2025-12-02 14:17:55 +00:00
Paul Bottein 7f885010de Add dialog to reorder areas and floors (#28272) 2025-12-02 15:12:36 +01:00
Paul Bottein 356d51f974 Only show current weather in home overview (#28288) 2025-12-02 15:38:34 +02:00
Dave T 38a907e51e Separate action field YAML examples (#27218)
* Comma separate field examples if it is a list

* Remove prettier ignore and json.stringify all examples

* Use YAML format

---------

Co-authored-by: Petar Petrov <MindFreeze@users.noreply.github.com>
2025-12-02 13:34:25 +00:00
Bram Kragten 87c0b1d887 fix paste in add tca dialog (#28286) 2025-12-02 14:30:16 +01:00
Paul Bottein 0f195015b7 Fix container alignment in section view (#28287) 2025-12-02 15:29:11 +02:00
Petar Petrov 17a976af67 Fix index value for grid return in power sankey card (#28281) 2025-12-02 14:47:15 +02:00
Aidan Timson a41a7e822a Remove placeholder for non device area picker in entity settings (#28285)
Remove placeholder for non device area picker
2025-12-02 11:52:02 +00:00
dependabot[bot] 5473bf56c6 Bump express from 4.21.2 to 4.22.1 (#28280)
Bumps [express](https://github.com/expressjs/express) from 4.21.2 to 4.22.1.
- [Release notes](https://github.com/expressjs/express/releases)
- [Changelog](https://github.com/expressjs/express/blob/v4.22.1/History.md)
- [Commits](https://github.com/expressjs/express/compare/4.21.2...v4.22.1)

---
updated-dependencies:
- dependency-name: express
  dependency-version: 4.22.1
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-12-02 08:17:59 +02:00
karwosts 029eba7ab8 Safer lookup of description_placeholders when service is invalid (#28273) 2025-12-02 08:08:36 +02:00
Silas Krause 824a3f288d Revert custom markdown styles (#28277) 2025-12-02 08:07:45 +02:00
renovate[bot] fdd89c05d3 Update dependency prettier to v3.7.2 (#28276)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-12-02 08:06:30 +02:00
Bram Kragten a40512e0b5 Bumped version to 20251201.0 2025-12-01 16:35:54 +01:00
Paul Bottein b2122570fb Clean reference to floor compare (#28269)
Fix floor compare
2025-12-01 16:35:34 +01:00
Paul Bottein 885f9333d2 Add helper for floor level (#28268)
* Add helper for floor level

* Update src/translations/en.json

Co-authored-by: Petar Petrov <MindFreeze@users.noreply.github.com>

---------

Co-authored-by: Petar Petrov <MindFreeze@users.noreply.github.com>
2025-12-01 16:35:33 +01:00
Aidan Timson f812e7e9fb Match more-info-update backup preferences (#28266) 2025-12-01 16:35:32 +01:00
Wendelin 64dad39f6e Fix automation trigger ha icon (#28265) 2025-12-01 16:35:31 +01:00
Simon Lamon df0fb423ed Include background in light, climate and security views (#28264)
* Include background

* Remove background key

* Add imports
2025-12-01 16:35:30 +01:00
Wendelin 4c3156f290 Respect system area sort in automation target tree (#28263) 2025-12-01 16:35:29 +01:00
Petar Petrov ecdf374902 Reduce the duration of init animation for charts to 500ms (#28262)
Reduce the duration of init animation for charts
2025-12-01 16:35:29 +01:00
Aidan Timson 3e924e0cde Add missing key for labs to show in quick bar (#28261) 2025-12-01 16:35:27 +01:00
Bram Kragten 6fb71e12c8 Use name instead of description_configured for triggers and conditions (#28260) 2025-12-01 16:35:27 +01:00
Wendelin 6138aa5489 Fix ha-bottom-sheet closed event (#28257) 2025-12-01 16:35:26 +01:00
Aidan Timson 61e865d3a6 Fix 1px padding for subpage titles (#28256) 2025-12-01 16:35:24 +01:00
Aidan Timson febcbf6242 Make labs toolbar icon use default color (#28255) 2025-12-01 16:35:23 +01:00
Petar Petrov 6a2fac6a9e Fix refresh in energy panel subviews (#28252) 2025-12-01 16:35:22 +01:00
karwosts b60c5467fc Add water devices to energy data download (#28242) 2025-12-01 16:35:21 +01:00
Petar Petrov ecd563406e Add power view and restructure energy dashboard layout (#28240) 2025-12-01 16:35:19 +01:00
Silas Krause d5b66315e2 Fix markdown rendering for cached html (#28229)
* Render markdown table in wrapper.

* Fix markdown styles

* Fix formatting

* fix rendering for cache
2025-12-01 16:35:18 +01:00
karwosts 5b1719fc6e Add missing helper to language selector (#28218) 2025-12-01 16:35:17 +01:00
Silas Krause add22cf2e9 Fix markdown styles regression (#28202)
* Render markdown table in wrapper.

* Fix markdown styles

* Fix formatting
2025-12-01 16:35:16 +01:00
Paul Bottein 21509191fa Fix ha icon size (#28201) 2025-12-01 16:35:15 +01:00
Paul Bottein 1a73cccf0d Fix safe area for sidebar section views in Android (#28194) 2025-12-01 16:35:14 +01:00
Aidan Timson 407d68250a Fix ha-wa-dialog fullscreen and make alerts not fullscreen (#28175) 2025-12-01 16:35:13 +01:00
Paul Bottein c33cb7fff9 Clean reference to floor compare (#28269)
Fix floor compare
2025-12-01 16:47:09 +02:00
Paul Bottein de53ad8dce Add helper for floor level (#28268)
* Add helper for floor level

* Update src/translations/en.json

Co-authored-by: Petar Petrov <MindFreeze@users.noreply.github.com>

---------

Co-authored-by: Petar Petrov <MindFreeze@users.noreply.github.com>
2025-12-01 15:43:57 +01:00
Simon Lamon 2dec7490b6 Include background in light, climate and security views (#28264)
* Include background

* Remove background key

* Add imports
2025-12-01 16:20:50 +02:00
Aidan Timson 6ed4bd5ce8 Match more-info-update backup preferences (#28266) 2025-12-01 15:51:31 +02:00
Petar Petrov 4e899c56ed Reduce the duration of init animation for charts to 500ms (#28262)
Reduce the duration of init animation for charts
2025-12-01 15:43:20 +02:00
Petar Petrov 53c20a0493 Add power view and restructure energy dashboard layout (#28240) 2025-12-01 14:16:11 +01:00
Wendelin be2d6e9212 Fix automation trigger ha icon (#28265) 2025-12-01 13:05:36 +00:00
Wendelin 915442c571 Respect system area sort in automation target tree (#28263) 2025-12-01 14:01:06 +01:00
Aidan Timson de6ebc2d0a Add missing key for labs to show in quick bar (#28261) 2025-12-01 12:26:41 +00:00
Bram Kragten bcb12fa062 Use name instead of description_configured for triggers and conditions (#28260) 2025-12-01 13:19:19 +01:00
Aidan Timson 078915743d Make labs toolbar icon use default color (#28255) 2025-12-01 12:08:25 +01:00
Petar Petrov 54c524127f Fix refresh in energy panel subviews (#28252) 2025-12-01 12:07:45 +01:00
Wendelin 334e1c35e1 Fix ha-bottom-sheet closed event (#28257) 2025-12-01 12:04:15 +01:00
Aidan Timson 528c7727e2 Fix 1px padding for subpage titles (#28256) 2025-12-01 12:03:38 +01:00
Aidan Timson d1043e33df Fix subpage layout icon alignment (#28254) 2025-12-01 09:54:25 +00:00
dependabot[bot] b088f2c0e5 Bump home-assistant/wheels from 2025.10.0 to 2025.11.0 (#28251)
Bumps [home-assistant/wheels](https://github.com/home-assistant/wheels) from 2025.10.0 to 2025.11.0.
- [Release notes](https://github.com/home-assistant/wheels/releases)
- [Commits](https://github.com/home-assistant/wheels/compare/2025.10.0...2025.11.0)

---
updated-dependencies:
- dependency-name: home-assistant/wheels
  dependency-version: 2025.11.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-12-01 08:53:24 +02:00
dependabot[bot] b33f407493 Bump relative-ci/agent-action from 3.2.0 to 3.2.1 (#28250)
Bumps [relative-ci/agent-action](https://github.com/relative-ci/agent-action) from 3.2.0 to 3.2.1.
- [Release notes](https://github.com/relative-ci/agent-action/releases)
- [Commits](https://github.com/relative-ci/agent-action/compare/feb19ddc698445db27401f1490f6ac182da0816f...c45aaa919ef85620af54242a241ac17a8fa35983)

---
updated-dependencies:
- dependency-name: relative-ci/agent-action
  dependency-version: 3.2.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-12-01 08:48:44 +02:00
dependabot[bot] 502d76b316 Bump actions/setup-python from 6.0.0 to 6.1.0 (#28249)
Bumps [actions/setup-python](https://github.com/actions/setup-python) from 6.0.0 to 6.1.0.
- [Release notes](https://github.com/actions/setup-python/releases)
- [Commits](https://github.com/actions/setup-python/compare/e797f83bcb11b83ae66e0230d6156d7c80228e7c...83679a892e2d95755f2dac6acb0bfd1e9ac5d548)

---
updated-dependencies:
- dependency-name: actions/setup-python
  dependency-version: 6.1.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-12-01 08:48:24 +02:00
dependabot[bot] 1ddc07c215 Bump softprops/action-gh-release from 2.4.2 to 2.5.0 (#28248)
Bumps [softprops/action-gh-release](https://github.com/softprops/action-gh-release) from 2.4.2 to 2.5.0.
- [Release notes](https://github.com/softprops/action-gh-release/releases)
- [Changelog](https://github.com/softprops/action-gh-release/blob/master/CHANGELOG.md)
- [Commits](https://github.com/softprops/action-gh-release/compare/5be0e66d93ac7ed76da52eca8bb058f665c3a5fe...a06a81a03ee405af7f2048a818ed3f03bbf83c7b)

---
updated-dependencies:
- dependency-name: softprops/action-gh-release
  dependency-version: 2.5.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-12-01 08:47:32 +02:00
dependabot[bot] a611a5fc4e Bump github/codeql-action from 4.31.4 to 4.31.5 (#28247)
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 4.31.4 to 4.31.5.
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/github/codeql-action/compare/e12f0178983d466f2f6028f5cc7a6d786fd97f4b...fdbfb4d2750291e159f0156def62b853c2798ca2)

---
updated-dependencies:
- dependency-name: github/codeql-action
  dependency-version: 4.31.5
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-12-01 08:46:51 +02:00
eringerli c13bece6d0 fix stacking of multiple power sources (#28243) 2025-12-01 06:25:47 +00:00
Paulus Schoutsen 28a89ff9e6 Add custom element decorators instead of customElements.define (#28235)
* Add custom element decorators instead of customElements.define

* Ignore

* prettier
2025-12-01 06:38:31 +01:00
karwosts 81b5ddec9d Add water devices to energy data download (#28242) 2025-11-30 16:00:14 +01:00
renovate[bot] ce86aabe32 Update dependency prettier to v3.7.1 (#28239)
* Update dependency prettier to v3.7.1

* format

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Petar Petrov <MindFreeze@users.noreply.github.com>
2025-11-30 13:33:41 +00:00
Silas Krause a8910bcbe4 Fix markdown rendering for cached html (#28229)
* Render markdown table in wrapper.

* Fix markdown styles

* Fix formatting

* fix rendering for cache
2025-11-30 15:21:39 +02:00
ildar170975 0e4cf9f62d ha-picker-field: change left padding to align with other controls (#28217)
change --md-list-item-leading-space & --md-list-item-trailing-space
2025-11-29 14:00:27 +02:00
renovate[bot] 506635d649 Update vaadinWebComponents monorepo to v24.9.6 (#28225)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-11-29 11:44:28 +00:00
karwosts 27e24ee49b Add missing helper to language selector (#28218) 2025-11-29 12:35:04 +01:00
renovate[bot] bcd712b48c Update vitest monorepo to v4.0.14 (#28215)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-11-28 20:23:38 +01:00
renovate[bot] 461ef9b916 Update dependency @rspack/core to v1.6.5 (#28207)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-11-28 11:14:57 +01:00
renovate[bot] b794989daa Update dependency @bundle-stats/plugin-webpack-filter to v4.21.7 (#28205)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-11-28 08:29:33 +02:00
Silas Krause 6727ffaae0 Fix markdown styles regression (#28202)
* Render markdown table in wrapper.

* Fix markdown styles

* Fix formatting
2025-11-28 08:28:57 +02:00
Paul Bottein 4df8501b20 Fix ha icon size (#28201) 2025-11-27 22:54:44 +01:00
Aidan Timson 539d0e443f Fix ha-wa-dialog fullscreen and make alerts not fullscreen (#28175) 2025-11-27 22:01:30 +01:00
renovate[bot] 9c9d274b5c Update dependency typescript-eslint to v8.48.0 (#28196)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-11-27 19:20:07 +01:00
Paul Bottein d6e6bc0e80 Fix safe area for sidebar section views in Android (#28194) 2025-11-27 19:46:56 +02:00
ildar170975 530a70b168 Automations, scripts, scenes: add a tooltip for relative time (#28158)
* add a tooltip for last_triggered

* add a tooltip for last_triggered

* add a tooltip for last_activated

* Apply suggestions from code review

* Apply suggestion from @MindFreeze

Co-authored-by: Petar Petrov <MindFreeze@users.noreply.github.com>

* Apply suggestion from @MindFreeze

Co-authored-by: Petar Petrov <MindFreeze@users.noreply.github.com>

* Apply suggestion from @MindFreeze

Co-authored-by: Petar Petrov <MindFreeze@users.noreply.github.com>

---------

Co-authored-by: Petar Petrov <MindFreeze@users.noreply.github.com>
2025-11-27 19:44:11 +02:00
Wendelin 23137500f8 Add TCA by target sort like item collections (#28192) 2025-11-27 17:03:27 +01:00
Wendelin 63e7ed21a4 Fix lab automations icons and sidebar width (#28184)
Co-authored-by: Petar Petrov <MindFreeze@users.noreply.github.com>
2025-11-27 16:57:42 +01:00
Petar Petrov 92611f46f4 Fix water sankey calculation to include total supply from sources (#28191) 2025-11-27 16:44:56 +01:00
Bram Kragten 9bc896241d Always store token when using develop and serve (#28179) 2025-11-27 16:43:36 +01:00
Paul Bottein 2baafe620c Add hint to reorder areas and floors (#28189) 2025-11-27 16:32:23 +01:00
Wendelin ce52bbaf8c Show hidden entities in target tree (#28181)
* Show hidden entities in target tree

* Fix types
2025-11-27 15:44:50 +02:00
Wendelin 0b4b8d9082 "Add TCA" dialog desktop height to 800px (#28182) 2025-11-27 14:42:18 +01:00
Petar Petrov bddbb773b7 Fix sankey chart resizing (#28180) 2025-11-27 15:41:46 +02:00
Paul Bottein d52e1e8835 Use hui-root for panel energy (#28149)
* Use hui-root for panel energy

* Review feedback

* Set empty prefs
2025-11-27 15:35:36 +02:00
Petar Petrov 0a9dccfd19 Refactor power sankey hierarchy to handle devices with not power sensor (#28164) 2025-11-27 12:21:55 +01:00
Petar Petrov bfd78670cc Disable axis pointer on the energy devices bar chart to fix refresh issues on touch devices (#28163) 2025-11-27 12:20:06 +01:00
Petar Petrov 11276af1a0 Handle grouping by floor and area in power sankey card (#28162) 2025-11-27 12:19:42 +01:00
Paul Bottein d7be46c00b Fix box shadow for sidebar tabs (#28170) 2025-11-27 12:19:15 +01:00
Paul Bottein 94f32ce242 Fix disabled dashboard picker when no custom dashboard (#28172) 2025-11-27 12:18:48 +01:00
Wendelin ef3e8186bc Fix add condition default tab and blank styles (#28166) 2025-11-27 12:18:21 +01:00
Paul Bottein 50fcf622aa Fix labs back button (#28174) 2025-11-27 12:42:55 +02:00
Paul Bottein 77c2444be8 Restore sidebar view when clicking back (#28167) 2025-11-27 12:42:36 +02:00
Wendelin e5cb26cd3d Fix automation add TCA autofocus (#28168)
Fix automation add tca autofocus
2025-11-27 11:28:18 +01:00
Simon Lamon 2896519bfd Don't show more info for untracked consumption (#28151) 2025-11-27 09:55:23 +02:00
ildar170975 0b6e35eb53 Data tables: make sorting direction 2-state instead of 3-state (#28160)
* sorting is 2-state

* sorting is 2-state

* sorting is 2-state
2025-11-27 09:54:38 +02:00
Iván Pereira e80a855f87 Fix hide sidebar tooltip on touchend events (#28042)
* fix: hide sidebar tooltip on touchend events

* Add a comment recommended by Copilot

* Clear timeouts id in disconnectedCallback
2025-11-27 09:03:23 +02:00
dependabot[bot] 7c88cf4e30 Bump node-forge from 1.3.1 to 1.3.2 (#28157)
Bumps [node-forge](https://github.com/digitalbazaar/forge) from 1.3.1 to 1.3.2.
- [Changelog](https://github.com/digitalbazaar/forge/blob/main/CHANGELOG.md)
- [Commits](https://github.com/digitalbazaar/forge/compare/v1.3.1...v1.3.2)

---
updated-dependencies:
- dependency-name: node-forge
  dependency-version: 1.3.2
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-11-27 06:49:09 +01:00
Petar Petrov 9001cd3e65 Replace gauges with energy usage graph in energy overview (#28150) 2025-11-26 17:37:18 +01:00
renovate[bot] ca8923d8f4 Update dependency glob to v13 (#28135)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-11-26 18:13:05 +02:00
872 changed files with 33664 additions and 16762 deletions
+5 -4
View File
@@ -22,11 +22,13 @@ You are an assistant helping with development of the Home Assistant frontend. Th
```bash
yarn lint # ESLint + Prettier + TypeScript + Lit
yarn format # Auto-fix ESLint + Prettier
yarn lint:types # TypeScript compiler
yarn lint:types # TypeScript compiler (run WITHOUT file arguments)
yarn test # Vitest
script/develop # Development server
```
> **WARNING:** Never run `tsc` or `yarn lint:types` with file arguments (e.g., `yarn lint:types src/file.ts`). When `tsc` receives file arguments, it ignores `tsconfig.json` and emits `.js` files into `src/`, polluting the codebase. Always run `yarn lint:types` without arguments. For individual file type checking, rely on IDE diagnostics. If `.js` files are accidentally generated, clean up with `git clean -fd src/`.
### Component Prefixes
- `ha-` - Home Assistant components
@@ -154,7 +156,7 @@ try {
- **Use CSS custom properties**: Leverage the theme system
- **Use spacing tokens**: Prefer `--ha-space-*` tokens over hardcoded values for consistent spacing
- Spacing scale: `--ha-space-0` (0px) through `--ha-space-20` (80px) in 4px increments
- Spacing scale: `--ha-space-1` (4px) through `--ha-space-20` (80px) in 4px increments
- Defined in `src/resources/theme/core.globals.ts`
- Common values: `--ha-space-2` (8px), `--ha-space-4` (16px), `--ha-space-8` (32px)
- **Mobile-first responsive**: Design for mobile, enhance for desktop
@@ -619,7 +621,6 @@ this.hass.localize("ui.panel.config.updates.update_available", {
#### Key Terminology
- **"add-on"** (hyphenated, not "addon")
- **"integration"** (preferred over "component")
- **Technical terms**: Use lowercase (automation, entity, device, service)
@@ -711,7 +712,7 @@ this.hass.localize("ui.panel.config.automation.delete_confirm", {
- [ ] American English spelling
- [ ] Friendly, informational tone
- [ ] Avoids abbreviations and jargon
- [ ] Correct terminology (add-on not addon, integration not component)
- [ ] Correct terminology (integration not component)
### Component-Specific Checks
+4 -4
View File
@@ -21,12 +21,12 @@ jobs:
url: ${{ steps.deploy.outputs.NETLIFY_LIVE_URL || steps.deploy.outputs.NETLIFY_URL }}
steps:
- name: Check out files from GitHub
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
ref: dev
- name: Setup Node
uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6.0.0
uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0
with:
node-version-file: ".nvmrc"
cache: yarn
@@ -56,12 +56,12 @@ jobs:
url: ${{ steps.deploy.outputs.NETLIFY_LIVE_URL || steps.deploy.outputs.NETLIFY_URL }}
steps:
- name: Check out files from GitHub
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
ref: master
- name: Setup Node
uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6.0.0
uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0
with:
node-version-file: ".nvmrc"
cache: yarn
+18 -11
View File
@@ -24,9 +24,9 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Check out files from GitHub
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- name: Setup Node
uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6.0.0
uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0
with:
node-version-file: ".nvmrc"
cache: yarn
@@ -37,7 +37,7 @@ jobs:
- name: Build resources
run: ./node_modules/.bin/gulp gen-icons-json build-translations build-locale-data gather-gallery-pages
- name: Setup lint cache
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
uses: actions/cache@8b402f58fbc84540c8b491a91e594a4576fec3d7 # v5.0.2
with:
path: |
node_modules/.cache/prettier
@@ -58,9 +58,9 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Check out files from GitHub
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- name: Setup Node
uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6.0.0
uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0
with:
node-version-file: ".nvmrc"
cache: yarn
@@ -76,9 +76,9 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Check out files from GitHub
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- name: Setup Node
uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6.0.0
uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0
with:
node-version-file: ".nvmrc"
cache: yarn
@@ -89,20 +89,27 @@ jobs:
env:
IS_TEST: "true"
- name: Upload bundle stats
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
with:
name: frontend-bundle-stats
path: build/stats/*.json
if-no-files-found: error
- name: Upload frontend build
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
with:
name: frontend-build
path: hass_frontend/
if-no-files-found: error
retention-days: 7
supervisor:
name: Build supervisor
needs: [lint, test]
runs-on: ubuntu-latest
steps:
- name: Check out files from GitHub
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- name: Setup Node
uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6.0.0
uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0
with:
node-version-file: ".nvmrc"
cache: yarn
@@ -113,7 +120,7 @@ jobs:
env:
IS_TEST: "true"
- name: Upload bundle stats
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
with:
name: supervisor-bundle-stats
path: build/stats/*.json
+4 -4
View File
@@ -23,7 +23,7 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
# We must fetch at least the immediate parents so that if this is
# a pull request then we can checkout the head.
@@ -36,14 +36,14 @@ jobs:
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@e12f0178983d466f2f6028f5cc7a6d786fd97f4b # v4.31.4
uses: github/codeql-action/init@cdefb33c0f6224e58673d9004f47f7cb3e328b89 # v4.31.10
with:
languages: ${{ matrix.language }}
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@e12f0178983d466f2f6028f5cc7a6d786fd97f4b # v4.31.4
uses: github/codeql-action/autobuild@cdefb33c0f6224e58673d9004f47f7cb3e328b89 # v4.31.10
# ️ Command-line programs to run using the OS shell.
# 📚 https://git.io/JvXDl
@@ -57,4 +57,4 @@ jobs:
# make release
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@e12f0178983d466f2f6028f5cc7a6d786fd97f4b # v4.31.4
uses: github/codeql-action/analyze@cdefb33c0f6224e58673d9004f47f7cb3e328b89 # v4.31.10
+4 -4
View File
@@ -22,12 +22,12 @@ jobs:
url: ${{ steps.deploy.outputs.NETLIFY_LIVE_URL || steps.deploy.outputs.NETLIFY_URL }}
steps:
- name: Check out files from GitHub
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
ref: dev
- name: Setup Node
uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6.0.0
uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0
with:
node-version-file: ".nvmrc"
cache: yarn
@@ -57,12 +57,12 @@ jobs:
url: ${{ steps.deploy.outputs.NETLIFY_LIVE_URL || steps.deploy.outputs.NETLIFY_URL }}
steps:
- name: Check out files from GitHub
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
ref: master
- name: Setup Node
uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6.0.0
uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0
with:
node-version-file: ".nvmrc"
cache: yarn
+2 -2
View File
@@ -16,10 +16,10 @@ jobs:
url: ${{ steps.deploy.outputs.NETLIFY_LIVE_URL || steps.deploy.outputs.NETLIFY_URL }}
steps:
- name: Check out files from GitHub
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- name: Setup Node
uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6.0.0
uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0
with:
node-version-file: ".nvmrc"
cache: yarn
+2 -2
View File
@@ -21,10 +21,10 @@ jobs:
if: github.repository == 'home-assistant/frontend' && contains(github.event.pull_request.labels.*.name, 'needs design preview')
steps:
- name: Check out files from GitHub
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- name: Setup Node
uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6.0.0
uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0
with:
node-version-file: ".nvmrc"
cache: yarn
+1 -1
View File
@@ -9,7 +9,7 @@ jobs:
lock:
runs-on: ubuntu-latest
steps:
- uses: dessant/lock-threads@1bf7ec25051fe7c00bdd17e6a7cf3d7bfb7dc771 # v5.0.1
- uses: dessant/lock-threads@7266a7ce5c1df01b1c6db85bf8cd86c737dadbe7 # v6.0.0
with:
github-token: ${{ github.token }}
process-only: "issues, prs"
+5 -5
View File
@@ -20,15 +20,15 @@ jobs:
contents: write
steps:
- name: Checkout the repository
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- name: Set up Python ${{ env.PYTHON_VERSION }}
uses: actions/setup-python@e797f83bcb11b83ae66e0230d6156d7c80228e7c # v6
uses: actions/setup-python@83679a892e2d95755f2dac6acb0bfd1e9ac5d548 # v6
with:
python-version: ${{ env.PYTHON_VERSION }}
- name: Setup Node
uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6.0.0
uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0
with:
node-version-file: ".nvmrc"
cache: yarn
@@ -57,14 +57,14 @@ jobs:
run: tar -czvf translations.tar.gz translations
- name: Upload build artifacts
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
with:
name: wheels
path: dist/home_assistant_frontend*.whl
if-no-files-found: error
- name: Upload translations
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
with:
name: translations
path: translations.tar.gz
+1 -1
View File
@@ -17,7 +17,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Send bundle stats and build information to RelativeCI
uses: relative-ci/agent-action@feb19ddc698445db27401f1490f6ac182da0816f # v3.2.0
uses: relative-ci/agent-action@3c681926017930047fc03acaa35cd6a44efcbfc3 # v3.2.2
with:
key: ${{ secrets[format('RELATIVE_CI_KEY_{0}_{1}', matrix.bundle, matrix.build)] }}
token: ${{ github.token }}
+21 -14
View File
@@ -19,14 +19,17 @@ jobs:
release:
name: Release
runs-on: ubuntu-latest
environment: pypi
permissions:
contents: write # Required to upload release assets
id-token: write # For "Trusted Publisher" to PyPi
if: github.repository_owner == 'home-assistant'
steps:
- name: Checkout the repository
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- name: Set up Python ${{ env.PYTHON_VERSION }}
uses: actions/setup-python@e797f83bcb11b83ae66e0230d6156d7c80228e7c # v6.0.0
uses: actions/setup-python@83679a892e2d95755f2dac6acb0bfd1e9ac5d548 # v6.1.0
with:
python-version: ${{ env.PYTHON_VERSION }}
@@ -34,7 +37,7 @@ jobs:
uses: home-assistant/actions/helpers/verify-version@master
- name: Setup Node
uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6.0.0
uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0
with:
node-version-file: ".nvmrc"
cache: yarn
@@ -46,16 +49,20 @@ jobs:
run: ./script/translations_download
env:
LOKALISE_TOKEN: ${{ secrets.LOKALISE_TOKEN }}
- name: Build and release package
run: |
python3 -m pip install twine build
export TWINE_USERNAME="__token__"
export TWINE_PASSWORD="${{ secrets.TWINE_TOKEN }}"
python3 -m pip install build
export SKIP_FETCH_NIGHTLY_TRANSLATIONS=1
script/release
- name: Publish to PyPI
uses: pypa/gh-action-pypi-publish@ed0c53931b1dc9bd32cbe73a98c7f6766f8a527e # v1.13.0
with:
skip-existing: true
- name: Upload release assets
uses: softprops/action-gh-release@5be0e66d93ac7ed76da52eca8bb058f665c3a5fe # v2.4.2
uses: softprops/action-gh-release@a06a81a03ee405af7f2048a818ed3f03bbf83c7b # v2.5.0
with:
files: |
dist/*.whl
@@ -75,7 +82,7 @@ jobs:
# home-assistant/wheels doesn't support SHA pinning
- name: Build wheels
uses: home-assistant/wheels@2025.10.0
uses: home-assistant/wheels@2025.12.0
with:
abi: cp313
tag: musllinux_1_2
@@ -91,9 +98,9 @@ jobs:
contents: write # Required to upload release assets
steps:
- name: Checkout the repository
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- name: Setup Node
uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6.0.0
uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0
with:
node-version-file: ".nvmrc"
cache: yarn
@@ -108,7 +115,7 @@ jobs:
- name: Tar folder
run: tar -czf landing-page/home_assistant_frontend_landingpage-${{ github.event.release.tag_name }}.tar.gz -C landing-page/dist .
- name: Upload release asset
uses: softprops/action-gh-release@5be0e66d93ac7ed76da52eca8bb058f665c3a5fe # v2.4.2
uses: softprops/action-gh-release@a06a81a03ee405af7f2048a818ed3f03bbf83c7b # v2.5.0
with:
files: landing-page/home_assistant_frontend_landingpage-${{ github.event.release.tag_name }}.tar.gz
@@ -120,9 +127,9 @@ jobs:
contents: write # Required to upload release assets
steps:
- name: Checkout the repository
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- name: Setup Node
uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6.0.0
uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0
with:
node-version-file: ".nvmrc"
cache: yarn
@@ -137,6 +144,6 @@ jobs:
- name: Tar folder
run: tar -czf hassio/home_assistant_frontend_supervisor-${{ github.event.release.tag_name }}.tar.gz -C hassio/build .
- name: Upload release asset
uses: softprops/action-gh-release@5be0e66d93ac7ed76da52eca8bb058f665c3a5fe # v2.4.2
uses: softprops/action-gh-release@a06a81a03ee405af7f2048a818ed3f03bbf83c7b # v2.5.0
with:
files: hassio/home_assistant_frontend_supervisor-${{ github.event.release.tag_name }}.tar.gz
+1 -1
View File
@@ -10,7 +10,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: 90 days stale policy
uses: actions/stale@5f858e3efba33a5ca4407a664cc011ad407f2008 # v10.1.0
uses: actions/stale@997185467fa4f803885201cee163a9f38240193d # v10.1.1
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
days-before-stale: 90
+1 -1
View File
@@ -14,7 +14,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout the repository
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- name: Upload Translations
run: |
+2 -1
View File
@@ -15,7 +15,7 @@ dist/
!.yarn/sdks
!.yarn/versions
.pnp.*
/node_modules/
node_modules/
yarn-error.log
npm-debug.log
@@ -56,4 +56,5 @@ test/coverage/
# AI tooling
.claude
.cursor
+1 -1
View File
@@ -1 +1 @@
22.21.1
24.13.0
+2
View File
@@ -1,5 +1,7 @@
compressionLevel: mixed
npmMinimalAgeGate: "3d"
defaultSemverRangePrefix: ""
enableGlobalCache: false
-2
View File
@@ -20,8 +20,6 @@ module.exports.ignorePackages = () => [];
// Files from NPM packages that we should replace with empty file
module.exports.emptyPackages = ({ isHassioBuild, isLandingPageBuild }) =>
[
require.resolve("@vaadin/vaadin-material-styles/typography.js"),
require.resolve("@vaadin/vaadin-material-styles/font-icons.js"),
// Icons in supervisor conflict with icons in HA so we don't load.
(isHassioBuild || isLandingPageBuild) &&
require.resolve(
+3 -1
View File
@@ -156,7 +156,9 @@ const createTestTranslation = () =>
*/
const createMasterTranslation = () =>
gulp
.src([EN_SRC, ...(mergeBackend ? [`${inBackendDir}/en.json`] : [])])
.src([EN_SRC, ...(mergeBackend ? [`${inBackendDir}/en.json`] : [])], {
allowEmpty: true,
})
.pipe(new CustomJSON(lokaliseTransform))
.pipe(new MergeJSON("en"))
.pipe(gulp.dest(workDir));
+50 -7
View File
@@ -168,12 +168,16 @@ const createRspackConfig = ({
);
},
}),
new rspack.NormalModuleReplacementPlugin(
new RegExp(
bundle.emptyPackages({ isHassioBuild, isLandingPageBuild }).join("|")
),
path.resolve(paths.root_dir, "src/util/empty.js")
),
bundle.emptyPackages({ isHassioBuild, isLandingPageBuild }).length
? new rspack.NormalModuleReplacementPlugin(
new RegExp(
bundle
.emptyPackages({ isHassioBuild, isLandingPageBuild })
.join("|")
),
path.resolve(paths.root_dir, "src/util/empty.js")
)
: false,
!isProdBuild && new LogStartCompilePlugin(),
isProdBuild &&
new StatsWriterPlugin({
@@ -201,6 +205,7 @@ const createRspackConfig = ({
"lit/decorators$": "lit/decorators.js",
"lit/directive$": "lit/directive.js",
"lit/directives/until$": "lit/directives/until.js",
"lit/directives/ref$": "lit/directives/ref.js",
"lit/directives/class-map$": "lit/directives/class-map.js",
"lit/directives/style-map$": "lit/directives/style-map.js",
"lit/directives/if-defined$": "lit/directives/if-defined.js",
@@ -209,7 +214,9 @@ const createRspackConfig = ({
"lit/directives/join$": "lit/directives/join.js",
"lit/directives/repeat$": "lit/directives/repeat.js",
"lit/directives/live$": "lit/directives/live.js",
"lit/directives/keyed$": "lit/directives/keyed.js",
"lit/directives/keyed$": latestBuild
? "lit/directives/keyed.js"
: path.resolve(__dirname, "../src/common/lit/keyed-es5.ts"),
"lit/polyfill-support$": "lit/polyfill-support.js",
"@lit-labs/virtualizer/layouts/grid":
"@lit-labs/virtualizer/layouts/grid.js",
@@ -217,6 +224,42 @@ const createRspackConfig = ({
"@lit-labs/virtualizer/polyfills/resize-observer-polyfill/ResizeObserver.js",
"@lit-labs/observers/resize-controller":
"@lit-labs/observers/resize-controller.js",
"@formatjs/intl-durationformat/should-polyfill$":
"@formatjs/intl-durationformat/should-polyfill.js",
"@formatjs/intl-durationformat/polyfill-force$":
"@formatjs/intl-durationformat/polyfill-force.js",
"@formatjs/intl-datetimeformat/should-polyfill":
"@formatjs/intl-datetimeformat/should-polyfill.js",
"@formatjs/intl-datetimeformat/polyfill-force":
"@formatjs/intl-datetimeformat/polyfill-force.js",
"@formatjs/intl-displaynames/should-polyfill":
"@formatjs/intl-displaynames/should-polyfill.js",
"@formatjs/intl-displaynames/polyfill-force":
"@formatjs/intl-displaynames/polyfill-force.js",
"@formatjs/intl-getcanonicallocales/should-polyfill":
"@formatjs/intl-getcanonicallocales/should-polyfill.js",
"@formatjs/intl-getcanonicallocales/polyfill-force":
"@formatjs/intl-getcanonicallocales/polyfill-force.js",
"@formatjs/intl-listformat/should-polyfill":
"@formatjs/intl-listformat/should-polyfill.js",
"@formatjs/intl-listformat/polyfill-force":
"@formatjs/intl-listformat/polyfill-force.js",
"@formatjs/intl-locale/should-polyfill":
"@formatjs/intl-locale/should-polyfill.js",
"@formatjs/intl-locale/polyfill-force":
"@formatjs/intl-locale/polyfill-force.js",
"@formatjs/intl-numberformat/should-polyfill":
"@formatjs/intl-numberformat/should-polyfill.js",
"@formatjs/intl-numberformat/polyfill-force":
"@formatjs/intl-numberformat/polyfill-force.js",
"@formatjs/intl-pluralrules/should-polyfill":
"@formatjs/intl-pluralrules/should-polyfill.js",
"@formatjs/intl-pluralrules/polyfill-force":
"@formatjs/intl-pluralrules/polyfill-force.js",
"@formatjs/intl-relativetimeformat/should-polyfill":
"@formatjs/intl-relativetimeformat/should-polyfill.js",
"@formatjs/intl-relativetimeformat/polyfill-force":
"@formatjs/intl-relativetimeformat/polyfill-force.js",
},
},
output: {
+5 -3
View File
@@ -5,17 +5,19 @@ const castContext = framework.CastReceiverContext.getInstance();
const playerManager = castContext.getPlayerManager();
playerManager.setMessageInterceptor(
framework.messages.MessageType.LOAD,
"LOAD" as framework.messages.MessageType.LOAD,
(loadRequestData) => {
const media = loadRequestData.media;
// Special handling if it came from Google Assistant
if (media.entity) {
media.contentId = media.entity;
media.streamType = framework.messages.StreamType.LIVE;
media.streamType = "LIVE" as framework.messages.StreamType.LIVE;
media.contentType = "application/vnd.apple.mpegurl";
// @ts-ignore
// type definition is wrong, should be "FMP4" instead of "fmp4"
// https://developers.google.com/cast/docs/reference/web_receiver/cast.framework.messages#.HlsVideoSegmentFormat
media.hlsVideoSegmentFormat =
framework.messages.HlsVideoSegmentFormat.FMP4;
"FMP4" as framework.messages.HlsVideoSegmentFormat.FMP4;
}
return loadRequestData;
}
+28 -27
View File
@@ -1,10 +1,9 @@
import { framework } from "./cast_framework";
import { CAST_NS } from "../../../src/cast/const";
import type { HassMessage } from "../../../src/cast/receiver_messages";
import "../../../src/resources/custom-card-support";
import { castContext } from "./cast_context";
import { framework } from "./cast_framework";
import { HcMain } from "./layout/hc-main";
import type { ReceivedMessage } from "./types";
const lovelaceController = new HcMain();
document.body.append(lovelaceController);
@@ -40,7 +39,8 @@ const playDummyMedia = (viewTitle?: string) => {
loadRequestData.media.contentId =
"https://cast.home-assistant.io/images/google-nest-hub.png";
loadRequestData.media.contentType = "image/jpeg";
loadRequestData.media.streamType = framework.messages.StreamType.NONE;
loadRequestData.media.streamType =
"NONE" as framework.messages.StreamType.NONE;
const metadata = new framework.messages.GenericMediaMetadata();
metadata.title = viewTitle;
loadRequestData.media.metadata = metadata;
@@ -89,31 +89,30 @@ const showMediaPlayer = () => {
const options = new framework.CastReceiverOptions();
options.disableIdleTimeout = true;
options.customNamespaces = {
[CAST_NS]: framework.system.MessageType.JSON,
// type definition is wrong, should be "JSON" instead of "json"
// https://developers.google.com/cast/docs/reference/web_receiver/cast.framework.system#.MessageType
[CAST_NS]: "JSON" as framework.system.MessageType.JSON,
};
castContext.addCustomMessageListener(
CAST_NS,
// @ts-ignore
(ev: ReceivedMessage<HassMessage>) => {
// We received a show Lovelace command, stop media from playing, hide media player and show Lovelace controller
if (
playerManager.getPlayerState() !== framework.messages.PlayerState.IDLE
) {
playerManager.stop();
} else {
showLovelaceController();
}
const msg = ev.data;
msg.senderId = ev.senderId;
lovelaceController.processIncomingMessage(msg);
castContext.addCustomMessageListener(CAST_NS, (ev) => {
// We received a show Lovelace command, stop media from playing, hide media player and show Lovelace controller
if (
playerManager.getPlayerState() !==
("IDLE" as framework.messages.PlayerState.IDLE)
) {
playerManager.stop();
} else {
showLovelaceController();
}
);
const msg = ev.data as HassMessage;
msg.senderId = ev.senderId;
lovelaceController.processIncomingMessage(msg);
});
const playerManager = castContext.getPlayerManager();
playerManager.setMessageInterceptor(
framework.messages.MessageType.LOAD,
"LOAD" as framework.messages.MessageType.LOAD,
(loadRequestData) => {
if (
loadRequestData.media.contentId ===
@@ -127,24 +126,26 @@ playerManager.setMessageInterceptor(
// Special handling if it came from Google Assistant
if (media.entity) {
media.contentId = media.entity;
media.streamType = framework.messages.StreamType.LIVE;
media.streamType = "LIVE" as framework.messages.StreamType.LIVE;
media.contentType = "application/vnd.apple.mpegurl";
// @ts-ignore
// type definition is wrong, should be "FMP4" instead of "fmp4"
// https://developers.google.com/cast/docs/reference/web_receiver/cast.framework.messages#.HlsVideoSegmentFormat
media.hlsVideoSegmentFormat =
framework.messages.HlsVideoSegmentFormat.FMP4;
"FMP4" as framework.messages.HlsVideoSegmentFormat.FMP4;
}
return loadRequestData;
}
);
playerManager.addEventListener(
framework.events.EventType.MEDIA_STATUS,
"MEDIA_STATUS" as framework.events.EventType.MEDIA_STATUS,
(event) => {
if (
event.mediaStatus?.playerState === framework.messages.PlayerState.IDLE &&
event.mediaStatus?.playerState ===
("IDLE" as framework.messages.PlayerState.IDLE) &&
event.mediaStatus?.idleReason &&
event.mediaStatus?.idleReason !==
framework.messages.IdleReason.INTERRUPTED
("INTERRUPTED" as framework.messages.IdleReason.INTERRUPTED)
) {
// media finished or stopped, return to default Lovelace
showLovelaceController();
+4 -6
View File
@@ -305,9 +305,8 @@ export class HcMain extends HassElement {
await llColl.refresh();
this._unsubLovelace = llColl.subscribe(async (rawConfig) => {
if (isStrategyDashboard(rawConfig)) {
const { generateLovelaceDashboardStrategy } = await import(
"../../../../src/panels/lovelace/strategies/get-strategy"
);
const { generateLovelaceDashboardStrategy } =
await import("../../../../src/panels/lovelace/strategies/get-strategy");
const config = await generateLovelaceDashboardStrategy(
rawConfig,
this.hass!
@@ -347,9 +346,8 @@ export class HcMain extends HassElement {
}
private async _generateDefaultLovelaceConfig() {
const { generateLovelaceDashboardStrategy } = await import(
"../../../../src/panels/lovelace/strategies/get-strategy"
);
const { generateLovelaceDashboardStrategy } =
await import("../../../../src/panels/lovelace/strategies/get-strategy");
this._handleNewLovelaceConfig(
await generateLovelaceDashboardStrategy(DEFAULT_CONFIG, this.hass!)
);
-6
View File
@@ -1,6 +0,0 @@
export interface ReceivedMessage<T> {
gj: boolean;
data: T;
senderId: string;
type: "message";
}
+1 -1
View File
@@ -1,4 +1,4 @@
import type { AreaRegistryEntry } from "../../../src/data/area_registry";
import type { AreaRegistryEntry } from "../../../src/data/area/area_registry";
import type { MockHomeAssistant } from "../../../src/fake_data/provide_hass";
export const mockAreaRegistry = (
+1 -1
View File
@@ -1,4 +1,4 @@
import type { DeviceRegistryEntry } from "../../../src/data/device_registry";
import type { DeviceRegistryEntry } from "../../../src/data/device/device_registry";
import type { MockHomeAssistant } from "../../../src/fake_data/provide_hass";
export const mockDeviceRegistry = (
+29 -3
View File
@@ -44,18 +44,24 @@ export const mockEnergy = (hass: MockHomeAssistant) => {
number_energy_price: null,
},
],
power: [
{ stat_rate: "sensor.power_grid" },
{ stat_rate: "sensor.power_grid_return" },
],
cost_adjustment_day: 0,
},
{
type: "solar",
stat_energy_from: "sensor.solar_production",
stat_rate: "sensor.power_solar",
config_entry_solar_forecast: ["solar_forecast"],
},
/* {
{
type: "battery",
stat_energy_from: "sensor.battery_output",
stat_energy_to: "sensor.battery_input",
}, */
stat_rate: "sensor.power_battery",
},
{
type: "gas",
stat_energy_from: "sensor.energy_gas",
@@ -63,28 +69,48 @@ export const mockEnergy = (hass: MockHomeAssistant) => {
entity_energy_price: null,
number_energy_price: null,
},
{
type: "water",
stat_energy_from: "sensor.energy_water",
stat_cost: "sensor.energy_water_cost",
entity_energy_price: null,
number_energy_price: null,
},
],
device_consumption: [
{
stat_consumption: "sensor.energy_car",
stat_rate: "sensor.power_car",
},
{
stat_consumption: "sensor.energy_ac",
stat_rate: "sensor.power_ac",
},
{
stat_consumption: "sensor.energy_washing_machine",
stat_rate: "sensor.power_washing_machine",
},
{
stat_consumption: "sensor.energy_dryer",
stat_rate: "sensor.power_dryer",
},
{
stat_consumption: "sensor.energy_heat_pump",
stat_rate: "sensor.power_heat_pump",
},
{
stat_consumption: "sensor.energy_boiler",
stat_rate: "sensor.power_boiler",
},
],
device_consumption_water: [
{
stat_consumption: "sensor.water_kitchen",
},
{
stat_consumption: "sensor.water_garden",
},
],
device_consumption_water: [],
})
);
hass.mockWS(
+95
View File
@@ -154,6 +154,38 @@ export const energyEntities = () =>
unit_of_measurement: "EUR",
},
},
"sensor.power_grid": {
entity_id: "sensor.power_grid",
state: "500",
attributes: {
state_class: "measurement",
unit_of_measurement: "W",
},
},
"sensor.power_grid_return": {
entity_id: "sensor.power_grid_return",
state: "-100",
attributes: {
state_class: "measurement",
unit_of_measurement: "W",
},
},
"sensor.power_solar": {
entity_id: "sensor.power_solar",
state: "200",
attributes: {
state_class: "measurement",
unit_of_measurement: "W",
},
},
"sensor.power_battery": {
entity_id: "sensor.power_battery",
state: "100",
attributes: {
state_class: "measurement",
unit_of_measurement: "W",
},
},
"sensor.energy_gas_cost": {
entity_id: "sensor.energy_gas_cost",
state: "2",
@@ -171,6 +203,15 @@ export const energyEntities = () =>
unit_of_measurement: "m³",
},
},
"sensor.energy_water": {
entity_id: "sensor.energy_water",
state: "4000",
attributes: {
last_reset: "1970-01-01T00:00:00:00+00",
friendly_name: "Water",
unit_of_measurement: "L",
},
},
"sensor.energy_car": {
entity_id: "sensor.energy_car",
state: "4",
@@ -225,4 +266,58 @@ export const energyEntities = () =>
unit_of_measurement: "kWh",
},
},
"sensor.power_car": {
entity_id: "sensor.power_car",
state: "40",
attributes: {
state_class: "measurement",
friendly_name: "Electric car",
unit_of_measurement: "W",
},
},
"sensor.power_ac": {
entity_id: "sensor.power_ac",
state: "30",
attributes: {
state_class: "measurement",
friendly_name: "Air conditioning",
unit_of_measurement: "W",
},
},
"sensor.power_washing_machine": {
entity_id: "sensor.power_washing_machine",
state: "60",
attributes: {
state_class: "measurement",
friendly_name: "Washing machine",
unit_of_measurement: "W",
},
},
"sensor.power_dryer": {
entity_id: "sensor.power_dryer",
state: "55",
attributes: {
state_class: "measurement",
friendly_name: "Dryer",
unit_of_measurement: "W",
},
},
"sensor.power_heat_pump": {
entity_id: "sensor.power_heat_pump",
state: "60",
attributes: {
state_class: "measurement",
friendly_name: "Heat pump",
unit_of_measurement: "W",
},
},
"sensor.power_boiler": {
entity_id: "sensor.power_boiler",
state: "70",
attributes: {
state_class: "measurement",
friendly_name: "Boiler",
unit_of_measurement: "W",
},
},
});
+1 -1
View File
@@ -1,4 +1,4 @@
import type { EntityRegistryEntry } from "../../../src/data/entity_registry";
import type { EntityRegistryEntry } from "../../../src/data/entity/entity_registry";
import type { MockHomeAssistant } from "../../../src/fake_data/provide_hass";
export const mockEntityRegistry = (
+1 -1
View File
@@ -1,4 +1,4 @@
import type { LabelRegistryEntry } from "../../../src/data/label_registry";
import type { LabelRegistryEntry } from "../../../src/data/label/label_registry";
import type { MockHomeAssistant } from "../../../src/fake_data/provide_hass";
export const mockLabelRegistry = (
+1 -5
View File
@@ -17,17 +17,15 @@ const generateMeanStatistics = (
end: Date,
// eslint-disable-next-line default-param-last
period: "5minute" | "hour" | "day" | "month" = "hour",
initValue: number,
maxDiff: number
): StatisticValue[] => {
const statistics: StatisticValue[] = [];
let currentDate = new Date(start);
currentDate.setMinutes(0, 0, 0);
let lastVal = initValue;
const now = new Date();
while (end > currentDate && currentDate < now) {
const delta = Math.random() * maxDiff;
const mean = lastVal + delta;
const mean = delta;
statistics.push({
start: currentDate.getTime(),
end: currentDate.getTime(),
@@ -38,7 +36,6 @@ const generateMeanStatistics = (
state: mean,
sum: null,
});
lastVal = mean;
currentDate =
period === "day"
? addDays(currentDate, 1)
@@ -336,7 +333,6 @@ export const mockRecorder = (mockHass: MockHomeAssistant) => {
start,
end,
period,
state,
state * (state > 80 ? 0.05 : 0.1)
);
}
+6
View File
@@ -187,5 +187,11 @@ export default tseslint.config(
],
"no-use-before-define": "off",
},
},
{
files: ["src/util/recorder-worklet.js"],
languageOptions: {
globals: globals.audioWorklet,
},
}
);
@@ -142,7 +142,7 @@ export class DemoAutomationDescribeAction extends LitElement {
<div class="action">
<span>
${this._action
? describeAction(this.hass, [], [], {}, this._action)
? describeAction(this.hass, [], this._action)
: "<invalid YAML>"}
</span>
<ha-yaml-editor
@@ -155,7 +155,7 @@ export class DemoAutomationDescribeAction extends LitElement {
${ACTIONS.map(
(conf) => html`
<div class="action">
<span>${describeAction(this.hass, [], [], {}, conf as any)}</span>
<span>${describeAction(this.hass, [], conf as any)}</span>
<pre>${dump(conf)}</pre>
</div>
`
@@ -0,0 +1,3 @@
---
title: Adaptive dialog (ha-adaptive-dialog)
---
@@ -0,0 +1,732 @@
import { css, html, LitElement } from "lit";
import { customElement, state } from "lit/decorators";
import { mdiCog, mdiHelp } from "@mdi/js";
import "../../../../src/components/ha-button";
import "../../../../src/components/ha-card";
import "../../../../src/components/ha-dialog-footer";
import "../../../../src/components/ha-adaptive-dialog";
import "../../../../src/components/ha-form/ha-form";
import "../../../../src/components/ha-icon-button";
import type { HaFormSchema } from "../../../../src/components/ha-form/types";
import { provideHass } from "../../../../src/fake_data/provide_hass";
import type { HomeAssistant } from "../../../../src/types";
const SCHEMA: HaFormSchema[] = [
{ type: "string", name: "Name", default: "", autofocus: true },
{ type: "string", name: "Email", default: "" },
];
type DialogType =
| false
| "basic"
| "basic-subtitle-below"
| "basic-subtitle-above"
| "form"
| "form-block-mode"
| "actions"
| "large"
| "small";
@customElement("demo-components-ha-adaptive-dialog")
export class DemoHaAdaptiveDialog extends LitElement {
@state() private _openDialog: DialogType = false;
@state() private _hass?: HomeAssistant;
protected firstUpdated() {
const hass = provideHass(this);
this._hass = hass;
}
protected render() {
return html`
<div class="content">
<h1>Adaptive dialog <code>&lt;ha-adaptive-dialog&gt;</code></h1>
<p class="subtitle">
Responsive dialog component that automatically switches between a full
dialog and bottom sheet based on screen size.
</p>
<h2>Demos</h2>
<div class="buttons">
<ha-button @click=${this._handleOpenDialog("basic")}
>Basic adaptive dialog</ha-button
>
<ha-button @click=${this._handleOpenDialog("basic-subtitle-below")}
>Adaptive dialog with subtitle below</ha-button
>
<ha-button @click=${this._handleOpenDialog("basic-subtitle-above")}
>Adaptive dialog with subtitle above</ha-button
>
<ha-button @click=${this._handleOpenDialog("small")}
>Small width adaptive dialog</ha-button
>
<ha-button @click=${this._handleOpenDialog("large")}
>Large width adaptive dialog</ha-button
>
<ha-button @click=${this._handleOpenDialog("form")}
>Adaptive dialog with form</ha-button
>
<ha-button @click=${this._handleOpenDialog("form-block-mode")}
>Adaptive dialog with form (block mode change)</ha-button
>
<ha-button @click=${this._handleOpenDialog("actions")}
>Adaptive dialog with actions</ha-button
>
</div>
<ha-card>
<div class="card-content">
<p>
<strong>Tip:</strong> Resize your browser window to see the
responsive behavior. The dialog automatically switches to a bottom
sheet on narrow screens (&lt;870px width) or short screens
(&lt;500px height).
</p>
</div>
</ha-card>
<ha-adaptive-dialog
.hass=${this._hass}
.open=${this._openDialog === "basic"}
header-title="Basic adaptive dialog"
@closed=${this._handleClosed}
>
<div>Adaptive dialog content</div>
</ha-adaptive-dialog>
<ha-adaptive-dialog
.hass=${this._hass}
.open=${this._openDialog === "basic-subtitle-below"}
header-title="Adaptive dialog with subtitle"
header-subtitle="This is an adaptive dialog with a subtitle below"
@closed=${this._handleClosed}
>
<div>Adaptive dialog content</div>
</ha-adaptive-dialog>
<ha-adaptive-dialog
.hass=${this._hass}
.open=${this._openDialog === "basic-subtitle-above"}
header-title="Adaptive dialog with subtitle above"
header-subtitle="This is an adaptive dialog with a subtitle above"
header-subtitle-position="above"
@closed=${this._handleClosed}
>
<div>Adaptive dialog content</div>
</ha-adaptive-dialog>
<ha-adaptive-dialog
.hass=${this._hass}
.open=${this._openDialog === "small"}
width="small"
header-title="Small adaptive dialog"
@closed=${this._handleClosed}
>
<div>This dialog uses the small width preset (320px).</div>
</ha-adaptive-dialog>
<ha-adaptive-dialog
.hass=${this._hass}
.open=${this._openDialog === "large"}
width="large"
header-title="Large adaptive dialog"
@closed=${this._handleClosed}
>
<div>This dialog uses the large width preset (1024px).</div>
</ha-adaptive-dialog>
<ha-adaptive-dialog
.hass=${this._hass}
.open=${this._openDialog === "form"}
header-title="Adaptive dialog with form"
header-subtitle="This is an adaptive dialog with a form"
@closed=${this._handleClosed}
>
<ha-form autofocus .schema=${SCHEMA}></ha-form>
<ha-dialog-footer slot="footer">
<ha-button
@click=${this._handleClosed}
slot="secondaryAction"
variant="plain"
>Cancel</ha-button
>
<ha-button
@click=${this._handleClosed}
slot="primaryAction"
variant="accent"
>Submit</ha-button
>
</ha-dialog-footer>
</ha-adaptive-dialog>
<ha-adaptive-dialog
.hass=${this._hass}
.open=${this._openDialog === "form-block-mode"}
header-title="Adaptive dialog with form (block mode change)"
header-subtitle="This form will not reset when the viewport size changes"
block-mode-change
@closed=${this._handleClosed}
>
<ha-form autofocus .schema=${SCHEMA}></ha-form>
<ha-dialog-footer slot="footer">
<ha-button
@click=${this._handleClosed}
slot="secondaryAction"
variant="plain"
>Cancel</ha-button
>
<ha-button
@click=${this._handleClosed}
slot="primaryAction"
variant="accent"
>Submit</ha-button
>
</ha-dialog-footer>
</ha-adaptive-dialog>
<ha-adaptive-dialog
.hass=${this._hass}
.open=${this._openDialog === "actions"}
header-title="Adaptive dialog with actions"
header-subtitle="This is an adaptive dialog with header actions"
@closed=${this._handleClosed}
>
<div slot="headerActionItems">
<ha-icon-button label="Settings" path=${mdiCog}></ha-icon-button>
<ha-icon-button label="Help" path=${mdiHelp}></ha-icon-button>
</div>
<div>Adaptive dialog content</div>
</ha-adaptive-dialog>
<h2>Design</h2>
<h3>Responsive behavior</h3>
<p>
The <code>ha-adaptive-dialog</code> component automatically switches
between two modes based on screen size:
</p>
<ul>
<li>
<strong>Dialog mode:</strong> Used on larger screens (width &gt;
870px and height &gt; 500px). Renders as a centered dialog using
<code>ha-wa-dialog</code>.
</li>
<li>
<strong>Bottom sheet mode:</strong> Used on mobile devices and
smaller screens (width ≤ 870px or height ≤ 500px). Renders as a
drawer from the bottom using <code>ha-bottom-sheet</code>.
</li>
</ul>
<p>
The mode is determined automatically and updates when the window is
resized. To prevent mode changes after the initial mount (useful for
preventing form resets), use the <code>block-mode-change</code>
attribute.
</p>
<h3>Width</h3>
<p>
In dialog mode, there are multiple width presets available. These are
ignored in bottom sheet mode.
</p>
<table>
<thead>
<tr>
<th>Name</th>
<th>Value</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>small</code></td>
<td><code>min(320px, var(--full-width))</code></td>
</tr>
<tr>
<td><code>medium</code></td>
<td><code>min(580px, var(--full-width))</code></td>
</tr>
<tr>
<td><code>large</code></td>
<td><code>min(1024px, var(--full-width))</code></td>
</tr>
<tr>
<td><code>full</code></td>
<td><code>var(--full-width)</code></td>
</tr>
</tbody>
</table>
<p>Adaptive dialogs have a default width of <code>medium</code>.</p>
<h3>Header</h3>
<p>
The header contains a navigation icon, title, subtitle, and action
items.
</p>
<table>
<thead>
<tr>
<th>Slot</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>headerNavigationIcon</code></td>
<td>
Leading header action (e.g., close/back button). In bottom sheet
mode, defaults to a close button if not provided.
</td>
</tr>
<tr>
<td><code>headerTitle</code></td>
<td>The header title content.</td>
</tr>
<tr>
<td><code>headerSubtitle</code></td>
<td>The header subtitle content.</td>
</tr>
<tr>
<td><code>headerActionItems</code></td>
<td>Trailing header actions (e.g., icon buttons, menus).</td>
</tr>
</tbody>
</table>
<h4>Header title</h4>
<p>
The header title can be set using the <code>header-title</code>
attribute or by providing custom content in the
<code>headerTitle</code> slot.
</p>
<h4>Header subtitle</h4>
<p>
The header subtitle can be set using the
<code>header-subtitle</code> attribute or by providing custom content
in the <code>headerSubtitle</code> slot. The subtitle position
relative to the title can be controlled with the
<code>header-subtitle-position</code> attribute.
</p>
<h4>Header navigation icon</h4>
<p>
In bottom sheet mode, a close button is automatically provided if no
custom navigation icon is specified. In dialog mode, the dialog can be
closed via the standard dialog close button.
</p>
<h4>Header action items</h4>
<p>
The header action items usually contain icon buttons and/or menu
buttons.
</p>
<h3>Body</h3>
<p>The body is the content of the adaptive dialog.</p>
<h3>Footer</h3>
<p>The footer is the footer of the adaptive dialog.</p>
<p>
It is recommended to use the <code>ha-dialog-footer</code> component
for the footer and to style the buttons inside the footer as follows:
</p>
<table>
<thead>
<tr>
<th>Slot</th>
<th>Description</th>
<th>Variant to use</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>secondaryAction</code></td>
<td>The secondary action button(s).</td>
<td><code>plain</code></td>
</tr>
<tr>
<td><code>primaryAction</code></td>
<td>The primary action button(s).</td>
<td><code>accent</code></td>
</tr>
</tbody>
</table>
<h2>Implementation</h2>
<h3>When to use</h3>
<p>
Use <code>ha-adaptive-dialog</code> when you need a dialog that should
adapt to different screen sizes automatically. This is particularly
useful for:
</p>
<ul>
<li>Forms and data entry that need to work well on mobile devices</li>
<li>
Content that benefits from full-screen presentation on small devices
</li>
<li>
Interfaces that need consistent behavior across desktop and mobile
</li>
</ul>
<p>
If you don't need responsive behavior, use
<code>ha-wa-dialog</code> directly for desktop-only dialogs or
<code>ha-bottom-sheet</code> for mobile-only sheets.
</p>
<p>
Use the <code>block-mode-change</code> attribute when you want to
prevent the dialog from switching modes after it's opened. This is
especially useful for forms, as it prevents form data from being lost
when users resize their browser window.
</p>
<h3>Example usage</h3>
<pre><code>&lt;ha-adaptive-dialog
.hass=\${this.hass}
open
width="medium"
header-title="Dialog title"
header-subtitle="Dialog subtitle"
&gt;
&lt;div slot="headerActionItems"&gt;
&lt;ha-icon-button label="Settings" path="mdiCog"&gt;&lt;/ha-icon-button&gt;
&lt;ha-icon-button label="Help" path="mdiHelp"&gt;&lt;/ha-icon-button&gt;
&lt;/div&gt;
&lt;div&gt;Dialog content&lt;/div&gt;
&lt;ha-dialog-footer slot="footer"&gt;
&lt;ha-button slot="secondaryAction" variant="plain"
&gt;Cancel&lt;/ha-button
&gt;
&lt;ha-button slot="primaryAction" variant="accent"&gt;Submit&lt;/ha-button&gt;
&lt;/ha-dialog-footer&gt;
&lt;/ha-adaptive-dialog&gt;</code></pre>
<p>Example with <code>block-mode-change</code> for forms:</p>
<pre><code>&lt;ha-adaptive-dialog
.hass=\${this.hass}
open
header-title="Edit configuration"
block-mode-change
&gt;
&lt;ha-form .schema=\${schema} .data=\${data}&gt;&lt;/ha-form&gt;
&lt;ha-dialog-footer slot="footer"&gt;
&lt;ha-button slot="secondaryAction" variant="plain"
&gt;Cancel&lt;/ha-button
&gt;
&lt;ha-button slot="primaryAction" variant="accent"&gt;Save&lt;/ha-button&gt;
&lt;/ha-dialog-footer&gt;
&lt;/ha-adaptive-dialog&gt;</code></pre>
<h3>API</h3>
<p>
This component combines <code>ha-wa-dialog</code> and
<code>ha-bottom-sheet</code> with automatic mode switching based on
screen size.
</p>
<h4>Attributes</h4>
<table>
<thead>
<tr>
<th>Attribute</th>
<th>Description</th>
<th>Default</th>
<th>Options</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>open</code></td>
<td>Controls the adaptive dialog open state.</td>
<td><code>false</code></td>
<td><code>false</code>, <code>true</code></td>
</tr>
<tr>
<td><code>width</code></td>
<td>
Preferred dialog width preset (dialog mode only, ignored in
bottom sheet mode).
</td>
<td><code>medium</code></td>
<td>
<code>small</code>, <code>medium</code>, <code>large</code>,
<code>full</code>
</td>
</tr>
<tr>
<td><code>header-title</code></td>
<td>Header title text when no custom title slot is provided.</td>
<td></td>
<td></td>
</tr>
<tr>
<td><code>header-subtitle</code></td>
<td>
Header subtitle text when no custom subtitle slot is provided.
</td>
<td></td>
<td></td>
</tr>
<tr>
<td><code>header-subtitle-position</code></td>
<td>Position of the subtitle relative to the title.</td>
<td><code>below</code></td>
<td><code>above</code>, <code>below</code></td>
</tr>
<tr>
<td><code>aria-labelledby</code></td>
<td>
The ID of the element that labels the dialog (for
accessibility).
</td>
<td></td>
<td></td>
</tr>
<tr>
<td><code>aria-describedby</code></td>
<td>
The ID of the element that describes the dialog (for
accessibility).
</td>
<td></td>
<td></td>
</tr>
<tr>
<td><code>block-mode-change</code></td>
<td>
When set, the mode is determined at mount time based on the
current screen size, but subsequent mode changes are blocked.
Useful for preventing forms from resetting when the viewport
size changes.
</td>
<td><code>false</code></td>
<td><code>false</code>, <code>true</code></td>
</tr>
</tbody>
</table>
<h4>CSS custom properties</h4>
<table>
<thead>
<tr>
<th>CSS Property</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>--ha-dialog-surface-background</code></td>
<td>Dialog/sheet background color.</td>
</tr>
<tr>
<td><code>--ha-dialog-border-radius</code></td>
<td>Border radius of the dialog surface (dialog mode only).</td>
</tr>
<tr>
<td><code>--ha-dialog-show-duration</code></td>
<td>Show animation duration (dialog mode only).</td>
</tr>
<tr>
<td><code>--ha-dialog-hide-duration</code></td>
<td>Hide animation duration (dialog mode only).</td>
</tr>
</tbody>
</table>
<h4>Events</h4>
<table>
<thead>
<tr>
<th>Event</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>opened</code></td>
<td>
Fired when the adaptive dialog is shown (dialog mode only).
</td>
</tr>
<tr>
<td><code>closed</code></td>
<td>
Fired after the adaptive dialog is hidden (dialog mode only).
</td>
</tr>
<tr>
<td><code>after-show</code></td>
<td>Fired after show animation completes (dialog mode only).</td>
</tr>
</tbody>
</table>
<h3>Focus management</h3>
<p>
To automatically focus an element when the adaptive dialog opens, add
the
<code>autofocus</code> attribute to it. Components with
<code>delegatesFocus: true</code> (like <code>ha-form</code>) will
forward focus to their first focusable child.
</p>
<p>Example:</p>
<pre><code>&lt;ha-adaptive-dialog .hass=\${this.hass} open&gt;
&lt;ha-form autofocus .schema=\${schema}&gt;&lt;/ha-form&gt;
&lt;/ha-adaptive-dialog&gt;</code></pre>
</div>
`;
}
private _handleOpenDialog = (dialog: DialogType) => () => {
this._openDialog = dialog;
};
private _handleClosed = () => {
this._openDialog = false;
};
static styles = [
css`
:host {
display: block;
padding: var(--ha-space-4);
}
.content {
max-width: 1000px;
margin: 0 auto;
}
h1 {
margin-top: 0;
margin-bottom: var(--ha-space-2);
}
h2 {
margin-top: var(--ha-space-6);
margin-bottom: var(--ha-space-3);
}
h3,
h4 {
margin-top: var(--ha-space-4);
margin-bottom: var(--ha-space-2);
}
p {
margin: var(--ha-space-2) 0;
line-height: 1.6;
}
ul {
margin: var(--ha-space-2) 0;
padding-left: var(--ha-space-5);
}
li {
margin: var(--ha-space-1) 0;
line-height: 1.6;
}
.subtitle {
color: var(--secondary-text-color);
font-size: 1.1em;
margin-bottom: var(--ha-space-4);
}
table {
width: 100%;
border-collapse: collapse;
margin: var(--ha-space-3) 0;
}
th,
td {
text-align: left;
padding: var(--ha-space-2);
border-bottom: 1px solid var(--divider-color);
}
th {
font-weight: 500;
}
code {
background-color: var(--secondary-background-color);
padding: 2px 6px;
border-radius: 4px;
font-family: monospace;
font-size: 0.9em;
}
pre {
background-color: var(--secondary-background-color);
padding: var(--ha-space-3);
border-radius: 8px;
overflow-x: auto;
margin: var(--ha-space-3) 0;
}
pre code {
background-color: transparent;
padding: 0;
}
.buttons {
display: flex;
flex-direction: row;
flex-wrap: wrap;
gap: var(--ha-space-2);
margin: var(--ha-space-4) 0;
}
.card-content {
padding: var(--ha-space-3);
}
a {
color: var(--primary-color);
}
`,
];
}
declare global {
interface HTMLElementTagNameMap {
"demo-components-ha-adaptive-dialog": DemoHaAdaptiveDialog;
}
}
+3 -3
View File
@@ -10,12 +10,12 @@ import { mockHassioSupervisor } from "../../../../demo/src/stubs/hassio_supervis
import { computeInitialHaFormData } from "../../../../src/components/ha-form/compute-initial-ha-form-data";
import "../../../../src/components/ha-form/ha-form";
import type { HaFormSchema } from "../../../../src/components/ha-form/types";
import type { AreaRegistryEntry } from "../../../../src/data/area_registry";
import type { AreaRegistryEntry } from "../../../../src/data/area/area_registry";
import type { DeviceRegistryEntry } from "../../../../src/data/device/device_registry";
import { getEntity } from "../../../../src/fake_data/entity";
import { provideHass } from "../../../../src/fake_data/provide_hass";
import type { HomeAssistant } from "../../../../src/types";
import "../../components/demo-black-white-row";
import type { DeviceRegistryEntry } from "../../../../src/data/device_registry";
const ENTITIES = [
getEntity("alarm_control_panel", "alarm", "disarmed", {
@@ -169,7 +169,7 @@ const SCHEMAS: {
{
title: "Selectors",
translations: {
addon: "Addon",
addon: "App",
entity: "Entity",
device: "Device",
area: "Area",
+34 -4
View File
@@ -11,11 +11,11 @@ import { mockLabelRegistry } from "../../../../demo/src/stubs/label_registry";
import "../../../../src/components/ha-formfield";
import "../../../../src/components/ha-selector/ha-selector";
import "../../../../src/components/ha-settings-row";
import type { AreaRegistryEntry } from "../../../../src/data/area_registry";
import type { AreaRegistryEntry } from "../../../../src/data/area/area_registry";
import type { BlueprintInput } from "../../../../src/data/blueprint";
import type { DeviceRegistryEntry } from "../../../../src/data/device_registry";
import type { DeviceRegistryEntry } from "../../../../src/data/device/device_registry";
import type { FloorRegistryEntry } from "../../../../src/data/floor_registry";
import type { LabelRegistryEntry } from "../../../../src/data/label_registry";
import type { LabelRegistryEntry } from "../../../../src/data/label/label_registry";
import { showDialog } from "../../../../src/dialogs/make-dialog-manager";
import { getEntity } from "../../../../src/fake_data/entity";
import { provideHass } from "../../../../src/fake_data/provide_hass";
@@ -40,6 +40,9 @@ const ENTITIES = [
getEntity("switch", "coffee", "off", {
friendly_name: "Coffee",
}),
getEntity("number", "number", 5, {
friendly_name: "Number",
}),
];
const DEVICES: DeviceRegistryEntry[] = [
@@ -236,7 +239,7 @@ const SCHEMAS: {
selector: { config_entry: {} },
},
duration: { name: "Duration", selector: { duration: {} } },
addon: { name: "Addon", selector: { addon: {} } },
addon: { name: "App", selector: { addon: {} } },
number_box: {
name: "Number Box",
selector: {
@@ -377,6 +380,33 @@ const SCHEMAS: {
name: "Constant",
selector: { constant: { value: true, label: "Yes!" } },
},
choose: {
name: "Choose",
selector: {
choose: {
choices: {
number: {
selector: {
number: {
min: 0,
max: 100,
step: 0.1,
},
},
},
entity: {
selector: {
entity: {
filter: {
domain: "number",
},
},
},
},
},
},
},
},
},
},
{
+1 -5
View File
@@ -139,7 +139,7 @@ export class DemoHaWaDialog extends LitElement {
</tr>
<tr>
<td><code>large</code></td>
<td><code>min(720px, var(--full-width))</code></td>
<td><code>min(1024px, var(--full-width))</code></td>
</tr>
<tr>
<td><code>full</code></td>
@@ -381,10 +381,6 @@ export class DemoHaWaDialog extends LitElement {
<td><code>--dialog-z-index</code></td>
<td>Z-index for the dialog.</td>
</tr>
<tr>
<td><code>--dialog-surface-position</code></td>
<td>CSS position of the dialog surface.</td>
</tr>
<tr>
<td><code>--dialog-surface-margin-top</code></td>
<td>Top margin for the dialog surface.</td>
+2 -2
View File
@@ -6,8 +6,8 @@ import { customElement, property, state } from "lit/decorators";
import { classMap } from "lit/directives/class-map";
import type { IntegrationManifest } from "../../../../src/data/integration";
import type { DeviceRegistryEntry } from "../../../../src/data/device_registry";
import type { EntityRegistryEntry } from "../../../../src/data/entity_registry";
import type { DeviceRegistryEntry } from "../../../../src/data/device/device_registry";
import type { EntityRegistryEntry } from "../../../../src/data/entity/entity_registry";
import { provideHass } from "../../../../src/fake_data/provide_hass";
import "../../../../src/panels/config/integrations/ha-config-flow-card";
import type {
@@ -83,10 +83,10 @@ export class HassioAddonRepositoryEl extends LitElement {
? this.supervisor.localize(
"common.new_version_available"
)
: this.supervisor.localize("addon.state.installed")
: this.supervisor.localize("app.state.installed")
: addon.available
? this.supervisor.localize("addon.state.not_installed")
: this.supervisor.localize("addon.state.not_available")}
? this.supervisor.localize("app.state.not_installed")
: this.supervisor.localize("app.state.not_available")}
.iconClass=${addon.installed
? addon.update_available
? "update"
+1 -1
View File
@@ -120,7 +120,7 @@ export class HassioAddonStore extends LitElement {
? html`
<div class="advanced">
<a href="/profile" target="_top">
${this.supervisor.localize("store.missing_addons")}
${this.supervisor.localize("store.missing_apps")}
</a>
</div>
`
@@ -44,7 +44,7 @@ class HassioAddonAudio extends LitElement {
return html`
<ha-card
outlined
.header=${this.supervisor.localize("addon.configuration.audio.header")}
.header=${this.supervisor.localize("app.configuration.audio.header")}
>
<div class="card-content">
${this._error
@@ -52,9 +52,7 @@ class HassioAddonAudio extends LitElement {
: nothing}
${this._inputDevices &&
html`<ha-select
.label=${this.supervisor.localize(
"addon.configuration.audio.input"
)}
.label=${this.supervisor.localize("app.configuration.audio.input")}
@selected=${this._setInputDevice}
@closed=${stopPropagation}
fixedMenuPosition
@@ -72,9 +70,7 @@ class HassioAddonAudio extends LitElement {
</ha-select>`}
${this._outputDevices &&
html`<ha-select
.label=${this.supervisor.localize(
"addon.configuration.audio.output"
)}
.label=${this.supervisor.localize("app.configuration.audio.output")}
@selected=${this._setOutputDevice}
@closed=${stopPropagation}
fixedMenuPosition
@@ -153,7 +149,7 @@ class HassioAddonAudio extends LitElement {
const noDevice: HassioHardwareAudioDevice = {
device: "default",
name: this.supervisor.localize("addon.configuration.audio.default"),
name: this.supervisor.localize("app.configuration.audio.default"),
};
try {
@@ -81,7 +81,7 @@ class HassioAddonConfigDashboard extends LitElement {
`
: nothing}
`
: this.supervisor.localize("addon.configuration.no_configuration")}
: this.supervisor.localize("app.configuration.no_configuration")}
</div>
`;
}
@@ -219,7 +219,7 @@ class HassioAddonConfig extends LitElement {
<ha-card outlined>
<div class="header">
<h2>
${this.supervisor.localize("addon.configuration.options.header")}
${this.supervisor.localize("app.configuration.options.header")}
</h2>
<div class="card-menu">
<ha-button-menu @action=${this._handleAction}>
@@ -231,10 +231,10 @@ class HassioAddonConfig extends LitElement {
<ha-list-item .disabled=${!this._canShowSchema || this.disabled}>
${this._yamlMode
? this.supervisor.localize(
"addon.configuration.options.edit_in_ui"
"app.configuration.options.edit_in_ui"
)
: this.supervisor.localize(
"addon.configuration.options.edit_in_yaml"
"app.configuration.options.edit_in_yaml"
)}
</ha-list-item>
<ha-list-item
@@ -279,7 +279,7 @@ class HassioAddonConfig extends LitElement {
: html`
<ha-alert alert-type="error">
${this.supervisor.localize(
"addon.configuration.options.invalid_yaml"
"app.configuration.options.invalid_yaml"
)}
</ha-alert>
`}
@@ -288,7 +288,7 @@ class HassioAddonConfig extends LitElement {
? html`<ha-formfield
class="show-additional"
.label=${this.supervisor.localize(
"addon.configuration.options.show_unused_optional"
"app.configuration.options.show_unused_optional"
)}
>
<ha-switch
@@ -397,7 +397,7 @@ class HassioAddonConfig extends LitElement {
};
fireEvent(this, "hass-api-called", eventdata);
} catch (err: any) {
this._error = this.supervisor.localize("addon.failed_to_reset", {
this._error = this.supervisor.localize("app.failed_to_reset", {
error: extractApiErrorMessage(err),
});
}
@@ -440,7 +440,7 @@ class HassioAddonConfig extends LitElement {
await suggestAddonRestart(this, this.hass, this.supervisor, this.addon);
}
} catch (err: any) {
this._error = this.supervisor.localize("addon.failed_to_save", {
this._error = this.supervisor.localize("app.failed_to_save", {
error: extractApiErrorMessage(err),
});
eventdata.success = false;
@@ -56,14 +56,12 @@ class HassioAddonNetwork extends LitElement {
return html`
<ha-card
outlined
.header=${this.supervisor.localize(
"addon.configuration.network.header"
)}
.header=${this.supervisor.localize("app.configuration.network.header")}
>
<div class="card-content">
<p>
${this.supervisor.localize(
"addon.configuration.network.introduction"
"app.configuration.network.introduction"
)}
</p>
${this._error
@@ -87,7 +85,7 @@ class HassioAddonNetwork extends LitElement {
? html`<ha-formfield
class="show-optional"
.label=${this.supervisor.localize(
"addon.configuration.network.show_disabled"
"app.configuration.network.show_disabled"
)}
>
<ha-switch
@@ -187,7 +185,7 @@ class HassioAddonNetwork extends LitElement {
await suggestAddonRestart(this, this.hass, this.supervisor, this.addon);
}
} catch (err: any) {
this._error = this.supervisor.localize("addon.failed_to_reset", {
this._error = this.supervisor.localize("app.failed_to_reset", {
error: extractApiErrorMessage(err),
});
button.actionError();
@@ -229,7 +227,7 @@ class HassioAddonNetwork extends LitElement {
await suggestAddonRestart(this, this.hass, this.supervisor, this.addon);
}
} catch (err: any) {
this._error = this.supervisor.localize("addon.failed_to_save", {
this._error = this.supervisor.localize("app.failed_to_save", {
error: extractApiErrorMessage(err),
});
button.actionError();
@@ -83,7 +83,7 @@ class HassioAddonDocumentationDashboard extends LitElement {
);
} catch (err: any) {
this._error = this.supervisor.localize(
"addon.documentation.get_documentation",
"app.documentation.get_documentation",
{ error: extractApiErrorMessage(err) }
);
}
+10 -10
View File
@@ -2,7 +2,7 @@ import {
mdiCogs,
mdiFileDocument,
mdiInformationVariant,
mdiMathLog,
mdiTextBoxOutline,
} from "@mdi/js";
import type { CSSResultGroup, TemplateResult } from "lit";
import { css, html, LitElement } from "lit";
@@ -89,7 +89,7 @@ class HassioAddonDashboard extends LitElement {
const addonTabs: PageNavigation[] = [
{
translationKey: "addon.panel.info",
translationKey: "app.panel.info",
path: `/hassio/addon/${this.addon.slug}/info`,
iconPath: mdiInformationVariant,
},
@@ -97,7 +97,7 @@ class HassioAddonDashboard extends LitElement {
if (this.addon.documentation) {
addonTabs.push({
translationKey: "addon.panel.documentation",
translationKey: "app.panel.documentation",
path: `/hassio/addon/${this.addon.slug}/documentation`,
iconPath: mdiFileDocument,
});
@@ -106,14 +106,14 @@ class HassioAddonDashboard extends LitElement {
if (this.addon.version) {
addonTabs.push(
{
translationKey: "addon.panel.configuration",
translationKey: "app.panel.configuration",
path: `/hassio/addon/${this.addon.slug}/config`,
iconPath: mdiCogs,
},
{
translationKey: "addon.panel.log",
translationKey: "app.panel.log",
path: `/hassio/addon/${this.addon.slug}/logs`,
iconPath: mdiMathLog,
iconPath: mdiTextBoxOutline,
}
);
}
@@ -195,10 +195,10 @@ class HassioAddonDashboard extends LitElement {
) {
if (
!(await showConfirmationDialog(this, {
title: this.supervisor.localize("my.add_addon_repository_title"),
title: this.supervisor.localize("my.add_app_repository_title"),
text: this.supervisor.localize(
"my.add_addon_repository_description",
{ addon: requestedAddon, repository: requestedAddonRepository }
"my.add_app_repository_description",
{ app: requestedAddon, repository: requestedAddonRepository }
),
confirmText: this.supervisor.localize("common.add"),
dismissText: this.supervisor.localize("common.cancel"),
@@ -224,7 +224,7 @@ class HassioAddonDashboard extends LitElement {
(addon) => addon.slug === requestedAddon
);
if (!validAddon) {
this._error = this.supervisor.localize("my.error_addon_not_found");
this._error = this.supervisor.localize("my.error_app_not_found");
} else {
navigate(`/hassio/addon/${requestedAddon}`, { replace: true });
}
+69 -74
View File
@@ -150,11 +150,11 @@ class HassioAddonInfo extends LitElement {
: undefined;
const metrics = [
{
description: this.supervisor.localize("addon.dashboard.cpu_usage"),
description: this.supervisor.localize("app.dashboard.cpu_usage"),
value: this._metrics?.cpu_percent,
},
{
description: this.supervisor.localize("addon.dashboard.ram_usage"),
description: this.supervisor.localize("app.dashboard.ram_usage"),
value: this._metrics?.memory_percent,
tooltip: `${bytesToString(this._metrics?.memory_usage)}/${bytesToString(
this._metrics?.memory_limit
@@ -181,11 +181,11 @@ class HassioAddonInfo extends LitElement {
<ha-alert
alert-type="error"
.title=${this.supervisor.localize(
"addon.dashboard.protection_mode.title"
"app.dashboard.protection_mode.title"
)}
>
${this.supervisor.localize(
"addon.dashboard.protection_mode.content"
"app.dashboard.protection_mode.content"
)}
<ha-button
variant="danger"
@@ -193,7 +193,7 @@ class HassioAddonInfo extends LitElement {
@click=${this._protectionToggled}
>
${this.supervisor.localize(
"addon.dashboard.protection_mode.enable"
"app.dashboard.protection_mode.enable"
)}
</ha-button>
</ha-alert>
@@ -220,7 +220,7 @@ class HassioAddonInfo extends LitElement {
? html`
<ha-svg-icon
.title=${this.supervisor.localize(
"dashboard.addon_running"
"dashboard.app_running"
)}
class="running"
.path=${mdiPlayCircle}
@@ -229,7 +229,7 @@ class HassioAddonInfo extends LitElement {
: html`
<ha-svg-icon
.title=${this.supervisor.localize(
"dashboard.addon_stopped"
"dashboard.app_stopped"
)}
class="stopped"
.path=${mdiCircleOffOutline}
@@ -242,22 +242,19 @@ class HassioAddonInfo extends LitElement {
<div class="description light-color">
${this.addon.version
? html`
${this.supervisor.localize(
"addon.dashboard.current_version",
{ version: this.addon.version }
)}
${this.supervisor.localize("app.dashboard.current_version", {
version: this.addon.version,
})}
<div class="changelog" @click=${this._openChangelog}>
(<span class="changelog-link"
>${this.supervisor.localize(
"addon.dashboard.changelog"
"app.dashboard.changelog"
)}</span
>)
</div>
`
: html`<span class="changelog-link" @click=${this._openChangelog}
>${this.supervisor.localize(
"addon.dashboard.changelog"
)}</span
>${this.supervisor.localize("app.dashboard.changelog")}</span
>`}
</div>
@@ -274,7 +271,7 @@ class HassioAddonInfo extends LitElement {
id="stage"
.label=${capitalizeFirstLetter(
this.supervisor.localize(
`addon.dashboard.capability.stages.${this.addon.stage}`
`app.dashboard.capability.stages.${this.addon.stage}`
)
)}
>
@@ -298,7 +295,7 @@ class HassioAddonInfo extends LitElement {
id="rating"
.label=${capitalizeFirstLetter(
this.supervisor.localize(
"addon.dashboard.capability.label.rating"
"app.dashboard.capability.label.rating"
)
)}
>
@@ -313,7 +310,7 @@ class HassioAddonInfo extends LitElement {
id="host_network"
.label=${capitalizeFirstLetter(
this.supervisor.localize(
"addon.dashboard.capability.label.host"
"app.dashboard.capability.label.host"
)
)}
>
@@ -329,7 +326,7 @@ class HassioAddonInfo extends LitElement {
id="full_access"
.label=${capitalizeFirstLetter(
this.supervisor.localize(
"addon.dashboard.capability.label.hardware"
"app.dashboard.capability.label.hardware"
)
)}
>
@@ -345,7 +342,7 @@ class HassioAddonInfo extends LitElement {
id="homeassistant_api"
.label=${capitalizeFirstLetter(
this.supervisor.localize(
"addon.dashboard.capability.label.core"
"app.dashboard.capability.label.core"
)
)}
>
@@ -364,7 +361,7 @@ class HassioAddonInfo extends LitElement {
id="hassio_api"
.label=${capitalizeFirstLetter(
this.supervisor.localize(
`addon.dashboard.capability.role.${this.addon.hassio_role}`
`app.dashboard.capability.role.${this.addon.hassio_role}`
) || this.addon.hassio_role
)}
>
@@ -383,7 +380,7 @@ class HassioAddonInfo extends LitElement {
id="docker_api"
.label=${capitalizeFirstLetter(
this.supervisor.localize(
"addon.dashboard.capability.label.docker"
"app.dashboard.capability.label.docker"
)
)}
>
@@ -399,7 +396,7 @@ class HassioAddonInfo extends LitElement {
id="host_pid"
.label=${capitalizeFirstLetter(
this.supervisor.localize(
"addon.dashboard.capability.label.host_pid"
"app.dashboard.capability.label.host_pid"
)
)}
>
@@ -416,7 +413,7 @@ class HassioAddonInfo extends LitElement {
id="apparmor"
.label=${capitalizeFirstLetter(
this.supervisor.localize(
"addon.dashboard.capability.label.apparmor"
"app.dashboard.capability.label.apparmor"
)
)}
>
@@ -432,7 +429,7 @@ class HassioAddonInfo extends LitElement {
id="auth_api"
.label=${capitalizeFirstLetter(
this.supervisor.localize(
"addon.dashboard.capability.label.auth"
"app.dashboard.capability.label.auth"
)
)}
>
@@ -448,7 +445,7 @@ class HassioAddonInfo extends LitElement {
id="ingress"
.label=${capitalizeFirstLetter(
this.supervisor.localize(
"addon.dashboard.capability.label.ingress"
"app.dashboard.capability.label.ingress"
)
)}
>
@@ -467,7 +464,7 @@ class HassioAddonInfo extends LitElement {
id="signed"
.label=${capitalizeFirstLetter(
this.supervisor.localize(
"addon.dashboard.capability.label.signed"
"app.dashboard.capability.label.signed"
)
)}
>
@@ -482,7 +479,7 @@ class HassioAddonInfo extends LitElement {
@click=${this._showSystemManagedDialog}
id="system_managed"
.label=${capitalizeFirstLetter(
this.supervisor.localize("addon.system_managed.badge")
this.supervisor.localize("app.system_managed.badge")
)}
>
<ha-svg-icon
@@ -496,7 +493,7 @@ class HassioAddonInfo extends LitElement {
<div class="description light-color">
${this.addon.description}.<br />
${this.supervisor.localize("addon.dashboard.visit_addon_page", {
${this.supervisor.localize("app.dashboard.visit_app_page", {
name: html`<a
href=${this.addon.url!}
target="_blank"
@@ -527,12 +524,12 @@ class HassioAddonInfo extends LitElement {
<ha-settings-row ?three-line=${this.narrow}>
<span slot="heading">
${this.supervisor.localize(
"addon.dashboard.option.boot.title"
"app.dashboard.option.boot.title"
)}
</span>
<span slot="description">
${this.supervisor.localize(
"addon.dashboard.option.boot.description"
"app.dashboard.option.boot.description"
)}
</span>
<ha-switch
@@ -548,12 +545,12 @@ class HassioAddonInfo extends LitElement {
<ha-settings-row ?three-line=${this.narrow}>
<span slot="heading">
${this.supervisor.localize(
"addon.dashboard.option.watchdog.title"
"app.dashboard.option.watchdog.title"
)}
</span>
<span slot="description">
${this.supervisor.localize(
"addon.dashboard.option.watchdog.description"
"app.dashboard.option.watchdog.description"
)}
</span>
<ha-switch
@@ -572,12 +569,12 @@ class HassioAddonInfo extends LitElement {
<ha-settings-row ?three-line=${this.narrow}>
<span slot="heading">
${this.supervisor.localize(
"addon.dashboard.option.auto_update.title"
"app.dashboard.option.auto_update.title"
)}
</span>
<span slot="description">
${this.supervisor.localize(
"addon.dashboard.option.auto_update.description"
"app.dashboard.option.auto_update.description"
)}
</span>
<ha-switch
@@ -595,12 +592,12 @@ class HassioAddonInfo extends LitElement {
<ha-settings-row ?three-line=${this.narrow}>
<span slot="heading">
${this.supervisor.localize(
"addon.dashboard.option.ingress_panel.title"
"app.dashboard.option.ingress_panel.title"
)}
</span>
<span slot="description">
${this.supervisor.localize(
"addon.dashboard.option.ingress_panel.description"
"app.dashboard.option.ingress_panel.description"
)}
</span>
<ha-switch
@@ -618,12 +615,12 @@ class HassioAddonInfo extends LitElement {
<ha-settings-row ?three-line=${this.narrow}>
<span slot="heading">
${this.supervisor.localize(
"addon.dashboard.option.protected.title"
"app.dashboard.option.protected.title"
)}
</span>
<span slot="description">
${this.supervisor.localize(
"addon.dashboard.option.protected.description"
"app.dashboard.option.protected.description"
)}
</span>
<ha-switch
@@ -644,7 +641,7 @@ class HassioAddonInfo extends LitElement {
${this.addon.version && this.addon.state === "started"
? html`<ha-settings-row ?three-line=${this.narrow}>
<span slot="heading">
${this.supervisor.localize("addon.dashboard.hostname")}
${this.supervisor.localize("app.dashboard.hostname")}
</span>
<code slot="description"> ${this.addon.hostname} </code>
</ha-settings-row>
@@ -671,14 +668,14 @@ class HassioAddonInfo extends LitElement {
? html`
<ha-alert alert-type="warning">
${this.supervisor.localize(
"addon.dashboard.not_available_arch"
"app.dashboard.not_available_arch"
)}
</ha-alert>
`
: html`
<ha-alert alert-type="warning">
${this.supervisor.localize(
"addon.dashboard.not_available_version",
"app.dashboard.not_available_version",
{
core_version_installed: this.supervisor.core.version,
core_version_needed: addonStoreInfo!.homeassistant,
@@ -699,14 +696,14 @@ class HassioAddonInfo extends LitElement {
@click=${this._stopClicked}
.disabled=${systemManaged && !this.controlEnabled}
>
${this.supervisor.localize("addon.dashboard.stop")}
${this.supervisor.localize("app.dashboard.stop")}
</ha-progress-button>
<ha-progress-button
variant="danger"
appearance="plain"
@click=${this._restartClicked}
>
${this.supervisor.localize("addon.dashboard.restart")}
${this.supervisor.localize("app.dashboard.restart")}
</ha-progress-button>
`
: html`
@@ -715,7 +712,7 @@ class HassioAddonInfo extends LitElement {
.progress=${this.addon.state === "startup"}
appearance="plain"
>
${this.supervisor.localize("addon.dashboard.start")}
${this.supervisor.localize("app.dashboard.start")}
</ha-progress-button>
`
: nothing}
@@ -729,7 +726,7 @@ class HassioAddonInfo extends LitElement {
@click=${this._uninstallClicked}
.disabled=${systemManaged && !this.controlEnabled}
>
${this.supervisor.localize("addon.dashboard.uninstall")}
${this.supervisor.localize("app.dashboard.uninstall")}
</ha-progress-button>
${this.addon.build
? html`
@@ -738,7 +735,7 @@ class HassioAddonInfo extends LitElement {
appearance="plain"
@click=${this._rebuildClicked}
>
${this.supervisor.localize("addon.dashboard.rebuild")}
${this.supervisor.localize("app.dashboard.rebuild")}
</ha-progress-button>
`
: nothing}
@@ -761,7 +758,7 @@ class HassioAddonInfo extends LitElement {
: undefined}
>
${this.supervisor.localize(
"addon.dashboard.open_web_ui"
"app.dashboard.open_web_ui"
)}
</ha-button>
`
@@ -772,7 +769,7 @@ class HassioAddonInfo extends LitElement {
.disabled=${!this.addon.available}
@click=${this._installClicked}
>
${this.supervisor.localize("addon.dashboard.install")}
${this.supervisor.localize("app.dashboard.install")}
</ha-progress-button>
`}
</div>
@@ -804,7 +801,7 @@ class HassioAddonInfo extends LitElement {
"state" in this.addon &&
this.addon.state === "startup"
) {
// Addon is starting up, wait for it to start
// App is starting up, wait for it to start
this._scheduleDataUpdate();
}
}
@@ -858,11 +855,11 @@ class HassioAddonInfo extends LitElement {
private _showMoreInfo(ev): void {
const id = ev.currentTarget.id as AddonCapability;
showHassioMarkdownDialog(this, {
title: this.supervisor.localize(`addon.dashboard.capability.${id}.title`),
title: this.supervisor.localize(`app.dashboard.capability.${id}.title`),
content:
id === "stage"
? this.supervisor.localize(
`addon.dashboard.capability.${id}.description`,
`app.dashboard.capability.${id}.description`,
{
icon_stable: `<ha-svg-icon path="${STAGE_ICON.stable}"></ha-svg-icon>`,
icon_experimental: `<ha-svg-icon path="${STAGE_ICON.experimental}"></ha-svg-icon>`,
@@ -870,7 +867,7 @@ class HassioAddonInfo extends LitElement {
}
)
: this.supervisor.localize(
`addon.dashboard.capability.${id}.description`
`app.dashboard.capability.${id}.description`
),
});
}
@@ -936,7 +933,7 @@ class HassioAddonInfo extends LitElement {
};
fireEvent(this, "hass-api-called", eventdata);
} catch (err: any) {
this._error = this.supervisor.localize("addon.failed_to_save", {
this._error = this.supervisor.localize("app.failed_to_save", {
error: extractApiErrorMessage(err),
});
}
@@ -956,7 +953,7 @@ class HassioAddonInfo extends LitElement {
};
fireEvent(this, "hass-api-called", eventdata);
} catch (err: any) {
this._error = this.supervisor.localize("addon.failed_to_save", {
this._error = this.supervisor.localize("app.failed_to_save", {
error: extractApiErrorMessage(err),
});
}
@@ -976,7 +973,7 @@ class HassioAddonInfo extends LitElement {
};
fireEvent(this, "hass-api-called", eventdata);
} catch (err: any) {
this._error = this.supervisor.localize("addon.failed_to_save", {
this._error = this.supervisor.localize("app.failed_to_save", {
error: extractApiErrorMessage(err),
});
}
@@ -996,7 +993,7 @@ class HassioAddonInfo extends LitElement {
};
fireEvent(this, "hass-api-called", eventdata);
} catch (err: any) {
this._error = this.supervisor.localize("addon.failed_to_save", {
this._error = this.supervisor.localize("app.failed_to_save", {
error: extractApiErrorMessage(err),
});
}
@@ -1016,7 +1013,7 @@ class HassioAddonInfo extends LitElement {
};
fireEvent(this, "hass-api-called", eventdata);
} catch (err: any) {
this._error = this.supervisor.localize("addon.failed_to_save", {
this._error = this.supervisor.localize("app.failed_to_save", {
error: extractApiErrorMessage(err),
});
}
@@ -1030,13 +1027,13 @@ class HassioAddonInfo extends LitElement {
);
showHassioMarkdownDialog(this, {
title: this.supervisor.localize("addon.dashboard.changelog"),
title: this.supervisor.localize("app.dashboard.changelog"),
content: extractChangelog(this.addon as HassioAddonDetails, content),
});
} catch (err: any) {
showAlertDialog(this, {
title: this.supervisor.localize(
"addon.dashboard.action_error.get_changelog"
"app.dashboard.action_error.get_changelog"
),
text: extractApiErrorMessage(err),
});
@@ -1066,7 +1063,7 @@ class HassioAddonInfo extends LitElement {
fireEvent(this, "hass-api-called", eventdata);
} catch (err: any) {
showAlertDialog(this, {
title: this.supervisor.localize("addon.dashboard.action_error.install"),
title: this.supervisor.localize("app.dashboard.action_error.install"),
text: extractApiErrorMessage(err),
});
}
@@ -1091,7 +1088,7 @@ class HassioAddonInfo extends LitElement {
fireEvent(this, "hass-api-called", eventdata);
} catch (err: any) {
showAlertDialog(this, {
title: this.supervisor.localize("addon.dashboard.action_error.stop"),
title: this.supervisor.localize("app.dashboard.action_error.stop"),
text: extractApiErrorMessage(err),
});
}
@@ -1112,7 +1109,7 @@ class HassioAddonInfo extends LitElement {
fireEvent(this, "hass-api-called", eventdata);
} catch (err: any) {
showAlertDialog(this, {
title: this.supervisor.localize("addon.dashboard.action_error.restart"),
title: this.supervisor.localize("app.dashboard.action_error.restart"),
text: extractApiErrorMessage(err),
});
}
@@ -1127,7 +1124,7 @@ class HassioAddonInfo extends LitElement {
await rebuildLocalAddon(this.hass, this.addon.slug);
} catch (err: any) {
showAlertDialog(this, {
title: this.supervisor.localize("addon.dashboard.action_error.rebuild"),
title: this.supervisor.localize("app.dashboard.action_error.rebuild"),
text: extractApiErrorMessage(err),
});
}
@@ -1145,12 +1142,12 @@ class HassioAddonInfo extends LitElement {
if (!validate.valid) {
await showConfirmationDialog(this, {
title: this.supervisor.localize(
"addon.dashboard.action_error.start_invalid_config"
"app.dashboard.action_error.start_invalid_config"
),
text: validate.message.split(" Got ")[0],
confirm: () => this._openConfiguration(),
confirmText: this.supervisor.localize(
"addon.dashboard.action_error.go_to_config"
"app.dashboard.action_error.go_to_config"
),
dismissText: this.supervisor.localize("common.cancel"),
});
@@ -1162,7 +1159,7 @@ class HassioAddonInfo extends LitElement {
button.actionError();
button.progress = false;
showAlertDialog(this, {
title: "Failed to validate addon configuration",
title: "Failed to validate app configuration",
text: extractApiErrorMessage(err),
});
return;
@@ -1181,7 +1178,7 @@ class HassioAddonInfo extends LitElement {
button.actionError();
button.progress = false;
showAlertDialog(this, {
title: this.supervisor.localize("addon.dashboard.action_error.start"),
title: this.supervisor.localize("app.dashboard.action_error.start"),
text: extractApiErrorMessage(err),
});
return;
@@ -1207,13 +1204,13 @@ class HassioAddonInfo extends LitElement {
};
const confirmed = await showConfirmationDialog(this, {
title: this.supervisor.localize("dialog.uninstall_addon.title", {
title: this.supervisor.localize("dialog.uninstall_app.title", {
name: this.addon.name,
}),
text: html`
<ha-formfield
.label=${html`<p>
${this.supervisor.localize("dialog.uninstall_addon.remove_data")}
${this.supervisor.localize("dialog.uninstall_app.remove_data")}
</p>`}
>
<ha-switch
@@ -1223,7 +1220,7 @@ class HassioAddonInfo extends LitElement {
></ha-switch>
</ha-formfield>
`,
confirmText: this.supervisor.localize("dialog.uninstall_addon.uninstall"),
confirmText: this.supervisor.localize("dialog.uninstall_app.uninstall"),
dismissText: this.supervisor.localize("common.cancel"),
destructive: true,
});
@@ -1245,9 +1242,7 @@ class HassioAddonInfo extends LitElement {
button.actionSuccess();
} catch (err: any) {
showAlertDialog(this, {
title: this.supervisor.localize(
"addon.dashboard.action_error.uninstall"
),
title: this.supervisor.localize("app.dashboard.action_error.uninstall"),
text: extractApiErrorMessage(err),
});
button.actionError();
@@ -19,14 +19,14 @@ class HassioAddonSystemManaged extends LitElement {
return html`
<ha-alert
alert-type="warning"
.title=${this.supervisor.localize("addon.system_managed.title")}
.title=${this.supervisor.localize("app.system_managed.title")}
.narrow=${this.narrow}
>
${this.supervisor.localize("addon.system_managed.description")}
${this.supervisor.localize("app.system_managed.description")}
${!this.hideButton
? html`
<ha-button slot="action" @click=${this._takeControl}>
${this.supervisor.localize("addon.system_managed.take_control")}
${this.supervisor.localize("app.system_managed.take_control")}
</ha-button>
`
: nothing}
@@ -216,7 +216,7 @@ export class SupervisorBackupContent extends LitElement {
? html`
<ha-formfield
.label=${html`<supervisor-formfield-label
.label=${this.supervisor?.localize("backup.addons")}
.label=${this.supervisor?.localize("backup.apps")}
.iconPath=${mdiPuzzle}
>
</supervisor-formfield-label>`}
+6 -8
View File
@@ -33,13 +33,13 @@ class HassioAddons extends LitElement {
suffix
.filter=${this._filter}
@value-changed=${this._handleSearchChange}
.label=${this.supervisor.localize("dashboard.search_addons")}
.label=${this.supervisor.localize("dashboard.search_apps")}
>
</search-input>
</div>
<div class="content">
${!atLeastVersion(this.hass.config.version, 2021, 12)
? html`<h1>${this.supervisor.localize("dashboard.addons")}</h1>`
? html`<h1>${this.supervisor.localize("dashboard.apps")}</h1>`
: ""}
<div class="card-group">
${!this.supervisor.addon.addons.length
@@ -47,7 +47,7 @@ class HassioAddons extends LitElement {
<ha-card outlined>
<div class="card-content">
<button class="link" @click=${this._openStore}>
${this.supervisor.localize("dashboard.no_addons")}
${this.supervisor.localize("dashboard.no_apps")}
</button>
</div>
</ha-card>
@@ -67,14 +67,12 @@ class HassioAddons extends LitElement {
? mdiArrowUpBoldCircle
: mdiPuzzle}
.iconTitle=${addon.state !== "started"
? this.supervisor.localize("dashboard.addon_stopped")
? this.supervisor.localize("dashboard.app_stopped")
: addon.update_available!
? this.supervisor.localize(
"dashboard.addon_new_version"
"dashboard.app_new_version"
)
: this.supervisor.localize(
"dashboard.addon_running"
)}
: this.supervisor.localize("dashboard.app_running")}
.iconClass=${addon.update_available
? addon.state === "started"
? "update"
+2 -2
View File
@@ -39,7 +39,7 @@ class HassioDashboard extends LitElement {
.narrow=${this.narrow}
.route=${this.route}
back-path="/config"
.header=${this.supervisor.localize("panel.addons")}
.header=${this.supervisor.localize("panel.apps")}
>
<ha-icon-button
slot="toolbar-icon"
@@ -81,7 +81,7 @@ class HassioDashboard extends LitElement {
<span slot="header">
${this.supervisor.localize(
atLeastVersion(this.hass.config.version, 2021, 12)
? "panel.addons"
? "panel.apps"
: "panel.dashboard"
)}
</span>
@@ -88,8 +88,8 @@ class HassioRegistriesDialog extends LitElement {
<ha-button
?disabled=${Boolean(
!this._input.registry ||
!this._input.username ||
!this._input.password
!this._input.username ||
!this._input.password
)}
@click=${this._addNewRegistry}
appearance="filled"
@@ -64,9 +64,9 @@ class HassioRepositoriesDialog extends LitElement {
repos
.filter(
(repo) =>
repo.slug !== "core" && // The core add-ons repository
repo.slug !== "local" && // Locally managed add-ons
repo.slug !== "a0d7b954" && // Home Assistant Community Add-ons
repo.slug !== "core" && // The core apps repository
repo.slug !== "local" && // Locally managed apps
repo.slug !== "a0d7b954" && // Home Assistant Community Apps
repo.slug !== "5c53de3b" && // The ESPHome repository
repo.slug !== "d5369777" // Music Assistant repository
)
+3 -3
View File
@@ -16,11 +16,11 @@ export const suggestAddonRestart = async (
addon: HassioAddonDetails
): Promise<void> => {
const confirmed = await showConfirmationDialog(element, {
title: supervisor.localize("dialog.restart_addon.title", {
title: supervisor.localize("dialog.restart_app.title", {
name: addon.name,
}),
text: supervisor.localize("dialog.restart_addon.text"),
confirmText: supervisor.localize("dialog.restart_addon.restart"),
text: supervisor.localize("dialog.restart_app.text"),
confirmText: supervisor.localize("dialog.restart_app.restart"),
dismissText: supervisor.localize("common.cancel"),
});
if (confirmed) {
@@ -89,14 +89,12 @@ class HassioSystemManagedDialog extends LitElement {
? html`<img src=${addonImage} alt=${this._addon.name} />`
: html`<ha-svg-icon .path=${mdiPuzzle}></ha-svg-icon>`}
</div>
${this._supervisor.localize("addon.system_managed.title")}.<br />
${this._supervisor.localize("addon.system_managed.description")}
${this._supervisor.localize("app.system_managed.title")}.<br />
${this._supervisor.localize("app.system_managed.description")}
${this._configEntry
? html`
<h3>
${this._supervisor.localize(
"addon.system_managed.managed_by"
)}:
${this._supervisor.localize("app.system_managed.managed_by")}:
</h3>
<ha-md-list>
<ha-md-list-item
+1 -1
View File
@@ -14,7 +14,7 @@ export const supervisorTabs = (hass: HomeAssistant): PageNavigation[] =>
: [
{
translationKey: atLeastVersion(hass.config.version, 2021, 12)
? "panel.addons"
? "panel.apps"
: "panel.dashboard",
path: `/hassio/dashboard`,
iconPath: atLeastVersion(hass.config.version, 2021, 12)
+20 -20
View File
@@ -114,14 +114,14 @@ class HassioIngressView extends LitElement {
}
if (!addonInfo.version) {
await showAlertDialog(this, {
text: this.supervisor.localize("my.error_addon_not_installed"),
text: this.supervisor.localize("my.error_app_not_installed"),
title: addonInfo.name,
});
await nextRender();
navigate(`/hassio/addon/${addonInfo.slug}/info`, { replace: true });
} else if (!addonInfo.ingress) {
await showAlertDialog(this, {
text: this.supervisor.localize("my.error_addon_no_ingress"),
text: this.supervisor.localize("my.error_app_no_ingress"),
title: addonInfo.name,
});
await nextRender();
@@ -162,8 +162,8 @@ class HassioIngressView extends LitElement {
await this.updateComplete;
await showAlertDialog(this, {
text:
this.supervisor.localize("ingress.error_addon_info") ||
"Unable to fetch add-on info to start Ingress",
this.supervisor.localize("ingress.error_app_info") ||
"Unable to fetch app info to start Ingress",
title: "Supervisor",
});
await nextRender();
@@ -175,8 +175,8 @@ class HassioIngressView extends LitElement {
await this.updateComplete;
await showAlertDialog(this, {
text:
this.supervisor.localize("ingress.error_addon_not_installed") ||
"The add-on is not installed. Please install it first",
this.supervisor.localize("ingress.error_app_not_installed") ||
"The app is not installed. Please install it first",
title: addon.name,
});
await nextRender();
@@ -188,8 +188,8 @@ class HassioIngressView extends LitElement {
await this.updateComplete;
await showAlertDialog(this, {
text:
this.supervisor.localize("ingress.error_addon_not_supported") ||
"This add-on does not support Ingress",
this.supervisor.localize("ingress.error_app_not_supported") ||
"This app does not support Ingress",
title: addon.name,
});
await nextRender();
@@ -201,18 +201,18 @@ class HassioIngressView extends LitElement {
await this.updateComplete;
const confirm = await showConfirmationDialog(this, {
text:
this.supervisor.localize("ingress.error_addon_not_running") ||
"The add-on is not running. Do you want to start it now?",
this.supervisor.localize("ingress.error_app_not_running") ||
"The app is not running. Do you want to start it now?",
title: addon.name,
confirmText:
this.supervisor.localize("ingress.start_addon") || "Start add-on",
this.supervisor.localize("ingress.start_app") || "Start app",
dismissText: this.supervisor.localize("common.no") || "No",
});
if (confirm) {
try {
this._loadingMessage =
this.supervisor.localize("ingress.addon_starting") ||
"The add-on is starting, this can take some time...";
this.supervisor.localize("ingress.app_starting") ||
"The app is starting, this can take some time...";
await startHassioAddon(this.hass, addonSlug);
fireEvent(this, "supervisor-collection-refresh", {
collection: "addon",
@@ -222,8 +222,8 @@ class HassioIngressView extends LitElement {
} catch (_err) {
await showAlertDialog(this, {
text:
this.supervisor.localize("ingress.error_starting_addon") ||
"Error starting the add-on",
this.supervisor.localize("ingress.error_starting_app") ||
"Error starting the app",
title: addon.name,
});
await nextRender();
@@ -238,10 +238,10 @@ class HassioIngressView extends LitElement {
}
if (addon.state === "startup") {
// Addon is starting up, wait for it to start
// App is starting up, wait for it to start
this._loadingMessage =
this.supervisor.localize("ingress.addon_starting") ||
"The add-on is starting, this can take some time...";
this.supervisor.localize("ingress.app_starting") ||
"The app is starting, this can take some time...";
this._fetchDataTimeout = window.setTimeout(() => {
this._fetchData(addonSlug);
@@ -301,8 +301,8 @@ class HassioIngressView extends LitElement {
await this.updateComplete;
showConfirmationDialog(this, {
text:
this.supervisor.localize("ingress.error_addon_not_ready") ||
"The add-on seems to not be ready, it might still be starting. Do you want to try again?",
this.supervisor.localize("ingress.error_app_not_ready") ||
"The app seems to not be ready, it might still be starting. Do you want to try again?",
title: this._addon.name,
confirmText: this.supervisor.localize("ingress.retry") || "Retry",
dismissText: this.supervisor.localize("common.no") || "No",
@@ -261,16 +261,16 @@ class UpdateAvailableCard extends LitElement {
private _computeCreateBackupTexts():
| { title: string; description?: string }
| undefined {
// Addon backup
// App backup
if (
this._updateType === "addon" &&
atLeastVersion(this.hass.config.version, 2025, 2, 0)
) {
const version = this._version;
return {
title: this.supervisor.localize("update_available.create_backup.addon"),
title: this.supervisor.localize("update_available.create_backup.app"),
description: this.supervisor.localize(
"update_available.create_backup.addon_description",
"update_available.create_backup.app_description",
{ version: version }
),
};
@@ -363,11 +363,11 @@ class UpdateAvailableCard extends LitElement {
)
) {
this._error = this.supervisor.localize(
"addon.dashboard.not_available_arch"
"app.dashboard.not_available_arch"
);
} else {
this._error = this.supervisor.localize(
"addon.dashboard.not_available_version",
"app.dashboard.not_available_version",
{
core_version_installed: this.supervisor.core.version,
core_version_needed: addonStoreInfo.homeassistant,
@@ -1,4 +1,3 @@
import "@material/mwc-linear-progress/mwc-linear-progress";
import memoizeOne from "memoize-one";
import { type CSSResultGroup, LitElement, css, html, nothing } from "lit";
import { customElement, property } from "lit/decorators";
+57 -59
View File
@@ -26,39 +26,39 @@
"license": "Apache-2.0",
"type": "module",
"dependencies": {
"@babel/runtime": "7.28.4",
"@babel/runtime": "7.28.6",
"@braintree/sanitize-url": "7.1.1",
"@codemirror/autocomplete": "6.20.0",
"@codemirror/commands": "6.10.0",
"@codemirror/language": "6.11.3",
"@codemirror/commands": "6.10.1",
"@codemirror/language": "6.12.1",
"@codemirror/legacy-modes": "6.5.2",
"@codemirror/search": "6.5.11",
"@codemirror/state": "6.5.2",
"@codemirror/view": "6.38.8",
"@codemirror/search": "6.6.0",
"@codemirror/state": "6.5.4",
"@codemirror/view": "6.39.11",
"@date-fns/tz": "1.4.1",
"@egjs/hammerjs": "2.0.17",
"@formatjs/intl-datetimeformat": "6.18.2",
"@formatjs/intl-displaynames": "6.8.13",
"@formatjs/intl-durationformat": "0.7.6",
"@formatjs/intl-getcanonicallocales": "2.5.6",
"@formatjs/intl-listformat": "7.7.13",
"@formatjs/intl-locale": "4.2.13",
"@formatjs/intl-numberformat": "8.15.6",
"@formatjs/intl-pluralrules": "5.4.6",
"@formatjs/intl-relativetimeformat": "11.4.13",
"@fullcalendar/core": "6.1.19",
"@fullcalendar/daygrid": "6.1.19",
"@fullcalendar/interaction": "6.1.19",
"@fullcalendar/list": "6.1.19",
"@fullcalendar/luxon3": "6.1.19",
"@fullcalendar/timegrid": "6.1.19",
"@home-assistant/webawesome": "3.0.0-ha.0",
"@formatjs/intl-datetimeformat": "7.2.0",
"@formatjs/intl-displaynames": "7.2.0",
"@formatjs/intl-durationformat": "0.10.0",
"@formatjs/intl-getcanonicallocales": "3.2.0",
"@formatjs/intl-listformat": "8.2.0",
"@formatjs/intl-locale": "5.2.0",
"@formatjs/intl-numberformat": "9.2.0",
"@formatjs/intl-pluralrules": "6.2.0",
"@formatjs/intl-relativetimeformat": "12.2.0",
"@fullcalendar/core": "6.1.20",
"@fullcalendar/daygrid": "6.1.20",
"@fullcalendar/interaction": "6.1.20",
"@fullcalendar/list": "6.1.20",
"@fullcalendar/luxon3": "6.1.20",
"@fullcalendar/timegrid": "6.1.20",
"@home-assistant/webawesome": "3.0.0-ha.2",
"@lezer/highlight": "1.2.3",
"@lit-labs/motion": "1.0.9",
"@lit-labs/observers": "2.0.6",
"@lit-labs/motion": "1.1.0",
"@lit-labs/observers": "2.1.0",
"@lit-labs/virtualizer": "2.1.1",
"@lit/context": "1.1.6",
"@lit/reactive-element": "2.1.1",
"@lit/reactive-element": "2.1.2",
"@material/chips": "=14.0.0-canary.53b3cad2f.0",
"@material/data-table": "=14.0.0-canary.53b3cad2f.0",
"@material/mwc-base": "0.27.0",
@@ -85,12 +85,10 @@
"@mdi/js": "7.4.47",
"@mdi/svg": "7.4.47",
"@replit/codemirror-indentation-markers": "6.5.3",
"@swc/helpers": "0.5.17",
"@swc/helpers": "0.5.18",
"@thomasloven/round-slider": "0.6.0",
"@tsparticles/engine": "3.9.1",
"@tsparticles/preset-links": "3.2.0",
"@vaadin/combo-box": "24.9.5",
"@vaadin/vaadin-themable-mixin": "24.9.5",
"@vibrant/color": "4.0.0",
"@vue/web-component-wrapper": "1.3.0",
"@webcomponents/scoped-custom-element-registry": "0.0.10",
@@ -114,13 +112,13 @@
"hls.js": "1.6.15",
"home-assistant-js-websocket": "9.6.0",
"idb-keyval": "6.2.2",
"intl-messageformat": "10.7.18",
"intl-messageformat": "11.1.0",
"js-yaml": "4.1.1",
"leaflet": "1.9.4",
"leaflet-draw": "patch:leaflet-draw@npm%3A1.0.4#./.yarn/patches/leaflet-draw-npm-1.0.4-0ca0ebcf65.patch",
"leaflet.markercluster": "1.5.3",
"lit": "3.3.1",
"lit-html": "3.3.1",
"lit": "3.3.2",
"lit-html": "3.3.2",
"luxon": "3.7.2",
"marked": "17.0.1",
"memoize-one": "6.0.0",
@@ -135,7 +133,7 @@
"stacktrace-js": "2.0.2",
"superstruct": "2.0.2",
"tinykeys": "3.0.0",
"ua-parser-js": "2.0.6",
"ua-parser-js": "2.0.8",
"vue": "2.7.16",
"vue2-daterange-picker": "0.6.8",
"weekstart": "2.0.0",
@@ -148,20 +146,20 @@
"xss": "1.0.15"
},
"devDependencies": {
"@babel/core": "7.28.5",
"@babel/core": "7.28.6",
"@babel/helper-define-polyfill-provider": "0.6.5",
"@babel/plugin-transform-runtime": "7.28.5",
"@babel/preset-env": "7.28.5",
"@bundle-stats/plugin-webpack-filter": "4.21.6",
"@lokalise/node-api": "15.4.0",
"@babel/preset-env": "7.28.6",
"@bundle-stats/plugin-webpack-filter": "4.21.8",
"@lokalise/node-api": "15.6.0",
"@octokit/auth-oauth-device": "8.0.3",
"@octokit/plugin-retry": "8.0.3",
"@octokit/rest": "22.0.1",
"@rsdoctor/rspack-plugin": "1.3.11",
"@rspack/core": "1.6.4",
"@rspack/dev-server": "1.1.4",
"@rsdoctor/rspack-plugin": "1.5.0",
"@rspack/core": "1.7.2",
"@rspack/dev-server": "1.1.5",
"@types/babel__plugin-transform-runtime": "7.9.5",
"@types/chromecast-caf-receiver": "6.0.22",
"@types/chromecast-caf-receiver": "6.0.25",
"@types/chromecast-caf-sender": "1.0.11",
"@types/color-name": "2.0.0",
"@types/culori": "4.0.1",
@@ -178,12 +176,12 @@
"@types/tar": "6.1.13",
"@types/ua-parser-js": "0.7.39",
"@types/webspeechapi": "0.0.29",
"@vitest/coverage-v8": "4.0.13",
"@vitest/coverage-v8": "4.0.17",
"babel-loader": "10.0.0",
"babel-plugin-template-html-minifier": "4.1.0",
"browserslist-useragent-regexp": "4.1.3",
"del": "8.0.1",
"eslint": "9.39.1",
"eslint": "9.39.2",
"eslint-config-airbnb-base": "15.0.0",
"eslint-config-prettier": "10.1.8",
"eslint-import-resolver-webpack": "0.13.10",
@@ -193,15 +191,15 @@
"eslint-plugin-unused-imports": "4.3.0",
"eslint-plugin-wc": "3.0.2",
"fancy-log": "2.0.0",
"fs-extra": "11.3.2",
"glob": "12.0.0",
"fs-extra": "11.3.3",
"glob": "13.0.0",
"gulp": "5.0.1",
"gulp-brotli": "3.0.0",
"gulp-json-transform": "0.5.0",
"gulp-rename": "2.1.0",
"html-minifier-terser": "7.2.0",
"husky": "9.1.7",
"jsdom": "27.2.0",
"jsdom": "27.4.0",
"jszip": "3.10.1",
"lint-staged": "16.2.7",
"lit-analyzer": "2.0.3",
@@ -209,35 +207,35 @@
"lodash.template": "4.5.0",
"map-stream": "0.0.7",
"pinst": "3.0.0",
"prettier": "3.6.2",
"rspack-manifest-plugin": "5.2.0",
"prettier": "3.8.0",
"rspack-manifest-plugin": "5.2.1",
"serve": "14.2.5",
"sinon": "21.0.0",
"tar": "7.5.2",
"terser-webpack-plugin": "5.3.14",
"sinon": "21.0.1",
"tar": "7.5.3",
"terser-webpack-plugin": "5.3.16",
"ts-lit-plugin": "2.0.2",
"typescript": "5.9.3",
"typescript-eslint": "8.47.0",
"vite-tsconfig-paths": "5.1.4",
"vitest": "4.0.13",
"typescript-eslint": "8.53.0",
"vite-tsconfig-paths": "6.0.4",
"vitest": "4.0.17",
"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"
},
"resolutions": {
"@material/mwc-button@^0.25.3": "^0.27.0",
"lit": "3.3.1",
"lit-html": "3.3.1",
"lit": "3.3.2",
"lit-html": "3.3.2",
"clean-css": "5.3.3",
"@lit/reactive-element": "2.1.1",
"@fullcalendar/daygrid": "6.1.19",
"globals": "16.5.0",
"@lit/reactive-element": "2.1.2",
"@fullcalendar/daygrid": "6.1.20",
"globals": "17.0.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",
"glob@^10.2.2": "^10.5.0"
},
"packageManager": "yarn@4.12.0",
"volta": {
"node": "22.21.1"
"node": "24.13.0"
}
}
+1 -1
View File
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
[project]
name = "home-assistant-frontend"
version = "20251127.0"
version = "20251229.0"
license = "Apache-2.0"
license-files = ["LICENSE*"]
description = "The Home Assistant frontend"
+1 -3
View File
@@ -1,5 +1,4 @@
#!/bin/sh
# Pushes a new version to PyPi.
# Stop on errors
set -e
@@ -12,5 +11,4 @@ yarn install
script/build_frontend
rm -rf dist home_assistant_frontend.egg-info
python3 -m build
python3 -m twine upload dist/*.whl --skip-existing
python3 -m build -q
+11 -14
View File
@@ -38,13 +38,11 @@ export class HaAuthFormString extends HaFormString {
}
</style>
<ha-auth-textfield
.type=${
!this.isPassword
.type=${!this.isPassword
? this.stringType
: this.unmaskedPassword
? "text"
: "password"
}
: "password"}
.label=${this.label}
.value=${this.data || ""}
.helper=${this.helper}
@@ -55,18 +53,17 @@ export class HaAuthFormString extends HaFormString {
.name=${this.schema.name}
.autocomplete=${this.schema.autocomplete}
?autofocus=${this.schema.autofocus}
.suffix=${
this.isPassword
? // reserve some space for the icon.
html`<div style="width: 24px"></div>`
: this.schema.description?.suffix
}
.validationMessage=${this.schema.required ? this.localize?.("ui.panel.page-authorize.form.error_required") : undefined}
.suffix=${this.isPassword
? // reserve some space for the icon.
html`<div style="width: 24px"></div>`
: this.schema.description?.suffix}
.validationMessage=${this.schema.required
? this.localize?.("ui.panel.page-authorize.form.error_required")
: undefined}
@input=${this._valueChanged}
@change=${this._valueChanged}
></ha-auth-textfield>
${this.renderIcon()}
</ha-auth-textfield>
></ha-auth-textfield>
${this.renderIcon()}
`;
}
}
+1 -1
View File
@@ -1,4 +1,4 @@
import type { AreaRegistryEntry } from "../../data/area_registry";
import type { AreaRegistryEntry } from "../../data/area/area_registry";
import type { FloorRegistryEntry } from "../../data/floor_registry";
export interface AreasFloorHierarchy {
+3 -1
View File
@@ -1,7 +1,6 @@
export const THEME_COLORS = new Set([
"primary",
"accent",
"disabled",
"red",
"pink",
"purple",
@@ -25,6 +24,9 @@ export const THEME_COLORS = new Set([
"blue-grey",
"black",
"white",
"primary-text",
"secondary-text",
"disabled",
]);
export function computeCssColor(color: string): string {
+1 -1
View File
@@ -79,7 +79,7 @@ export const generateColorPalette = (
}
return steps.map((step) => {
const name = `color-${label}-${step}`;
const name = `ha-color-${label}-${step}`;
// Base color at 50%
if (step === 50) {
+2 -2
View File
@@ -93,8 +93,8 @@ export const calcDateRange = (
];
case "now-12m":
return [
calcDate(subMonths(today, 12), startOfMonth, hass.locale, hass.config),
calcDate(subMonths(today, 1), endOfMonth, hass.locale, hass.config),
calcDate(today, subMonths, hass.locale, hass.config, 12),
calcDate(today, subMonths, hass.locale, hass.config, 0),
];
case "now-1h":
return [
+1 -1
View File
@@ -1,4 +1,4 @@
import type { AreaRegistryEntry } from "../../data/area_registry";
import type { AreaRegistryEntry } from "../../data/area/area_registry";
export const computeAreaName = (area: AreaRegistryEntry): string | undefined =>
area.name?.trim();
@@ -3,8 +3,8 @@ import {
DOMAIN_ATTRIBUTES_FORMATERS,
DOMAIN_ATTRIBUTES_UNITS,
TEMPERATURE_ATTRIBUTES,
} from "../../data/entity_attributes";
import type { EntityRegistryDisplayEntry } from "../../data/entity_registry";
} from "../../data/entity/entity_attributes";
import type { EntityRegistryDisplayEntry } from "../../data/entity/entity_registry";
import type { FrontendLocaleData } from "../../data/translation";
import type { WeatherEntity } from "../../data/weather";
import { getWeatherUnit } from "../../data/weather";
+3 -3
View File
@@ -1,12 +1,12 @@
import memoizeOne from "memoize-one";
import type { DeviceRegistryEntry } from "../../data/device_registry";
import type { DeviceRegistryEntry } from "../../data/device/device_registry";
import type {
EntityRegistryDisplayEntry,
EntityRegistryEntry,
} from "../../data/entity_registry";
} from "../../data/entity/entity_registry";
import type { HomeAssistant } from "../../types";
import { computeStateName } from "./compute_state_name";
import { getDuplicates } from "../string/get_duplicates";
import { computeStateName } from "./compute_state_name";
export const computeDeviceName = (
device: DeviceRegistryEntry
+1 -1
View File
@@ -2,7 +2,7 @@ import type { HassEntity } from "home-assistant-js-websocket";
import type {
EntityRegistryDisplayEntry,
EntityRegistryEntry,
} from "../../data/entity_registry";
} from "../../data/entity/entity_registry";
import type { HomeAssistant } from "../../types";
import { computeDeviceName } from "./compute_device_name";
import { computeStateName } from "./compute_state_name";
+3 -3
View File
@@ -1,12 +1,12 @@
import type { HassConfig, HassEntity } from "home-assistant-js-websocket";
import { UNAVAILABLE, UNKNOWN } from "../../data/entity";
import type { EntityRegistryDisplayEntry } from "../../data/entity_registry";
import { UNAVAILABLE, UNKNOWN } from "../../data/entity/entity";
import type { EntityRegistryDisplayEntry } from "../../data/entity/entity_registry";
import type { FrontendLocaleData } from "../../data/translation";
import { TimeZone } from "../../data/translation";
import type { HomeAssistant } from "../../types";
import { DURATION_UNITS, formatDuration } from "../datetime/format_duration";
import { formatDate } from "../datetime/format_date";
import { formatDateTime } from "../datetime/format_date_time";
import { DURATION_UNITS, formatDuration } from "../datetime/format_duration";
import { formatTime } from "../datetime/format_time";
import {
formatNumber,
@@ -1,4 +1,4 @@
import type { AreaRegistryEntry } from "../../../data/area_registry";
import type { AreaRegistryEntry } from "../../../data/area/area_registry";
import type { FloorRegistryEntry } from "../../../data/floor_registry";
import type { HomeAssistant } from "../../../types";
@@ -1,5 +1,5 @@
import type { AreaRegistryEntry } from "../../../data/area_registry";
import type { DeviceRegistryEntry } from "../../../data/device_registry";
import type { AreaRegistryEntry } from "../../../data/area/area_registry";
import type { DeviceRegistryEntry } from "../../../data/device/device_registry";
import type { FloorRegistryEntry } from "../../../data/floor_registry";
import type { HomeAssistant } from "../../../types";
@@ -1,11 +1,11 @@
import type { HassEntity } from "home-assistant-js-websocket";
import type { AreaRegistryEntry } from "../../../data/area_registry";
import type { DeviceRegistryEntry } from "../../../data/device_registry";
import type { AreaRegistryEntry } from "../../../data/area/area_registry";
import type { DeviceRegistryEntry } from "../../../data/device/device_registry";
import type {
EntityRegistryDisplayEntry,
EntityRegistryEntry,
ExtEntityRegistryEntry,
} from "../../../data/entity_registry";
} from "../../../data/entity/entity_registry";
import type { FloorRegistryEntry } from "../../../data/floor_registry";
import type { HomeAssistant } from "../../../types";
+9 -9
View File
@@ -1,14 +1,14 @@
import type { HomeAssistant } from "../../types";
import type { IntegrationManifest } from "../../data/integration";
import { computeDomain } from "./compute_domain";
import { HELPERS_CRUD } from "../../data/helpers_crud";
import type { Helper } from "../../panels/config/helpers/const";
import { isHelperDomain } from "../../panels/config/helpers/const";
import { isComponentLoaded } from "../config/is_component_loaded";
import type { EntityRegistryEntry } from "../../data/entity_registry";
import { removeEntityRegistryEntry } from "../../data/entity_registry";
import type { ConfigEntry } from "../../data/config_entries";
import { deleteConfigEntry } from "../../data/config_entries";
import type { EntityRegistryEntry } from "../../data/entity/entity_registry";
import { removeEntityRegistryEntry } from "../../data/entity/entity_registry";
import { HELPERS_CRUD } from "../../data/helpers_crud";
import type { IntegrationManifest } from "../../data/integration";
import type { Helper } from "../../panels/config/helpers/const";
import { isHelperDomain } from "../../panels/config/helpers/const";
import type { HomeAssistant } from "../../types";
import { isComponentLoaded } from "../config/is_component_loaded";
import { computeDomain } from "./compute_domain";
export const isDeletableEntity = (
hass: HomeAssistant,
+10 -2
View File
@@ -15,6 +15,7 @@ export interface EntityFilter {
label?: string | string[];
entity_category?: EntityCategory | EntityCategory[];
hidden_platform?: string | string[];
hidden_domains?: string | string[];
}
export type EntityFilterFunc = (entityId: string) => boolean;
@@ -38,6 +39,9 @@ export const generateEntityFilter = (
const domains = filter.domain
? new Set(ensureArray(filter.domain))
: undefined;
const hiddenDomains = filter.hidden_domains
? new Set(ensureArray(filter.hidden_domains))
: undefined;
const deviceClasses = filter.device_class
? new Set(ensureArray(filter.device_class))
: undefined;
@@ -57,12 +61,16 @@ export const generateEntityFilter = (
if (!stateObj) {
return false;
}
if (domains) {
if (domains || hiddenDomains) {
const domain = computeDomain(entityId);
if (!domains.has(domain)) {
if (domains && !domains.has(domain)) {
return false;
}
if (hiddenDomains && hiddenDomains.has(domain)) {
return false;
}
}
if (deviceClasses) {
const dc = stateObj.attributes.device_class || "none";
if (!deviceClasses.has(dc)) {
+3 -3
View File
@@ -1,9 +1,9 @@
import type { HassEntity } from "home-assistant-js-websocket";
import { computeStateDomain } from "./compute_state_domain";
import { UNAVAILABLE_STATES } from "../../data/entity";
import { UNAVAILABLE_STATES } from "../../data/entity/entity";
import type { HomeAssistant } from "../../types";
import { computeDomain } from "./compute_domain";
import { stringCompare } from "../string/compare";
import { computeDomain } from "./compute_domain";
import { computeStateDomain } from "./compute_state_domain";
export const FIXED_DOMAIN_STATES = {
alarm_control_panel: [
+2 -2
View File
@@ -1,7 +1,7 @@
import type { HassEntity } from "home-assistant-js-websocket";
import { computeStateDomain } from "./compute_state_domain";
import { isUnavailableState, UNAVAILABLE } from "../../data/entity";
import { isUnavailableState, UNAVAILABLE } from "../../data/entity/entity";
import type { HomeAssistant } from "../../types";
import { computeStateDomain } from "./compute_state_domain";
export const computeGroupEntitiesState = (states: HassEntity[]): string => {
if (!states.length) {
+1 -1
View File
@@ -1,5 +1,5 @@
import type { HassEntity } from "home-assistant-js-websocket";
import { isUnavailableState, OFF, UNAVAILABLE } from "../../data/entity";
import { isUnavailableState, OFF, UNAVAILABLE } from "../../data/entity/entity";
import { computeDomain } from "./compute_domain";
export function stateActive(stateObj: HassEntity, state?: string): boolean {
+1 -1
View File
@@ -1,5 +1,5 @@
import type { HassEntity } from "home-assistant-js-websocket";
import { UNAVAILABLE } from "../../data/entity";
import { UNAVAILABLE } from "../../data/entity/entity";
import type { HomeAssistant } from "../../types";
import { DOMAINS_WITH_CARD } from "../const";
import { canToggleState } from "./can_toggle_state";
+1 -1
View File
@@ -1,6 +1,6 @@
/** Return a color representing a state. */
import type { HassEntity } from "home-assistant-js-websocket";
import { UNAVAILABLE } from "../../data/entity";
import { UNAVAILABLE } from "../../data/entity/entity";
import type { GroupEntity } from "../../data/group";
import { computeGroupDomain } from "../../data/group";
import { computeCssVariable } from "../../resources/css-variables";
+53
View File
@@ -0,0 +1,53 @@
/**
* ES5-compatible implementation of the keyed directive.
* Based on lit-html's keyed directive but written to avoid ES5 minification issues.
*
* This implementation avoids parameter destructuring in the update() method,
* which causes Terser with ecma: 5 to generate invalid references like `_k`.
*
* Used only for ES5 builds (legacy browsers). Modern builds use the original
* lit-html keyed directive.
*
* @see https://github.com/home-assistant/frontend/issues/28732
*/
// eslint-disable-next-line import/extensions
import { directive, Directive } from "lit-html/directive.js";
// eslint-disable-next-line import/extensions
import { setCommittedValue } from "lit-html/directive-helpers.js";
// eslint-disable-next-line lit/no-legacy-imports
import { nothing } from "lit-html";
// eslint-disable-next-line import/extensions
import type { Part } from "lit-html/directive.js";
class KeyedES5 extends Directive {
private _key: unknown = nothing;
render(k: unknown, v: unknown) {
this._key = k;
return v;
}
update(part: unknown, args: [unknown, unknown]) {
const k = args[0];
const v = args[1];
if (k !== this._key) {
// Clear the part before returning a value. The one-arg form of
// setCommittedValue sets the value to a sentinel which forces a
// commit the next render.
setCommittedValue(part as Part);
this._key = k;
}
return v;
}
}
/**
* Associates a renderable value with a unique key. When the key changes, the
* previous DOM is removed and disposed before rendering the next value, even
* if the value - such as a template - is the same.
*
* This is useful for forcing re-renders of stateful components, or working
* with code that expects new data to generate new HTML elements, such as some
* animation techniques.
*/
export const keyed = directive(KeyedES5);
+42 -25
View File
@@ -17,32 +17,45 @@ export interface NavigateOptions {
// max time to wait for dialogs to close before navigating
const DIALOG_WAIT_TIMEOUT = 500;
export const navigate = async (
path: string,
options?: NavigateOptions,
timestamp = Date.now()
) => {
/**
* Ensures all dialogs are closed before navigation.
* Returns true if navigation can proceed, false if a dialog refused to close.
*/
const ensureDialogsClosed = async (timestamp: number): Promise<boolean> => {
const { history } = mainWindow;
if (history.state?.dialog && Date.now() - timestamp < DIALOG_WAIT_TIMEOUT) {
const closed = await closeAllDialogs();
if (!closed) {
// eslint-disable-next-line no-console
console.warn("Navigation blocked, because dialog refused to close");
return false;
}
return new Promise<boolean>((resolve) => {
// need to wait for history state to be updated in case a dialog was closed
setTimeout(() => {
navigate(path, options, timestamp).then(resolve);
});
});
if (!history.state?.dialog || Date.now() - timestamp >= DIALOG_WAIT_TIMEOUT) {
return true;
}
const closed = await closeAllDialogs();
if (!closed) {
// eslint-disable-next-line no-console
console.warn("Navigation blocked, because dialog refused to close");
return false;
}
// wait for history state to be updated after dialog closed
await new Promise<void>((resolve) => {
setTimeout(resolve);
});
return ensureDialogsClosed(timestamp);
};
export const navigate = async (path: string, options?: NavigateOptions) => {
const canProceed = await ensureDialogsClosed(Date.now());
if (!canProceed) {
return false;
}
const replace = options?.replace || false;
if (__DEMO__) {
if (replace) {
history.replaceState(
history.state?.root ? { root: true } : (options?.data ?? null),
mainWindow.history.replaceState(
mainWindow.history.state?.root
? { root: true }
: (options?.data ?? null),
"",
`${mainWindow.location.pathname}#${path}`
);
@@ -50,13 +63,13 @@ export const navigate = async (
mainWindow.location.hash = path;
}
} else if (replace) {
history.replaceState(
history.state?.root ? { root: true } : (options?.data ?? null),
mainWindow.history.replaceState(
mainWindow.history.state?.root ? { root: true } : (options?.data ?? null),
"",
path
);
} else {
history.pushState(options?.data ?? null, "", path);
mainWindow.history.pushState(options?.data ?? null, "", path);
}
fireEvent(mainWindow, "location-changed", {
replace,
@@ -68,10 +81,14 @@ export const navigate = async (
* Navigate back in history, with fallback to a default path if no history exists.
* This prevents a user from getting stuck when they navigate directly to a page with no history.
*/
export const goBack = (fallbackPath?: string) => {
const { history } = mainWindow;
export const goBack = async (fallbackPath?: string): Promise<void> => {
const canProceed = await ensureDialogsClosed(Date.now());
if (!canProceed) {
return;
}
// Check if we have history to go back to
const { history } = mainWindow;
if (history.length > 1) {
history.back();
return;
+1 -1
View File
@@ -2,7 +2,7 @@ import type {
HassEntity,
HassEntityAttributeBase,
} from "home-assistant-js-websocket";
import type { EntityRegistryDisplayEntry } from "../../data/entity_registry";
import type { EntityRegistryDisplayEntry } from "../../data/entity/entity_registry";
import type { FrontendLocaleData } from "../../data/translation";
import { NumberFormat } from "../../data/translation";
import { round } from "./round";
+2 -3
View File
@@ -45,9 +45,8 @@ export const computeFormatFunctions = async (
formatEntityAttributeName: FormatEntityAttributeNameFunc;
formatEntityName: FormatEntityNameFunc;
}> => {
const { computeStateDisplay } = await import(
"../entity/compute_state_display"
);
const { computeStateDisplay } =
await import("../entity/compute_state_display");
const { computeAttributeValueDisplay, computeAttributeNameDisplay } =
await import("../entity/compute_attribute_display");
+14
View File
@@ -0,0 +1,14 @@
import type { Route } from "../../types";
export const computeRouteTail = (route: Route) => {
const dividerPos = route.path.indexOf("/", 1);
return dividerPos === -1
? {
prefix: route.prefix + route.path,
path: "",
}
: {
prefix: route.prefix + route.path.substring(0, dividerPos),
path: route.path.substring(dividerPos),
};
};
+31 -4
View File
@@ -1,6 +1,16 @@
// From https://github.com/epoberezkin/fast-deep-equal
// MIT License - Copyright (c) 2017 Evgeny Poberezkin
export const deepEqual = (a: any, b: any): boolean => {
interface DeepEqualOptions {
/** Compare Symbol properties in addition to string keys */
compareSymbols?: boolean;
}
export const deepEqual = (
a: any,
b: any,
options?: DeepEqualOptions
): boolean => {
if (a === b) {
return true;
}
@@ -18,7 +28,7 @@ export const deepEqual = (a: any, b: any): boolean => {
return false;
}
for (i = length; i-- !== 0; ) {
if (!deepEqual(a[i], b[i])) {
if (!deepEqual(a[i], b[i], options)) {
return false;
}
}
@@ -35,7 +45,7 @@ export const deepEqual = (a: any, b: any): boolean => {
}
}
for (i of a.entries()) {
if (!deepEqual(i[1], b.get(i[0]))) {
if (!deepEqual(i[1], b.get(i[0]), options)) {
return false;
}
}
@@ -93,11 +103,28 @@ export const deepEqual = (a: any, b: any): boolean => {
for (i = length; i-- !== 0; ) {
const key = keys[i];
if (!deepEqual(a[key], b[key])) {
if (!deepEqual(a[key], b[key], options)) {
return false;
}
}
// Compare Symbol properties if requested
if (options?.compareSymbols) {
const symbolsA = Object.getOwnPropertySymbols(a);
const symbolsB = Object.getOwnPropertySymbols(b);
if (symbolsA.length !== symbolsB.length) {
return false;
}
for (const sym of symbolsA) {
if (!Object.prototype.hasOwnProperty.call(b, sym)) {
return false;
}
if (!deepEqual(a[sym], b[sym], options)) {
return false;
}
}
}
return true;
}
+19
View File
@@ -0,0 +1,19 @@
export const startMediaProgressInterval = (
interval: number | undefined,
callback: () => void,
intervalMs = 1000
): number => {
if (interval) {
return interval;
}
return window.setInterval(callback, intervalMs);
};
export const stopMediaProgressInterval = (
interval: number | undefined
): number | undefined => {
if (interval) {
clearInterval(interval);
}
return undefined;
};
+29 -14
View File
@@ -1,30 +1,45 @@
/**
* Executes a callback within a View Transition if supported, otherwise runs it directly.
* Executes a synchronous callback within a View Transition if supported, otherwise runs it directly.
*
* @param callback - Function to execute. Can be synchronous or return a Promise. The callback will be passed a boolean indicating whether the view transition is available.
* @param callback - Synchronous function to execute. The callback will be passed a boolean indicating whether the view transition is available.
* @returns Promise that resolves when the transition completes (or immediately if not supported)
*
* @example
* ```typescript
* // Synchronous callback
* withViewTransition(() => {
* this.large = !this.large;
* });
*
* // Async callback
* await withViewTransition(async () => {
* await this.updateData();
* });
* ```
*/
export const withViewTransition = (
callback: (viewTransitionAvailable: boolean) => void | Promise<void>
callback: (viewTransitionAvailable: boolean) => void
): Promise<void> => {
if (document.startViewTransition) {
return document.startViewTransition(() => callback(true)).finished;
if (!document.startViewTransition) {
callback(false);
return Promise.resolve();
}
// Fallback: Execute callback directly without transition
const result = callback(false);
return result instanceof Promise ? result : Promise.resolve();
let callbackInvoked = false;
try {
// View Transitions require DOM updates to happen synchronously within
// the callback. Execute the callback immediately (synchronously).
const transition = document.startViewTransition(() => {
callbackInvoked = true;
callback(true);
});
return transition.finished;
} catch (err) {
// eslint-disable-next-line no-console
console.warn(
"View transition failed, falling back to direct execution.",
err
);
// Make sure the callback is invoked exactly once.
if (!callbackInvoked) {
callback(false);
return Promise.resolve();
}
return Promise.reject(err);
}
};
+186
View File
@@ -0,0 +1,186 @@
import type { HaSlider } from "../../components/ha-slider";
interface VolumeSliderControllerOptions {
getSlider: () => HaSlider | undefined;
step: number;
onSetVolume: (value: number) => void;
onSetVolumeDebounced?: (value: number) => void;
onValueUpdated?: (value: number) => void;
}
export class VolumeSliderController {
private _touchStartX = 0;
private _touchStartY = 0;
private _touchStartValue = 0;
private _touchDragging = false;
private _touchScrolling = false;
private _dragging = false;
private _lastValue = 0;
private _options: VolumeSliderControllerOptions;
constructor(options: VolumeSliderControllerOptions) {
this._options = options;
}
public get isInteracting(): boolean {
return this._touchDragging || this._dragging;
}
public setStep(step: number): void {
this._options.step = step;
}
public handleInput = (ev: Event): void => {
ev.stopPropagation();
const value = Number((ev.target as HaSlider).value);
this._dragging = true;
this._updateValue(value);
this._options.onSetVolumeDebounced?.(value);
};
public handleChange = (ev: Event): void => {
ev.stopPropagation();
const value = Number((ev.target as HaSlider).value);
this._dragging = false;
this._updateValue(value);
this._options.onSetVolume(value);
};
public handleTouchStart = (ev: TouchEvent): void => {
ev.stopPropagation();
const touch = ev.touches[0];
this._touchStartX = touch.clientX;
this._touchStartY = touch.clientY;
this._touchStartValue = this._getSliderValue();
this._touchDragging = false;
this._touchScrolling = false;
this._showTooltip();
};
public handleTouchMove = (ev: TouchEvent): void => {
if (this._touchScrolling) {
return;
}
const touch = ev.touches[0];
const deltaX = touch.clientX - this._touchStartX;
const deltaY = touch.clientY - this._touchStartY;
const absDeltaX = Math.abs(deltaX);
const absDeltaY = Math.abs(deltaY);
if (!this._touchDragging) {
if (absDeltaY > 10 && absDeltaY > absDeltaX * 2) {
this._touchScrolling = true;
return;
}
if (absDeltaX > 8) {
this._touchDragging = true;
}
}
if (this._touchDragging) {
ev.preventDefault();
const newValue = this._getVolumeFromTouch(touch.clientX);
this._updateValue(newValue);
}
};
public handleTouchEnd = (ev: TouchEvent): void => {
if (this._touchScrolling) {
this._touchScrolling = false;
this._hideTooltip();
return;
}
const touch = ev.changedTouches[0];
if (!this._touchDragging) {
const tapValue = this._getVolumeFromTouch(touch.clientX);
const delta =
tapValue > this._touchStartValue
? this._options.step
: -this._options.step;
const newValue = this._roundVolumeValue(this._touchStartValue + delta);
this._updateValue(newValue);
this._options.onSetVolume(newValue);
} else {
const finalValue = this._getVolumeFromTouch(touch.clientX);
this._updateValue(finalValue);
this._options.onSetVolume(finalValue);
}
this._touchDragging = false;
this._dragging = false;
this._hideTooltip();
};
public handleTouchCancel = (): void => {
this._touchDragging = false;
this._touchScrolling = false;
this._dragging = false;
this._updateValue(this._touchStartValue);
this._hideTooltip();
};
public handleWheel = (ev: WheelEvent): void => {
ev.preventDefault();
ev.stopPropagation();
const direction = ev.deltaY > 0 ? -1 : 1;
const currentValue = this._getSliderValue();
const newValue = this._roundVolumeValue(
currentValue + direction * this._options.step
);
this._updateValue(newValue);
this._options.onSetVolume(newValue);
};
private _getVolumeFromTouch(clientX: number): number {
const slider = this._options.getSlider();
if (!slider) {
return 0;
}
const rect = slider.getBoundingClientRect();
const x = Math.min(Math.max(clientX - rect.left, 0), rect.width);
const percentage = (x / rect.width) * 100;
return this._roundVolumeValue(percentage);
}
private _roundVolumeValue(value: number): number {
return Math.min(
Math.max(Math.round(value / this._options.step) * this._options.step, 0),
100
);
}
private _getSliderValue(): number {
const slider = this._options.getSlider();
if (slider) {
return Number(slider.value);
}
return this._lastValue;
}
private _updateValue(value: number): void {
this._lastValue = value;
this._options.onValueUpdated?.(value);
const slider = this._options.getSlider();
if (slider) {
slider.value = value;
}
}
private _showTooltip(): void {
const slider = this._options.getSlider() as any;
slider?.showTooltip?.();
}
private _hideTooltip(): void {
const slider = this._options.getSlider() as any;
slider?.hideTooltip?.();
}
}
+1
View File
@@ -593,6 +593,7 @@ export class HaChartBase extends LitElement {
}
const options = {
animation: !this._reducedMotion,
animationDuration: 500,
darkMode: this._themes.darkMode ?? false,
aria: { show: true },
dataZoom: this._getDataZoomConfig(),
+27 -1
View File
@@ -2,9 +2,13 @@ import { customElement, property, state } from "lit/decorators";
import { LitElement, html, css } from "lit";
import type { EChartsType } from "echarts/core";
import type { SankeySeriesOption } from "echarts/types/dist/echarts";
import type { CallbackDataParams } from "echarts/types/src/util/types";
import type {
CallbackDataParams,
ECElementEvent,
} from "echarts/types/src/util/types";
import memoizeOne from "memoize-one";
import { ResizeController } from "@lit-labs/observers/resize-controller";
import { fireEvent } from "../../common/dom/fire_event";
import SankeyChart from "../../resources/echarts/components/sankey/install";
import type { HomeAssistant } from "../../types";
import type { ECOption } from "../../resources/echarts/echarts";
@@ -21,6 +25,7 @@ export interface Node {
label?: string;
color?: string;
passThrough?: boolean;
entityId?: string;
}
export interface Link {
source: string;
@@ -83,6 +88,7 @@ export class HaSankeyChart extends LitElement {
.options=${options}
height="100%"
.extraComponents=${[SankeyChart]}
@chart-click=${this._handleChartClick}
></ha-chart-base>`;
}
@@ -103,6 +109,22 @@ export class HaSankeyChart extends LitElement {
return null;
};
private _handleChartClick = (ev: CustomEvent<ECElementEvent>) => {
const detail = ev.detail;
// Only handle node clicks (not links)
if (detail.dataType !== "node") {
return;
}
const nodeId = (detail.data as Record<string, any>)?.id;
if (!nodeId) {
return;
}
const node = this.data.nodes.find((n) => n.id === nodeId);
if (node?.entityId) {
fireEvent(this, "node-click", { node });
}
};
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))].sort();
@@ -167,6 +189,7 @@ export class HaSankeyChart extends LitElement {
curveness: 0.5,
},
layoutIterations: 0,
animationDuration: 500,
label: {
formatter: (params) =>
data.nodes.find((node) => node.id === (params.data as Node).id)
@@ -293,4 +316,7 @@ declare global {
interface HTMLElementTagNameMap {
"ha-sankey-chart": HaSankeyChart;
}
interface HASSDomEvents {
"node-click": { node: Node };
}
}
+207
View File
@@ -0,0 +1,207 @@
import type { EChartsType } from "echarts/core";
import type { SunburstSeriesOption } from "echarts/types/dist/echarts";
import type { CallbackDataParams } from "echarts/types/src/util/types";
import { css, html, LitElement, nothing } from "lit";
import { customElement, property } from "lit/decorators";
import memoizeOne from "memoize-one";
import { getGraphColorByIndex } from "../../common/color/colors";
import { filterXSS } from "../../common/util/xss";
import type { ECOption } from "../../resources/echarts/echarts";
import type { HomeAssistant } from "../../types";
import "./ha-chart-base";
// eslint-disable-next-line @typescript-eslint/naming-convention, @typescript-eslint/consistent-type-imports
let SunburstChart: typeof import("echarts/lib/chart/sunburst/install");
export interface SunburstNode {
id: string;
name?: string;
value: number;
itemStyle?: {
color?: string;
};
children?: SunburstNode[];
}
@customElement("ha-sunburst-chart")
export class HaSunburstChart extends LitElement {
public hass!: HomeAssistant;
@property({ attribute: false }) public data?: SunburstNode;
@property({ type: String, attribute: false }) public valueFormatter?: (
value: number
) => string;
public chart?: EChartsType;
constructor() {
super();
if (!SunburstChart) {
import("echarts/lib/chart/sunburst/install").then((module) => {
SunburstChart = module;
this.requestUpdate();
});
}
}
render() {
if (!SunburstChart || !this.data) {
return nothing;
}
const options = {
tooltip: {
trigger: "item",
formatter: this._renderTooltip,
appendTo: document.body,
},
} as ECOption;
return html`<ha-chart-base
.data=${this._createData(this.data)}
.options=${options}
height="100%"
.extraComponents=${[SunburstChart]}
></ha-chart-base>`;
}
private _renderTooltip = (params: CallbackDataParams) => {
const data = params.data as { name: string; value: number };
const value = this.valueFormatter
? this.valueFormatter(data.value)
: data.value;
return `${params.marker} ${filterXSS(data.name)}<br>${value}`;
};
private _createData = memoizeOne(
(data: SunburstNode): SunburstSeriesOption => {
const computedStyles = getComputedStyle(this);
// Transform to echarts format (uses 'name' instead of 'id')
const transformNode = (
node: SunburstNode,
index: number,
depth: number,
parentColor?: string
) => {
const result = {
...node,
name: node.name || node.id,
};
if (depth > 0 && !node.itemStyle?.color) {
// Don't assign color to root node
result.itemStyle = {
color: parentColor ?? getGraphColorByIndex(index, computedStyles),
};
}
if (node.children && node.children.length > 0) {
result.children = node.children.map((child, i) =>
transformNode(child, i, depth + 1, result.itemStyle?.color)
);
}
return result;
};
const transformedData = transformNode(data, 0, 0);
return {
type: "sunburst",
data: transformedData.children || [transformedData],
radius: [0, "90%"],
sort: undefined, // Keep original order
label: {
show: false,
align: "center",
rotate: "radial",
minAngle: 15,
hideOverlap: true,
},
emphasis: {
focus: "ancestor",
label: {
show: false,
},
},
itemStyle: {
borderRadius: 2,
},
levels: this._generateLevels(this._getMaxDepth(data)),
} as SunburstSeriesOption;
}
);
private _getMaxDepth(node: SunburstNode, currentDepth = 0): number {
if (!node.children || node.children.length === 0) {
return currentDepth;
}
return Math.max(
...node.children.map((child) =>
this._getMaxDepth(child, currentDepth + 1)
)
);
}
private _generateLevels(depth: number): SunburstSeriesOption["levels"] {
const levels: SunburstSeriesOption["levels"] = [];
// Root level (center) - transparent, small fixed size
const rootRadius = 15;
const outerRadius = 95;
const availableRadius = outerRadius - rootRadius;
levels.push({
r0: "0%",
r: `${rootRadius}%`,
itemStyle: {
color: "transparent",
},
});
if (depth === 0) {
return levels;
}
// Distribute remaining radius among data levels using weighted distribution
// First level gets most space, each subsequent level gets progressively smaller
const weights = Array.from({ length: depth }, (_, i) => depth - i);
const totalWeight = weights.reduce((sum, w) => sum + w, 0);
let currentRadius = rootRadius;
for (let i = 0; i < depth; i++) {
const levelRadius = (weights[i] / totalWeight) * availableRadius;
const r0 = currentRadius;
const r = currentRadius + levelRadius;
currentRadius = r;
levels.push({
r0: `${r0}%`,
r: `${r}%`,
// Show labels only on first level
...(i === 0 ? { label: { show: true } } : {}),
});
}
return levels;
}
static styles = css`
:host {
display: block;
flex: 1;
}
ha-chart-base {
width: 100%;
height: 100%;
}
`;
}
declare global {
interface HTMLElementTagNameMap {
"ha-sunburst-chart": HaSunburstChart;
}
}
@@ -1,6 +1,6 @@
import type { PropertyValues } from "lit";
import { html, LitElement } from "lit";
import { property, state } from "lit/decorators";
import { customElement, property, state } from "lit/decorators";
import type { VisualMapComponentOption } from "echarts/components";
import type { LineSeriesOption } from "echarts/charts";
import type { YAXisOption } from "echarts/types/dist/shared";
@@ -21,12 +21,14 @@ import { measureTextWidth } from "../../util/text";
import { fireEvent } from "../../common/dom/fire_event";
import { CLIMATE_HVAC_ACTION_TO_MODE } from "../../data/climate";
import { blankBeforeUnit } from "../../common/translations/blank_before_unit";
import { filterXSS } from "../../common/util/xss";
const safeParseFloat = (value) => {
const parsed = parseFloat(value);
return isFinite(parsed) ? parsed : null;
};
@customElement("state-history-chart-line")
export class StateHistoryChartLine extends LitElement {
@property({ attribute: false }) public hass!: HomeAssistant;
@@ -183,7 +185,7 @@ export class StateHistoryChartLine extends LitElement {
}
if (param.seriesName) {
return `${param.marker} ${param.seriesName}: ${value}`;
return `${param.marker} ${filterXSS(param.seriesName)}: ${value}`;
}
return `${param.marker} ${value}`;
})
@@ -795,7 +797,6 @@ export class StateHistoryChartLine extends LitElement {
return Math.abs(value) < 1 ? value : roundingFn(value);
}
}
customElements.define("state-history-chart-line", StateHistoryChartLine);
declare global {
interface HTMLElementTagNameMap {
@@ -373,6 +373,7 @@ export class StateHistoryChartTimeline extends LitElement {
itemName: 3,
},
renderItem: this._renderItem,
progressive: 0,
});
});
+16 -12
View File
@@ -184,17 +184,11 @@ export class StatisticsChart extends LitElement {
}
private _datasetHidden(ev: CustomEvent) {
if (!this._legendData) {
return;
}
this._hiddenStats.add(ev.detail.id);
this.requestUpdate("_hiddenStats");
}
private _datasetUnhidden(ev: CustomEvent) {
if (!this._legendData) {
return;
}
this._hiddenStats.delete(ev.detail.id);
this.requestUpdate("_hiddenStats");
}
@@ -521,7 +515,9 @@ export class StatisticsChart extends LitElement {
`ui.components.statistics_charts.statistic_types.${type}`
),
symbol: "none",
sampling: "minmax",
// minmax sampling operates independently per series, breaking stacking alignment
// https://github.com/apache/echarts/issues/11879
sampling: band && drawBands ? "lttb" : "minmax",
animationDurationUpdate: 0,
lineStyle: {
width: 1.5,
@@ -539,10 +535,17 @@ export class StatisticsChart extends LitElement {
if (band && this.chartType === "line") {
series.stack = `band-${statistic_id}`;
series.stackStrategy = "all";
if (drawBands && type === bandTop) {
(series as LineSeriesOption).areaStyle = {
color: color + "3F",
};
if (this._hiddenStats.has(`${statistic_id}-${bandBottom}`)) {
// changing the stackOrder forces echarts to render the stacked series that are not hidden #28472
series.stackOrder = "seriesDesc";
(series as LineSeriesOption).areaStyle = undefined;
} else {
series.stackOrder = "seriesAsc";
if (drawBands && type === bandTop) {
(series as LineSeriesOption).areaStyle = {
color: color + "3F",
};
}
}
}
if (!this.hideLegend) {
@@ -586,7 +589,8 @@ export class StatisticsChart extends LitElement {
} else if (
type === bandTop &&
this.chartType === "line" &&
drawBands
drawBands &&
!this._hiddenStats.has(`${statistic_id}-${bandBottom}`)
) {
const top = stat[bandTop] || 0;
val.push(Math.abs(top - (stat[bandBottom] || 0)));
+3 -3
View File
@@ -3,11 +3,11 @@ import { getGraphColorByIndex } from "../../common/color/colors";
import { hex2rgb, lab2hex, rgb2lab } from "../../common/color/convert-color";
import { labBrighten } from "../../common/color/lab";
import { computeDomain } from "../../common/entity/compute_domain";
import { stateColorProperties } from "../../common/entity/state_color";
import { UNAVAILABLE, UNKNOWN } from "../../data/entity";
import { computeCssValue } from "../../resources/css-variables";
import { computeStateDomain } from "../../common/entity/compute_state_domain";
import { FIXED_DOMAIN_STATES } from "../../common/entity/get_states";
import { stateColorProperties } from "../../common/entity/state_color";
import { UNAVAILABLE, UNKNOWN } from "../../data/entity/entity";
import { computeCssValue } from "../../resources/css-variables";
const DOMAIN_STATE_SHADES: Record<string, Record<string, number>> = {
media_player: {
@@ -2,15 +2,17 @@ import type { TemplateResult } from "lit";
import { css, html, LitElement, nothing } from "lit";
import { customElement, property } from "lit/decorators";
import { repeat } from "lit/directives/repeat";
import type { LabelRegistryEntry } from "../../data/label_registry";
import { computeCssColor } from "../../common/color/compute-color";
import { fireEvent } from "../../common/dom/fire_event";
import "../ha-label";
import { stopPropagation } from "../../common/dom/stop_propagation";
import { stringCompare } from "../../common/string/compare";
import type { LabelRegistryEntry } from "../../data/label/label_registry";
import "../chips/ha-chip-set";
import "../ha-button-menu";
import "../ha-dropdown";
import "../ha-dropdown-item";
import type { HaDropdownItem } from "../ha-dropdown-item";
import "../ha-icon";
import "../ha-list-item";
import "../ha-label";
@customElement("ha-data-table-labels")
class HaDataTableLabels extends LitElement {
@@ -26,12 +28,11 @@ class HaDataTableLabels extends LitElement {
(label) => this._renderLabel(label, true)
)}
${labels.length > 2
? html`<ha-button-menu
absolute
? html`<ha-dropdown
role="button"
tabindex="0"
@click=${this._handleIconOverflowMenuOpened}
@closed=${this._handleIconOverflowMenuClosed}
@click=${stopPropagation}
@wa-select=${this._handleDropdownSelect}
>
<ha-label slot="trigger" class="plus" dense>
+${labels.length - 2}
@@ -40,12 +41,12 @@ class HaDataTableLabels extends LitElement {
labels.slice(2),
(label) => label.label_id,
(label) => html`
<ha-list-item @click=${this._labelClicked} .item=${label}>
<ha-dropdown-item .value=${label.label_id} .item=${label}>
${this._renderLabel(label, false)}
</ha-list-item>
</ha-dropdown-item>
`
)}
</ha-button-menu>`
</ha-dropdown>`
: nothing}
</ha-chip-set>
`;
@@ -81,21 +82,12 @@ class HaDataTableLabels extends LitElement {
fireEvent(this, "label-clicked", { label });
}
protected _handleIconOverflowMenuOpened(e) {
e.stopPropagation();
// If this component is used inside a data table, the z-index of the row
// needs to be increased. Otherwise the ha-button-menu would be displayed
// underneath the next row in the table.
const row = this.closest(".mdc-data-table__row") as HTMLDivElement | null;
if (row) {
row.style.zIndex = "1";
}
}
protected _handleIconOverflowMenuClosed() {
const row = this.closest(".mdc-data-table__row") as HTMLDivElement | null;
if (row) {
row.style.zIndex = "";
private _handleDropdownSelect(
ev: CustomEvent<{ item: HaDropdownItem & { item?: LabelRegistryEntry } }>
) {
const label = ev.detail?.item?.item;
if (label) {
fireEvent(this, "label-clicked", { label });
}
}
@@ -114,9 +106,6 @@ class HaDataTableLabels extends LitElement {
--ha-label-background-color: var(--color, var(--grey-color));
--ha-label-background-opacity: 0.5;
}
ha-button-menu {
border-radius: 10px;
}
.plus {
--ha-label-background-color: transparent;
border: 1px solid var(--divider-color);
+10 -4
View File
@@ -16,8 +16,10 @@ import memoizeOne from "memoize-one";
import { restoreScroll } from "../../common/decorators/restore-scroll";
import { fireEvent } from "../../common/dom/fire_event";
import { stringCompare } from "../../common/string/compare";
import type { LocalizeFunc } from "../../common/translations/localize";
import { debounce } from "../../common/util/debounce";
import { groupBy } from "../../common/util/group-by";
import { nextRender } from "../../common/util/render-status";
import { haStyleScrollbar } from "../../resources/styles";
import { loadVirtualizer } from "../../resources/virtualizer";
import type { HomeAssistant } from "../../types";
@@ -26,8 +28,6 @@ import type { HaCheckbox } from "../ha-checkbox";
import "../ha-svg-icon";
import "../search-input";
import { filterData, sortData } from "./sort-filter";
import type { LocalizeFunc } from "../../common/translations/localize";
import { nextRender } from "../../common/util/render-status";
export interface RowClickedEvent {
id: string;
@@ -838,10 +838,10 @@ export class HaDataTable extends LitElement {
} else if (this.sortDirection === "asc") {
this.sortDirection = "desc";
} else {
this.sortDirection = null;
this.sortDirection = "asc";
}
this.sortColumn = this.sortDirection === null ? undefined : columnId;
this.sortColumn = columnId;
fireEvent(this, "sorting-changed", {
column: columnId,
@@ -1364,6 +1364,9 @@ export class HaDataTable extends LitElement {
.mdc-data-table__header-cell > * {
transition: var(--float-start) 0.2s ease;
}
.mdc-data-table__header-cell--numeric > span {
transition: none;
}
.mdc-data-table__header-cell ha-svg-icon {
top: -3px;
position: absolute;
@@ -1402,6 +1405,9 @@ export class HaDataTable extends LitElement {
}
.secondary {
color: var(--secondary-text-color);
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.scroller {
height: calc(100% - 57px);

Some files were not shown because too many files have changed in this diff Show More