Compare commits

..

578 Commits

Author SHA1 Message Date
Wendelin
efece17f50 Merge branch 'dev' of github.com:home-assistant/frontend into gulp-ts 2025-07-24 08:25:06 +02:00
Abílio Costa
3e2f5b0dd3 Handle visibility changes in camera players (#26235)
* Handle visibility changes in webrtc player

* Implement visibility handling for hls

* Remove console logs
2025-07-23 19:31:39 +02:00
dependabot[bot]
aae1a3604c Bump axios from 1.10.0 to 1.11.0 (#26273)
Bumps [axios](https://github.com/axios/axios) from 1.10.0 to 1.11.0.
- [Release notes](https://github.com/axios/axios/releases)
- [Changelog](https://github.com/axios/axios/blob/v1.x/CHANGELOG.md)
- [Commits](https://github.com/axios/axios/compare/v1.10.0...v1.11.0)

---
updated-dependencies:
- dependency-name: axios
  dependency-version: 1.11.0
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-23 17:03:08 +00:00
Bram Kragten
e31b9c4264 Update translations action with dispatch 2025-07-23 14:54:35 +02:00
Marcin
90a9dbafbf Fixed icon (#26249) 2025-07-23 14:52:07 +02:00
Marcin
7041557ee2 Changed area dashboard preview icon (#26269) 2025-07-23 14:50:51 +02:00
Joost Lekkerkerker
3d6e5ef1f0 Render AI task entities with formatted time (#26265) 2025-07-23 14:49:51 +02:00
Petar Petrov
d9bf605c3f Improve ZHA routes vizualization (#26270) 2025-07-23 14:48:47 +02:00
Copilot
20dab92ad8 Sort devices and services alphabetically in integration pages (#26231)
Co-authored-by: balloob <1444314+balloob@users.noreply.github.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
2025-07-23 14:41:34 +02:00
Petar Petrov
98ed3bdd4d Add handle to axis pointer in charts on mobile (#26088)
* Add handle to axis pointer in charts on mobile

* Ignore hidden xAxis

* simplify
2025-07-23 13:13:43 +02:00
Petar Petrov
f5bc6309ae Add features to light & cover groups more-info (#26187)
* Add features to light & cover groups more-info

* 12 column tiles
2025-07-23 13:13:09 +02:00
Simon Lamon
620ebd8a61 Correct lokalise docker image (#26267)
Mistyped docker iamge
2025-07-23 13:11:57 +02:00
Norbert Rittel
ca30af5c8a Various spelling fixes in user-facing strings (#26261)
* Various spelling fixes in user-facing strings

* Fix triple apostrophes
2025-07-23 13:23:17 +03:00
Simon Lamon
9d30ce348f Bump Lokalise docker image to latest v3.1.4 (#26226)
Bump lokalise to latest version v3.1.4
2025-07-23 11:44:36 +02:00
karwosts
07c7b07362 Stabilize step flow errors (#26258) 2025-07-23 08:33:48 +03:00
karwosts
c13a80ce5e Hide hardware integrations in brand sub-menu (#26252)
* Hide hardware integrations in brand sub-menu

* Filter before sort
2025-07-22 16:16:03 +02:00
Wendelin
13868478f7 Download core logs via supervisor (#26251)
Use supervisor download dialog for core downloads
2025-07-22 14:55:11 +03:00
dependabot[bot]
77aca59dda Bump form-data from 4.0.3 to 4.0.4 (#26248)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-22 09:04:27 +02:00
renovate[bot]
b86605949b Update dependency marked to v16.1.1 (#26247)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-22 09:08:42 +03:00
renovate[bot]
cd19022e2e Update dependency eslint-config-prettier to v10.1.8 (#26246)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-22 09:08:17 +03:00
Petar Petrov
03368c1859 Improve Z-Wave firmware update dialog on device page (#26158)
Co-authored-by: Bram Kragten <mail@bramkragten.nl>
2025-07-21 13:55:31 +00:00
Petar Petrov
8e0ed288e1 Tweak the color of sum/change lines in statistics chart (#26242) 2025-07-21 10:57:18 +02:00
Petar Petrov
879e0ed3d5 Show more details in statistics legend when only 1 entity (#26241) 2025-07-21 10:57:13 +02:00
renovate[bot]
657275fd17 Update dependency marked to v16.1.0 (#26238)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-21 08:48:59 +03:00
Paul Bottein
3d1c908a01 Add support for multiple entities and hide_states option in state and attribute selectors (#26207)
* Add support for multiple entities and target for state selector

* Add support for multiple entities for attribute selector

* Improve context support

* Add combine mode and fix hidden and entity category for service control

* Don't use combine mode

* Refactor options
2025-07-21 08:48:25 +03:00
Norbert Rittel
713e8e7b71 Fix missing sentence-casing in Quickbar navigation items (#26224)
Fix missing sentence-casing in Quickbar navigation

Also replace one occurrence of "configuration" with "settings" as this is now it's menu title.
2025-07-20 10:17:48 +02:00
Petar Petrov
9e597d22a5 Handle predefined options in Z-Wave config panel (#26097)
* Handle predefined options in Z-Wave config panel

* use ha-combo-box

* lint

* display invalid status on the input

* show number and label

* compute items outside of render
2025-07-19 09:18:27 +03:00
Petar Petrov
259e8a14da Fix history for energy_storage device class (#26223) 2025-07-18 20:34:05 +02:00
renovate[bot]
4de4243b55 Update rspack monorepo to v1.4.8 (#26222)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-18 18:35:35 +02:00
Paul Bottein
a667cb627b Add reorder option to entity selector (#26217) 2025-07-18 18:08:54 +02:00
Paul Bottein
9461634670 Fix interactions translation in area card editor (#26218) 2025-07-18 16:00:02 +02:00
Petar Petrov
51b79b33fb Disable network graph emphasis on mobile (#26106) 2025-07-18 14:04:22 +02:00
renovate[bot]
539884295b Update rspack monorepo to v1.4.7 (#26216)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-18 12:40:48 +02:00
Paul Bottein
e1192403d9 Update card size icon for area strategy (#26213) 2025-07-18 10:22:37 +02:00
renovate[bot]
f5c49c83a0 Update dependency @codemirror/view to v6.38.1 (#26214)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-18 10:22:16 +02:00
Petar Petrov
faae7a2322 ZWaveJS network graph (#26112)
* ZwaveJS network visualization

* more progress

* working version

* lint

* remove unused code

* Update src/translations/en.json

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

* remove "live" toggle and use deepEqual

* styling tweak

---------

Co-authored-by: Norbert Rittel <norbert@rittel.de>
2025-07-18 10:12:28 +02:00
Petar Petrov
f6aa55ef74 Fix entities link on integration page (#26167) 2025-07-18 10:01:33 +02:00
Petar Petrov
1a0afc5079 Show more details on storage page (#26202) 2025-07-18 08:31:31 +02:00
Christoph
4a50ca4ea5 do not set "___ADD_NEW___" value in ha-area-picker (#26210) 2025-07-18 08:37:04 +03:00
Logan Rosen
6cb27ede09 Refresh store collection when adding or removing repository (#26174)
* Refresh store collection when adding new repository

* Remove store refresh from `hassio-addon-store`

* Only refresh store when adding/removing repositories
2025-07-18 08:35:41 +03:00
Petar Petrov
1b68c51a05 Add Sankey chart to the energy dashboard (#26192)
* Add Sankey chart to the energy dashboard

* hide floors & areas if there is an explicit hierarchy
2025-07-18 06:30:21 +02:00
renovate[bot]
5f2b11ca9f Update dependency typescript-eslint to v8.37.0 (#26211)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-18 06:08:59 +02:00
Tommy Goode
ec6666a4ea Add 'state' option for secondary entity info on Entities card (#26201)
* add 'state' option for secondary entity info on Entities card

* Use formatEntityState instead of computeStateDisplay
2025-07-17 14:02:09 +00:00
Paul Bottein
a10dbb64f0 Small improvements for area strategy editor (#26206) 2025-07-17 16:39:38 +03:00
Stefan Agner
aa17be0e33 Add Supervisor unhealthy reason translations (#26190)
* Add Supervisor unhealthy reason translations

This adds translations for new Supervisor unhealthy reasons, including:
- `oserror_bad_message` (https://github.com/home-assistant/supervisor/pull/4750)
- `duplicate_os_installation` (https://github.com/home-assistant/supervisor/pull/6024)

While at it, sort the keys alphabetically for consistency.
2025-07-17 10:27:36 +02:00
Norbert Rittel
a8919703ee Fix description of Picture elements card (#26203)
- change explanation from plural to singular to match first sentence
- remove the exclamation mark from the middle of the sentence and fix wrong capitalization
2025-07-17 11:01:36 +03:00
Norbert Rittel
1c66a5e437 Sentence-case "Enable state reporting" for Alexa (#26204)
Makes it consistent with identical `enable_state_reporting` string for `google`.
2025-07-17 11:00:33 +03:00
Paul Bottein
767d785d04 Increase area card default height when using camera and features (#26205) 2025-07-17 10:59:29 +03:00
Paul Bottein
0839528e22 Add option to change the area card size for area dashboard (#26199) 2025-07-17 09:07:24 +03:00
Norbert Rittel
1012245ef7 Different sentence-casing fixes in user-facing strings (#26200)
* Several casing fixes in en.json

* Include "Security Devices PIN"

* Include "Browser Media Player"
2025-07-17 09:03:00 +03:00
karwosts
0d6db8b834 Show picture-elements error messages for elements (#26196) 2025-07-17 09:01:42 +03:00
Petar Petrov
adea2efb01 Fix "Cancel exclusion" button for Z-Wave (#26188) 2025-07-16 17:29:28 +02:00
dcapslock
818914b837 Include card error message in card error (#26184)
Pass card error message to createErrorCardElement
2025-07-16 17:28:42 +02:00
Paul Bottein
b207528ecf Remove specific icons for area controls card features (#26195) 2025-07-16 17:27:05 +02:00
Norbert Rittel
039ef18d8c Fix spelling of "to log in to" (verb) and "login" (noun) (#26189)
Fix spelling of "to log in to" and "login"
2025-07-16 12:22:52 +03:00
Petar Petrov
db387834f2 Fix entity renaming when adding a new device (#26177) 2025-07-16 11:00:49 +03:00
Petar Petrov
1b7d9f9e3b Remove vis-data dependency (#26186) 2025-07-16 08:42:37 +02:00
Paulus Schoutsen
ed8c9f5ce5 AI Task automation save improvements (#26140)
* also assign category

* Extract Suggest AI button

* Add sick animation

* Show AI Task pref but disabled if not done loading

* Lint

* Update progress wording

* Define better interface

* Add My panel

* Adjust instructions to params.domain

* Mention sentence capitalization

* Update label when failure

* Keep width during suggestion
2025-07-16 08:20:37 +03:00
Norbert Rittel
c3bf1d8770 Consistently capitalize "Companion" for the mobile apps (#26180) 2025-07-15 19:27:04 +02:00
Paul Bottein
7db4693082 Don't show members for legacy groups (#26179) 2025-07-15 17:05:38 +00:00
Petar Petrov
72a12a4ba4 Fix for charts with identically named entities (#26166)
* Fix for charts with identically named entities

* lint

* type fix
2025-07-15 19:01:58 +02:00
Paul Bottein
aee9e4b0a5 Show group members in more info (#26178)
* Should group members in more info

* Fix flickering
2025-07-15 19:51:46 +03:00
Petar Petrov
55f6affc9e Fix number format in statistics charts (#26176)
fix number format in statistics charts
2025-07-15 18:40:23 +02:00
renovate[bot]
1e5f2f7215 Update dependency eslint to v9.31.0 (#26171)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-15 08:14:15 +03:00
renovate[bot]
da864d5bb7 Update dependency lit-html to v3.3.1 (#26162)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-14 12:23:55 +02:00
Paul Bottein
8d60f39cf4 Improve aria support in control elements (#26107)
* Improve aria support in control elements

* Use radiogroup for control select

* Fix switch
2025-07-14 12:56:31 +03:00
renovate[bot]
2045519814 Update dependency @lit/reactive-element to v2.1.1 (#26159)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-14 08:35:27 +00:00
renovate[bot]
3f70e88a4f Update dependency lit to v3.3.1 (#26160)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-14 11:27:40 +03:00
renovate[bot]
6ed5fbe102 Update dependency @lit-labs/observers to v2.0.6 (#26155)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-14 11:26:43 +03:00
renovate[bot]
4e72d5083d Update dependency @lit/context to v1.1.6 (#26157)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-14 11:25:55 +03:00
renovate[bot]
f9e102e537 Update dependency @lit-labs/virtualizer to v2.1.1 (#26156)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-14 11:05:03 +03:00
renovate[bot]
e54363875b Update dependency @lit-labs/motion to v1.0.9 (#26154)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-14 09:10:11 +03:00
dcapslock
1ce4e2a799 Improve performance of Helpers config page (#26153) 2025-07-14 08:42:37 +03:00
karwosts
80b86a89f0 Render energy-gas in the display unit of the sources (#26143) 2025-07-14 08:34:53 +03:00
renovate[bot]
1a316d251e Update rspack monorepo to v1.4.6 (#26148)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-13 09:00:49 +00:00
renovate[bot]
a74f90b768 Update dependency luxon to v3.7.1 (#26147)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-13 10:51:09 +02:00
renovate[bot]
fc6e457581 Update dependency @types/leaflet to v1.9.20 (#26142)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-11 23:25:08 +02:00
karwosts
ad7b8b66f2 Render energy-water in the display unit of the sources (#26141)
Render energy-water in the display unit of the source
2025-07-11 19:31:27 +03:00
renovate[bot]
0714677a8a Update dependency hls.js to v1.6.7 (#26137)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-11 12:37:28 +02:00
renovate[bot]
0a946a5c43 Update rspack monorepo to v1.4.5 (#26138)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-11 12:37:04 +02:00
renovate[bot]
4930a8d88e Update dependency typescript-eslint to v8.36.0 (#26136)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-11 12:36:55 +02:00
Petar Petrov
8b781cec8e Handle disabled ZWave provisionning entries (#26132)
* Handle disabled ZWave provisionning entries

* Update src/translations/en.json

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

---------

Co-authored-by: Simon Lamon <32477463+silamon@users.noreply.github.com>
Co-authored-by: Norbert Rittel <norbert@rittel.de>
2025-07-11 12:36:19 +02:00
Petar Petrov
065c98c5d7 "Add device" primary button on protocol integration pages (#26130) 2025-07-11 10:37:25 +03:00
karwosts
69d8eeb7db Revert changes to persistent notification in sidebar (#25984) 2025-07-10 21:33:33 +02:00
Norbert Rittel
3b7d2869e5 Fix sentence-casing of two "More Info" button labels (#26135)
Fix sentence-casing of two "More Info" buttons

- the one in the Dev tools opens the "More info" dialog for the entity, so it's changed to that dialog's name
- the one for Thread configuration opens href=${documentationUrl(this.hass, `/integrations/thread`)}
therefore it's changed to "More information"
2025-07-10 16:07:11 +00:00
renovate[bot]
bcda5cd0cf Update dependency core-js to v3.44.0 (#26134)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-10 16:02:35 +00:00
renovate[bot]
eeb64a25ff Update dependency @rsdoctor/rspack-plugin to v1.1.8 (#26133)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-10 16:01:56 +00:00
Petar Petrov
9134132ba9 Only show loading for slow flow steps to avoid flickering (#26131) 2025-07-10 17:59:07 +02:00
karwosts
1ded254e5a Fix some weather-forecast card editor issues (#26125) 2025-07-10 11:27:37 +03:00
Christoph
fc104a7992 add floor column to datatable in config devices page (#26103)
* add floor column to datatable in config devices page

* refactor conditions related to floor column in config devices page
2025-07-10 11:25:56 +03:00
karwosts
e7e062a222 Pause map autofit when user initiates pan/zoom (#26114)
* Pause map autofit when user initiates pan/zoom

* not a state

* a different approach
2025-07-09 17:32:20 +03:00
Franck Nijhof
5233086efb Add Task issue form (#26121) 2025-07-09 14:14:37 +02:00
Christoph
8d95f0d95d add unit tests for common/url/search-params.ts (#26115) 2025-07-09 14:11:28 +03:00
karwosts
5cf8b39703 Coerce all energy distribution values to the same unit (#26117) 2025-07-09 14:06:47 +03:00
Franck Nijhof
15dabe372c Adjust feature request links in issue reporting (#26123) 2025-07-09 12:40:37 +02:00
renovate[bot]
aab52a8bb2 Update dependency vis-data to v7.1.10 (#26122)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-09 10:27:49 +00:00
Norbert Rittel
aa52825b40 Capitalize "REST", remove excessive commas (#26109) 2025-07-08 12:57:30 +02:00
Christoph
2809a306e6 do not set "___ADD_NEW___" value in ha-floor-picker (#26102) 2025-07-08 12:40:24 +02:00
renovate[bot]
a6304d6284 Update rspack monorepo to v1.4.4 (#26105)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-08 08:50:51 +03:00
Paul Bottein
8e866e86d6 Use query params instead of path for media browser navigate ids (#26099) 2025-07-08 08:50:28 +03:00
Kevin Lakotko
2e8203f666 Sort groups if same as sort column (#26010)
* fix(grouping): if sorted by column sort group

* chore: use props to group for memoization
2025-07-07 19:23:27 +03:00
Paulus Schoutsen
b60f2e3201 Add extra margin AI Task pref (#26096)
Add extra margin AI Task
2025-07-07 12:11:35 +03:00
renovate[bot]
c5f57f436c Update rspack monorepo to v1.4.3 (#26093)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-07 10:17:53 +03:00
steinmn
3bb930b906 Fix flickering Edit sidebar dialog by locking content padding (#26084)
Fix flickering Edit sidebar dialog
2025-07-07 05:29:25 +00:00
Ezra Freedman
e75331e159 Weather card smallest width is not set correctly (#26082)
set result.width, not result.height
2025-07-06 10:12:59 +02:00
renovate[bot]
d6b66a7145 Update dependency @rsdoctor/rspack-plugin to v1.1.7 (#26087)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-06 08:07:11 +00:00
Yosi Levy
5c346798c8 RTL fixes for 7-25 (#26074) 2025-07-06 10:04:09 +02:00
renovate[bot]
5ffe37407a Update dependency hls.js to v1.6.6 (#26085)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-06 09:58:49 +02:00
renovate[bot]
2b056c0434 Update dependency @lokalise/node-api to v14.9.1 (#26081)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-06 09:58:06 +02:00
Paulus Schoutsen
27b36707e5 Automation save dialog to suggest name, description and labels (#26071)
* AI Task structure

* Suggest description and labels too
2025-07-06 09:57:16 +02:00
renovate[bot]
5760614b65 Update babel monorepo to v7.28.0 (#26079)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-05 12:17:24 +02:00
renovate[bot]
3835912b01 Update dependency @rsdoctor/rspack-plugin to v1.1.6 (#26078)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-05 12:14:01 +02:00
Petar Petrov
a385655c85 Remove deprecated dependency @types/glob (#26075) 2025-07-05 08:27:41 +02:00
karwosts
e177012108 Fix default range icon (#26069) 2025-07-04 23:34:38 +02:00
renovate[bot]
cc3234ad8f Update dependency eslint to v9.30.1 (#26072)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-04 22:47:44 +02:00
karwosts
4d932f0b4a Support translating number selector UoM (#26070) 2025-07-04 21:06:49 +03:00
renovate[bot]
257769cdc7 Update dependency globals to v16.3.0 (#26068)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-04 18:42:09 +02:00
renovate[bot]
6619f064eb Update dependency @lokalise/node-api to v14.9.0 (#26067)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-04 15:12:03 +02:00
renovate[bot]
382a47a082 Update rspack monorepo to v1.4.2 (#26066)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-04 15:11:40 +02:00
renovate[bot]
ad4be75fe1 Update dependency typescript-eslint to v8.35.1 (#26058)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-04 10:16:33 +03:00
Ezra Freedman
d605b67b41 Prevent uncaught TypeError on HuiWeatherForecastCard render (#26038) 2025-07-03 21:19:48 +02:00
renovate[bot]
dba6a3c756 Update fullcalendar monorepo to v6.1.18 (#26047)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-03 17:14:49 +03:00
c0ffeeca7
002e9ad071 Terminology: change controller to adapter (#26051)
* Terminology: change controller to adapter

* Update src/translations/en.json

Co-authored-by: AlCalzone <d.griesel@gmx.net>

* Apply suggestions from code review

---------

Co-authored-by: AlCalzone <d.griesel@gmx.net>
2025-07-03 15:51:35 +02:00
Paul Bottein
6e7874c2c9 Fix play media action (#26035) 2025-07-02 19:30:06 +02:00
Paul Bottein
978f9b0f83 Reduce media selector size (#26033) 2025-07-02 18:08:31 +02:00
renovate[bot]
2b88669a72 Update dependency eslint-plugin-lit-a11y to v5.1.0 (#26020)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-02 17:20:13 +02:00
renovate[bot]
252fd2bb6c Update dependency @bundle-stats/plugin-webpack-filter to v4.21.0 (#26032)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-02 17:19:41 +02:00
Paul Bottein
cc68a087a2 Fix zoom in statistic chart (#26034) 2025-07-02 17:18:39 +02:00
karwosts
3e1341a731 Fix glitchy 'show' checkboxes on integration page (#26021) 2025-07-02 13:43:06 +02:00
Bram Kragten
6be25270fd Dont fetch device actions on first updated (#26028) 2025-07-02 13:42:21 +02:00
Bram Kragten
ce929aea46 Disable fullscreen in trigger detail dialog (#26030) 2025-07-02 13:41:52 +02:00
Paul Bottein
8853bf6ea2 Improve styling of the code editor in fullscreen mode (#26029) 2025-07-02 13:41:26 +02:00
Paul Bottein
2241807745 Fix UI jump when using drag and drop in areas strategy editor (#26026) 2025-07-02 09:03:21 +00:00
Paul Bottein
50d705c943 Add missing domain icon import in area controls (#26023) 2025-07-01 21:47:20 +02:00
Paul Bottein
eb111d3c32 Add missing area helper (#26022) 2025-07-01 21:46:58 +02:00
Paul Bottein
1e59f9f4be Increase target area in tile card and area card (#26017) 2025-07-01 14:34:19 +02:00
Paul Bottein
523eb9522f Add dashboard title to strategy editor (#26015) 2025-07-01 14:33:36 +02:00
Paul Bottein
f6cb322819 Avoid selector to take to much space in action calls (#26014) 2025-07-01 14:32:54 +02:00
Paul Bottein
4f97756f4e Force narrow style for action, condition and trigger in blueprint (#26018) 2025-07-01 15:22:55 +03:00
Ezra Freedman
8644dd5271 Fix translation in the integration page for entities (#26009)
add call to localize
2025-07-01 06:48:13 +00:00
renovate[bot]
26d842f432 Update dependency @babel/helper-define-polyfill-provider to v0.6.5 (#26008)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-01 08:34:48 +02:00
renovate[bot]
ad4f14ffaf Update dependency eslint to v9.30.0 (#26012)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-01 08:31:30 +02:00
Paul Bottein
948c858e78 Fix object selector not displayed (#26007) 2025-06-30 16:15:37 +00:00
Paul Bottein
49099223d3 Do not display quality scale for custom integrations (#26006) 2025-06-30 16:10:08 +00:00
Paul Bottein
0fbd430594 Allow to re-order floors in areas dashboard (#26002)
* Allow to re-order floors in areas dashboard

* Move drag handle to right

* Improve typings

* Only show drag handle if there is at least 2 floors
2025-06-30 16:09:42 +00:00
Kevin Lakotko
8cc762d839 Fix use of numeric option for collator (#25917)
* fix(string): use numeric option for collator

* test: add natural sort comparison tests
2025-06-30 18:00:45 +02:00
Paul Bottein
89d9dd2893 Improve device row in integration page (#26005)
Improve device row in config entry page
2025-06-30 17:44:50 +02:00
renovate[bot]
b7d1ce1c37 Update rspack monorepo to v1.4.1 (#26001)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-30 17:22:39 +02:00
renovate[bot]
869d10ca3f Update CodeMirror (#26003)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-30 17:22:09 +02:00
Simon Lamon
f338089148 Pass area control service calls through hass (#25986)
Connection logging
2025-06-30 14:59:15 +02:00
renovate[bot]
06b0f9fcaf Update dependency @rsdoctor/rspack-plugin to v1.1.5 (#26000)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-30 13:49:05 +02:00
Simon Lamon
7ad07e4c55 Fix fullscreen yaml editor (transparency background) (#25989)
Fix fullscreen editor (transparency background)
2025-06-30 14:16:59 +03:00
renovate[bot]
ad65600d11 Update dependency marked to v16 (#25997)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-30 14:15:16 +03:00
renovate[bot]
e91d907e56 Update dependency prettier to v3.6.2 (#25996) 2025-06-30 08:26:28 +02:00
renovate[bot]
b35a1fc9e0 Update dependency @babel/core to v7.27.7 (#25992)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-29 20:54:40 +03:00
renovate[bot]
dd18ad96f3 Update dependency gulp-rename to v2.1.0 (#25985)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-29 17:16:40 +02:00
Norbert Rittel
62eec56e5f Fix grammar of Light, Sensor and Tile card descriptions (#25988)
* Fix grammar of Light, Sensor and Entity card descriptions

* Capitalize "Tile card" as a name

* Apply same change to Entity badge description
2025-06-29 17:16:09 +02:00
renovate[bot]
7187e25cad Update rspack monorepo to v1.4.0 (#25987)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-29 11:06:34 +02:00
Norbert Rittel
6d9e6a616d Fix sentence-casing, spelling and grammar issues (#25981)
* Fix sentence-casing, spelling and grammar issues

* Add "IP information" to the list

* More sentence-casing issues
2025-06-29 09:25:29 +02:00
renovate[bot]
44d87e3c66 Update dependency barcode-detector to v3.0.5 (#25980)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-28 17:41:15 +02:00
renovate[bot]
085e2460bc Update dependency prettier to v3.6.1 (#25978)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-28 17:40:47 +02:00
karwosts
1f8a9e4caf Improve settings page accessibility (No. 2) (#25965) 2025-06-27 19:38:11 +02:00
Franck Nijhof
f08877437e Add initial instructions file for GitHub Copilot and Claude Code (#25967) 2025-06-27 18:06:23 +02:00
renovate[bot]
6690d1ef22 Update dependency @types/leaflet to v1.9.19 (#25974)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-27 17:54:52 +02:00
Paul Bottein
9d8a5b366e Use entity format state if only one entity for that domain in the area card (#25964)
Use entity format state if only one entity is area card
2025-06-27 17:41:58 +02:00
Franck Nijhof
22c798c9d6 Add Claude to gitignore (#25966) 2025-06-27 15:59:14 +02:00
Norbert Rittel
8aabb1f32f Dev Tools: Remove excessive space from "Input date times" (#25973)
Remove excessive space from "input date times"
2025-06-27 15:57:52 +02:00
renovate[bot]
33d5cecc85 Update dependency ua-parser-js to v2.0.4 (#25968)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-27 15:12:14 +03:00
Paul Bottein
7693a4dc24 Use areas dashboard name in the top bar (#25969) 2025-06-27 10:40:15 +02:00
Paul Bottein
9ec38c7dd9 Bump vaadin to 24.7.9 (#25963) 2025-06-26 21:22:06 +00:00
Bram Kragten
e8cb85f7ff Disable fullscreen editor for editors that are already fullscreen (#25959)
* Disabled fullscreen editor for editors that are already fullscreen

* Update ha-code-editor.ts
2025-06-26 23:17:30 +02:00
renovate[bot]
ef964a2717 Update dependency typescript-eslint to v8.35.0 (#25956) 2025-06-26 19:32:39 +02:00
Paul Bottein
369881f8a6 Fix expand icon for entries and sub entries (#25955) 2025-06-26 19:21:15 +02:00
Bram Kragten
68e22d23f1 Fix filtering on device in entities config panel (#25948)
* Fix filtering on device in entities config panel

* fix

* set filters from url twice to catch race...
2025-06-26 16:42:11 +02:00
Paul Bottein
696ba69a9e Revert vaadin to 24.7.7 (#25953) 2025-06-26 14:41:58 +00:00
Paul Bottein
e2ab52e10e Don't limit combo-box dropdown size (#25952) 2025-06-26 14:12:07 +00:00
Bram Kragten
b154bc1502 Load title when fetching flow (#25951) 2025-06-26 14:07:46 +00:00
Paul Bottein
a952b880d8 Disable escape key to close edit card dialog (#25947) 2025-06-26 15:25:26 +02:00
Bram Kragten
018aceb542 Add label to version number (#25942)
Add label
2025-06-26 15:38:33 +03:00
Bram Kragten
2fb86f118e make sure header is always shown in data entry flow (#25941) 2025-06-26 11:07:08 +00:00
Bram Kragten
6c8caccfec Use different icon for services (#25939) 2025-06-26 13:05:28 +02:00
Paul Bottein
3dd3a80054 Remove alert classes and only use slot sensors for areas dashboard (#25937)
* Remove alert classes and only used slot sensors for areas dashboard

* Rename group to sensors

* Rename group to sensors
2025-06-26 13:05:05 +02:00
Bram Kragten
675310afdf add version number to integration page (#25940)
* add version number to integration page

* Update ha-config-integration-page.ts
2025-06-26 11:04:13 +00:00
Paul Bottein
f5df91d4c7 Better handle case when no floors in areas dashboard (#25933) 2025-06-26 12:18:34 +02:00
Bram Kragten
d8ab9b73ba Prevent overflow of ripple on device row on integration page (#25922) 2025-06-26 12:17:00 +02:00
renovate[bot]
89ab0b4a3d Update dependency prettier to v3.6.0 (#25930)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-26 10:18:03 +02:00
Eric Stern
dd4cb1df72 Fix logbook stream subscription (#25927) 2025-06-26 09:42:43 +02:00
Paulus Schoutsen
b81cd37776 Make the config entry row section wider on mobile (#25924) 2025-06-26 09:41:39 +02:00
Paulus Schoutsen
34112e7446 Fix wrapping of add subentry buttons (#25925) 2025-06-26 09:41:10 +02:00
Bram Kragten
2dee45b465 Update confirm disable messages (#25919) 2025-06-26 08:57:16 +03:00
Norbert Rittel
10eb0a8b87 Deduplicate weekdays in time conditions (#25915)
Replace weekdays conditions with references to common ui strings
2025-06-26 08:55:46 +03:00
Bram Kragten
551035238f Dont show internal quality scale (#25921)
dont show internal quality scale
2025-06-25 17:34:12 -04:00
Bram Kragten
eb9359e9e1 Only show own devices when there are devices... (#25920)
only show own devices when there are devices...
2025-06-25 17:31:43 -04:00
Bram Kragten
df2523a6a2 Merge branch 'rc' into dev 2025-06-25 17:25:23 +02:00
Bram Kragten
edb1e1bba7 Bumped version to 20250625.0 2025-06-25 17:24:02 +02:00
Bram Kragten
e5bc234ab3 make debug mode better visible, improve disabling device (#25910) 2025-06-25 17:23:22 +02:00
ildar170975
6006e926a7 fix hui-panel-view for a "warning_multiple_cards" (#25899) 2025-06-25 17:20:14 +02:00
Petar Petrov
93df473ad2 Translate select options in config flows (#25911) 2025-06-25 17:18:29 +02:00
Paul Bottein
af149dcfab Move exclude entities config to area card (#25909) 2025-06-25 16:18:47 +02:00
karwosts
3ab6a02994 Improve settings page accessibility (#25885) 2025-06-25 13:35:14 +00:00
Leon
e7a04eb3d2 Short-format negative and small numbers in energy-distribution-card (#25862) 2025-06-25 13:22:21 +00:00
karwosts
2dfe5f50a6 Support templates in action target (#25656) 2025-06-25 15:20:53 +02:00
Paul Bottein
174d54396f Add cover controls to area card and improve areas dashboard (#25892) 2025-06-25 13:14:41 +00:00
karwosts
5c1a8029bf Fix entity selector slicing value on load (#25854) 2025-06-25 15:11:23 +02:00
Franck Nijhof
884341656f Add full-screen button to code editors (#25903) 2025-06-25 13:07:31 +00:00
Bram Kragten
fcbc8de95a Update device row in integration page (#25907)
* Update ha-config-entry-device-row.ts

* Update src/panels/config/integrations/ha-config-entry-device-row.ts

---------

Co-authored-by: Paulus Schoutsen <balloob@gmail.com>
2025-06-25 12:16:11 +00:00
Paul Bottein
f90eb4fee0 Exclude entities in controls for areas dashboard (#25906) 2025-06-25 13:50:21 +03:00
Paulus Schoutsen
9afc4260c9 Move AI task prefs to system -> general (#25904)
Move AI task prefs
2025-06-25 08:27:09 +03:00
Franck Nijhof
3aafa47f6d Improve Entity ID auto-complete in YAML mode (#25901) 2025-06-24 16:22:31 -04:00
Paulus Schoutsen
35ba2fffda Also show sub entry services when sub entry expanded (#25900) 2025-06-24 19:46:47 +02:00
Paul Bottein
31bc708725 Improve alerts padding in area card (#25897) 2025-06-24 16:09:56 +00:00
Franck Nijhof
caa60e4e8c Fix warnings raised when migrating incomplete automation configuration (#25898) 2025-06-24 18:02:45 +02:00
Paul Bottein
edcca81acc Group area per floor in the areas strategy editor (#25895) 2025-06-24 15:28:46 +02:00
Stefan Agner
508e451f94 Add container arch to system health data (#25896) 2025-06-24 15:27:52 +02:00
Bram Kragten
bfcc36bb40 Update integration page layout (#25880) 2025-06-24 15:27:07 +02:00
Petar Petrov
976bf7c512 Update buttons in Z-Wave firmware update dialog (#25894)
Co-authored-by: Bram Kragten <mail@bramkragten.nl>
2025-06-24 15:20:30 +02:00
Petar Petrov
fb28c8971b Update Z-Wave text (#25893) 2025-06-24 14:31:26 +02:00
Paul Bottein
641a2eb77c Use area card in area strategy (#25879)
* Bring area card to area strategy

* Add device classes

* Use subview
2025-06-24 14:46:12 +03:00
Bram Kragten
47b90feffa Bumped version to 20250531.4 2025-06-24 09:58:11 +02:00
Paul Bottein
45e66d8b6e Don't send double card updated event when rendering the card (#25883) 2025-06-24 09:56:53 +02:00
Petar Petrov
73cd1e8e9d Fix duplicated requests in statistics-graph (#25878) 2025-06-24 09:56:52 +02:00
Petar Petrov
1a8ff83e2d Another fix for history chart axis rounding (#25852) 2025-06-24 09:56:51 +02:00
Petar Petrov
e6fbe0d538 Round chart limits with fit_y_data (#25851) 2025-06-24 09:56:51 +02:00
Paul Bottein
5ac6781f7d Remove debug type in secondary line in statistic picker (#25835) 2025-06-24 09:56:50 +02:00
Petar Petrov
7f7e693547 Fix bar chart data order when using the legend (#25832)
* Fix bar chart data order when using the legend

* type fix
2025-06-24 09:56:49 +02:00
Paul Bottein
51246f119c Fix disabled color in dark mode in production (#25818) 2025-06-24 09:56:48 +02:00
Anthony Relle
d764187e8c Update ElectricityMaps URL in Energy Dashboard (#25816)
fix: update electricitymap domain
2025-06-24 09:56:47 +02:00
Petar Petrov
6738b7d708 Fix sankey total calculation to account for included_in_stat (#25805) 2025-06-24 09:56:47 +02:00
Petar Petrov
77c458a0e5 Reduce reset-zoom button size on timeline charts (#25796) 2025-06-24 09:56:46 +02:00
ildar170975
876e36b4e0 hui-graph-footer-editor: add margin to ha-switch to prevent a scrollbar (#25645)
* add padding-bottom to card-config to prevent a scrollbar

* revert padding for card-config

* add margin to ha-switch

* revert margin for ha-switch

* set margin for ha-switch
2025-06-24 08:27:16 +03:00
Paul Bottein
dd64fa228c Add color options to area card (#25881)
* Add color options to area card

* Color all controls with the same color

* Clean area card
2025-06-24 08:23:58 +03:00
renovate[bot]
b3f5eb256f Update dependency eslint-plugin-import to v2.32.0 (#25890)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-24 06:25:30 +02:00
ildar170975
a5005c0840 Device page: sort related automations, scenes, scripts (#24742)
* sort related items

* use memoize for sorted _related

* fix for "_entities" & "_getEntitiesSorted"
2025-06-24 06:25:09 +02:00
Paul Bottein
c73122d7ee Don't send double card updated event when rendering the card (#25883) 2025-06-23 14:10:27 +02:00
Petar Petrov
82da36825e Fix duplicated requests in statistics-graph (#25878) 2025-06-23 11:25:46 +02:00
Petar Petrov
3e2a5bff4d Zwave delete device button on device page (#25766)
* Handle ZWaveJS device delete in frontend according to status

* finishing touches

* Fix custom value selected when clicking item in combo box (#25734)

* Assist Chat: handle intent progress delta not always being there (#25730)

handle intent progress data type change

* More support for no-grid energy dashboard (#25644)

* More support for no-grid energy dashboard

* Update src/panels/lovelace/cards/energy/hui-energy-distribution-card.ts

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

* lint

---------

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

* Z-Wave: apply sentence-style capitalization (#25739)

* Display full error for card preview mode (#25747)

* Fix edit card not working in chrome after editing (#25751)

* Change backup type order (#25759)

* Fix alerts refresh on device page (#25748)

* Fix alerts refresh on device page

* don't reset actions periodically

* reset stuff only on deviceId change

* Ensure grid options always return an object (#25760)

Assist Chat: handle intent progress delta not always being there (#25730)

handle intent progress data type change

More support for no-grid energy dashboard (#25644)

* More support for no-grid energy dashboard

* Update src/panels/lovelace/cards/energy/hui-energy-distribution-card.ts

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

* lint

---------

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

Z-Wave: apply sentence-style capitalization (#25739)

Display full error for card preview mode (#25747)

Fix edit card not working in chrome after editing (#25751)

Change backup type order (#25759)

Fix alerts refresh on device page (#25748)

* Fix alerts refresh on device page

* don't reset actions periodically

* reset stuff only on deviceId change

Ensure grid options always return an object (#25760)

* fix merge issue

* lint

* Update text and buttons

* Update src/translations/en.json

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

* update text

---------

Co-authored-by: Paul Bottein <paul.bottein@gmail.com>
Co-authored-by: Paulus Schoutsen <balloob@gmail.com>
Co-authored-by: karwosts <32912880+karwosts@users.noreply.github.com>
Co-authored-by: c0ffeeca7 <38767475+c0ffeeca7@users.noreply.github.com>
Co-authored-by: Norbert Rittel <norbert@rittel.de>
2025-06-23 11:07:19 +03:00
Paulus Schoutsen
1349d9d8e3 Hide AI Task from default dashboard (#25877) 2025-06-23 09:40:16 +02:00
Petar Petrov
f6f2cb0fce Round chart limits with fit_y_data (#25851) 2025-06-23 08:42:54 +03:00
Paulus Schoutsen
589fa75b17 Add support for accept keyword in media selector (#25808) 2025-06-22 14:02:39 -04:00
renovate[bot]
fdd6ccf379 Update dependency @rsdoctor/rspack-plugin to v1.1.4 (#25868)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-22 18:48:32 +03:00
Petar Petrov
f50d5d79a4 Another fix for history chart axis rounding (#25852) 2025-06-22 12:11:29 +02:00
iluvdata
ad589b32c9 allow previews in config_subentries_flow (#25859) 2025-06-21 08:09:13 +00:00
renovate[bot]
1990472970 Lock file maintenance (#25838)
* Lock file maintenance
2025-06-20 20:43:30 +00:00
Norbert Rittel
299713fd5e Fix inconsistently spelled occurrences of "add-on" (#25858)
* Fix inconsistently spelled occurrences of "add-on"

- add the missing hyphen on three occurrences of "addon"
- change one occurrence of "Add-on" to lowercase

* Also capitalize one inconsistent occurrence of "Ingress"
2025-06-20 22:09:09 +02:00
renovate[bot]
a13dae4745 Update vitest monorepo to v3.2.4 (#25857)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-20 18:30:39 +00:00
Paulus Schoutsen
8324c23618 Update people dashboard intro (#25856) 2025-06-20 20:30:25 +02:00
Norbert Rittel
9c8d6a939b Fix spelling of "to log in", "to set up" and more (#25855)
- add missing space to "log in" where it's the verb
- add missing space to "set up" where it's the verb
- fix sentence-casing of "Create area"
- fix spelling of "ID" as abbreviation
2025-06-20 20:20:00 +02:00
Paulus Schoutsen
1059b519af Add LLM Task to suggest automation name (#25778)
* Add AI Task to suggest automation name

* Use state and update styling
2025-06-20 12:07:47 -04:00
Paulus Schoutsen
52a02093e3 Allow changing LLM Task preferences (#25779)
* Allow changing LLM Task preferences

* value-changed
2025-06-20 12:07:29 -04:00
Paul Bottein
b608bd949b Add fields and multiple support to object selector (#25843)
* Add schema and multiple for object selector

* Add selector to gallery

* Fix description

* Improve formatting

* Add ellipsis

* Update fields instead of schema

* Update gallery

* Update format

* Fix format value

* Fix dialog size
2025-06-20 15:48:59 +02:00
Paul Bottein
f87e20cae9 Redesign area card (#25802)
* Use entity filter to get device classes in editor

* Add name and sensor states to area card

* Fix area type

* Add basic controls

* Fix editor

* Add image

* Add image type

* Add translation key for area controls

* Improve editor

* Fix unknown entity id in area

* Fix default feature position

* Add alert badge

* Add helper

* Display all alerts when using big card

* Disable covers and re-enable switches

* Filter compatible controls

* Use state icon for alerts

* Rename to display type

* Delete deprecated show camera

* Fix aspect ratio

* Improve helper

* Undo domain icon changes

* Undo domain icon changes

* Update types

* Fix translation cases

* Fix card size

* Feedback

* Don't fallback to compact

* Use plural form

* Refactor active color
2025-06-20 15:33:26 +02:00
renovate[bot]
d58186fec9 Update dependency typescript-eslint to v8.34.1 (#25848)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-20 15:01:44 +03:00
Bastian
f47336392c Fix/dhcp config network sort (#25799)
* Add ip sort method to compare helper

* Add ip sort functionality to dhcp config panel datatable

* Add type ip to DataTableColumnData

* Change ip sorting to padStart method for better readablity

* Rename ip compare method to clarify ipv4

* Enhance IP compare method to include ipv6

* Add compare IP test
2025-06-20 15:01:02 +03:00
karwosts
e9272b9a27 Remove gray colors from chart color set (#25844) 2025-06-20 13:50:12 +02:00
Norbert Rittel
b20d489bdd Fix sentence-casing of Z-Wave strings (#25846)
* Fix sentence-casing of Z-Wave strings

* Also fix casing of "Z-Wave JS Device Database"
2025-06-19 21:29:07 +02:00
Petar Petrov
f7634c45c2 Fix bar chart data order when using the legend (#25832)
* Fix bar chart data order when using the legend

* type fix
2025-06-19 17:49:58 +02:00
renovate[bot]
8ee80586a8 Update vaadinWebComponents monorepo to v24.8.0 (#25842)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-19 16:12:02 +02:00
Bram Kragten
6aa8a24aad Fix for my links ending with a slash (#25841) 2025-06-19 15:51:11 +03:00
Norbert Rittel
65e78de41c Improve explanation of 'Ping a Matter device' dialog (#25839)
* Fix explanation of 'Ping a Matter device' dialog

- change to more descriptive wording using third-person singular
- replace first "on" with "of" to clarify (currently "on" contradicts "server-side")
- remove the wrong hyphen in "IP-addresses"
2025-06-19 11:00:22 +00:00
Norbert Rittel
573c1db081 Add hyphen to all compounds with "-powered" (#25840) 2025-06-19 12:49:07 +02:00
Paul Bottein
cf03e041a8 Fix combobox helper (#25834)
* Fix combobox helper

* Pass disabled to all helpers
2025-06-18 17:57:11 +02:00
Paul Bottein
b4dbfa6f70 Remove debug type in secondary line in statistic picker (#25835) 2025-06-18 15:44:27 +00:00
Bastian
723bb4dfeb Change duration input to ha-time-input component (#25800)
* Change duration input to ha-time-input component

* Change ha-time-input to duration-input component

* Add DurationDict to ForDict cast
2025-06-18 15:31:15 +00:00
renovate[bot]
98dcce6af1 Update dependency lint-staged to v16.1.2 (#25833)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-18 17:24:40 +02:00
karwosts
e3cdd69835 Display yaml errors in all ha-yaml-editor (#25819) 2025-06-18 09:32:06 +03:00
karwosts
0ddf3aa675 Uncap width of ha-statistics-picker (#25822) 2025-06-17 21:12:50 +02:00
renovate[bot]
9c9ce78ff9 Update dependency lint-staged to v16.1.1 (#25817)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-17 20:05:09 +02:00
Paulus Schoutsen
4f8c50aaa9 Show voice ID in Cloud Pref (#25809)
* Show voice ID in Cloud Pref

* Address style comments

* Update src/panels/config/cloud/account/cloud-tts-pref.ts

---------

Co-authored-by: Bram Kragten <mail@bramkragten.nl>
2025-06-17 13:32:27 +00:00
Petar Petrov
3cfc6297b5 Fix sankey total calculation to account for included_in_stat (#25805) 2025-06-17 15:14:33 +02:00
Paul Bottein
cc0586bf36 Fix disabled color in dark mode in production (#25818) 2025-06-17 15:14:07 +02:00
Petar Petrov
bdf48140e4 Reduce reset-zoom button size on timeline charts (#25796) 2025-06-17 15:07:57 +02:00
Anthony Relle
d7f4a7acb0 Update ElectricityMaps URL in Energy Dashboard (#25816)
fix: update electricitymap domain
2025-06-17 09:54:34 +00:00
renovate[bot]
154e85eb45 Update dependency eslint-plugin-lit-a11y to v5.0.1 (#25812)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-17 10:16:13 +03:00
renovate[bot]
ea15e5a44e Update dependency eslint-plugin-lit-a11y to v5 (#25718)
* Update dependency eslint-plugin-lit-a11y to v5

* Update import

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Simon Lamon <32477463+silamon@users.noreply.github.com>
2025-06-17 09:06:44 +03:00
renovate[bot]
d581c4b0aa Update dependency eslint to v9.29.0 (#25810)
* Update dependency eslint to v9.29.0

* fix warning

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Petar Petrov <MindFreeze@users.noreply.github.com>
2025-06-17 05:55:13 +00:00
karwosts
5b7655cf72 Fix automation drag&drop loses item (#25811) 2025-06-17 08:42:20 +03:00
dependabot[bot]
634e1dbde8 Bump softprops/action-gh-release from 2.2.2 to 2.3.2 (#25795)
Bumps [softprops/action-gh-release](https://github.com/softprops/action-gh-release) from 2.2.2 to 2.3.2.
- [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/v2.2.2...v2.3.2)

---
updated-dependencies:
- dependency-name: softprops/action-gh-release
  dependency-version: 2.3.2
  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-06-16 11:03:16 +03:00
renovate[bot]
a255463a76 Update dependency sinon to v21 (#25794)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-16 08:53:23 +03:00
renovate[bot]
3c40b3112e Update dependency @codemirror/view to v6.37.2 (#25791)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-16 08:24:44 +03:00
renovate[bot]
9f33ec55f5 Update dependency glob to v11.0.3 (#25792)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-16 08:24:01 +03:00
Simon Lamon
c35c4d16f0 Remove Google Assistant link (#25780) 2025-06-15 17:17:38 +03:00
Simon Lamon
159c4d100a Add perform action with to translations (#25781) 2025-06-15 17:15:08 +03:00
quinnter
05035a281b Improved new dashboard dialog (#25676)
* tidied cards and more translations

* fix container heading padding

* updated filter to use fusejs, changes to how list is localized
2025-06-14 10:55:14 +02:00
renovate[bot]
67c7a3931f Update dependency typescript-eslint to v8.34.0 (#25770)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-13 10:18:48 +03:00
Paulus Schoutsen
cf41a43070 Hide backup during onboarding (#25768) 2025-06-12 13:48:59 -04:00
renovate[bot]
5c385d5368 Update vitest monorepo to v3.2.3 (#25765)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-12 16:25:22 +03:00
renovate[bot]
0ae78300c9 Update dependency core-js to v3.43.0 (#25761)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-12 16:24:57 +03:00
Paul Bottein
de42714505 20250531.3 (#25764) 2025-06-12 14:23:03 +02:00
Paul Bottein
359460b570 Bumped version to 20250531.3 2025-06-12 14:22:11 +02:00
Paul Bottein
38545a01dd Ensure grid options always return an object (#25760) 2025-06-12 14:21:51 +02:00
Paul Bottein
8cead75087 Change backup type order (#25759) 2025-06-12 14:21:50 +02:00
Petar Petrov
7f68447a4f Fix alerts refresh on device page (#25748)
* Fix alerts refresh on device page

* don't reset actions periodically

* reset stuff only on deviceId change
2025-06-12 14:21:49 +02:00
Paul Bottein
01d2ef13c6 Ensure grid options always return an object (#25760) 2025-06-12 10:44:20 +03:00
Petar Petrov
af6911e848 Fix alerts refresh on device page (#25748)
* Fix alerts refresh on device page

* don't reset actions periodically

* reset stuff only on deviceId change
2025-06-12 09:40:36 +02:00
Paul Bottein
21af10fd28 Change backup type order (#25759) 2025-06-12 07:29:58 +00:00
Paul Bottein
380f760f79 20250531.2 (#25752) 2025-06-11 16:27:54 +02:00
Paul Bottein
bffe38c827 Bumped version to 20250531.2 2025-06-11 16:27:06 +02:00
Paul Bottein
89d0746c7c Fix edit card not working in chrome after editing (#25751) 2025-06-11 16:25:20 +02:00
Paul Bottein
6d30d15638 Fix edit card not working in chrome after editing (#25751) 2025-06-11 14:15:50 +00:00
Paul Bottein
7e2059e836 20250531.1 (#25749) 2025-06-11 14:42:10 +02:00
Paul Bottein
0d97962578 Bumped version to 20250531.1 2025-06-11 14:30:59 +02:00
Paul Bottein
4c5015e178 Display full error for card preview mode (#25747) 2025-06-11 14:29:55 +02:00
Paul Bottein
28214aebc5 Reduce keypad gap and margin in alarm panel card (#25735) 2025-06-11 14:29:54 +02:00
Paul Bottein
a26ca7d065 Fix custom value selected when clicking item in combo box (#25734) 2025-06-11 14:29:54 +02:00
Paul Bottein
2ab20aef69 Allow to open more info using query params (#25733) 2025-06-11 14:29:53 +02:00
Petar Petrov
8149ee60cb Fix period boundaries in Energy dashboard (#25728) 2025-06-11 14:29:52 +02:00
Petar Petrov
89ce6870f6 Handle tiny values in a log chart (#25727) 2025-06-11 14:29:51 +02:00
Mathieu
4307e2350f Adjust tooltip positioning in ha-sidebar for not first lis… (#25696)
fix(tooltip): fix tooltip positioning in ha-sidebar for not first listbox
2025-06-11 14:29:50 +02:00
karwosts
7dc4d555ae Hoist integration card tooltips (#25679) 2025-06-11 14:29:50 +02:00
Bram Kragten
1483e8e38f Set answers to yes and no for cloud pipeline confirm (#25674) 2025-06-11 14:29:49 +02:00
Simon Lamon
5daec6bbc5 Calendar add event button gap alignment (#25662)
Calendar gap alignment
2025-06-11 14:29:48 +02:00
Paul Bottein
d542b52ebd Display full error for card preview mode (#25747) 2025-06-11 13:04:54 +03:00
c0ffeeca7
43cc49bb32 Z-Wave: apply sentence-style capitalization (#25739) 2025-06-11 09:13:32 +03:00
karwosts
b3f0a6328e More support for no-grid energy dashboard (#25644)
* More support for no-grid energy dashboard

* Update src/panels/lovelace/cards/energy/hui-energy-distribution-card.ts

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

* lint

---------

Co-authored-by: Petar Petrov <MindFreeze@users.noreply.github.com>
2025-06-11 09:11:46 +03:00
Paulus Schoutsen
9d6a7e7e6f Assist Chat: handle intent progress delta not always being there (#25730)
handle intent progress data type change
2025-06-10 10:59:10 -04:00
Paul Bottein
78d7da21aa Fix custom value selected when clicking item in combo box (#25734) 2025-06-10 16:46:09 +02:00
Paul Bottein
0474a24df6 Allow to open more info using query params (#25733) 2025-06-10 13:20:10 +03:00
Paul Bottein
6e7ac6fdf7 Reduce keypad gap and margin in alarm panel card (#25735) 2025-06-10 13:16:06 +03:00
Petar Petrov
7b9683df89 Fix period boundaries in Energy dashboard (#25728) 2025-06-10 10:28:51 +02:00
renovate[bot]
8523ddfd29 Update vaadinWebComponents monorepo to v24.7.8 (#25729)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-09 15:50:36 +03:00
Petar Petrov
2589e1a49f Handle tiny values in a log chart (#25727) 2025-06-09 14:45:23 +03:00
Paul Schreiber
5ce5f9a189 fix spelling of JavaScript in bug report template (#25726)
Correctly capitalize JavaScript in the bug report template.
2025-06-09 06:08:58 +00:00
renovate[bot]
6dd7217a20 Update dependency @babel/runtime to v7.27.6 (#25722)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-09 09:01:08 +03:00
renovate[bot]
0d02d0d334 Update vitest monorepo to v3.2.2 (#25723)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-09 09:00:45 +03:00
renovate[bot]
fed0dfa091 Update vitest monorepo to v3.2.1 (#25715)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-07 09:09:17 +02:00
renovate[bot]
39de40dec9 Update Yarn to v4.9.2 (#25714)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-07 09:09:11 +02:00
renovate[bot]
e1c42d9985 Update dependency typescript-eslint to v8.33.1 (#25712)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-06 20:33:20 +02:00
renovate[bot]
ad375c9b01 Update dependency hls.js to v1.6.5 (#25711)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-06 20:33:01 +02:00
renovate[bot]
07230e5ef5 Update dependency @codemirror/language to v6.11.1 (#25708)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-06 19:59:35 +02:00
renovate[bot]
52f5af6090 Update dependency @rsdoctor/rspack-plugin to v1.1.3 (#25709)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-06 19:59:08 +02:00
karwosts
3c07289077 Handle shorthand template conditions in trace (#25705) 2025-06-06 18:10:10 +02:00
Mathieu
8eb7fe8b0a Adjust tooltip positioning in ha-sidebar for not first lis… (#25696)
fix(tooltip): fix tooltip positioning in ha-sidebar for not first listbox
2025-06-05 04:35:32 +00:00
renovate[bot]
c8c2966d34 Update dependency gulp to v5.0.1 (#25698)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-05 06:25:43 +02:00
renovate[bot]
a8768a5d9d Update dependency @bundle-stats/plugin-webpack-filter to v4.20.2 (#25692)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-05 06:25:20 +02:00
karwosts
02bb7086e7 Hoist integration card tooltips (#25679) 2025-06-03 21:41:27 +02:00
renovate[bot]
42d8b2ae19 Update dependency lint-staged to v16 (#25463)
* Update dependency lint-staged to v16

* Remove shell parameter

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Simon Lamon <32477463+silamon@users.noreply.github.com>
2025-06-03 19:18:39 +00:00
renovate[bot]
e08f4a6bba Update dependency @types/chromecast-caf-receiver to v6.0.22 (#25681)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-03 17:32:25 +02:00
renovate[bot]
2e6c35d977 Update dependency hls.js to v1.6.4 (#25682)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-03 17:32:08 +02:00
renovate[bot]
17305a818b Update dependency eslint to v9.28.0 (#25683)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-03 01:32:02 +02:00
renovate[bot]
08389dad04 Update babel monorepo to v7.27.4 (#25680)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-02 22:36:58 +03:00
Bram Kragten
ab6ace46b5 Set answers to yes and no for cloud pipeline confirm (#25674) 2025-06-02 14:02:06 +00:00
renovate[bot]
535dedbbc4 Update dependency hls.js to v1.6.3 (#25669)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-02 16:01:37 +02:00
renovate[bot]
412eb0c647 Update dependency @codemirror/view to v6.37.1 (#25672)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-02 16:01:29 +02:00
renovate[bot]
87c8ebd493 Update dependency @codemirror/view to v6.37.0 (#25664)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-01 09:31:21 +02:00
Simon Lamon
6e49f89126 Calendar add event button gap alignment (#25662)
Calendar gap alignment
2025-06-01 09:39:10 +03:00
Bram Kragten
77eae6044d Bumped version to 20250531.0 2025-05-31 16:15:54 +02:00
Bram Kragten
84ac0cd41e Add css variables for start and end padding of tabs (#25654) 2025-05-31 16:15:28 +02:00
Bram Kragten
74f9c1551e Add label to collapse button in data table groups (#25653) 2025-05-31 16:15:27 +02:00
Bram Kragten
aebd6350c0 fix line height entity card (#25652) 2025-05-31 16:15:27 +02:00
ildar170975
4c78eb4797 Add cyrilic letters to slugify() (#25647)
* add cyrilic

* Update src/common/string/slugify.ts

---------

Co-authored-by: Petar Petrov <MindFreeze@users.noreply.github.com>
2025-05-31 16:15:26 +02:00
ildar170975
560e3890b9 Revert #25027 "more-info-camera: disable download_snapshot if idle" (#25643)
remove a check for "idle"
2025-05-31 16:15:25 +02:00
Ville Skyttä
e448268feb Spelling fixes (#25638) 2025-05-31 16:15:24 +02:00
Ville Skyttä
7ceba218fa Fix Zigbee capitalization in manage device button (#25637) 2025-05-31 16:15:24 +02:00
Petar Petrov
cd61725cf5 Fix Z-WaveJS device count in dashboard (#25635) 2025-05-31 16:15:23 +02:00
Petar Petrov
228860a1ee Use theme variables for network graph labels (#25634) 2025-05-31 16:15:22 +02:00
karwosts
9f69347e1d Cleanup some styling on disabled entity picker (#25632) 2025-05-31 16:15:21 +02:00
ildar170975
a099e65a9d Fix "unavailable" state in Area card (#25063)
* fix "unavailable" state

* Show "-" for unavailable/undefined
2025-05-31 10:45:58 +03:00
renovate[bot]
11e4a9f056 Update dependency typescript-eslint to v8.33.0 (#25657)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-30 17:52:29 +00:00
Bram Kragten
b617299eee Add css variables for start and end padding of tabs (#25654) 2025-05-30 16:48:15 +02:00
Bram Kragten
768f27b1b9 Add label to collapse button in data table groups (#25653) 2025-05-30 16:47:54 +02:00
Bram Kragten
5ed816df6d fix line height entity card (#25652) 2025-05-30 15:34:03 +02:00
renovate[bot]
6692ac7517 Update dependency @lokalise/node-api to v14.8.0 (#25651)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-30 14:11:04 +02:00
renovate[bot]
65499db0cb Update babel monorepo to v7.27.3 (#25650)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-30 14:27:05 +03:00
renovate[bot]
11a1eabf61 Update rspack monorepo to v1.3.12 (#25649)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-30 14:26:40 +03:00
ildar170975
b30fa122ba Revert #25027 "more-info-camera: disable download_snapshot if idle" (#25643)
remove a check for "idle"
2025-05-30 10:59:03 +03:00
ildar170975
6730d08b85 Map card: add prefix & suffix for "label_mode: attribute" (#25033)
* added prefix & suffix

* added prefix & suffix

* added prefix & suffix

* added prefix & suffix

* added prefix & suffix

* remove prefix, rename suffix -> unit

* remove prefix, rename suffix -> unit

* remove prefix, rename suffix -> unit

* remove prefix, rename suffix -> unit

* remove prefix, rename suffix -> unit
2025-05-30 10:56:35 +03:00
ildar170975
67003d6fd1 Add cyrilic letters to slugify() (#25647)
* add cyrilic

* Update src/common/string/slugify.ts

---------

Co-authored-by: Petar Petrov <MindFreeze@users.noreply.github.com>
2025-05-30 05:38:45 +00:00
Petar Petrov
414d46be65 Add device button on the Z-Wave controller's device page (#25636) 2025-05-29 15:29:34 +03:00
Petar Petrov
1485d1a1de Fix Z-WaveJS device count in dashboard (#25635) 2025-05-29 15:29:24 +03:00
Ville Skyttä
fd13e41524 Spelling fixes (#25638) 2025-05-29 10:48:50 +02:00
Petar Petrov
77f7ca0368 Use theme variables for network graph labels (#25634) 2025-05-29 10:05:26 +02:00
Ville Skyttä
7471250a07 Fix Zigbee capitalization in manage device button (#25637) 2025-05-29 07:59:58 +00:00
karwosts
8b0a63d791 Cleanup some styling on disabled entity picker (#25632) 2025-05-29 08:53:30 +03:00
renovate[bot]
57ffa814ed Update dependency @octokit/rest to v22 (#25633)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-29 08:51:54 +03:00
Bram Kragten
46e05f10d1 Bumped version to 20250528.0 2025-05-28 22:35:50 +02:00
Paul Bottein
a1819d6189 Improve search in add automation element dialog (#25626)
* Improve search in add automation element dialog

* Remove unexpected import

* Take min character search into account
2025-05-28 22:35:43 +02:00
Paul Bottein
48a3e1fd63 Put item at the top of picker result if there is an exact match with entity id (#25625) 2025-05-28 22:35:43 +02:00
Paul Bottein
139c8b3702 Fix picker field height (#25623) 2025-05-28 22:35:42 +02:00
Paul Bottein
9458946dcc Fix missing helper for entity picker (#25622) 2025-05-28 22:35:41 +02:00
Paul Bottein
b907dbefad Force narrow style for action, condition and trigger in flows (#25619) 2025-05-28 22:35:40 +02:00
Wendelin
5371fd649c Set markdown code line-height (#25618) 2025-05-28 22:35:40 +02:00
Paul Bottein
61d9b0d2a3 Improve action picker UI and search (#25525) 2025-05-28 22:35:39 +02:00
Paul Bottein
16e20456e2 Put item at the top of picker result if there is an exact match with entity id (#25625) 2025-05-28 22:33:42 +02:00
Paul Bottein
9c0ce41ebb Improve search in add automation element dialog (#25626)
* Improve search in add automation element dialog

* Remove unexpected import

* Take min character search into account
2025-05-28 19:38:33 +02:00
Wendelin
79e5c59fdf fix duplicates 2025-05-28 15:23:59 +02:00
Wendelin
0aa34a14dd Fix lint, remove unused file 2025-05-28 15:05:06 +02:00
Paul Bottein
b458a1d7c6 Improve action picker UI and search (#25525) 2025-05-28 15:03:17 +02:00
Wendelin
1ced9959fa Merge branch 'dev' of github.com:home-assistant/frontend into gulp-ts 2025-05-28 14:54:09 +02:00
Wendelin
1b67a6f358 Use tsx to run gulp 2025-05-28 14:50:25 +02:00
renovate[bot]
0eaeeb1141 Update dependency globals to v16.2.0 (#25624)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-28 14:51:35 +03:00
Paul Bottein
b7e63e697f Fix picker field height (#25623) 2025-05-28 14:07:22 +03:00
Paul Bottein
06db0f4b98 Fix missing helper for entity picker (#25622) 2025-05-28 14:06:45 +03:00
Paul Bottein
d33636c6fb Force narrow style for action, condition and trigger in flows (#25619) 2025-05-28 12:04:54 +02:00
Wendelin
bbb546159c Set markdown code line-height (#25618) 2025-05-28 10:04:54 +02:00
karwosts
e8fc36026a More error handling for preview flow (#25611)
* More error handling for preview flow

* await unsub
2025-05-28 07:04:03 +03:00
Bram Kragten
06270c771f Bumped version to 20250527.0 2025-05-27 21:43:42 +02:00
Norbert Rittel
ae49de8e71 Fix typo in restore_entity_id_selected::confirm_text (#25615) 2025-05-27 21:42:52 +02:00
Petar Petrov
6abdeeae20 Fix for history graph with tiny values (#25612) 2025-05-27 21:42:51 +02:00
Petar Petrov
116716c51d Fix duplicate legend items when comparing energy data (#25610) 2025-05-27 21:42:51 +02:00
Wendelin
77ee69b64d Fix font settings for button card (#25607) 2025-05-27 21:42:50 +02:00
Wendelin
1a57eeddde Fix sidebar loading and demo (#25606) 2025-05-27 21:42:49 +02:00
Petar Petrov
9131bf6dfd Fix double history graphs for a disabled entity (#25604) 2025-05-27 21:42:48 +02:00
Paul Bottein
1611423ca5 Fix duplicated items in strategy editor (#25600) 2025-05-27 21:42:48 +02:00
Petar Petrov
38f8c804af Fix for history graph with tiny values (#25612) 2025-05-27 20:46:03 +02:00
Petar Petrov
7c5bf26240 Fix duplicate legend items when comparing energy data (#25610) 2025-05-27 20:43:32 +02:00
Norbert Rittel
189067d14b Fix typo in restore_entity_id_selected::confirm_text (#25615) 2025-05-27 19:56:55 +02:00
Petar Petrov
e79e0f77b8 Navigate to newly added device (#25608) 2025-05-27 16:19:53 +02:00
Wendelin
b226e5c697 Fix font settings for button card (#25607) 2025-05-27 12:55:20 +02:00
Wendelin
52ad31601c Fix sidebar loading and demo (#25606) 2025-05-27 10:22:04 +02:00
Petar Petrov
cba3e4df7f Fix double history graphs for a disabled entity (#25604) 2025-05-27 09:08:58 +02:00
Paul Bottein
3532cfa974 Fix duplicated items in strategy editor (#25600) 2025-05-26 19:21:44 +02:00
Bram Kragten
de56c3376e Bumped version to 20250526.0 2025-05-26 18:32:32 +02:00
Bram Kragten
629eb29d42 Merge branch 'rc' into dev 2025-05-26 18:32:04 +02:00
Bram Kragten
61019447cf Update alarm card styling (#25598) 2025-05-26 18:31:27 +02:00
Bram Kragten
cde2b436d1 Add restore entity id (#25592) 2025-05-26 16:23:23 +00:00
Alex Gustafsson
6c7d750734 Add support for grouping media players (#24736)
Co-authored-by: Simon Lamon <32477463+silamon@users.noreply.github.com>
Co-authored-by: Bram Kragten <mail@bramkragten.nl>
2025-05-26 14:35:09 +00:00
Paul Bottein
fcf5ed7731 Use context instead of stateObj for card features (#25577)
Co-authored-by: Bram Kragten <mail@bramkragten.nl>
2025-05-26 13:59:26 +00:00
Cretezy
3ce639946c Make weather-forecast card more responsive (#24900)
Co-authored-by: Bram Kragten <mail@bramkragten.nl>
2025-05-26 13:26:32 +00:00
Wendelin
bb5f01ac81 Use failed add-ons and folders of backup (#25548)
Co-authored-by: Bram Kragten <mail@bramkragten.nl>
2025-05-26 13:25:57 +00:00
Wendelin
208e863327 Save sidebar in user data (#25555)
Co-authored-by: Petar Petrov <MindFreeze@users.noreply.github.com>
Co-authored-by: Bram Kragten <mail@bramkragten.nl>
2025-05-26 13:25:11 +00:00
karwosts
9f5f100e98 Tweak rules for entity-filter card (#25570)
Co-authored-by: Bram Kragten <mail@bramkragten.nl>
2025-05-26 13:24:10 +00:00
renovate[bot]
114c1fb98b Update vaadinWebComponents monorepo to v24.7.7 (#25596)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-26 15:20:08 +02:00
Bram Kragten
3e5bd64b83 Update ha-selector-action.ts 2025-05-26 15:14:59 +02:00
karwosts
02b4b8e334 Fix device actions in step-flow-form (#24539)
* Fix device actions in step-flow-form

* Move xlation fetch to device action

* also conditions & triggers

* move to firstUpdated
2025-05-26 14:19:09 +02:00
Petar Petrov
da8d43f5d1 Allow href="data:..." in config flow step description (#25559)
* Allow href="data:..." in config flow step description

* Update src/dialogs/config-flow/show-dialog-config-flow.ts
2025-05-26 13:56:11 +02:00
Paul Bottein
18aaa44d2d Use constant for Home Assistant bluetooth node in graph (#25595) 2025-05-26 12:26:06 +02:00
Paul Bottein
7fa697a768 Add actions section and add domains to other section in area dashboard (#25558)
* Add actions section and add domains to other section in area dashboard

* Add timer and input button

* Better grouping
2025-05-26 10:50:42 +02:00
Jan-Philipp Benecke
28fe60f02b Improve broken cards on dashboards (#25557) 2025-05-26 08:45:22 +00:00
dependabot[bot]
549451eccb Bump relative-ci/agent-action from 2.2.0 to 3.0.0 (#25593)
Bumps [relative-ci/agent-action](https://github.com/relative-ci/agent-action) from 2.2.0 to 3.0.0.
- [Release notes](https://github.com/relative-ci/agent-action/releases)
- [Commits](https://github.com/relative-ci/agent-action/compare/v2.2.0...v3.0.0)

---
updated-dependencies:
- dependency-name: relative-ci/agent-action
  dependency-version: 3.0.0
  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-05-26 08:26:06 +02:00
karwosts
113cc118cf Support for disabled selectors in config flow (#22592)
* Support for disabled selectors in config flow

* rename flag to readonly

* rename to read_only

* Merge branch 'dev' of https://github.com/home-assistant/frontend into disabled-fields-config-flow

* rework for new backend

* Fix disabled entity picker

* no longer used type

* Update src/dialogs/config-flow/step-flow-form.ts

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

---------

Co-authored-by: Petar Petrov <MindFreeze@users.noreply.github.com>
2025-05-23 20:52:42 +03:00
Bram Kragten
7ffb0f1e3b rename android-safe-area-inset to app-safe-area-inset (#25575) 2025-05-23 18:34:53 +02:00
renovate[bot]
60ef43044b Update octokit monorepo to v8.0.1 (#25576)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-23 17:37:26 +02:00
renovate[bot]
4e4a82e023 Update rspack monorepo to v1.3.11 (#25574)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-23 17:36:56 +02:00
Paulus Schoutsen
f563146165 Sort discoveries by title on integration page (#25578) 2025-05-23 17:33:47 +02:00
Petar Petrov
81ba2db93a Custom variable down sampling for line charts (#25561) 2025-05-23 15:20:41 +02:00
renovate[bot]
4d8176ad6e Update octokit monorepo to v8 (major) (#25573)
Update octokit monorepo to v8

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-23 14:13:11 +03:00
Petar Petrov
9b8be9f1af Fix chart labels for multi year periods (#25572) 2025-05-23 12:08:22 +02:00
Wendelin
c11d2c10df Enable keyboard sorting for items-display-editor (#25546)
* Enable keyboard sorting for items-display-editor

* Add alt + arrow and fix bugs

* Fix alt bug

* Improve selected drag highlight
2025-05-23 10:42:27 +02:00
Paul Bottein
412a0e9f6a Improve area floor picker UI and search (#25540)
* Improve area floor picker UI and search

* Improve area floor picker UI and search

* Remove noResultSorting
2025-05-23 10:35:47 +02:00
renovate[bot]
67dc830bbf Update dependency marked to v15.0.12 (#25571)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-23 08:52:22 +03:00
renovate[bot]
5581c10139 Update vitest monorepo to v3.1.4 (#25569)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-22 16:36:02 +00:00
renovate[bot]
ec26818c53 Update dependency @types/leaflet to v1.9.18 (#25568)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-22 18:26:19 +02:00
Paul Bottein
399458f811 Improve category picker UI and search (#25560) 2025-05-22 18:14:26 +02:00
Paul Bottein
3355986585 Restore screen readers support on pickers (#25553) 2025-05-22 09:51:12 +00:00
Franck Nijhof
9b7db191a6 Add range support to icon translations (#25541)
Co-authored-by: Bram Kragten <mail@bramkragten.nl>
2025-05-22 11:32:44 +02:00
Paulus Schoutsen
2d549ba22f Voice wizard: Wait 10s for update entity to change state (#25556) 2025-05-22 09:49:29 +02:00
Grzegorz Libiszewski
c3e155a95c Unified safe area (insets) for Android and iOS (#24689)
* feat: Introduce new css variables for safe area

* feat: Replace all safe area env with variable
2025-05-22 08:11:04 +03:00
Petar Petrov
754829a836 Localize ZHA visualization text (#25543) 2025-05-21 12:54:38 +00:00
c0ffeeca7
87bd039239 Add comma (#25547) 2025-05-21 15:44:16 +03:00
Wendelin
32b3c83337 Edit sidebar in a dialog (#25532) 2025-05-21 13:42:43 +02:00
karwosts
f0beef22d2 Add hint helpers to fields that support markdown (#25528)
* Add hint helpers to fields that support markdown

* reduce duplication
2025-05-21 08:13:28 +03:00
Petar Petrov
07e5f53469 Bluetooth network visualization (#25512)
* Bluetooth network visualization

* fix category symbol

* Add translations

* memoize bluetooth data

* throttle data updates to 10s

* handle proxies that appear as end devices too

* fix tab highlighting

* memoize fix
2025-05-21 07:59:44 +03:00
c0ffeeca7
97e0217906 Remote access strings: tiny typo fix (#25539) 2025-05-20 12:47:51 +00:00
Paul Bottein
006c7e1ea8 Improve floor picker UI and search (#25535)
* Improve floor picker UI and search

* sort by level
2025-05-20 14:45:40 +02:00
Andrej Shumkovski
9736d0cb55 Added Albanian (Shqip) Language (#25538)
Update translationMetadata.json

Added Shqip language following: 

https://developers.home-assistant.io/docs/translations/#maintainer-steps-to-add-a-new-language
2025-05-20 14:35:49 +02:00
Wendelin
9ec689382b Add has-fab to hass-tabs-subpage (#25536) 2025-05-20 14:00:27 +03:00
Paul Bottein
4de95f6710 Improve label picker UI and search (#25522) 2025-05-20 12:47:33 +02:00
Paul Bottein
a55ef8ad47 Fix entity picker in footer graph and media card (#25531) 2025-05-20 11:32:37 +02:00
Paul Bottein
01b398c2a3 Fix clear area action in area-picker (#25511)
* Fix clear area action in area-picker

* Fix area not displayed after creation
2025-05-20 10:01:01 +02:00
Paulus Schoutsen
83df10ef29 Tweaks to Assist chat dialog (#25494) 2025-05-20 08:39:56 +02:00
renovate[bot]
a026c72230 Update dependency eslint to v9.27.0 (#25529)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-20 07:44:11 +03:00
Petar Petrov
c4e391c264 Echarts network graph for ZHA (#25457)
* Echarts network graph for ZHA

* improve layout

* better diff

* remove vis-network

* not bad layout

* fix LQI and clean up a bit

* Use ha-chart-base and remove header

* legend

* use color vars

* use colorVariables

* fix

* add physics toggle

* tweak lines

* remove vis-network

* minor tweaks

* dynamically load graph chart

* type fix

* fix height

* navigate to device page on label click

* PR comments

* aria tweak

* make extraComponents non reactive

* PR comments

* quick fix

* just make hass non reactive

* button tweak

* Update src/components/chart/ha-network-graph.ts

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

---------

Co-authored-by: Wendelin <12148533+wendevlin@users.noreply.github.com>
2025-05-19 16:37:05 +03:00
karwosts
4b72a6029c Fix stack editor bugs (#25501)
* Fix stack editor bugs

* Update src/panels/lovelace/editor/config-elements/hui-stack-card-editor.ts

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

---------

Co-authored-by: Petar Petrov <MindFreeze@users.noreply.github.com>
2025-05-19 16:36:46 +03:00
Timothy
8b87188075 Add navigate command to the external bus (#25516) 2025-05-19 13:22:19 +00:00
Paul Bottein
2a4c6c9af5 Improve user picker UI and search (#25514)
Improve user picker
2025-05-19 13:53:19 +03:00
Paul Bottein
5cbadaa5f9 Fix labels in duration input (#25510) 2025-05-19 11:26:25 +02:00
Paul Bottein
15fd4134d0 Improve device picker UI and search (#25401)
* Improve device picker

* Improve device search quick bar

* Fix types

* Fix selected device in the dropdown

* Move filter to picker

* Rename filters

* Use generic picker

* Update src/dialogs/quick-bar/ha-quick-bar.ts

---------

Co-authored-by: Bram Kragten <mail@bramkragten.nl>
2025-05-19 09:24:54 +00:00
renovate[bot]
eda9abc3c5 Lock file maintenance (#25508)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-19 07:16:33 +03:00
karwosts
7e56d5f351 Fix loading behavior when manually typing card type (#25502) 2025-05-18 08:57:59 +03:00
renovate[bot]
5d4805cde6 Update dependency @codemirror/search to v6.5.11 (#25499)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-18 08:54:22 +03:00
karwosts
c94326bc08 Fix duplicate_id in energy-usage-graph (#25503) 2025-05-18 08:53:37 +03:00
karwosts
b61180baa6 Don't access hidden tabs via left/right arrow (#25495) 2025-05-17 12:43:12 +02:00
karwosts
bc15d1474e Force wrap too long expansion panel headers (#25496) 2025-05-17 12:42:08 +02:00
Bram Kragten
95c3013497 Merge branch 'rc' 2025-05-16 18:57:16 +02:00
Bram Kragten
69a156f352 Bumped version to 20250516.0 2025-05-16 18:57:02 +02:00
Paul Bottein
67f3d31a4b Fix domain not translated in entity picker and quick bar (#25444)
* Fix domain not translated in entity picker

* Remove unused param
2025-05-16 18:56:16 +02:00
Bram Kragten
98a2966432 Render choose and if action correctly on mobile (#25411) 2025-05-16 18:56:14 +02:00
karwosts
75a2c061c2 Fix card editor help links (#25408) 2025-05-16 18:56:13 +02:00
karwosts
724df18175 Fix devices graph max_devices (#25406) 2025-05-16 18:56:12 +02:00
Paul Bottein
c00b4120ab Fix selected entity in the entity picker dropdown (#25405) 2025-05-16 18:56:11 +02:00
Paul Bottein
d392bb4c83 Fallback to preferred pipeline if the pipeline doesn't exist (#25404) 2025-05-16 18:56:11 +02:00
Paul Bottein
30d46f2f8a Fix domain max-width in entity picker (#25400) 2025-05-16 18:56:10 +02:00
Paulus Schoutsen
7c879cc291 Add installation method to the about page (#25378)
Co-authored-by: Bram Kragten <mail@bramkragten.nl>
Co-authored-by: Franck Nijhof <git@frenck.dev>
2025-05-16 18:56:08 +02:00
renovate[bot]
9a731880f3 Update rspack monorepo to v1.3.10 (#25493)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-16 18:06:17 +02:00
Yosi Levy
77efaaf7de RTL base font fix (#25478)
* RTL base font fix

* Fix comments
2025-05-16 08:20:19 +03:00
Paulus Schoutsen
da96266454 Update media content type for picked TTS (#25489) 2025-05-16 08:18:31 +03:00
renovate[bot]
036d739d6e Update dependency @codemirror/view to v6.36.8 (#25487) 2025-05-15 19:56:20 +02:00
renovate[bot]
c274a94ee5 Update dependency typescript-eslint to v8.32.1 (#25488)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-15 19:53:57 +02:00
Paul Bottein
da7d359696 Use generic picker for statistic picker (#25484) 2025-05-15 19:38:36 +02:00
Paul Bottein
20a7b3870c Improve area picker UI and search (#25472)
* Improve area picker UI and search

* Feedbacks
2025-05-15 15:53:22 +02:00
Wendelin
9749a64ae1 Preload Roboto for Chrome OS (#25480) 2025-05-15 14:48:09 +02:00
renovate[bot]
68741f6ba4 Update vaadinWebComponents monorepo to v24.7.6 (#25475)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-15 14:33:08 +03:00
AlCalzone
e052ee04b4 Fix label for Thermostat Setback in Z-Wave JS installer panel (#25476) 2025-05-15 13:22:52 +02:00
Wendelin
d2cc4a624e Use ha-line-height css tokens in codebase (#25468) 2025-05-15 11:57:17 +02:00
Paul Bottein
5bcbe98f8e Create generic picker component (#25464)
* Create generic combo-box

* Fix focus

* Delete entity combo-box

* Rename components

* Create generic picker

* Fix undefined and placeholder

* Fix labels

* Fix icon and search

* Add missing hideClearIcon property to entity picker

* Make search string optional
2025-05-15 09:55:32 +00:00
Petar Petrov
beee76580d Keep screen on while adding new ZHA device (#25465) 2025-05-15 11:55:05 +02:00
karwosts
28e5a30772 Prioritize battery consumption before solar consumption (#25467) 2025-05-15 10:32:07 +03:00
Wendelin
62f2b286ae Fix scripts 2025-05-09 13:17:25 +02:00
Wendelin
8f7760f88f Implement correct types 2025-05-09 13:07:09 +02:00
Bram Kragten
7f6ce97199 Merge branch 'rc' 2025-05-09 12:11:58 +02:00
Bram Kragten
0742aed8e7 Bumped version to 20250509.0 2025-05-09 12:11:36 +02:00
Bram Kragten
f675dd3388 Fix width of device in create entry step (#25392) 2025-05-09 12:11:08 +02:00
Bram Kragten
9751cb4e50 Fix bottom padding in service control when in narrow mode (#25390) 2025-05-09 12:11:07 +02:00
Bram Kragten
7919028780 Fix sidebar keyboard navigation in edit mode (#25376) 2025-05-09 12:11:07 +02:00
Wendelin
1508c7c905 Fix backup custom retention save issue (#25368) 2025-05-09 12:11:06 +02:00
Wendelin
3fe907f388 Fix backup settings undefined cloudStatus (#25366) 2025-05-09 12:11:05 +02:00
J. Nick Koston
5cc87661b9 Add a dialog to SSDP to show raw data (#25362)
* Add a dialog to SSDP to show raw data

* tweaks

* Add a dialog to SSDP to show raw data

* reduce

* tweaks

* Update src/panels/config/integrations/integration-panels/ssdp/dialog-ssdp-raw-data.ts

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

* Update src/panels/config/integrations/integration-panels/ssdp/dialog-ssdp-discovery-info.ts

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

* Update src/panels/config/integrations/integration-panels/ssdp/dialog-ssdp-discovery-info.ts

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

* add dump

* preen

---------

Co-authored-by: Petar Petrov <MindFreeze@users.noreply.github.com>
2025-05-09 12:11:04 +02:00
Wendelin
fc372172a6 Fix ha-dialog actions padding to use safe-area-inset (#25359)
* Fix ha-dialog actions padding to use safe-area-inset

* Update src/components/ha-dialog.ts

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

---------

Co-authored-by: Petar Petrov <MindFreeze@users.noreply.github.com>
2025-05-09 12:11:03 +02:00
Simon Lamon
7bd9a39bf5 Fix bluetooth device info is encoding data twice (#25353)
Data is already encoded
2025-05-09 12:11:02 +02:00
Wendelin
ff3b65605e Use TS with gulp 2025-05-09 08:23:53 +02:00
Bram Kragten
f0341f28ab Merge branch 'rc' 2025-05-07 13:14:55 +02:00
Paul Bottein
603663e0cc Fix badge overlay in scrolling mode (#25352)
Co-authored-by: Bram Kragten <mail@bramkragten.nl>
2025-05-07 13:14:21 +02:00
Bram Kragten
80dddc9eef Only enable drag scroll controller when needed (#25351) 2025-05-07 13:14:20 +02:00
Bram Kragten
8494d0542e Bumped version to 20250507.0 2025-05-07 10:45:48 +02:00
Wendelin
467a5bef0b Fix data-table search clear button alignment (#25348) 2025-05-07 10:45:19 +02:00
Petar Petrov
24736e36ff Set <=0 chart values to null so they render as gaps on a log graph (#25347) 2025-05-07 10:45:18 +02:00
Paulus Schoutsen
604c00d772 Update network browser descriptions (#25345) 2025-05-07 10:45:17 +02:00
Bram Kragten
12bbba1bff fix height of stats graph card in section (#25344) 2025-05-07 10:45:16 +02:00
Bram Kragten
e3221ad4ee Merge branch 'rc' 2025-05-06 20:46:09 +02:00
Bram Kragten
7d3a7fa1db Bumped version to 20250506.0 2025-05-06 20:45:47 +02:00
Paul Bottein
5e67bf1fa7 Fix outlined icon button style (#25340) 2025-05-06 20:45:16 +02:00
Paul Bottein
7147c7578d Use right theme variable for dashboard tab color in edit mode (#25339) 2025-05-06 20:45:16 +02:00
Paul Bottein
90710fedf2 Simplify entity combo-box code (#25338) 2025-05-06 20:45:15 +02:00
Paul Bottein
9629159ef1 Use middle dot 00B7 as separator (#25336) 2025-05-06 20:45:14 +02:00
Paul Bottein
bfac6e1516 Add covers to overview view for area strategy (#25334) 2025-05-06 20:45:13 +02:00
Wendelin
7c288d1769 Fix sidebar item text width (#25332)
* Fix sidebar item text width to utilize full available space

* Update src/components/ha-sidebar.ts

Co-authored-by: Bram Kragten <mail@bramkragten.nl>

---------

Co-authored-by: Bram Kragten <mail@bramkragten.nl>
2025-05-06 20:45:12 +02:00
Paul Bottein
39119eeb2a Align side bar title with items (#25330) 2025-05-06 20:45:11 +02:00
Wendelin
9c16ce3342 Fix flow form padding end (#25328)
* Fix flow form padding end

* Use more end padding if docs are present
2025-05-06 20:45:10 +02:00
Paulus Schoutsen
3595fab5cb Show voice ID in TTS media browser (#25324)
* Show voice ID in TTS media browser

* Apply suggestions from code review

Co-authored-by: Paul Bottein <paul.bottein@gmail.com>

* Add copy button

* Now copy correct clipboard icon

* Improve styling

* GAP

---------

Co-authored-by: Paul Bottein <paul.bottein@gmail.com>
2025-05-06 20:45:09 +02:00
Wendelin
78b2d17f10 Add custom retention info to backup locations (#25318)
* Add retention messages to backup locations

* Fix mobile

* Use join
2025-05-06 20:45:09 +02:00
Paul Bottein
7b8b8f9d0b 20250502.1 (#25323) 2025-05-05 20:14:29 +02:00
Paul Bottein
b7f866faff Bumped version to 20250502.1 2025-05-05 20:12:59 +02:00
Paulus Schoutsen
37671fd613 Populate integration domain My link (#25322)
* Populate integration domain My link

* break out of loop

* Actually just return from function

* Consolidate code
2025-05-05 20:12:06 +02:00
Paulus Schoutsen
92905c1433 Clean up network browser nav (#25321)
* Clean up network browser nav

* Add ha-md-list
2025-05-05 20:12:05 +02:00
Paulus Schoutsen
cb7251cb5e Reorder my links (#25319) 2025-05-05 20:12:04 +02:00
Paul Bottein
44485c0de4 Do not display no areas in entity pickers (#25317) 2025-05-05 20:12:03 +02:00
Paul Bottein
1191a09576 Use new entity naming in card entity picker (#25316) 2025-05-05 20:12:03 +02:00
karwosts
c178488aac Add energy hourly calculations to CSV report (#25315) 2025-05-05 20:12:02 +02:00
Wendelin
9f6463eec0 Fix zwave add device LR/mesh icons (#25313)
Fix zwave LR/mesh icons
2025-05-05 20:12:01 +02:00
Wendelin
70fef59401 Fix options and repair flow success (#25312) 2025-05-05 20:12:00 +02:00
Wendelin
3e053e07c6 Fix selected entity overflow (#25311) 2025-05-05 20:11:59 +02:00
Wendelin
376cac6002 Fix select entity change (#25310) 2025-05-05 20:11:58 +02:00
Paul Bottein
5cd68301ed Fix pasting yaml in automation code editor (#25309)
Fix pasting yaml in code editor
2025-05-05 20:11:57 +02:00
Wendelin
3121721ac7 Revert "Use md-select for entity-row and state-card" (#25308)
Revert "Use md-select for entity-row and state-card (#25307)"

This reverts commit 3c9dce20e2.
2025-05-05 20:11:56 +02:00
Wendelin
868daf692d Use md-select for entity-row and state-card (#25307) 2025-05-05 20:11:56 +02:00
Wendelin
75e9ac9e73 Fix flow-form header (#25305) 2025-05-05 20:11:55 +02:00
Paulus Schoutsen
f6e36f2038 Add profile security link to My Home Assistant (#25303) 2025-05-05 20:11:54 +02:00
Bram Kragten
55770f3e02 Fix display of disabled items in traces (#25293) 2025-05-05 20:11:53 +02:00
Bram Kragten
cfc7f91f03 Fix select entity row opening more info on select (#25292) 2025-05-05 20:11:52 +02:00
Jan-Philipp Benecke
74488c0b96 Use new entity picker style in quick bar (#25265)
* Use new entity picker style in quick bar

* Cleanup

* Add missing no area

* Process code review
2025-05-05 20:11:51 +02:00
Bram Kragten
1154d1769d Bumped version to 20250502.0 2025-05-02 21:34:23 +03:00
Bram Kragten
a820cd4576 Fix decorators with properties (#25282)
* Fix decorators with properties

* Green build

---------

Co-authored-by: Simon Lamon <32477463+silamon@users.noreply.github.com>
2025-05-02 21:33:56 +03:00
Bram Kragten
678a8a85cb Fix alignment of ha-labeled-slider (#25279) 2025-05-02 21:33:55 +03:00
karwosts
358e450e60 Fix disabled language picker (#25278) 2025-05-02 21:33:54 +03:00
Jan-Philipp Benecke
32acef8fad Add save shortcut to shortcuts dialog (#25271) 2025-05-02 21:33:53 +03:00
J. Nick Koston
fae619085c Add my links for the Bluetooth monitors (#25270)
The plan is to link these in the Bluetooth docs for help debugging
2025-05-02 21:33:52 +03:00
Paulus Schoutsen
5d89563aa5 Import missing components on init page (#25269) 2025-05-02 21:33:52 +03:00
Bram Kragten
d7dd11ba7f Improve error handling in automation i18n (#25266) 2025-05-02 21:33:51 +03:00
Jan-Philipp Benecke
4624cc609f Always show backup location retention settings (#25261)
Always show backup location retention settings
2025-05-02 21:33:50 +03:00
karwosts
f24b6a4cb1 Fix typo in energy calculation (#25259)
* New energy calculation

* more tests and stricter tests. change priority order

* more test and fix error
2025-05-02 21:33:49 +03:00
Jan-Philipp Benecke
2b06742bb9 Hide the tab when view is a subview (#25256) 2025-05-02 21:33:48 +03:00
Jan-Philipp Benecke
9e5b7462af Add ? as shortcut for shortcuts dialog (#25253)
Bind shortcuts dialog to `?` key
2025-05-02 21:33:47 +03:00
J. Nick Koston
a544ff4c8a Improve message when no discovery data is found (#25252)
* Improve message when no discovery data is found

It was pointed out its a bit confusing when a device has not been
discovered yet for the discovery/network browser panels as we
only said there was no data. Give the user a better hint
as to why there is no data.

* Improve message when no discovery data is found

It was pointed out its a bit confusing when a device has not been
discovered yet for the discovery/network browser panels as we
only said there was no data. Give the user a better hint
as to why there is no data.

* Improve message when no discovery data is found

It was pointed out its a bit confusing when a device has not been
discovered yet for the discovery/network browser panels as we
only said there was no data. Give the user a better hint
as to why there is no data.

* Improve message when no discovery data is found

It was pointed out its a bit confusing when a device has not been
discovered yet for the discovery/network browser panels as we
only said there was no data. Give the user a better hint
as to why there is no data.
2025-05-02 21:33:46 +03:00
J. Nick Koston
b81d2013dc Fix formatting of mac address fields in device info (#25251)
Previous change lost the `:` seperator, and unexpectedly MAC became
title case instead of MAC when dhcp is loaded.
2025-05-02 21:33:45 +03:00
J. Nick Koston
9b7e2886b6 Better explain when DHCP discovery data will be available (#25250)
It was pointed out that users likely may not know what DHCP is
and wonder why the data is not available yet.
2025-05-02 21:33:44 +03:00
karwosts
69eaf178ca New energy calculation formula (#25242)
* New energy calculation

* more tests and stricter tests. change priority order
2025-05-02 21:33:44 +03:00
Yosi Levy
1a14511fa6 Various RTL fixes (#25231) 2025-05-02 21:33:43 +03:00
Paul Bottein
e517175f68 20250430.2 (#25246) 2025-04-30 17:52:11 +02:00
Paul Bottein
ee9cbf7370 Bumped version to 20250430.2 2025-04-30 17:50:44 +02:00
Bram Kragten
efd7b380a9 Handle errrors/wrong values on paste (#25245) 2025-04-30 17:49:56 +02:00
Paul Bottein
46cc254f77 Use code font family variable in combo-box (#25243) 2025-04-30 17:49:55 +02:00
Paul Bottein
d996ba818f 20250430.1 (#25244) 2025-04-30 16:10:12 +02:00
Paul Bottein
e5f41ceb3e Bumped version to 20250430.1 2025-04-30 16:08:42 +02:00
Bram Kragten
2e4ce71d06 Improve trigger condition check on paste (#25241) 2025-04-30 16:08:03 +02:00
Bram Kragten
50e39de974 Allow pasting more script config (#25240)
* Allow pasting more script config

* Update manual-script-editor.ts
2025-04-30 16:08:02 +02:00
Bram Kragten
1ba941282c Allow pasting more automation config formats (#25239) 2025-04-30 16:08:01 +02:00
J. Nick Koston
b656ddc1f0 Add DHCP Browser entry point to network (#25235)
* Add DHCP Browser entry point to network

* lint
2025-04-30 16:08:00 +02:00
Paul Bottein
a699149388 20250430.0 (#25237) 2025-04-30 13:10:20 +02:00
612 changed files with 22437 additions and 13979 deletions

View File

@@ -11,7 +11,7 @@ body:
**Please do not report issues for custom cards.**
[fr]: https://github.com/home-assistant/frontend/discussions
[fr]: https://github.com/orgs/home-assistant/discussions
[releases]: https://github.com/home-assistant/home-assistant/releases
- type: checkboxes
attributes:
@@ -108,9 +108,9 @@ body:
render: yaml
- type: textarea
attributes:
label: Javascript errors shown in your browser console/inspector
label: JavaScript errors shown in your browser console/inspector
description: >
If you come across any Javascript or other error logs, e.g., in your
If you come across any JavaScript or other error logs, e.g., in your
browser console/inspector please provide them.
render: txt
- type: textarea

View File

@@ -1,7 +1,7 @@
blank_issues_enabled: false
contact_links:
- name: Request a feature for the UI / Dashboards
url: https://github.com/home-assistant/frontend/discussions/category_choices
url: https://github.com/orgs/home-assistant/discussions
about: Request a new feature for the Home Assistant frontend.
- name: Report a bug that is NOT related to the UI / Dashboards
url: https://github.com/home-assistant/core/issues

53
.github/ISSUE_TEMPLATE/task.yml vendored Normal file
View File

@@ -0,0 +1,53 @@
name: Task
description: For staff only - Create a task
type: Task
body:
- type: markdown
attributes:
value: |
## ⚠️ RESTRICTED ACCESS
**This form is restricted to Open Home Foundation staff and authorized contributors only.**
If you are a community member wanting to contribute, please:
- For bug reports: Use the [bug report form](https://github.com/home-assistant/frontend/issues/new?template=bug_report.yml)
- For feature requests: Submit to [Feature Requests](https://github.com/orgs/home-assistant/discussions)
---
### For authorized contributors
Use this form to create tasks for development work, improvements, or other actionable items that need to be tracked.
- type: textarea
id: description
attributes:
label: Description
description: |
Provide a clear and detailed description of the task that needs to be accomplished.
Be specific about what needs to be done, why it's important, and any constraints or requirements.
placeholder: |
Describe the task, including:
- What needs to be done
- Why this task is needed
- Expected outcome
- Any constraints or requirements
validations:
required: true
- type: textarea
id: additional_context
attributes:
label: Additional context
description: |
Any additional information, links, research, or context that would be helpful.
Include links to related issues, research, prototypes, roadmap opportunities etc.
placeholder: |
- Roadmap opportunity: [link]
- Epic: [link]
- Feature request: [link]
- Technical design documents: [link]
- Prototype/mockup: [link]
- Dependencies: [links]
validations:
required: false

592
.github/copilot-instructions.md vendored Normal file
View File

@@ -0,0 +1,592 @@
# GitHub Copilot & Claude Code Instructions
You are an assistant helping with development of the Home Assistant frontend. The frontend is built using Lit-based Web Components and TypeScript, providing a responsive and performant interface for home automation control.
## Table of Contents
- [Quick Reference](#quick-reference)
- [Core Architecture](#core-architecture)
- [Development Standards](#development-standards)
- [Component Library](#component-library)
- [Common Patterns](#common-patterns)
- [Text and Copy Guidelines](#text-and-copy-guidelines)
- [Development Workflow](#development-workflow)
- [Review Guidelines](#review-guidelines)
## Quick Reference
### Essential Commands
```bash
yarn lint # ESLint + Prettier + TypeScript + Lit
yarn format # Auto-fix ESLint + Prettier
yarn lint:types # TypeScript compiler
yarn test # Vitest
script/develop # Development server
```
### Component Prefixes
- `ha-` - Home Assistant components
- `hui-` - Lovelace UI components
- `dialog-` - Dialog components
### Import Patterns
```typescript
import type { HomeAssistant } from "../types";
import { fireEvent } from "../common/dom/fire_event";
import { showAlertDialog } from "../dialogs/generic/show-alert-dialog";
```
## Core Architecture
The Home Assistant frontend is a modern web application that:
- Uses Web Components (custom elements) built with Lit framework
- Is written entirely in TypeScript with strict type checking
- Communicates with the backend via WebSocket API
- Provides comprehensive theming and internationalization
## Development Standards
### Code Quality Requirements
**Linting and Formatting (Enforced by Tools)**
- ESLint config extends Airbnb, TypeScript strict, Lit, Web Components, Accessibility
- Prettier with ES5 trailing commas enforced
- No console statements (`no-console: "error"`) - use proper logging
- Import organization: No unused imports, consistent type imports
**Naming Conventions**
- PascalCase for types and classes
- camelCase for variables, methods
- Private methods require leading underscore
- Public methods forbid leading underscore
### TypeScript Usage
- **Always use strict TypeScript**: Enable all strict flags, avoid `any` types
- **Proper type imports**: Use `import type` for type-only imports
- **Define interfaces**: Create proper interfaces for data structures
- **Type component properties**: All Lit properties must be properly typed
- **No unused variables**: Prefix with `_` if intentionally unused
- **Consistent imports**: Use `@typescript-eslint/consistent-type-imports`
```typescript
// Good
import type { HomeAssistant } from "../types";
interface EntityConfig {
entity: string;
name?: string;
}
@property({ type: Object })
hass!: HomeAssistant;
// Bad
@property()
hass: any;
```
### Web Components with Lit
- **Use Lit 3.x patterns**: Follow modern Lit practices
- **Extend appropriate base classes**: Use `LitElement`, `SubscribeMixin`, or other mixins as needed
- **Define custom element names**: Use `ha-` prefix for components
```typescript
@customElement("ha-my-component")
export class HaMyComponent extends LitElement {
@property({ attribute: false })
hass!: HomeAssistant;
@state()
private _config?: MyComponentConfig;
static get styles() {
return css`
:host {
display: block;
}
`;
}
render() {
return html`<div>Content</div>`;
}
}
```
### Component Guidelines
- **Use composition**: Prefer composition over inheritance
- **Lazy load panels**: Heavy panels should be dynamically imported
- **Optimize renders**: Use `@state()` for internal state, `@property()` for public API
- **Handle loading states**: Always show appropriate loading indicators
- **Support themes**: Use CSS custom properties from theme
### Data Management
- **Use WebSocket API**: All backend communication via home-assistant-js-websocket
- **Cache appropriately**: Use collections and caching for frequently accessed data
- **Handle errors gracefully**: All API calls should have error handling
- **Update real-time**: Subscribe to state changes for live updates
```typescript
// Good
try {
const result = await fetchEntityRegistry(this.hass.connection);
this._processResult(result);
} catch (err) {
showAlertDialog(this, {
text: `Failed to load: ${err.message}`,
});
}
```
### Styling Guidelines
- **Use CSS custom properties**: Leverage the theme system
- **Mobile-first responsive**: Design for mobile, enhance for desktop
- **Follow Material Design**: Use Material Web Components where appropriate
- **Support RTL**: Ensure all layouts work in RTL languages
```typescript
static get styles() {
return css`
:host {
--spacing: 16px;
padding: var(--spacing);
color: var(--primary-text-color);
background-color: var(--card-background-color);
}
@media (max-width: 600px) {
:host {
--spacing: 8px;
}
}
`;
}
```
### Performance Best Practices
- **Code split**: Split code at the panel/dialog level
- **Lazy load**: Use dynamic imports for heavy components
- **Optimize bundle**: Keep initial bundle size minimal
- **Use virtual scrolling**: For long lists, implement virtual scrolling
- **Memoize computations**: Cache expensive calculations
### Testing Requirements
- **Write tests**: Add tests for data processing and utilities
- **Test with Vitest**: Use the established test framework
- **Mock appropriately**: Mock WebSocket connections and API calls
- **Test accessibility**: Ensure components are accessible
## Component Library
### Dialog Components
**Available Dialog Types:**
- `ha-md-dialog` - Preferred for new code (Material Design 3)
- `ha-dialog` - Legacy component still widely used
**Opening Dialogs (Fire Event Pattern - Recommended):**
```typescript
fireEvent(this, "show-dialog", {
dialogTag: "dialog-example",
dialogImport: () => import("./dialog-example"),
dialogParams: { title: "Example", data: someData },
});
```
**Dialog Implementation Requirements:**
- Implement `HassDialog<T>` interface
- Use `createCloseHeading()` for standard headers
- Import `haStyleDialog` for consistent styling
- Return `nothing` when no params (loading state)
- Fire `dialog-closed` event when closing
- Add `dialogInitialFocus` for accessibility
````
### Form Component (ha-form)
- Schema-driven using `HaFormSchema[]`
- Supports entity, device, area, target, number, boolean, time, action, text, object, select, icon, media, location selectors
- Built-in validation with error display
- Use `dialogInitialFocus` in dialogs
- Use `computeLabel`, `computeError`, `computeHelper` for translations
```typescript
<ha-form
.hass=${this.hass}
.data=${this._data}
.schema=${this._schema}
.error=${this._errors}
.computeLabel=${(schema) => this.hass.localize(`ui.panel.${schema.name}`)}
@value-changed=${this._valueChanged}
></ha-form>
````
### Alert Component (ha-alert)
- Types: `error`, `warning`, `info`, `success`
- Properties: `title`, `alert-type`, `dismissable`, `icon`, `action`, `rtl`
- Content announced by screen readers when dynamically displayed
```html
<ha-alert alert-type="error">Error message</ha-alert>
<ha-alert alert-type="warning" title="Warning">Description</ha-alert>
<ha-alert alert-type="success" dismissable>Success message</ha-alert>
```
## Common Patterns
### Creating a Panel
```typescript
@customElement("ha-panel-myfeature")
export class HaPanelMyFeature extends SubscribeMixin(LitElement) {
@property({ attribute: false })
hass!: HomeAssistant;
@property({ type: Boolean, reflect: true })
narrow!: boolean;
@property()
route!: Route;
hassSubscribe() {
return [
subscribeEntityRegistry(this.hass.connection, (entities) => {
this._entities = entities;
}),
];
}
}
```
### Creating a Dialog
```typescript
@customElement("dialog-my-feature")
export class DialogMyFeature
extends LitElement
implements HassDialog<MyDialogParams>
{
@property({ attribute: false })
hass!: HomeAssistant;
@state()
private _params?: MyDialogParams;
public async showDialog(params: MyDialogParams): Promise<void> {
this._params = params;
}
public closeDialog(): void {
this._params = undefined;
fireEvent(this, "dialog-closed", { dialog: this.localName });
}
protected render() {
if (!this._params) {
return nothing;
}
return html`
<ha-dialog
open
@closed=${this.closeDialog}
.heading=${createCloseHeading(this.hass, this._params.title)}
>
<!-- Dialog content -->
<ha-button @click=${this.closeDialog} slot="secondaryAction">
${this.hass.localize("ui.common.cancel")}
</ha-button>
<ha-button @click=${this._submit} slot="primaryAction">
${this.hass.localize("ui.common.save")}
</ha-button>
</ha-dialog>
`;
}
static styles = [haStyleDialog, css``];
}
```
### Dialog Design Guidelines
- Max width: 560px (Alert/confirmation: 320px fixed width)
- Close X-icon on top left (all screen sizes)
- Submit button grouped with cancel at bottom right
- Keep button labels short: "Save", "Delete", "Enable"
- Destructive actions use red warning button
- Always use a title (best practice)
- Strive for minimalism
#### Creating a Lovelace Card
**Purpose**: Cards allow users to tell different stories about their house (based on gallery)
```typescript
@customElement("hui-my-card")
export class HuiMyCard extends LitElement implements LovelaceCard {
@property({ attribute: false })
hass!: HomeAssistant;
@state()
private _config?: MyCardConfig;
public setConfig(config: MyCardConfig): void {
if (!config.entity) {
throw new Error("Entity required");
}
this._config = config;
}
public getCardSize(): number {
return 3; // Height in grid units
}
// Optional: Editor for card configuration
public static getConfigElement(): LovelaceCardEditor {
return document.createElement("hui-my-card-editor");
}
// Optional: Stub config for card picker
public static getStubConfig(): object {
return { entity: "" };
}
}
```
**Card Guidelines:**
- Cards are highly customizable for different households
- Implement `LovelaceCard` interface with `setConfig()` and `getCardSize()`
- Use proper error handling in `setConfig()`
- Consider all possible states (loading, error, unavailable)
- Support different entity types and states
- Follow responsive design principles
- Add configuration editor when needed
### Internationalization
- **Use localize**: Always use the localization system
- **Add translation keys**: Add keys to src/translations/en.json
- **Support placeholders**: Use proper placeholder syntax
```typescript
this.hass.localize("ui.panel.config.updates.update_available", {
count: 5,
});
```
### Accessibility
- **ARIA labels**: Add appropriate ARIA labels
- **Keyboard navigation**: Ensure all interactions work with keyboard
- **Screen reader support**: Test with screen readers
- **Color contrast**: Meet WCAG AA standards
## Development Workflow
### Setup and Commands
1. **Setup**: `script/setup` - Install dependencies
2. **Develop**: `script/develop` - Development server
3. **Lint**: `yarn lint` - Run all linting before committing
4. **Test**: `yarn test` - Add and run tests
5. **Build**: `script/build_frontend` - Test production build
### Common Pitfalls to Avoid
- Don't use `querySelector` - Use refs or component properties
- Don't manipulate DOM directly - Let Lit handle rendering
- Don't use global styles - Scope styles to components
- Don't block the main thread - Use web workers for heavy computation
- Don't ignore TypeScript errors - Fix all type issues
### Security Best Practices
- Sanitize HTML - Never use `unsafeHTML` with user content
- Validate inputs - Always validate user inputs
- Use HTTPS - All external resources must use HTTPS
- CSP compliance - Ensure code works with Content Security Policy
### Text and Copy Guidelines
#### Terminology Standards
**Delete vs Remove** (Based on gallery/src/pages/Text/remove-delete-add-create.markdown)
- **Use "Remove"** for actions that can be restored or reapplied:
- Removing a user's permission
- Removing a user from a group
- Removing links between items
- Removing a widget from dashboard
- Removing an item from a cart
- **Use "Delete"** for permanent, non-recoverable actions:
- Deleting a field
- Deleting a value in a field
- Deleting a task
- Deleting a group
- Deleting a permission
- Deleting a calendar event
**Create vs Add** (Create pairs with Delete, Add pairs with Remove)
- **Use "Add"** for already-existing items:
- Adding a permission to a user
- Adding a user to a group
- Adding links between items
- Adding a widget to dashboard
- Adding an item to a cart
- **Use "Create"** for something made from scratch:
- Creating a new field
- Creating a new task
- Creating a new group
- Creating a new permission
- Creating a new calendar event
#### Writing Style (Consistent with Home Assistant Documentation)
- **Use American English**: Standard spelling and terminology
- **Friendly, informational tone**: Be inspiring, personal, comforting, engaging
- **Address users directly**: Use "you" and "your"
- **Be inclusive**: Objective, non-discriminatory language
- **Be concise**: Use clear, direct language
- **Be consistent**: Follow established terminology patterns
- **Use active voice**: "Delete the automation" not "The automation should be deleted"
- **Avoid jargon**: Use terms familiar to home automation users
#### Language Standards
- **Always use "Home Assistant"** in full, never "HA" or "HASS"
- **Avoid abbreviations**: Spell out terms when possible
- **Use sentence case everywhere**: Titles, headings, buttons, labels, UI elements
- ✅ "Create new automation"
- ❌ "Create New Automation"
- ✅ "Device settings"
- ❌ "Device Settings"
- **Oxford comma**: Use in lists (item 1, item 2, and item 3)
- **Replace Latin terms**: Use "like" instead of "e.g.", "for example" instead of "i.e."
- **Avoid CAPS for emphasis**: Use bold or italics instead
- **Write for all skill levels**: Both technical and non-technical users
#### Key Terminology
- **"add-on"** (hyphenated, not "addon")
- **"integration"** (preferred over "component")
- **Technical terms**: Use lowercase (automation, entity, device, service)
#### Translation Considerations
- **Add translation keys**: All user-facing text must be translatable
- **Use placeholders**: Support dynamic content in translations
- **Keep context**: Provide enough context for translators
```typescript
// Good
this.hass.localize("ui.panel.config.automation.delete_confirm", {
name: automation.alias,
});
// Bad - hardcoded text
("Are you sure you want to delete this automation?");
```
### Common Review Issues (From PR Analysis)
#### User Experience and Accessibility
- **Form validation**: Always provide proper field labels and validation feedback
- **Form accessibility**: Prevent password managers from incorrectly identifying fields
- **Loading states**: Show clear progress indicators during async operations
- **Error handling**: Display meaningful error messages when operations fail
- **Mobile responsiveness**: Ensure components work well on small screens
- **Hit targets**: Make clickable areas large enough for touch interaction
- **Visual feedback**: Provide clear indication of interactive states
#### Dialog and Modal Patterns
- **Dialog width constraints**: Respect minimum and maximum width requirements
- **Interview progress**: Show clear progress for multi-step operations
- **State persistence**: Handle dialog state properly during background operations
- **Cancel behavior**: Ensure cancel/close buttons work consistently
- **Form prefilling**: Use smart defaults but allow user override
#### Component Design Patterns
- **Terminology consistency**: Use "Join"/"Apply" instead of "Group" when appropriate
- **Visual hierarchy**: Ensure proper font sizes and spacing ratios
- **Grid alignment**: Components should align to the design grid system
- **Badge placement**: Position badges and indicators consistently
- **Color theming**: Respect theme variables and design system colors
#### Code Quality Issues
- **Null checking**: Always check if entities exist before accessing properties
- **TypeScript safety**: Handle potentially undefined array/object access
- **Import organization**: Remove unused imports and use proper type imports
- **Event handling**: Properly subscribe and unsubscribe from events
- **Memory leaks**: Clean up subscriptions and event listeners
#### Configuration and Props
- **Optional parameters**: Make configuration fields optional when sensible
- **Smart defaults**: Provide reasonable default values
- **Future extensibility**: Design APIs that can be extended later
- **Validation**: Validate configuration before applying changes
## Review Guidelines
### Core Requirements Checklist
- [ ] TypeScript strict mode passes (`yarn lint:types`)
- [ ] No ESLint errors or warnings (`yarn lint:eslint`)
- [ ] Prettier formatting applied (`yarn lint:prettier`)
- [ ] Lit analyzer passes (`yarn lint:lit`)
- [ ] Component follows Lit best practices
- [ ] Proper error handling implemented
- [ ] Loading states handled
- [ ] Mobile responsive
- [ ] Theme variables used
- [ ] Translations added
- [ ] Accessible to screen readers
- [ ] Tests added (where applicable)
- [ ] No console statements (use proper logging)
- [ ] Unused imports removed
- [ ] Proper naming conventions
### Text and Copy Checklist
- [ ] Follows terminology guidelines (Delete vs Remove, Create vs Add)
- [ ] Localization keys added for all user-facing text
- [ ] Uses "Home Assistant" (never "HA" or "HASS")
- [ ] Sentence case for ALL text (titles, headings, buttons, labels)
- [ ] American English spelling
- [ ] Friendly, informational tone
- [ ] Avoids abbreviations and jargon
- [ ] Correct terminology (add-on not addon, integration not component)
### Component-Specific Checks
- [ ] Dialogs implement HassDialog interface
- [ ] Dialog styling uses haStyleDialog
- [ ] Dialog accessibility includes dialogInitialFocus
- [ ] ha-alert used correctly for messages
- [ ] ha-form uses proper schema structure
- [ ] Components handle all states (loading, error, unavailable)
- [ ] Entity existence checked before property access
- [ ] Event subscriptions properly cleaned up

View File

@@ -35,7 +35,7 @@ jobs:
run: yarn install --immutable
- name: Build Cast
run: ./node_modules/.bin/gulp build-cast
run: yarn run-task build-cast
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
@@ -70,7 +70,7 @@ jobs:
run: yarn install --immutable
- name: Build Cast
run: ./node_modules/.bin/gulp build-cast
run: yarn run-task build-cast
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View File

@@ -35,7 +35,7 @@ jobs:
- name: Check for duplicate dependencies
run: yarn dedupe --check
- name: Build resources
run: ./node_modules/.bin/gulp gen-icons-json build-translations build-locale-data gather-gallery-pages
run: yarn run-task gen-icons-json build-translations build-locale-data gather-gallery-pages
- name: Setup lint cache
uses: actions/cache@v4.2.3
with:
@@ -67,7 +67,7 @@ jobs:
- name: Install dependencies
run: yarn install --immutable
- name: Build resources
run: ./node_modules/.bin/gulp gen-icons-json build-translations build-locale-data
run: yarn run-task gen-icons-json build-translations build-locale-data
- name: Run Tests
run: yarn run test
build:
@@ -85,7 +85,7 @@ jobs:
- name: Install dependencies
run: yarn install --immutable
- name: Build Application
run: ./node_modules/.bin/gulp build-app
run: yarn run-task build-app
env:
IS_TEST: "true"
- name: Upload bundle stats
@@ -109,7 +109,7 @@ jobs:
- name: Install dependencies
run: yarn install --immutable
- name: Build Application
run: ./node_modules/.bin/gulp build-hassio
run: yarn run-task build-hassio
env:
IS_TEST: "true"
- name: Upload bundle stats

View File

@@ -36,7 +36,7 @@ jobs:
run: yarn install --immutable
- name: Build Demo
run: ./node_modules/.bin/gulp build-demo
run: yarn run-task build-demo
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
@@ -71,7 +71,7 @@ jobs:
run: yarn install --immutable
- name: Build Demo
run: ./node_modules/.bin/gulp build-demo
run: yarn run-task build-demo
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View File

@@ -28,7 +28,7 @@ jobs:
run: yarn install --immutable
- name: Build Gallery
run: ./node_modules/.bin/gulp build-gallery
run: yarn run-task build-gallery
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View File

@@ -33,7 +33,7 @@ jobs:
run: yarn install --immutable
- name: Build Gallery
run: ./node_modules/.bin/gulp build-gallery
run: yarn run-task build-gallery
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

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@v2.2.0
uses: relative-ci/agent-action@v3.0.0
with:
key: ${{ secrets[format('RELATIVE_CI_KEY_{0}_{1}', matrix.bundle, matrix.build)] }}
token: ${{ github.token }}

View File

@@ -55,7 +55,7 @@ jobs:
script/release
- name: Upload release assets
uses: softprops/action-gh-release@v2.2.2
uses: softprops/action-gh-release@v2.3.2
with:
files: |
dist/*.whl
@@ -107,7 +107,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@v2.2.2
uses: softprops/action-gh-release@v2.3.2
with:
files: landing-page/home_assistant_frontend_landingpage-${{ github.event.release.tag_name }}.tar.gz
@@ -136,6 +136,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@v2.2.2
uses: softprops/action-gh-release@v2.3.2
with:
files: hassio/home_assistant_frontend_supervisor-${{ github.event.release.tag_name }}.tar.gz

View File

@@ -0,0 +1,58 @@
name: Restrict task creation
# yamllint disable-line rule:truthy
on:
issues:
types: [opened]
jobs:
check-authorization:
runs-on: ubuntu-latest
# Only run if this is a Task issue type (from the issue form)
if: github.event.issue.issue_type == 'Task'
steps:
- name: Check if user is authorized
uses: actions/github-script@v7
with:
script: |
const issueAuthor = context.payload.issue.user.login;
// Check if user is an organization member
try {
await github.rest.orgs.checkMembershipForUser({
org: 'home-assistant',
username: issueAuthor
});
console.log(`✅ ${issueAuthor} is an organization member`);
return; // Authorized
} catch (error) {
console.log(`❌ ${issueAuthor} is not authorized to create Task issues`);
}
// Close the issue with a comment
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
body: `Hi @${issueAuthor}, thank you for your contribution!\n\n` +
`Task issues are restricted to Open Home Foundation staff and authorized contributors.\n\n` +
`If you would like to:\n` +
`- Report a bug: Please use the [bug report form](https://github.com/home-assistant/frontend/issues/new?template=bug_report.yml)\n` +
`- Request a feature: Please submit to [Feature Requests](https://github.com/orgs/home-assistant/discussions)\n\n` +
`If you believe you should have access to create Task issues, please contact the maintainers.`
});
await github.rest.issues.update({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
state: 'closed'
});
// Add a label to indicate this was auto-closed
await github.rest.issues.addLabels({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
labels: ['auto-closed']
});

View File

@@ -1,6 +1,7 @@
name: Translations
on:
workflow_dispatch:
push:
branches:
- dev

4
.gitignore vendored
View File

@@ -53,3 +53,7 @@ src/cast/dev_const.ts
# test coverage
test/coverage/
# AI tooling
.claude

View File

@@ -1 +1 @@
yarn run lint-staged --relative --shell "/bin/bash"
yarn run lint-staged --relative

File diff suppressed because one or more lines are too long

View File

@@ -6,4 +6,4 @@ enableGlobalCache: false
nodeLinker: node-modules
yarnPath: .yarn/releases/yarn-4.9.1.cjs
yarnPath: .yarn/releases/yarn-4.9.2.cjs

1
CLAUDE.md Symbolic link
View File

@@ -0,0 +1 @@
.github/copilot-instructions.md

View File

@@ -1,6 +1,6 @@
import defineProvider from "@babel/helper-define-polyfill-provider";
import { join } from "node:path";
import paths from "../paths.cjs";
import paths from "../paths";
const POLYFILL_DIR = join(paths.root_dir, "src/resources/polyfills");

View File

@@ -1,42 +1,41 @@
const path = require("path");
const env = require("./env.cjs");
const paths = require("./paths.cjs");
const { dependencies } = require("../package.json");
import path from "node:path";
import packageJson from "../package.json" assert { type: "json" };
import { version } from "./env.ts";
import paths, { dirname } from "./paths.ts";
const BABEL_PLUGINS = path.join(__dirname, "babel-plugins");
const dependencies = packageJson.dependencies;
const BABEL_PLUGINS = path.join(dirname, "babel-plugins");
// GitHub base URL to use for production source maps
// Nightly builds use the commit SHA, otherwise assumes there is a tag that matches the version
module.exports.sourceMapURL = () => {
const ref = env.version().endsWith("dev")
export const sourceMapURL = () => {
const ref = version().endsWith("dev")
? process.env.GITHUB_SHA || "dev"
: env.version();
: version();
return `https://raw.githubusercontent.com/home-assistant/frontend/${ref}/`;
};
// Files from NPM Packages that should not be imported
module.exports.ignorePackages = () => [];
// Files from NPM packages that we should replace with empty file
module.exports.emptyPackages = ({ isHassioBuild }) =>
export const emptyPackages = ({ isHassioBuild }) =>
[
require.resolve("@vaadin/vaadin-material-styles/typography.js"),
require.resolve("@vaadin/vaadin-material-styles/font-icons.js"),
import.meta.resolve("@vaadin/vaadin-material-styles/typography.js"),
import.meta.resolve("@vaadin/vaadin-material-styles/font-icons.js"),
// Icons in supervisor conflict with icons in HA so we don't load.
isHassioBuild &&
require.resolve(
import.meta.resolve(
path.resolve(paths.root_dir, "src/components/ha-icon.ts")
),
isHassioBuild &&
require.resolve(
import.meta.resolve(
path.resolve(paths.root_dir, "src/components/ha-icon-picker.ts")
),
].filter(Boolean);
module.exports.definedVars = ({ isProdBuild, latestBuild, defineOverlay }) => ({
export const definedVars = ({ isProdBuild, latestBuild, defineOverlay }) => ({
__DEV__: !isProdBuild,
__BUILD__: JSON.stringify(latestBuild ? "modern" : "legacy"),
__VERSION__: JSON.stringify(env.version()),
__VERSION__: JSON.stringify(version()),
__DEMO__: false,
__SUPERVISOR__: false,
__BACKWARDS_COMPAT__: false,
@@ -53,7 +52,7 @@ module.exports.definedVars = ({ isProdBuild, latestBuild, defineOverlay }) => ({
...defineOverlay,
});
module.exports.htmlMinifierOptions = {
export const htmlMinifierOptions = {
caseSensitive: true,
collapseWhitespace: true,
conservativeCollapse: true,
@@ -65,16 +64,16 @@ module.exports.htmlMinifierOptions = {
},
};
module.exports.terserOptions = ({ latestBuild, isTestBuild }) => ({
export const terserOptions = ({ latestBuild, isTestBuild }) => ({
safari10: !latestBuild,
ecma: latestBuild ? 2015 : 5,
ecma: latestBuild ? (2015 as const) : (5 as const),
module: latestBuild,
format: { comments: false },
sourceMap: !isTestBuild,
});
/** @type {import('@rspack/core').SwcLoaderOptions} */
module.exports.swcOptions = () => ({
export const swcOptions = () => ({
jsc: {
loose: true,
externalHelpers: true,
@@ -86,11 +85,16 @@ module.exports.swcOptions = () => ({
},
});
module.exports.babelOptions = ({
export const babelOptions = ({
latestBuild,
isProdBuild,
isTestBuild,
sw,
}: {
latestBuild?: boolean;
isProdBuild?: boolean;
isTestBuild?: boolean;
sw?: boolean;
}) => ({
babelrc: false,
compact: false,
@@ -137,7 +141,7 @@ module.exports.babelOptions = ({
"@polymer/polymer/lib/utils/html-tag.js": ["html"],
},
strictCSS: true,
htmlMinifier: module.exports.htmlMinifierOptions,
htmlMinifier: htmlMinifierOptions,
failOnError: false, // we can turn this off in case of false positives
},
],
@@ -160,7 +164,7 @@ module.exports.babelOptions = ({
// themselves to prevent self-injection.
plugins: [
[
path.join(BABEL_PLUGINS, "custom-polyfill-plugin.js"),
path.join(BABEL_PLUGINS, "custom-polyfill-plugin.ts"),
{ method: "usage-global" },
],
],
@@ -221,8 +225,20 @@ const publicPath = (latestBuild, root = "") =>
}
*/
module.exports.config = {
app({ isProdBuild, latestBuild, isStatsBuild, isTestBuild, isWDS }) {
export const config = {
app({
isProdBuild,
latestBuild,
isStatsBuild,
isTestBuild,
isWDS,
}: {
isProdBuild?: boolean;
latestBuild?: boolean;
isStatsBuild?: boolean;
isTestBuild?: boolean;
isWDS?: boolean;
}) {
return {
name: "frontend" + nameSuffix(latestBuild),
entry: {
@@ -257,7 +273,7 @@ module.exports.config = {
outputPath: outputPath(paths.demo_output_root, latestBuild),
publicPath: publicPath(latestBuild),
defineOverlay: {
__VERSION__: JSON.stringify(`DEMO-${env.version()}`),
__VERSION__: JSON.stringify(`DEMO-${version()}`),
__DEMO__: true,
},
isProdBuild,
@@ -267,7 +283,7 @@ module.exports.config = {
},
cast({ isProdBuild, latestBuild }) {
const entry = {
const entry: Record<string, string> = {
launcher: path.resolve(paths.cast_dir, "src/launcher/entrypoint.ts"),
media: path.resolve(paths.cast_dir, "src/media/entrypoint.ts"),
};

View File

@@ -1,34 +0,0 @@
const fs = require("fs");
const path = require("path");
const paths = require("./paths.cjs");
const isTrue = (value) => value === "1" || value?.toLowerCase() === "true";
module.exports = {
isProdBuild() {
return (
process.env.NODE_ENV === "production" || module.exports.isStatsBuild()
);
},
isStatsBuild() {
return isTrue(process.env.STATS);
},
isTestBuild() {
return isTrue(process.env.IS_TEST);
},
isNetlify() {
return isTrue(process.env.NETLIFY);
},
version() {
const version = fs
.readFileSync(path.resolve(paths.root_dir, "pyproject.toml"), "utf8")
.match(/version\W+=\W"(\d{8}\.\d(?:\.dev)?)"/);
if (!version) {
throw Error("Version not found");
}
return version[1];
},
isDevContainer() {
return isTrue(process.env.DEV_CONTAINER);
},
};

21
build-scripts/env.ts Normal file
View File

@@ -0,0 +1,21 @@
import fs from "node:fs";
import path from "node:path";
import paths from "./paths.ts";
const isTrue = (value) => value === "1" || value?.toLowerCase() === "true";
export const isProdBuild = () =>
process.env.NODE_ENV === "production" || isStatsBuild();
export const isStatsBuild = () => isTrue(process.env.STATS);
export const isTestBuild = () => isTrue(process.env.IS_TEST);
export const isNetlify = () => isTrue(process.env.NETLIFY);
export const version = () => {
const pyProjectVersion = fs
.readFileSync(path.resolve(paths.root_dir, "pyproject.toml"), "utf8")
.match(/version\W+=\W"(\d{8}\.\d(?:\.dev)?)"/);
if (!pyProjectVersion) {
throw Error("Version not found");
}
return pyProjectVersion[1];
};
export const isDevContainer = () => isTrue(process.env.DEV_CONTAINER);

View File

@@ -1,57 +0,0 @@
import gulp from "gulp";
import env from "../env.cjs";
import "./clean.js";
import "./compress.js";
import "./entry-html.js";
import "./gather-static.js";
import "./gen-icons-json.js";
import "./locale-data.js";
import "./service-worker.js";
import "./translations.js";
import "./rspack.js";
gulp.task(
"develop-app",
gulp.series(
async function setEnv() {
process.env.NODE_ENV = "development";
},
"clean",
gulp.parallel(
"gen-service-worker-app-dev",
"gen-icons-json",
"gen-pages-app-dev",
"build-translations",
"build-locale-data"
),
"copy-static-app",
"rspack-watch-app"
)
);
gulp.task(
"build-app",
gulp.series(
async function setEnv() {
process.env.NODE_ENV = "production";
},
"clean",
gulp.parallel("gen-icons-json", "build-translations", "build-locale-data"),
"copy-static-app",
"rspack-prod-app",
gulp.parallel("gen-pages-app-prod", "gen-service-worker-app-prod"),
// Don't compress running tests
...(env.isTestBuild() || env.isStatsBuild() ? [] : ["compress-app"])
)
);
gulp.task(
"analyze-app",
gulp.series(
async function setEnv() {
process.env.STATS = "1";
},
"clean",
"rspack-prod-app"
)
);

54
build-scripts/gulp/app.ts Normal file
View File

@@ -0,0 +1,54 @@
import { parallel, series } from "gulp";
import { isStatsBuild, isTestBuild } from "../env.ts";
import { clean } from "./clean.ts";
import { compressApp } from "./compress.ts";
import { genPagesAppDev, genPagesAppProd } from "./entry-html.ts";
import { copyStaticApp } from "./gather-static.ts";
import { genIconsJson } from "./gen-icons-json.ts";
import { buildLocaleData } from "./locale-data.ts";
import { rspackProdApp, rspackWatchApp } from "./rspack.ts";
import {
genServiceWorkerAppDev,
genServiceWorkerAppProd,
} from "./service-worker.ts";
import { buildTranslations } from "./translations.ts";
// develop-app
export const developApp = series(
async () => {
process.env.NODE_ENV = "development";
},
clean,
parallel(
genServiceWorkerAppDev,
genIconsJson,
genPagesAppDev,
buildTranslations,
buildLocaleData
),
copyStaticApp,
rspackWatchApp
);
// build-app
export const buildApp = series(
async () => {
process.env.NODE_ENV = "production";
},
clean,
parallel(genIconsJson, buildTranslations, buildLocaleData),
copyStaticApp,
rspackProdApp,
parallel(genPagesAppProd, genServiceWorkerAppProd),
// Don't compress running tests
...(isTestBuild() || isStatsBuild() ? [] : [compressApp])
);
// analyze-app
export const analyzeApp = series(
async () => {
process.env.STATS = "1";
},
clean,
rspackProdApp
);

View File

@@ -1,37 +0,0 @@
import gulp from "gulp";
import "./clean.js";
import "./entry-html.js";
import "./gather-static.js";
import "./service-worker.js";
import "./translations.js";
import "./rspack.js";
gulp.task(
"develop-cast",
gulp.series(
async function setEnv() {
process.env.NODE_ENV = "development";
},
"clean-cast",
"translations-enable-merge-backend",
gulp.parallel("gen-icons-json", "build-translations", "build-locale-data"),
"copy-static-cast",
"gen-pages-cast-dev",
"rspack-dev-server-cast"
)
);
gulp.task(
"build-cast",
gulp.series(
async function setEnv() {
process.env.NODE_ENV = "production";
},
"clean-cast",
"translations-enable-merge-backend",
gulp.parallel("gen-icons-json", "build-translations", "build-locale-data"),
"copy-static-cast",
"rspack-prod-cast",
"gen-pages-cast-prod"
)
);

View File

@@ -0,0 +1,38 @@
import { parallel, series } from "gulp";
import { cleanCast } from "./clean.ts";
import { genPagesCastDev, genPagesCastProd } from "./entry-html.ts";
import { copyStaticCast } from "./gather-static.ts";
import { genIconsJson } from "./gen-icons-json.ts";
import { buildLocaleData } from "./locale-data.ts";
import { rspackDevServerCast, rspackProdCast } from "./rspack.ts";
import "./service-worker.ts";
import {
buildTranslations,
translationsEnableMergeBackend,
} from "./translations.ts";
// develop-cast
export const developCast = series(
async () => {
process.env.NODE_ENV = "development";
},
cleanCast,
translationsEnableMergeBackend,
parallel(genIconsJson, buildTranslations, buildLocaleData),
copyStaticCast,
genPagesCastDev,
rspackDevServerCast
);
// build-cast
export const buildCast = series(
async () => {
process.env.NODE_ENV = "production";
},
cleanCast,
translationsEnableMergeBackend,
parallel(genIconsJson, buildTranslations, buildLocaleData),
copyStaticCast,
rspackProdCast,
genPagesCastProd
);

View File

@@ -1,51 +0,0 @@
import { deleteSync } from "del";
import gulp from "gulp";
import paths from "../paths.cjs";
import "./translations.js";
gulp.task(
"clean",
gulp.parallel("clean-translations", async () =>
deleteSync([paths.app_output_root, paths.build_dir])
)
);
gulp.task(
"clean-demo",
gulp.parallel("clean-translations", async () =>
deleteSync([paths.demo_output_root, paths.build_dir])
)
);
gulp.task(
"clean-cast",
gulp.parallel("clean-translations", async () =>
deleteSync([paths.cast_output_root, paths.build_dir])
)
);
gulp.task("clean-hassio", async () =>
deleteSync([paths.hassio_output_root, paths.build_dir])
);
gulp.task(
"clean-gallery",
gulp.parallel("clean-translations", async () =>
deleteSync([
paths.gallery_output_root,
paths.gallery_build,
paths.build_dir,
])
)
);
gulp.task(
"clean-landing-page",
gulp.parallel("clean-translations", async () =>
deleteSync([
paths.landingPage_output_root,
paths.landingPage_build,
paths.build_dir,
])
)
);

View File

@@ -0,0 +1,31 @@
import { deleteSync } from "del";
import { parallel } from "gulp";
import paths from "../paths.ts";
import { cleanTranslations } from "./translations.ts";
export const clean = parallel(cleanTranslations, async () =>
deleteSync([paths.app_output_root, paths.build_dir])
);
export const cleanDemo = parallel(cleanTranslations, async () =>
deleteSync([paths.demo_output_root, paths.build_dir])
);
export const cleanCast = parallel(cleanTranslations, async () =>
deleteSync([paths.cast_output_root, paths.build_dir])
);
export const cleanHassio = async () =>
deleteSync([paths.hassio_output_root, paths.build_dir]);
export const cleanGallery = parallel(cleanTranslations, async () =>
deleteSync([paths.gallery_output_root, paths.gallery_build, paths.build_dir])
);
export const cleanLandingPage = parallel(cleanTranslations, async () =>
deleteSync([
paths.landingPage_output_root,
paths.landingPage_build,
paths.build_dir,
])
);

View File

@@ -1,10 +1,10 @@
// Tasks to compress
import { constants } from "node:zlib";
import gulp from "gulp";
import { dest, parallel, src } from "gulp";
import brotli from "gulp-brotli";
import zopfli from "gulp-zopfli-green";
import paths from "../paths.cjs";
import { constants } from "node:zlib";
import paths from "../paths.ts";
const filesGlob = "*.{js,json,css,svg,xml}";
const brotliOptions = {
@@ -16,27 +16,25 @@ const brotliOptions = {
const zopfliOptions = { threshold: 150 };
const compressModern = (rootDir, modernDir, compress) =>
gulp
.src([`${modernDir}/**/${filesGlob}`, `${rootDir}/sw-modern.js`], {
base: rootDir,
allowEmpty: true,
})
src([`${modernDir}/**/${filesGlob}`, `${rootDir}/sw-modern.js`], {
base: rootDir,
allowEmpty: true,
})
.pipe(compress === "zopfli" ? zopfli(zopfliOptions) : brotli(brotliOptions))
.pipe(gulp.dest(rootDir));
.pipe(dest(rootDir));
const compressOther = (rootDir, modernDir, compress) =>
gulp
.src(
[
`${rootDir}/**/${filesGlob}`,
`!${modernDir}/**/${filesGlob}`,
`!${rootDir}/{sw-modern,service_worker}.js`,
`${rootDir}/{authorize,onboarding}.html`,
],
{ base: rootDir, allowEmpty: true }
)
src(
[
`${rootDir}/**/${filesGlob}`,
`!${modernDir}/**/${filesGlob}`,
`!${rootDir}/{sw-modern,service_worker}.js`,
`${rootDir}/{authorize,onboarding}.html`,
],
{ base: rootDir, allowEmpty: true }
)
.pipe(compress === "zopfli" ? zopfli(zopfliOptions) : brotli(brotliOptions))
.pipe(gulp.dest(rootDir));
.pipe(dest(rootDir));
const compressAppModernBrotli = () =>
compressModern(paths.app_output_root, paths.app_output_latest, "brotli");
@@ -66,21 +64,16 @@ const compressHassioOtherBrotli = () =>
const compressHassioOtherZopfli = () =>
compressOther(paths.hassio_output_root, paths.hassio_output_latest, "zopfli");
gulp.task(
"compress-app",
gulp.parallel(
compressAppModernBrotli,
compressAppOtherBrotli,
compressAppModernZopfli,
compressAppOtherZopfli
)
export const compressApp = parallel(
compressAppModernBrotli,
compressAppOtherBrotli,
compressAppModernZopfli,
compressAppOtherZopfli
);
gulp.task(
"compress-hassio",
gulp.parallel(
compressHassioModernBrotli,
compressHassioOtherBrotli,
compressHassioModernZopfli,
compressHassioOtherZopfli
)
export const compressHassio = parallel(
compressHassioModernBrotli,
compressHassioOtherBrotli,
compressHassioModernZopfli,
compressHassioOtherZopfli
);

View File

@@ -1,54 +0,0 @@
import gulp from "gulp";
import "./clean.js";
import "./entry-html.js";
import "./gather-static.js";
import "./gen-icons-json.js";
import "./service-worker.js";
import "./translations.js";
import "./rspack.js";
gulp.task(
"develop-demo",
gulp.series(
async function setEnv() {
process.env.NODE_ENV = "development";
},
"clean-demo",
"translations-enable-merge-backend",
gulp.parallel(
"gen-icons-json",
"gen-pages-demo-dev",
"build-translations",
"build-locale-data"
),
"copy-static-demo",
"rspack-dev-server-demo"
)
);
gulp.task(
"build-demo",
gulp.series(
async function setEnv() {
process.env.NODE_ENV = "production";
},
"clean-demo",
// Cast needs to be backwards compatible and older HA has no translations
"translations-enable-merge-backend",
gulp.parallel("gen-icons-json", "build-translations", "build-locale-data"),
"copy-static-demo",
"rspack-prod-demo",
"gen-pages-demo-prod"
)
);
gulp.task(
"analyze-demo",
gulp.series(
async function setEnv() {
process.env.STATS = "1";
},
"clean",
"rspack-prod-demo"
)
);

View File

@@ -0,0 +1,47 @@
import { parallel, series } from "gulp";
import { clean, cleanDemo } from "./clean.ts";
import { genPagesDemoDev, genPagesDemoProd } from "./entry-html.ts";
import { copyStaticDemo } from "./gather-static.ts";
import { genIconsJson } from "./gen-icons-json.ts";
import { buildLocaleData } from "./locale-data.ts";
import { rspackDevServerDemo, rspackProdDemo } from "./rspack.ts";
import "./service-worker.ts";
import {
buildTranslations,
translationsEnableMergeBackend,
} from "./translations.ts";
// develop-demo
export const developDemo = series(
async function setEnv() {
process.env.NODE_ENV = "development";
},
cleanDemo,
translationsEnableMergeBackend,
parallel(genIconsJson, genPagesDemoDev, buildTranslations, buildLocaleData),
copyStaticDemo,
rspackDevServerDemo
);
// build-demo
export const buildDemo = series(
async function setEnv() {
process.env.NODE_ENV = "production";
},
cleanDemo,
// Cast needs to be backwards compatible and older HA has no translations
translationsEnableMergeBackend,
parallel(genIconsJson, buildTranslations, buildLocaleData),
copyStaticDemo,
rspackProdDemo,
genPagesDemoProd
);
// analyze-demo
export const analyzeDemo = series(
async function setEnv() {
process.env.STATS = "1";
},
clean,
rspackProdDemo
);

View File

@@ -1,10 +1,10 @@
import fs from "fs/promises";
import gulp from "gulp";
import path from "path";
import mapStream from "map-stream";
import transform from "gulp-json-transform";
import { LokaliseApi } from "@lokalise/node-api";
import { dest, series, src } from "gulp";
import transform from "gulp-json-transform";
import JSZip from "jszip";
import mapStream from "map-stream";
import fs from "node:fs/promises";
import path from "node:path";
const inDir = "translations";
const inDirFrontend = `${inDir}/frontend`;
@@ -12,11 +12,14 @@ const inDirBackend = `${inDir}/backend`;
const srcMeta = "src/translations/translationMetadata.json";
const encoding = "utf8";
function hasHtml(data) {
return /<\S*>/i.test(data);
}
const hasHtml = (data) => /<\S*>/i.test(data);
function recursiveCheckHasHtml(file, data, errors, recKey) {
const recursiveCheckHasHtml = (
file,
data,
errors: string[],
recKey?: string
) => {
Object.keys(data).forEach(function (key) {
if (typeof data[key] === "object") {
const nextRecKey = recKey ? `${recKey}.${key}` : key;
@@ -25,9 +28,9 @@ function recursiveCheckHasHtml(file, data, errors, recKey) {
errors.push(`HTML found in ${file.path} at key ${recKey}.${key}`);
}
});
}
};
function checkHtml() {
const checkHtml = () => {
const errors = [];
return mapStream(function (file, cb) {
@@ -44,9 +47,9 @@ function checkHtml() {
}
cb(error, file);
});
}
};
function convertBackendTranslations(data, _file) {
const convertBackendTranslationsTransform = (data, _file) => {
const output = { component: {} };
if (!data.component) {
return output;
@@ -62,25 +65,22 @@ function convertBackendTranslations(data, _file) {
});
});
return output;
}
};
gulp.task("convert-backend-translations", function () {
return gulp
.src([`${inDirBackend}/*.json`])
.pipe(transform((data, file) => convertBackendTranslations(data, file)))
.pipe(gulp.dest(inDirBackend));
});
const convertBackendTranslations = () =>
src([`${inDirBackend}/*.json`])
.pipe(
transform((data, file) => convertBackendTranslationsTransform(data, file))
)
.pipe(dest(inDirBackend));
gulp.task("check-translations-html", function () {
return gulp
.src([`${inDirFrontend}/*.json`, `${inDirBackend}/*.json`])
.pipe(checkHtml());
});
const checkTranslationsHtml = () =>
src([`${inDirFrontend}/*.json`, `${inDirBackend}/*.json`]).pipe(checkHtml());
gulp.task("check-all-files-exist", async function () {
const checkAllFilesExist = async () => {
const file = await fs.readFile(srcMeta, { encoding });
const meta = JSON.parse(file);
const writings = [];
const writings: Promise<void>[] = [];
Object.keys(meta).forEach((lang) => {
writings.push(
fs.writeFile(`${inDirFrontend}/${lang}.json`, JSON.stringify({}), {
@@ -92,14 +92,14 @@ gulp.task("check-all-files-exist", async function () {
);
});
await Promise.allSettled(writings);
});
};
const lokaliseProjects = {
backend: "130246255a974bd3b5e8a1.51616605",
frontend: "3420425759f6d6d241f598.13594006",
};
gulp.task("fetch-lokalise", async function () {
const fetchLokalise = async () => {
let apiKey;
try {
apiKey =
@@ -168,14 +168,11 @@ gulp.task("fetch-lokalise", async function () {
})
)
);
});
};
gulp.task(
"download-translations",
gulp.series(
"fetch-lokalise",
"convert-backend-translations",
"check-translations-html",
"check-all-files-exist"
)
export const downloadTranslations = series(
fetchLokalise,
convertBackendTranslations,
checkTranslationsHtml,
checkAllFilesExist
);

View File

@@ -6,12 +6,11 @@ import {
getPreUserAgentRegexes,
} from "browserslist-useragent-regexp";
import fs from "fs-extra";
import gulp from "gulp";
import { minify } from "html-minifier-terser";
import template from "lodash.template";
import { dirname, extname, resolve } from "node:path";
import { htmlMinifierOptions, terserOptions } from "../bundle.cjs";
import paths from "../paths.cjs";
import { htmlMinifierOptions, terserOptions } from "../bundle.ts";
import paths from "../paths.ts";
// macOS companion app has no way to obtain the Safari version used by WKWebView,
// and it is not in the default user agent string. So we add an additional regex
@@ -34,9 +33,9 @@ const getCommonTemplateVars = () => {
mobileToDesktop: true,
throwOnMissing: true,
});
const minSafariVersion = browserRegexes.find(
(regex) => regex.family === "safari"
)?.matchedVersions[0][0];
const minSafariVersion =
browserRegexes.find((regex) => regex.family === "safari")
?.matchedVersions[0][0] ?? 18;
const minMacOSVersion = SAFARI_TO_MACOS[minSafariVersion];
if (!minMacOSVersion) {
throw Error(
@@ -106,10 +105,10 @@ const genPagesDevTask =
resolve(inputRoot, inputSub, `${page}.template`),
{
...commonVars,
latestEntryJS: entries.map(
latestEntryJS: (entries as string[]).map(
(entry) => `${publicRoot}/frontend_latest/${entry}.js`
),
es5EntryJS: entries.map(
es5EntryJS: (entries as string[]).map(
(entry) => `${publicRoot}/frontend_es5/${entry}.js`
),
latestCustomPanelJS: `${publicRoot}/frontend_latest/custom-panel.js`,
@@ -128,7 +127,7 @@ const genPagesProdTask =
inputRoot,
outputRoot,
outputLatest,
outputES5,
outputES5?: string,
inputSub = "src/html"
) =>
async () => {
@@ -139,14 +138,18 @@ const genPagesProdTask =
? fs.readJsonSync(resolve(outputES5, "manifest.json"))
: {};
const commonVars = getCommonTemplateVars();
const minifiedHTML = [];
const minifiedHTML: Promise<void>[] = [];
for (const [page, entries] of Object.entries(pageEntries)) {
const content = renderTemplate(
resolve(inputRoot, inputSub, `${page}.template`),
{
...commonVars,
latestEntryJS: entries.map((entry) => latestManifest[`${entry}.js`]),
es5EntryJS: entries.map((entry) => es5Manifest[`${entry}.js`]),
latestEntryJS: (entries as string[]).map(
(entry) => latestManifest[`${entry}.js`]
),
es5EntryJS: (entries as string[]).map(
(entry) => es5Manifest[`${entry}.js`]
),
latestCustomPanelJS: latestManifest["custom-panel.js"],
es5CustomPanelJS: es5Manifest["custom-panel.js"],
}
@@ -167,20 +170,18 @@ const APP_PAGE_ENTRIES = {
"index.html": ["core", "app"],
};
gulp.task(
"gen-pages-app-dev",
genPagesDevTask(APP_PAGE_ENTRIES, paths.root_dir, paths.app_output_root)
export const genPagesAppDev = genPagesDevTask(
APP_PAGE_ENTRIES,
paths.root_dir,
paths.app_output_root
);
gulp.task(
"gen-pages-app-prod",
genPagesProdTask(
APP_PAGE_ENTRIES,
paths.root_dir,
paths.app_output_root,
paths.app_output_latest,
paths.app_output_es5
)
export const genPagesAppProd = genPagesProdTask(
APP_PAGE_ENTRIES,
paths.root_dir,
paths.app_output_root,
paths.app_output_latest,
paths.app_output_es5
);
const CAST_PAGE_ENTRIES = {
@@ -190,104 +191,82 @@ const CAST_PAGE_ENTRIES = {
"receiver.html": ["receiver"],
};
gulp.task(
"gen-pages-cast-dev",
genPagesDevTask(CAST_PAGE_ENTRIES, paths.cast_dir, paths.cast_output_root)
export const genPagesCastDev = genPagesDevTask(
CAST_PAGE_ENTRIES,
paths.cast_dir,
paths.cast_output_root
);
gulp.task(
"gen-pages-cast-prod",
genPagesProdTask(
CAST_PAGE_ENTRIES,
paths.cast_dir,
paths.cast_output_root,
paths.cast_output_latest,
paths.cast_output_es5
)
export const genPagesCastProd = genPagesProdTask(
CAST_PAGE_ENTRIES,
paths.cast_dir,
paths.cast_output_root,
paths.cast_output_latest,
paths.cast_output_es5
);
const DEMO_PAGE_ENTRIES = { "index.html": ["main"] };
gulp.task(
"gen-pages-demo-dev",
genPagesDevTask(DEMO_PAGE_ENTRIES, paths.demo_dir, paths.demo_output_root)
export const genPagesDemoDev = genPagesDevTask(
DEMO_PAGE_ENTRIES,
paths.demo_dir,
paths.demo_output_root
);
gulp.task(
"gen-pages-demo-prod",
genPagesProdTask(
DEMO_PAGE_ENTRIES,
paths.demo_dir,
paths.demo_output_root,
paths.demo_output_latest,
paths.demo_output_es5
)
export const genPagesDemoProd = genPagesProdTask(
DEMO_PAGE_ENTRIES,
paths.demo_dir,
paths.demo_output_root,
paths.demo_output_latest,
paths.demo_output_es5
);
const GALLERY_PAGE_ENTRIES = { "index.html": ["entrypoint"] };
gulp.task(
"gen-pages-gallery-dev",
genPagesDevTask(
GALLERY_PAGE_ENTRIES,
paths.gallery_dir,
paths.gallery_output_root
)
export const genPagesGalleryDev = genPagesDevTask(
GALLERY_PAGE_ENTRIES,
paths.gallery_dir,
paths.gallery_output_root
);
gulp.task(
"gen-pages-gallery-prod",
genPagesProdTask(
GALLERY_PAGE_ENTRIES,
paths.gallery_dir,
paths.gallery_output_root,
paths.gallery_output_latest
)
export const genPagesGalleryProd = genPagesProdTask(
GALLERY_PAGE_ENTRIES,
paths.gallery_dir,
paths.gallery_output_root,
paths.gallery_output_latest
);
const LANDING_PAGE_PAGE_ENTRIES = { "index.html": ["entrypoint"] };
gulp.task(
"gen-pages-landing-page-dev",
genPagesDevTask(
LANDING_PAGE_PAGE_ENTRIES,
paths.landingPage_dir,
paths.landingPage_output_root
)
export const genPagesLandingPageDev = genPagesDevTask(
LANDING_PAGE_PAGE_ENTRIES,
paths.landingPage_dir,
paths.landingPage_output_root
);
gulp.task(
"gen-pages-landing-page-prod",
genPagesProdTask(
LANDING_PAGE_PAGE_ENTRIES,
paths.landingPage_dir,
paths.landingPage_output_root,
paths.landingPage_output_latest,
paths.landingPage_output_es5
)
export const genPagesLandingPageProd = genPagesProdTask(
LANDING_PAGE_PAGE_ENTRIES,
paths.landingPage_dir,
paths.landingPage_output_root,
paths.landingPage_output_latest,
paths.landingPage_output_es5
);
const HASSIO_PAGE_ENTRIES = { "entrypoint.js": ["entrypoint"] };
gulp.task(
"gen-pages-hassio-dev",
genPagesDevTask(
HASSIO_PAGE_ENTRIES,
paths.hassio_dir,
paths.hassio_output_root,
"src",
paths.hassio_publicPath
)
export const genPagesHassioDev = genPagesDevTask(
HASSIO_PAGE_ENTRIES,
paths.hassio_dir,
paths.hassio_output_root,
"src",
paths.hassio_publicPath
);
gulp.task(
"gen-pages-hassio-prod",
genPagesProdTask(
HASSIO_PAGE_ENTRIES,
paths.hassio_dir,
paths.hassio_output_root,
paths.hassio_output_latest,
paths.hassio_output_es5,
"src"
)
export const genPagesHassioProd = genPagesProdTask(
HASSIO_PAGE_ENTRIES,
paths.hassio_dir,
paths.hassio_output_root,
paths.hassio_output_latest,
paths.hassio_output_es5,
"src"
);

View File

@@ -1,14 +1,14 @@
// Task to download the latest Lokalise translations from the nightly workflow artifacts
// Task to download the latest 00Lokalise translations from the nightly workflow artifacts
import { createOAuthDeviceAuth } from "@octokit/auth-oauth-device";
import { retry } from "@octokit/plugin-retry";
import { Octokit } from "@octokit/rest";
import { deleteAsync } from "del";
import { mkdir, readFile, writeFile } from "fs/promises";
import gulp from "gulp";
import { series } from "gulp";
import jszip from "jszip";
import path from "path";
import process from "process";
import { mkdir, readFile, writeFile } from "node:fs/promises";
import path from "node:path";
import process from "node:process";
import { extract } from "tar";
const MAX_AGE = 24; // hours
@@ -22,12 +22,13 @@ const TOKEN_FILE = path.posix.join(EXTRACT_DIR, "token.json");
const ARTIFACT_FILE = path.posix.join(EXTRACT_DIR, "artifact.json");
let allowTokenSetup = false;
gulp.task("allow-setup-fetch-nightly-translations", (done) => {
export const allowSetupFetchNightlyTranslations = (done) => {
allowTokenSetup = true;
done();
});
};
gulp.task("fetch-nightly-translations", async function () {
export const fetchNightlyTranslations = async () => {
// Skip all when environment flag is set (assumes translations are already in place)
if (process.env?.SKIP_FETCH_NIGHTLY_TRANSLATIONS) {
console.log("Skipping fetch due to environment signal");
@@ -54,7 +55,7 @@ gulp.task("fetch-nightly-translations", async function () {
// To store file writing promises
const createExtractDir = mkdir(EXTRACT_DIR, { recursive: true });
const writings = [];
const writings: Promise<void>[] = [];
// Authenticate to GitHub using GitHub action token if it exists,
// otherwise look for a saved user token or generate a new one if none
@@ -87,7 +88,7 @@ gulp.task("fetch-nightly-translations", async function () {
});
tokenAuth = await auth({ type: "oauth" });
writings.push(
createExtractDir.then(
createExtractDir.then(() =>
writeFile(TOKEN_FILE, JSON.stringify(tokenAuth, null, 2))
)
);
@@ -131,13 +132,13 @@ gulp.task("fetch-nightly-translations", async function () {
throw Error("Latest nightly workflow run has no translations artifact");
}
writings.push(
createExtractDir.then(
createExtractDir.then(() =>
writeFile(ARTIFACT_FILE, JSON.stringify(latestArtifact, null, 2))
)
);
// Remove the current translations
const deleteCurrent = Promise.all(writings).then(
const deleteCurrent = Promise.all(writings).then(() =>
deleteAsync([`${EXTRACT_DIR}/*`, `!${ARTIFACT_FILE}`, `!${TOKEN_FILE}`])
);
@@ -148,24 +149,22 @@ gulp.task("fetch-nightly-translations", async function () {
artifact_id: latestArtifact.id,
archive_format: "zip",
});
// @ts-ignore OctokitResponse<unknown, 302> doesn't allow to check for 200
if (downloadResponse.status !== 200) {
throw Error("Failure downloading translations artifact");
}
// Artifact is a tarball, but GitHub adds it to a zip file
console.log("Unpacking downloaded translations...");
const zip = await jszip.loadAsync(downloadResponse.data);
const zip = await jszip.loadAsync(downloadResponse.data as any);
await deleteCurrent;
const extractStream = zip.file(/.*/)[0].nodeStream().pipe(extract());
await new Promise((resolve, reject) => {
extractStream.on("close", resolve).on("error", reject);
});
});
};
gulp.task(
"setup-and-fetch-nightly-translations",
gulp.series(
"allow-setup-fetch-nightly-translations",
"fetch-nightly-translations"
)
export const setupAndFetchNightlyTranslations = series(
allowSetupFetchNightlyTranslations,
fetchNightlyTranslations
);

View File

@@ -1,44 +1,23 @@
import fs from "fs";
import { glob } from "glob";
import gulp from "gulp";
import { parallel, series, watch } from "gulp";
import yaml from "js-yaml";
import { marked } from "marked";
import ts from "typescript";
import { create } from "@custom-elements-manifest/analyzer";
import { litPlugin } from "@custom-elements-manifest/analyzer/src/features/framework-plugins/lit/lit.js";
import path from "path";
import paths from "../paths.cjs";
import "./clean.js";
import "./entry-html.js";
import "./gather-static.js";
import "./gen-icons-json.js";
import "./service-worker.js";
import "./translations.js";
import "./rspack.js";
import fs from "node:fs";
import path from "node:path";
import paths from "../paths.ts";
import { cleanGallery } from "./clean.ts";
import { genPagesGalleryDev, genPagesGalleryProd } from "./entry-html.ts";
import { copyStaticGallery } from "./gather-static.ts";
import { genIconsJson } from "./gen-icons-json.ts";
import { buildLocaleData } from "./locale-data.ts";
import { rspackDevServerGallery, rspackProdGallery } from "./rspack.ts";
import {
buildTranslations,
translationsEnableMergeBackend,
} from "./translations.ts";
gulp.task("generate-component-docs", async function generateComponentDocs() {
const filePaths = ["src/components/ha-alert.ts"];
const modules = await Promise.all(
filePaths.map(async (file) => {
const filePath = path.resolve(file);
console.log(`Reading ${file} -> ${filePath}`);
const source = fs.readFileSync(filePath).toString();
return ts.createSourceFile(file, source, ts.ScriptTarget.ES2015, true);
})
);
const manifest = create({
modules,
plugins: litPlugin(),
context: { dev: true },
});
console.log(manifest);
});
gulp.task("gather-gallery-pages", async function gatherPages() {
// gather-gallery-pages
export const gatherGalleryPages = async function gatherPages() {
const pageDir = path.resolve(paths.gallery_dir, "src/pages");
const files = await glob(path.resolve(pageDir, "**/*"));
@@ -47,7 +26,7 @@ gulp.task("gather-gallery-pages", async function gatherPages() {
let content = "export const PAGES = {\n";
const processed = new Set();
const processed = new Set<string>();
for (const file of files) {
if (fs.lstatSync(file).isDirectory()) {
@@ -72,7 +51,9 @@ gulp.task("gather-gallery-pages", async function gatherPages() {
if (descriptionContent.startsWith("---")) {
const metadataEnd = descriptionContent.indexOf("---", 3);
metadata = yaml.load(descriptionContent.substring(3, metadataEnd));
metadata = yaml.load(
descriptionContent.substring(3, metadataEnd)
) as any;
descriptionContent = descriptionContent
.substring(metadataEnd + 3)
.trim();
@@ -82,7 +63,9 @@ gulp.task("gather-gallery-pages", async function gatherPages() {
if (descriptionContent === "") {
hasDescription = false;
} else {
descriptionContent = marked(descriptionContent).replace(/`/g, "\\`");
// eslint-disable-next-line no-await-in-loop
descriptionContent = await marked(descriptionContent);
descriptionContent = descriptionContent.replace(/`/g, "\\`");
fs.mkdirSync(path.resolve(galleryBuild, category), { recursive: true });
fs.writeFileSync(
path.resolve(galleryBuild, `${pageId}-description.ts`),
@@ -120,7 +103,10 @@ gulp.task("gather-gallery-pages", async function gatherPages() {
pagesToProcess[category].add(page);
}
for (const group of Object.values(sidebar)) {
for (const group of Object.values(sidebar) as {
category: string;
pages?: string[];
}[]) {
const toProcess = pagesToProcess[group.category];
delete pagesToProcess[group.category];
@@ -143,7 +129,7 @@ gulp.task("gather-gallery-pages", async function gatherPages() {
group.pages = [];
}
for (const page of Array.from(toProcess).sort()) {
group.pages.push(page);
group.pages.push(page as string);
}
}
@@ -151,7 +137,7 @@ gulp.task("gather-gallery-pages", async function gatherPages() {
sidebar.push({
category,
header: category,
pages: Array.from(pages).sort(),
pages: Array.from(pages as Set<string>).sort(),
});
}
@@ -162,55 +148,48 @@ gulp.task("gather-gallery-pages", async function gatherPages() {
content,
"utf-8"
);
});
};
gulp.task(
"develop-gallery",
gulp.series(
async function setEnv() {
process.env.NODE_ENV = "development";
},
"clean-gallery",
"translations-enable-merge-backend",
gulp.parallel(
"gen-icons-json",
"build-translations",
"build-locale-data",
"gather-gallery-pages"
),
"copy-static-gallery",
"gen-pages-gallery-dev",
gulp.parallel(
"rspack-dev-server-gallery",
async function watchMarkdownFiles() {
gulp.watch(
[
path.resolve(paths.gallery_dir, "src/pages/**/*.markdown"),
path.resolve(paths.gallery_dir, "sidebar.js"),
],
gulp.series("gather-gallery-pages")
);
}
)
)
// develop-gallery
export const developGallery = series(
async function setEnv() {
process.env.NODE_ENV = "development";
},
cleanGallery,
translationsEnableMergeBackend,
parallel(
genIconsJson,
buildTranslations,
buildLocaleData,
gatherGalleryPages
),
copyStaticGallery,
genPagesGalleryDev,
parallel(rspackDevServerGallery, async function watchMarkdownFiles() {
watch(
[
path.resolve(paths.gallery_dir, "src/pages/**/*.markdown"),
path.resolve(paths.gallery_dir, "sidebar.js"),
],
series(gatherGalleryPages)
);
})
);
gulp.task(
"build-gallery",
gulp.series(
async function setEnv() {
process.env.NODE_ENV = "production";
},
"clean-gallery",
"translations-enable-merge-backend",
gulp.parallel(
"gen-icons-json",
"build-translations",
"build-locale-data",
"gather-gallery-pages"
),
"copy-static-gallery",
"rspack-prod-gallery",
"gen-pages-gallery-prod"
)
// build-gallery
export const buildGallery = series(
async function setEnv() {
process.env.NODE_ENV = "production";
},
cleanGallery,
translationsEnableMergeBackend,
parallel(
genIconsJson,
buildTranslations,
buildLocaleData,
gatherGalleryPages
),
copyStaticGallery,
rspackProdGallery,
genPagesGalleryProd
);

View File

@@ -1,9 +1,8 @@
// Gulp task to gather all static files.
import fs from "fs-extra";
import gulp from "gulp";
import path from "path";
import paths from "../paths.cjs";
import path from "node:path";
import paths from "../paths.ts";
const npmPath = (...parts) =>
path.resolve(paths.root_dir, "node_modules", ...parts);
@@ -17,7 +16,7 @@ const genStaticPath =
(...parts) =>
path.resolve(staticDir, ...parts);
function copyTranslations(staticDir) {
const copyTranslations = (staticDir) => {
const staticPath = genStaticPath(staticDir);
// Translation output
@@ -25,23 +24,23 @@ function copyTranslations(staticDir) {
polyPath("build/translations/output"),
staticPath("translations")
);
}
};
function copyLocaleData(staticDir) {
const copyLocaleData = (staticDir) => {
const staticPath = genStaticPath(staticDir);
// Locale data output
fs.copySync(polyPath("build/locale-data"), staticPath("locale-data"));
}
};
function copyMdiIcons(staticDir) {
const copyMdiIcons = (staticDir) => {
const staticPath = genStaticPath(staticDir);
// MDI icons output
fs.copySync(polyPath("build/mdi"), staticPath("mdi"));
}
};
function copyPolyfills(staticDir) {
const copyPolyfills = (staticDir) => {
const staticPath = genStaticPath(staticDir);
// For custom panels using ES5 builds that don't use Babel 7+
@@ -70,9 +69,9 @@ function copyPolyfills(staticDir) {
npmPath("dialog-polyfill/dialog-polyfill.css"),
staticPath("polyfills/")
);
}
};
function copyFonts(staticDir) {
const copyFonts = (staticDir) => {
const staticPath = genStaticPath(staticDir);
// Local fonts
fs.copySync(
@@ -82,14 +81,14 @@ function copyFonts(staticDir) {
filter: (src) => !src.includes(".") || src.endsWith(".woff2"),
}
);
}
};
function copyQrScannerWorker(staticDir) {
const copyQrScannerWorker = (staticDir) => {
const staticPath = genStaticPath(staticDir);
copyFileDir(npmPath("qr-scanner/qr-scanner-worker.min.js"), staticPath("js"));
}
};
function copyMapPanel(staticDir) {
const copyMapPanel = (staticDir) => {
const staticPath = genStaticPath(staticDir);
copyFileDir(
npmPath("leaflet/dist/leaflet.css"),
@@ -103,43 +102,38 @@ function copyMapPanel(staticDir) {
npmPath("leaflet/dist/images"),
staticPath("images/leaflet/images/")
);
}
};
function copyZXingWasm(staticDir) {
const copyZXingWasm = (staticDir) => {
const staticPath = genStaticPath(staticDir);
copyFileDir(
npmPath("zxing-wasm/dist/reader/zxing_reader.wasm"),
staticPath("js")
);
}
};
gulp.task("copy-locale-data", async () => {
const staticDir = paths.app_output_static;
copyLocaleData(staticDir);
});
gulp.task("copy-translations-app", async () => {
export const copyTranslationsApp = async () => {
const staticDir = paths.app_output_static;
copyTranslations(staticDir);
});
};
gulp.task("copy-translations-supervisor", async () => {
export const copyTranslationsSupervisor = async () => {
const staticDir = paths.hassio_output_static;
copyTranslations(staticDir);
});
};
gulp.task("copy-translations-landing-page", async () => {
export const copyTranslationsLandingPage = async () => {
const staticDir = paths.landingPage_output_static;
copyTranslations(staticDir);
});
};
gulp.task("copy-static-supervisor", async () => {
export const copyStaticSupervisor = async () => {
const staticDir = paths.hassio_output_static;
copyLocaleData(staticDir);
copyFonts(staticDir);
});
};
gulp.task("copy-static-app", async () => {
export const copyStaticApp = async () => {
const staticDir = paths.app_output_static;
// Basic static files
fs.copySync(polyPath("public"), paths.app_output_root);
@@ -155,9 +149,9 @@ gulp.task("copy-static-app", async () => {
// Qr Scanner assets
copyZXingWasm(staticDir);
copyQrScannerWorker(staticDir);
});
};
gulp.task("copy-static-demo", async () => {
export const copyStaticDemo = async () => {
// Copy app static files
fs.copySync(
polyPath("public/static"),
@@ -171,9 +165,9 @@ gulp.task("copy-static-demo", async () => {
copyTranslations(paths.demo_output_static);
copyLocaleData(paths.demo_output_static);
copyMdiIcons(paths.demo_output_static);
});
};
gulp.task("copy-static-cast", async () => {
export const copyStaticCast = async () => {
// Copy app static files
fs.copySync(polyPath("public/static"), paths.cast_output_static);
// Copy cast static files
@@ -184,9 +178,9 @@ gulp.task("copy-static-cast", async () => {
copyTranslations(paths.cast_output_static);
copyLocaleData(paths.cast_output_static);
copyMdiIcons(paths.cast_output_static);
});
};
gulp.task("copy-static-gallery", async () => {
export const copyStaticGallery = async () => {
// Copy app static files
fs.copySync(polyPath("public/static"), paths.gallery_output_static);
// Copy gallery static files
@@ -200,9 +194,9 @@ gulp.task("copy-static-gallery", async () => {
copyTranslations(paths.gallery_output_static);
copyLocaleData(paths.gallery_output_static);
copyMdiIcons(paths.gallery_output_static);
});
};
gulp.task("copy-static-landing-page", async () => {
export const copyStaticLandingPage = async () => {
// Copy landing-page static files
fs.copySync(
path.resolve(paths.landingPage_dir, "public"),
@@ -211,4 +205,4 @@ gulp.task("copy-static-landing-page", async () => {
copyFonts(paths.landingPage_output_static);
copyTranslations(paths.landingPage_output_static);
});
};

View File

@@ -1,8 +1,7 @@
import fs from "fs";
import gulp from "gulp";
import fs from "node:fs";
import path from "node:path";
import hash from "object-hash";
import path from "path";
import paths from "../paths.cjs";
import paths from "../paths.ts";
const ICON_PACKAGE_PATH = path.resolve("node_modules/@mdi/svg/");
const META_PATH = path.resolve(ICON_PACKAGE_PATH, "meta.json");
@@ -21,7 +20,7 @@ const getMeta = () => {
encoding,
});
return {
path: svg.match(/ d="([^"]+)"/)[1],
path: svg.match(/ d="([^"]+)"/)?.[1],
name: icon.name,
tags: icon.tags,
aliases: icon.aliases,
@@ -55,14 +54,14 @@ const orderMeta = (meta) => {
};
const splitBySize = (meta) => {
const chunks = [];
const chunks: any[] = [];
const CHUNK_SIZE = 50000;
let curSize = 0;
let startKey;
let icons = [];
let icons: any[] = [];
Object.values(meta).forEach((icon) => {
Object.values(meta).forEach((icon: any) => {
if (startKey === undefined) {
startKey = icon.name;
}
@@ -94,10 +93,10 @@ const findDifferentiator = (curString, prevString) => {
return curString.substring(0, i + 1);
}
}
throw new Error("Cannot find differentiator", curString, prevString);
throw new Error(`Cannot find differentiator; ${curString}; ${prevString}`);
};
gulp.task("gen-icons-json", (done) => {
export const genIconsJson = (done) => {
const meta = getMeta();
const metaAndRemoved = addRemovedMeta(meta);
@@ -106,7 +105,7 @@ gulp.task("gen-icons-json", (done) => {
if (!fs.existsSync(OUTPUT_DIR)) {
fs.mkdirSync(OUTPUT_DIR, { recursive: true });
}
const parts = [];
const parts: any[] = [];
let lastEnd;
split.forEach((chunk) => {
@@ -153,13 +152,13 @@ gulp.task("gen-icons-json", (done) => {
);
done();
});
};
gulp.task("gen-dummy-icons-json", (done) => {
export const genDummyIconsJson = (done) => {
if (!fs.existsSync(OUTPUT_DIR)) {
fs.mkdirSync(OUTPUT_DIR, { recursive: true });
}
fs.writeFileSync(path.resolve(OUTPUT_DIR, "iconList.json"), "[]");
done();
});
};

View File

@@ -1,45 +0,0 @@
import gulp from "gulp";
import env from "../env.cjs";
import "./clean.js";
import "./compress.js";
import "./entry-html.js";
import "./gather-static.js";
import "./gen-icons-json.js";
import "./translations.js";
import "./rspack.js";
gulp.task(
"develop-hassio",
gulp.series(
async function setEnv() {
process.env.NODE_ENV = "development";
},
"clean-hassio",
"gen-dummy-icons-json",
"gen-pages-hassio-dev",
"build-supervisor-translations",
"copy-translations-supervisor",
"build-locale-data",
"copy-static-supervisor",
"rspack-watch-hassio"
)
);
gulp.task(
"build-hassio",
gulp.series(
async function setEnv() {
process.env.NODE_ENV = "production";
},
"clean-hassio",
"gen-dummy-icons-json",
"build-supervisor-translations",
"copy-translations-supervisor",
"build-locale-data",
"copy-static-supervisor",
"rspack-prod-hassio",
"gen-pages-hassio-prod",
...// Don't compress running tests
(env.isTestBuild() ? [] : ["compress-hassio"])
)
);

View File

@@ -0,0 +1,45 @@
import { series } from "gulp";
import { isTestBuild } from "../env.ts";
import { cleanHassio } from "./clean.ts";
import { compressHassio } from "./compress.ts";
import { genPagesHassioDev, genPagesHassioProd } from "./entry-html.ts";
import {
copyStaticSupervisor,
copyTranslationsSupervisor,
} from "./gather-static.ts";
import { genDummyIconsJson } from "./gen-icons-json.ts";
import { buildLocaleData } from "./locale-data.ts";
import { rspackProdHassio, rspackWatchHassio } from "./rspack.ts";
import { buildSupervisorTranslations } from "./translations.ts";
// develop-hassio
export const developHassio = series(
async function setEnv() {
process.env.NODE_ENV = "development";
},
cleanHassio,
genDummyIconsJson,
genPagesHassioDev,
buildSupervisorTranslations,
copyTranslationsSupervisor,
buildLocaleData,
copyStaticSupervisor,
rspackWatchHassio
);
// build-hassio
export const buildHassio = series(
async function setEnv() {
process.env.NODE_ENV = "production";
},
cleanHassio,
genDummyIconsJson,
buildSupervisorTranslations,
copyTranslationsSupervisor,
buildLocaleData,
copyStaticSupervisor,
rspackProdHassio,
genPagesHassioProd,
...// Don't compress running tests
(isTestBuild() ? [] : [compressHassio])
);

View File

@@ -1,17 +0,0 @@
import "./app.js";
import "./cast.js";
import "./clean.js";
import "./compress.js";
import "./demo.js";
import "./download-translations.js";
import "./entry-html.js";
import "./fetch-nightly-translations.js";
import "./gallery.js";
import "./gather-static.js";
import "./gen-icons-json.js";
import "./hassio.js";
import "./landing-page.js";
import "./locale-data.js";
import "./rspack.js";
import "./service-worker.js";
import "./translations.js";

View File

@@ -0,0 +1,42 @@
import { analyzeApp, buildApp, developApp } from "./app";
import { buildCast, developCast } from "./cast";
import { analyzeDemo, buildDemo, developDemo } from "./demo";
import { downloadTranslations } from "./download-translations";
import { setupAndFetchNightlyTranslations } from "./fetch-nightly-translations";
import { buildGallery, developGallery, gatherGalleryPages } from "./gallery";
import { genIconsJson } from "./gen-icons-json";
import { buildHassio, developHassio } from "./hassio";
import { buildLandingPage, developLandingPage } from "./landing-page";
import { buildLocaleData } from "./locale-data";
import { buildTranslations } from "./translations";
export default {
"develop-app": developApp,
"build-app": buildApp,
"analyze-app": analyzeApp,
"develop-cast": developCast,
"build-cast": buildCast,
"develop-demo": developDemo,
"build-demo": buildDemo,
"analyze-demo": analyzeDemo,
"develop-gallery": developGallery,
"build-gallery": buildGallery,
"gather-gallery-pages": gatherGalleryPages,
"develop-hassio": developHassio,
"build-hassio": buildHassio,
"develop-landing-page": developLandingPage,
"build-landing-page": buildLandingPage,
"setup-and-fetch-nightly-translations": setupAndFetchNightlyTranslations,
"download-translations": downloadTranslations,
"build-translations": buildTranslations,
"gen-icons-json": genIconsJson,
"build-locale-data": buildLocaleData,
};

View File

@@ -1,41 +0,0 @@
import gulp from "gulp";
import "./clean.js";
import "./compress.js";
import "./entry-html.js";
import "./gather-static.js";
import "./gen-icons-json.js";
import "./translations.js";
import "./rspack.js";
gulp.task(
"develop-landing-page",
gulp.series(
async function setEnv() {
process.env.NODE_ENV = "development";
},
"clean-landing-page",
"translations-enable-merge-backend",
"build-landing-page-translations",
"copy-translations-landing-page",
"build-locale-data",
"copy-static-landing-page",
"gen-pages-landing-page-dev",
"rspack-watch-landing-page"
)
);
gulp.task(
"build-landing-page",
gulp.series(
async function setEnv() {
process.env.NODE_ENV = "production";
},
"clean-landing-page",
"build-landing-page-translations",
"copy-translations-landing-page",
"build-locale-data",
"copy-static-landing-page",
"rspack-prod-landing-page",
"gen-pages-landing-page-prod"
)
);

View File

@@ -0,0 +1,46 @@
import { series } from "gulp";
import { cleanLandingPage } from "./clean.ts";
import "./compress.ts";
import {
genPagesLandingPageDev,
genPagesLandingPageProd,
} from "./entry-html.ts";
import {
copyStaticLandingPage,
copyTranslationsLandingPage,
} from "./gather-static.ts";
import { buildLocaleData } from "./locale-data.ts";
import { rspackProdLandingPage, rspackWatchLandingPage } from "./rspack.ts";
import {
buildLandingPageTranslations,
translationsEnableMergeBackend,
} from "./translations.ts";
// develop-landing-page
export const developLandingPage = series(
async function setEnv() {
process.env.NODE_ENV = "development";
},
cleanLandingPage,
translationsEnableMergeBackend,
buildLandingPageTranslations,
copyTranslationsLandingPage,
buildLocaleData,
copyStaticLandingPage,
genPagesLandingPageDev,
rspackWatchLandingPage
);
// build-landing-page
export const buildLandingPage = series(
async function setEnv() {
process.env.NODE_ENV = "production";
},
cleanLandingPage,
buildLandingPageTranslations,
copyTranslationsLandingPage,
buildLocaleData,
copyStaticLandingPage,
rspackProdLandingPage,
genPagesLandingPageProd
);

View File

@@ -1,8 +1,8 @@
import { deleteSync } from "del";
import { mkdir, readFile, writeFile } from "fs/promises";
import gulp from "gulp";
import { series } from "gulp";
import { mkdir, readFile, writeFile } from "node:fs/promises";
import { join, resolve } from "node:path";
import paths from "../paths.cjs";
import paths from "../paths.ts";
const formatjsDir = join(paths.root_dir, "node_modules", "@formatjs");
const outDir = join(paths.build_dir, "locale-data");
@@ -31,7 +31,7 @@ const convertToJSON = async (
join(formatjsDir, pkg, subDir, `${language}.js`),
"utf-8"
);
} catch (e) {
} catch (e: any) {
// Ignore if language is missing (i.e. not supported by @formatjs)
if (e.code === "ENOENT" && skipMissing) {
console.warn(`Skipped missing data for language ${lang} from ${pkg}`);
@@ -54,16 +54,16 @@ const convertToJSON = async (
await writeFile(join(outDir, `${pkg}/${lang}.json`), localeData);
};
gulp.task("clean-locale-data", async () => deleteSync([outDir]));
const cleanLocaleData = async () => deleteSync([outDir]);
gulp.task("create-locale-data", async () => {
const createLocaleData = async () => {
const translationMeta = JSON.parse(
await readFile(
resolve(paths.translations_src, "translationMetadata.json"),
"utf-8"
)
);
const conversions = [];
const conversions: any[] = [];
for (const pkg of Object.keys(INTL_POLYFILLS)) {
// eslint-disable-next-line no-await-in-loop
await mkdir(join(outDir, pkg), { recursive: true });
@@ -81,9 +81,6 @@ gulp.task("create-locale-data", async () => {
)
);
await Promise.all(conversions);
});
};
gulp.task(
"build-locale-data",
gulp.series("clean-locale-data", "create-locale-data")
);
export const buildLocaleData = series(cleanLocaleData, createLocaleData);

View File

@@ -1,13 +1,13 @@
// Tasks to run rspack.
import fs from "fs";
import path from "path";
import log from "fancy-log";
import gulp from "gulp";
import rspack from "@rspack/core";
import { RspackDevServer } from "@rspack/dev-server";
import env from "../env.cjs";
import paths from "../paths.cjs";
import log from "fancy-log";
import { series, watch } from "gulp";
import fs from "node:fs";
import path from "node:path";
import { isDevContainer, isStatsBuild, isTestBuild } from "../env.ts";
import paths from "../paths.ts";
import {
createAppConfig,
createCastConfig,
@@ -15,7 +15,17 @@ import {
createGalleryConfig,
createHassioConfig,
createLandingPageConfig,
} from "../rspack.cjs";
} from "../rspack.ts";
import {
copyTranslationsApp,
copyTranslationsLandingPage,
copyTranslationsSupervisor,
} from "./gather-static.ts";
import {
buildLandingPageTranslations,
buildSupervisorTranslations,
buildTranslations,
} from "./translations.ts";
const bothBuilds = (createConfigFunc, params) => [
createConfigFunc({ ...params, latestBuild: true }),
@@ -29,6 +39,14 @@ const isWsl =
.toLocaleLowerCase()
.includes("microsoft");
interface RunDevServer {
compiler: any;
contentBase: string;
port: number;
listenHost?: string;
proxy?: any;
}
/**
* @param {{
* compiler: import("@rspack/core").Compiler,
@@ -41,12 +59,12 @@ const runDevServer = async ({
compiler,
contentBase,
port,
listenHost = undefined,
proxy = undefined,
}) => {
listenHost,
proxy,
}: RunDevServer) => {
if (listenHost === undefined) {
// For dev container, we need to listen on all hosts
listenHost = env.isDevContainer() ? "0.0.0.0" : "localhost";
listenHost = isDevContainer() ? "0.0.0.0" : "localhost";
}
const server = new RspackDevServer(
{
@@ -68,7 +86,7 @@ const runDevServer = async ({
log("[rspack-dev-server]", `Project is running at http://localhost:${port}`);
};
const doneHandler = (done) => (err, stats) => {
const doneHandler = (done?: (value?: unknown) => void) => (err, stats) => {
if (err) {
log.error(err.stack || err);
if (err.details) {
@@ -97,49 +115,46 @@ const prodBuild = (conf) =>
);
});
gulp.task("rspack-watch-app", () => {
export const rspackWatchApp = () => {
// This command will run forever because we don't close compiler
rspack(
process.env.ES5
? bothBuilds(createAppConfig, { isProdBuild: false })
: createAppConfig({ isProdBuild: false, latestBuild: true })
).watch({ poll: isWsl }, doneHandler());
gulp.watch(
watch(
path.join(paths.translations_src, "en.json"),
gulp.series("build-translations", "copy-translations-app")
series(buildTranslations, copyTranslationsApp)
);
});
};
gulp.task("rspack-prod-app", () =>
export const rspackProdApp = () =>
prodBuild(
bothBuilds(createAppConfig, {
isProdBuild: true,
isStatsBuild: env.isStatsBuild(),
isTestBuild: env.isTestBuild(),
isStatsBuild: isStatsBuild(),
isTestBuild: isTestBuild(),
})
)
);
);
gulp.task("rspack-dev-server-demo", () =>
export const rspackDevServerDemo = () =>
runDevServer({
compiler: rspack(
createDemoConfig({ isProdBuild: false, latestBuild: true })
),
contentBase: paths.demo_output_root,
port: 8090,
})
);
});
gulp.task("rspack-prod-demo", () =>
export const rspackProdDemo = () =>
prodBuild(
bothBuilds(createDemoConfig, {
isProdBuild: true,
isStatsBuild: env.isStatsBuild(),
isStatsBuild: isStatsBuild(),
})
)
);
);
gulp.task("rspack-dev-server-cast", () =>
export const rspackDevServerCast = () =>
runDevServer({
compiler: rspack(
createCastConfig({ isProdBuild: false, latestBuild: true })
@@ -148,18 +163,16 @@ gulp.task("rspack-dev-server-cast", () =>
port: 8080,
// Accessible from the network, because that's how Cast hits it.
listenHost: "0.0.0.0",
})
);
});
gulp.task("rspack-prod-cast", () =>
export const rspackProdCast = () =>
prodBuild(
bothBuilds(createCastConfig, {
isProdBuild: true,
})
)
);
);
gulp.task("rspack-watch-hassio", () => {
export const rspackWatchHassio = () => {
// This command will run forever because we don't close compiler
rspack(
createHassioConfig({
@@ -168,23 +181,22 @@ gulp.task("rspack-watch-hassio", () => {
})
).watch({ ignored: /build/, poll: isWsl }, doneHandler());
gulp.watch(
watch(
path.join(paths.translations_src, "en.json"),
gulp.series("build-supervisor-translations", "copy-translations-supervisor")
series(buildSupervisorTranslations, copyTranslationsSupervisor)
);
});
};
gulp.task("rspack-prod-hassio", () =>
export const rspackProdHassio = () =>
prodBuild(
bothBuilds(createHassioConfig, {
isProdBuild: true,
isStatsBuild: env.isStatsBuild(),
isTestBuild: env.isTestBuild(),
isStatsBuild: isStatsBuild(),
isTestBuild: isTestBuild(),
})
)
);
);
gulp.task("rspack-dev-server-gallery", () =>
export const rspackDevServerGallery = () =>
runDevServer({
compiler: rspack(
createGalleryConfig({ isProdBuild: false, latestBuild: true })
@@ -192,19 +204,17 @@ gulp.task("rspack-dev-server-gallery", () =>
contentBase: paths.gallery_output_root,
port: 8100,
listenHost: "0.0.0.0",
})
);
});
gulp.task("rspack-prod-gallery", () =>
export const rspackProdGallery = () =>
prodBuild(
createGalleryConfig({
isProdBuild: true,
latestBuild: true,
})
)
);
);
gulp.task("rspack-watch-landing-page", () => {
export const rspackWatchLandingPage = () => {
// This command will run forever because we don't close compiler
rspack(
process.env.ES5
@@ -212,21 +222,17 @@ gulp.task("rspack-watch-landing-page", () => {
: createLandingPageConfig({ isProdBuild: false, latestBuild: true })
).watch({ poll: isWsl }, doneHandler());
gulp.watch(
watch(
path.join(paths.translations_src, "en.json"),
gulp.series(
"build-landing-page-translations",
"copy-translations-landing-page"
)
series(buildLandingPageTranslations, copyTranslationsLandingPage)
);
});
};
gulp.task("rspack-prod-landing-page", () =>
export const rspackProdLandingPage = () =>
prodBuild(
bothBuilds(createLandingPageConfig, {
isProdBuild: true,
isStatsBuild: env.isStatsBuild(),
isTestBuild: env.isTestBuild(),
isStatsBuild: isStatsBuild(),
isTestBuild: isTestBuild(),
})
)
);
);

View File

@@ -1,11 +1,10 @@
// Generate service workers
import { deleteAsync } from "del";
import gulp from "gulp";
import { mkdir, readFile, symlink, writeFile } from "node:fs/promises";
import { basename, join, relative } from "node:path";
import { injectManifest } from "workbox-build";
import paths from "../paths.cjs";
import paths from "../paths.ts";
const SW_MAP = {
[paths.app_output_latest]: "modern",
@@ -23,7 +22,7 @@ self.addEventListener('install', (event) => {
});
`.trim() + "\n";
gulp.task("gen-service-worker-app-dev", async () => {
export const genServiceWorkerAppDev = async () => {
await mkdir(paths.app_output_root, { recursive: true });
await Promise.all(
Object.values(SW_MAP).map((build) =>
@@ -32,9 +31,9 @@ gulp.task("gen-service-worker-app-dev", async () => {
})
)
);
});
};
gulp.task("gen-service-worker-app-prod", () =>
export const genServiceWorkerAppProd = () =>
Promise.all(
Object.entries(SW_MAP).map(async ([outPath, build]) => {
const manifest = JSON.parse(
@@ -83,5 +82,4 @@ gulp.task("gen-service-worker-app-prod", () =>
await symlink(basename(swDest), swOld);
}
})
)
);
);

View File

@@ -2,7 +2,7 @@
import { deleteAsync } from "del";
import { glob } from "glob";
import gulp from "gulp";
import { src as glupSrc, dest as gulpDest, parallel, series } from "gulp";
import rename from "gulp-rename";
import merge from "lodash.merge";
import { createHash } from "node:crypto";
@@ -10,9 +10,12 @@ import { mkdir, readFile } from "node:fs/promises";
import { basename, join } from "node:path";
import { PassThrough, Transform } from "node:stream";
import { finished } from "node:stream/promises";
import env from "../env.cjs";
import paths from "../paths.cjs";
import "./fetch-nightly-translations.js";
import { isProdBuild } from "../env.ts";
import paths from "../paths.ts";
import {
allowSetupFetchNightlyTranslations,
fetchNightlyTranslations,
} from "./fetch-nightly-translations.ts";
const inFrontendDir = "translations/frontend";
const inBackendDir = "translations/backend";
@@ -23,18 +26,20 @@ const TEST_LOCALE = "en-x-test";
let mergeBackend = false;
gulp.task(
"translations-enable-merge-backend",
gulp.parallel(async () => {
mergeBackend = true;
}, "allow-setup-fetch-nightly-translations")
);
// translations-enable-merge-backend
export const translationsEnableMergeBackend = parallel(async () => {
mergeBackend = true;
}, allowSetupFetchNightlyTranslations);
// Transform stream to apply a function on Vinyl JSON files (buffer mode only).
// The provided function can either return a new object, or an array of
// [object, subdirectory] pairs for fragmentizing the JSON.
class CustomJSON extends Transform {
constructor(func, reviver = null) {
_func: any;
_reviver: any;
constructor(func, reviver: any = null) {
super({ objectMode: true });
this._func = func;
this._reviver = reviver;
@@ -56,9 +61,17 @@ class CustomJSON extends Transform {
// Transform stream to merge Vinyl JSON files (buffer mode only).
class MergeJSON extends Transform {
_objects = [];
_objects: any[] = [];
constructor(stem, startObj = {}, reviver = null) {
_stem: any;
_startObj: any;
_reviver: any;
_outFile: any;
constructor(stem, startObj = {}, reviver: any = null) {
super({ objectMode: true, allowHalfOpen: false });
this._stem = stem;
this._startObj = structuredClone(startObj);
@@ -111,11 +124,12 @@ const testReviver = (_key, value) =>
const KEY_REFERENCE = /\[%key:([^%]+)%\]/;
const lokaliseTransform = (data, path, original = data) => {
const output = {};
for (const [key, value] of Object.entries(data)) {
for (const entry of Object.entries(data)) {
const [key, value] = entry as [string, string];
if (typeof value === "object") {
output[key] = lokaliseTransform(value, path, original);
} else {
output[key] = value.replace(KEY_REFERENCE, (_match, lokalise_key) => {
output[key] = value?.replace(KEY_REFERENCE, (_match, lokalise_key) => {
const replace = lokalise_key.split("::").reduce((tr, k) => {
if (!tr) {
throw Error(`Invalid key placeholder ${lokalise_key} in ${path}`);
@@ -132,18 +146,17 @@ const lokaliseTransform = (data, path, original = data) => {
return output;
};
gulp.task("clean-translations", () => deleteAsync([workDir]));
export const cleanTranslations = () => deleteAsync([workDir]);
const makeWorkDir = () => mkdir(workDir, { recursive: true });
const createTestTranslation = () =>
env.isProdBuild()
isProdBuild()
? Promise.resolve()
: gulp
.src(EN_SRC)
: glupSrc(EN_SRC)
.pipe(new CustomJSON(null, testReviver))
.pipe(rename(`${TEST_LOCALE}.json`))
.pipe(gulp.dest(workDir));
.pipe(gulpDest(workDir));
/**
* This task will build a master translation file, to be used as the base for
@@ -155,11 +168,10 @@ const createTestTranslation = () =>
* the Lokalise update to translations/en.json will not happen immediately.
*/
const createMasterTranslation = () =>
gulp
.src([EN_SRC, ...(mergeBackend ? [`${inBackendDir}/en.json`] : [])])
glupSrc([EN_SRC, ...(mergeBackend ? [`${inBackendDir}/en.json`] : [])])
.pipe(new CustomJSON(lokaliseTransform))
.pipe(new MergeJSON("en"))
.pipe(gulp.dest(workDir));
.pipe(gulpDest(workDir));
const FRAGMENTS = ["base"];
@@ -186,12 +198,12 @@ const createTranslations = async () => {
// each locale, then fragmentizes and flattens the data for final output.
const translationFiles = await glob([
`${inFrontendDir}/!(en).json`,
...(env.isProdBuild() ? [] : [`${workDir}/${TEST_LOCALE}.json`]),
...(isProdBuild() ? [] : [`${workDir}/${TEST_LOCALE}.json`]),
]);
const hashStream = new Transform({
objectMode: true,
transform: async (file, _, callback) => {
const hash = env.isProdBuild()
const hash = isProdBuild()
? createHash("md5").update(file.contents).digest("hex")
: "dev";
HASHES.set(file.stem, hash);
@@ -230,7 +242,7 @@ const createTranslations = async () => {
})
)
)
.pipe(gulp.dest(outDir));
.pipe(gulpDest(outDir));
// Send the English master downstream first, then for each other locale
// generate merged JSON data to continue piping. It begins with the master
@@ -240,15 +252,15 @@ const createTranslations = async () => {
// TODO: This is a naive interpretation of BCP47 that should be improved.
// Will be OK for now as long as we don't have anything more complicated
// than a base translation + region.
const masterStream = gulp
.src(`${workDir}/en.json`)
.pipe(new PassThrough({ objectMode: true }));
const masterStream = glupSrc(`${workDir}/en.json`).pipe(
new PassThrough({ objectMode: true })
);
masterStream.pipe(hashStream, { end: false });
const mergesFinished = [finished(masterStream)];
for (const translationFile of translationFiles) {
const locale = basename(translationFile, ".json");
const subtags = locale.split("-");
const mergeFiles = [];
const mergeFiles: string[] = [];
for (let i = 1; i <= subtags.length; i++) {
const lang = subtags.slice(0, i).join("-");
if (lang === TEST_LOCALE) {
@@ -260,9 +272,9 @@ const createTranslations = async () => {
}
}
}
const mergeStream = gulp
.src(mergeFiles, { allowEmpty: true })
.pipe(new MergeJSON(locale, enMaster, emptyReviver));
const mergeStream = glupSrc(mergeFiles, { allowEmpty: true }).pipe(
new MergeJSON(locale, enMaster, emptyReviver)
);
mergesFinished.push(finished(mergeStream));
mergeStream.pipe(hashStream, { end: false });
}
@@ -275,12 +287,11 @@ const createTranslations = async () => {
};
const writeTranslationMetaData = () =>
gulp
.src([`${paths.translations_src}/translationMetadata.json`])
glupSrc([`${paths.translations_src}/translationMetadata.json`])
.pipe(
new CustomJSON((meta) => {
// Add the test translation in development.
if (!env.isProdBuild()) {
if (!isProdBuild()) {
meta[TEST_LOCALE] = { nativeName: "Translation Test" };
}
// Filter out locales without a native name, and add the hashes.
@@ -300,28 +311,22 @@ const writeTranslationMetaData = () =>
};
})
)
.pipe(gulp.dest(workDir));
.pipe(gulpDest(workDir));
gulp.task(
"build-translations",
gulp.series(
gulp.parallel(
"fetch-nightly-translations",
gulp.series("clean-translations", makeWorkDir)
),
createTestTranslation,
createMasterTranslation,
createTranslations,
writeTranslationMetaData
)
export const buildTranslations = series(
parallel(fetchNightlyTranslations, series(cleanTranslations, makeWorkDir)),
createTestTranslation,
createMasterTranslation,
createTranslations,
writeTranslationMetaData
);
gulp.task(
"build-supervisor-translations",
gulp.series(setFragment("supervisor"), "build-translations")
export const buildSupervisorTranslations = series(
setFragment("supervisor"),
buildTranslations
);
gulp.task(
"build-landing-page-translations",
gulp.series(setFragment("landing-page"), "build-translations")
export const buildLandingPageTranslations = series(
setFragment("landing-page"),
buildTranslations
);

View File

@@ -5,10 +5,11 @@ import { version as babelVersion } from "@babel/core";
import presetEnv from "@babel/preset-env";
import compilationTargets from "@babel/helper-compilation-targets";
import coreJSCompat from "core-js-compat";
import { logPlugin } from "@babel/preset-env/lib/debug.js";
// eslint-disable-next-line import/no-relative-packages
import shippedPolyfills from "../node_modules/babel-plugin-polyfill-corejs3/lib/shipped-proposals.js";
import { babelOptions } from "./bundle.cjs";
import { babelOptions } from "./bundle.ts";
const detailsOpen = (heading) =>
`<details>\n<summary><h4>${heading}</h4></summary>\n`;
@@ -50,6 +51,12 @@ for (const buildType of ["Modern", "Legacy"]) {
const babelOpts = babelOptions({ latestBuild: browserslistEnv === "modern" });
const presetEnvOpts = babelOpts.presets[0][1];
if (typeof presetEnvOpts !== "object") {
throw new Error(
"The first preset in babelOptions is not an object. This is unexpected."
);
}
// Invoking preset-env in debug mode will log the included plugins
console.log(detailsOpen(`${buildType} Build Babel Plugins`));
presetEnv.default(dummyAPI, {

View File

@@ -1,63 +0,0 @@
const path = require("path");
module.exports = {
root_dir: path.resolve(__dirname, ".."),
build_dir: path.resolve(__dirname, "../build"),
app_output_root: path.resolve(__dirname, "../hass_frontend"),
app_output_static: path.resolve(__dirname, "../hass_frontend/static"),
app_output_latest: path.resolve(
__dirname,
"../hass_frontend/frontend_latest"
),
app_output_es5: path.resolve(__dirname, "../hass_frontend/frontend_es5"),
demo_dir: path.resolve(__dirname, "../demo"),
demo_output_root: path.resolve(__dirname, "../demo/dist"),
demo_output_static: path.resolve(__dirname, "../demo/dist/static"),
demo_output_latest: path.resolve(__dirname, "../demo/dist/frontend_latest"),
demo_output_es5: path.resolve(__dirname, "../demo/dist/frontend_es5"),
cast_dir: path.resolve(__dirname, "../cast"),
cast_output_root: path.resolve(__dirname, "../cast/dist"),
cast_output_static: path.resolve(__dirname, "../cast/dist/static"),
cast_output_latest: path.resolve(__dirname, "../cast/dist/frontend_latest"),
cast_output_es5: path.resolve(__dirname, "../cast/dist/frontend_es5"),
gallery_dir: path.resolve(__dirname, "../gallery"),
gallery_build: path.resolve(__dirname, "../gallery/build"),
gallery_output_root: path.resolve(__dirname, "../gallery/dist"),
gallery_output_latest: path.resolve(
__dirname,
"../gallery/dist/frontend_latest"
),
gallery_output_static: path.resolve(__dirname, "../gallery/dist/static"),
landingPage_dir: path.resolve(__dirname, "../landing-page"),
landingPage_build: path.resolve(__dirname, "../landing-page/build"),
landingPage_output_root: path.resolve(__dirname, "../landing-page/dist"),
landingPage_output_latest: path.resolve(
__dirname,
"../landing-page/dist/frontend_latest"
),
landingPage_output_es5: path.resolve(
__dirname,
"../landing-page/dist/frontend_es5"
),
landingPage_output_static: path.resolve(
__dirname,
"../landing-page/dist/static"
),
hassio_dir: path.resolve(__dirname, "../hassio"),
hassio_output_root: path.resolve(__dirname, "../hassio/build"),
hassio_output_static: path.resolve(__dirname, "../hassio/build/static"),
hassio_output_latest: path.resolve(
__dirname,
"../hassio/build/frontend_latest"
),
hassio_output_es5: path.resolve(__dirname, "../hassio/build/frontend_es5"),
hassio_publicPath: "/api/hassio/app",
translations_src: path.resolve(__dirname, "../src/translations"),
};

63
build-scripts/paths.ts Normal file
View File

@@ -0,0 +1,63 @@
import path, { dirname as pathDirname } from "node:path";
import { fileURLToPath } from "node:url";
export const dirname = pathDirname(fileURLToPath(import.meta.url));
export default {
root_dir: path.resolve(dirname, ".."),
build_dir: path.resolve(dirname, "../build"),
app_output_root: path.resolve(dirname, "../hass_frontend"),
app_output_static: path.resolve(dirname, "../hass_frontend/static"),
app_output_latest: path.resolve(dirname, "../hass_frontend/frontend_latest"),
app_output_es5: path.resolve(dirname, "../hass_frontend/frontend_es5"),
demo_dir: path.resolve(dirname, "../demo"),
demo_output_root: path.resolve(dirname, "../demo/dist"),
demo_output_static: path.resolve(dirname, "../demo/dist/static"),
demo_output_latest: path.resolve(dirname, "../demo/dist/frontend_latest"),
demo_output_es5: path.resolve(dirname, "../demo/dist/frontend_es5"),
cast_dir: path.resolve(dirname, "../cast"),
cast_output_root: path.resolve(dirname, "../cast/dist"),
cast_output_static: path.resolve(dirname, "../cast/dist/static"),
cast_output_latest: path.resolve(dirname, "../cast/dist/frontend_latest"),
cast_output_es5: path.resolve(dirname, "../cast/dist/frontend_es5"),
gallery_dir: path.resolve(dirname, "../gallery"),
gallery_build: path.resolve(dirname, "../gallery/build"),
gallery_output_root: path.resolve(dirname, "../gallery/dist"),
gallery_output_latest: path.resolve(
dirname,
"../gallery/dist/frontend_latest"
),
gallery_output_static: path.resolve(dirname, "../gallery/dist/static"),
landingPage_dir: path.resolve(dirname, "../landing-page"),
landingPage_build: path.resolve(dirname, "../landing-page/build"),
landingPage_output_root: path.resolve(dirname, "../landing-page/dist"),
landingPage_output_latest: path.resolve(
dirname,
"../landing-page/dist/frontend_latest"
),
landingPage_output_es5: path.resolve(
dirname,
"../landing-page/dist/frontend_es5"
),
landingPage_output_static: path.resolve(
dirname,
"../landing-page/dist/static"
),
hassio_dir: path.resolve(dirname, "../hassio"),
hassio_output_root: path.resolve(dirname, "../hassio/build"),
hassio_output_static: path.resolve(dirname, "../hassio/build/static"),
hassio_output_latest: path.resolve(
dirname,
"../hassio/build/frontend_latest"
),
hassio_output_es5: path.resolve(dirname, "../hassio/build/frontend_es5"),
hassio_publicPath: "/api/hassio/app",
translations_src: path.resolve(dirname, "../src/translations"),
};

View File

@@ -1,20 +1,25 @@
const { existsSync } = require("fs");
const path = require("path");
const rspack = require("@rspack/core");
// eslint-disable-next-line @typescript-eslint/naming-convention
const { RsdoctorRspackPlugin } = require("@rsdoctor/rspack-plugin");
// eslint-disable-next-line @typescript-eslint/naming-convention
const { StatsWriterPlugin } = require("webpack-stats-plugin");
const filterStats = require("@bundle-stats/plugin-webpack-filter");
// eslint-disable-next-line @typescript-eslint/naming-convention
const TerserPlugin = require("terser-webpack-plugin");
// eslint-disable-next-line @typescript-eslint/naming-convention
const { WebpackManifestPlugin } = require("rspack-manifest-plugin");
const log = require("fancy-log");
// eslint-disable-next-line @typescript-eslint/naming-convention
const WebpackBar = require("webpackbar/rspack");
const paths = require("./paths.cjs");
const bundle = require("./bundle.cjs");
import filterStats from "@bundle-stats/plugin-webpack-filter";
import { RsdoctorRspackPlugin } from "@rsdoctor/rspack-plugin";
import { DefinePlugin, NormalModuleReplacementPlugin } from "@rspack/core";
import { defineConfig } from "@rspack/cli";
import log from "fancy-log";
import { existsSync } from "node:fs";
import path from "node:path";
import { WebpackManifestPlugin } from "rspack-manifest-plugin";
import TerserPlugin from "terser-webpack-plugin";
import { StatsWriterPlugin } from "webpack-stats-plugin";
// @ts-ignore
import WebpackBar from "webpackbar/rspack";
import {
babelOptions,
config,
definedVars,
emptyPackages,
sourceMapURL,
swcOptions,
terserOptions,
} from "./bundle.ts";
import paths from "./paths.ts";
class LogStartCompilePlugin {
ignoredFirst = false;
@@ -30,7 +35,7 @@ class LogStartCompilePlugin {
}
}
const createRspackConfig = ({
export const createRspackConfig = ({
name,
entry,
outputPath,
@@ -42,12 +47,23 @@ const createRspackConfig = ({
isTestBuild,
isHassioBuild,
dontHash,
}: {
name: string;
entry: any;
outputPath: string;
publicPath: string;
defineOverlay?: Record<string, any>;
isProdBuild?: boolean;
latestBuild?: boolean;
isStatsBuild?: boolean;
isTestBuild?: boolean;
isHassioBuild?: boolean;
dontHash?: Set<string>;
}) => {
if (!dontHash) {
dontHash = new Set();
}
const ignorePackages = bundle.ignorePackages({ latestBuild });
return {
return defineConfig({
name,
mode: isProdBuild ? "production" : "development",
target: `browserslist:${latestBuild ? "modern" : "legacy"}`,
@@ -70,7 +86,7 @@ const createRspackConfig = ({
{
loader: "babel-loader",
options: {
...bundle.babelOptions({
...babelOptions({
latestBuild,
isProdBuild,
isTestBuild,
@@ -82,7 +98,7 @@ const createRspackConfig = ({
},
{
loader: "builtin:swc-loader",
options: bundle.swcOptions(),
options: swcOptions(),
},
],
resolve: {
@@ -103,7 +119,7 @@ const createRspackConfig = ({
new TerserPlugin({
parallel: true,
extractComments: true,
terserOptions: bundle.terserOptions({ latestBuild, isTestBuild }),
terserOptions: terserOptions({ latestBuild, isTestBuild }),
}),
],
moduleIds: isProdBuild && !isStatsBuild ? "deterministic" : "named",
@@ -122,7 +138,7 @@ const createRspackConfig = ({
!chunk.canBeInitial() &&
!new RegExp(
`^.+-work${latestBuild ? "(?:let|er)" : "let"}$`
).test(chunk.name),
).test(chunk?.name || ""),
},
},
plugins: [
@@ -131,44 +147,11 @@ const createRspackConfig = ({
// Only include the JS of entrypoints
filter: (file) => file.isInitial && !file.name.endsWith(".map"),
}),
new rspack.DefinePlugin(
bundle.definedVars({ isProdBuild, latestBuild, defineOverlay })
new DefinePlugin(
definedVars({ isProdBuild, latestBuild, defineOverlay })
),
new rspack.IgnorePlugin({
checkResource(resource, context) {
// Only use ignore to intercept imports that we don't control
// inside node_module dependencies.
if (
!context.includes("/node_modules/") ||
// calling define.amd will call require("!!webpack amd options")
resource.startsWith("!!webpack") ||
// loaded by webpack dev server but doesn't exist.
resource === "webpack/hot" ||
resource.startsWith("@swc/helpers")
) {
return false;
}
let fullPath;
try {
fullPath = resource.startsWith(".")
? path.resolve(context, resource)
: require.resolve(resource);
} catch (err) {
console.error(
"Error in Home Assistant ignore plugin",
resource,
context
);
throw err;
}
return ignorePackages.some((toIgnorePath) =>
fullPath.startsWith(toIgnorePath)
);
},
}),
new rspack.NormalModuleReplacementPlugin(
new RegExp(bundle.emptyPackages({ isHassioBuild }).join("|")),
new NormalModuleReplacementPlugin(
new RegExp(emptyPackages({ isHassioBuild }).join("|")),
path.resolve(paths.root_dir, "src/util/empty.js")
),
!isProdBuild && new LogStartCompilePlugin(),
@@ -184,7 +167,9 @@ const createRspackConfig = ({
isProdBuild &&
isStatsBuild &&
new RsdoctorRspackPlugin({
reportDir: path.join(paths.build_dir, "rsdoctor"),
output: {
reportDir: path.join(paths.build_dir, "rsdoctor"),
},
features: ["plugins", "bundle"],
supports: {
generateTileGraph: true,
@@ -219,7 +204,9 @@ const createRspackConfig = ({
output: {
module: latestBuild,
filename: ({ chunk }) =>
!isProdBuild || isStatsBuild || dontHash.has(chunk.name)
!isProdBuild ||
isStatsBuild ||
(chunk?.name && dontHash.has(chunk.name))
? "[name].js"
: "[name].[contenthash].js",
chunkFilename:
@@ -250,7 +237,7 @@ const createRspackConfig = ({
// dev tools, and they stay happy getting 404s with valid requests.
return `/unknown${path.resolve("/", info.resourcePath)}`;
}
return new URL(info.resourcePath, bundle.sourceMapURL()).href;
return new URL(info.resourcePath, sourceMapURL()).href;
}
: undefined,
])
@@ -260,35 +247,51 @@ const createRspackConfig = ({
layers: true,
outputModule: true,
},
};
});
};
const createAppConfig = ({
export const createAppConfig = ({
isProdBuild,
latestBuild,
isStatsBuild,
isTestBuild,
}: {
isProdBuild?: boolean;
latestBuild?: boolean;
isStatsBuild?: boolean;
isTestBuild?: boolean;
}) =>
createRspackConfig(
bundle.config.app({ isProdBuild, latestBuild, isStatsBuild, isTestBuild })
config.app({ isProdBuild, latestBuild, isStatsBuild, isTestBuild })
);
const createDemoConfig = ({ isProdBuild, latestBuild, isStatsBuild }) =>
createRspackConfig(
bundle.config.demo({ isProdBuild, latestBuild, isStatsBuild })
);
export const createDemoConfig = ({
isProdBuild,
latestBuild,
isStatsBuild,
}: {
isProdBuild?: boolean;
latestBuild?: boolean;
isStatsBuild?: boolean;
}) =>
createRspackConfig(config.demo({ isProdBuild, latestBuild, isStatsBuild }));
const createCastConfig = ({ isProdBuild, latestBuild }) =>
createRspackConfig(bundle.config.cast({ isProdBuild, latestBuild }));
export const createCastConfig = ({ isProdBuild, latestBuild }) =>
createRspackConfig(config.cast({ isProdBuild, latestBuild }));
const createHassioConfig = ({
export const createHassioConfig = ({
isProdBuild,
latestBuild,
isStatsBuild,
isTestBuild,
}: {
isProdBuild?: boolean;
latestBuild?: boolean;
isStatsBuild?: boolean;
isTestBuild?: boolean;
}) =>
createRspackConfig(
bundle.config.hassio({
config.hassio({
isProdBuild,
latestBuild,
isStatsBuild,
@@ -296,18 +299,8 @@ const createHassioConfig = ({
})
);
const createGalleryConfig = ({ isProdBuild, latestBuild }) =>
createRspackConfig(bundle.config.gallery({ isProdBuild, latestBuild }));
export const createGalleryConfig = ({ isProdBuild, latestBuild }) =>
createRspackConfig(config.gallery({ isProdBuild, latestBuild }));
const createLandingPageConfig = ({ isProdBuild, latestBuild }) =>
createRspackConfig(bundle.config.landingPage({ isProdBuild, latestBuild }));
module.exports = {
createAppConfig,
createDemoConfig,
createCastConfig,
createHassioConfig,
createGalleryConfig,
createRspackConfig,
createLandingPageConfig,
};
export const createLandingPageConfig = ({ isProdBuild, latestBuild }) =>
createRspackConfig(config.landingPage({ isProdBuild, latestBuild }));

42
build-scripts/runTask.ts Normal file
View File

@@ -0,0 +1,42 @@
// run-build.ts
import { series } from "gulp";
import { availableParallelism } from "node:os";
import tasks from "./gulp/index.ts";
process.env.UV_THREADPOOL_SIZE = availableParallelism().toString();
const runGulpTask = async (runTasks: string[]) => {
try {
for (const taskName of runTasks) {
if (tasks[taskName] === undefined) {
console.error(`Gulp task "${taskName}" does not exist.`);
console.log("Available tasks:");
Object.keys(tasks).forEach((task) => {
console.log(` - ${task}`);
});
process.exit(1);
}
}
await new Promise((resolve, reject) => {
series(...runTasks.map((taskName) => tasks[taskName]))((err?: Error) => {
if (err) {
reject(err);
} else {
resolve(null);
}
});
});
process.exit(0);
} catch (error: any) {
console.error(`Error running Gulp task "${runTasks}":`, error);
process.exit(1);
}
};
// Get the task name from command line arguments
// TODO arg validation
const tasksToRun = process.argv.slice(2);
runGulpTask(tasksToRun);

View File

@@ -6,4 +6,4 @@ set -e
cd "$(dirname "$0")/../.."
./node_modules/.bin/gulp build-cast
yarn run-task build-cast

View File

@@ -6,4 +6,4 @@ set -e
cd "$(dirname "$0")/../.."
./node_modules/.bin/gulp develop-cast
yarn run-task develop-cast

View File

@@ -88,7 +88,7 @@ class HcLayout extends LitElement {
font-family: var(--ha-card-header-font-family, inherit);
font-size: var(--ha-card-header-font-size, var(--ha-font-size-2xl));
letter-spacing: -0.012em;
line-height: 32px;
line-height: var(--ha-line-height-condensed);
padding: 24px 16px 16px;
display: block;
margin: 0;

View File

@@ -1,186 +0,0 @@
{
"schemaVersion": "1.0.0",
"readme": "",
"modules": [
{
"kind": "javascript-module",
"path": "src/components/ha-alert.ts",
"declarations": [
{
"kind": "class",
"description": "A custom alert component for displaying messages with various alert types.",
"name": "HaAlert",
"cssProperties": [
{
"description": "The color used for \"info\" alerts.",
"name": "--info-color"
},
{
"description": "The color used for \"warning\" alerts.",
"name": "--warning-color"
},
{
"description": "The color used for \"error\" alerts.",
"name": "--error-color"
},
{
"description": "The color used for \"success\" alerts.",
"name": "--success-color"
},
{
"description": "The primary text color used in the alert.",
"name": "--primary-text-color"
}
],
"cssParts": [
{
"description": "The container for the alert.",
"name": "issue-type"
},
{
"description": "The container for the alert icon.",
"name": "icon"
},
{
"description": "The container for the alert content.",
"name": "content"
},
{
"description": "The container for the alert actions.",
"name": "action"
},
{
"description": "The container for the alert title.",
"name": "title"
}
],
"slots": [
{
"description": "The main content of the alert.",
"name": ""
},
{
"description": "Slot for providing a custom icon for the alert.",
"name": "icon"
},
{
"description": "Slot for providing custom actions or buttons for the alert.",
"name": "action"
}
],
"members": [
{
"kind": "field",
"name": "title",
"type": {
"text": "string"
},
"privacy": "public",
"default": "\"\"",
"description": "The title of the alert. Defaults to an empty string.",
"attribute": "title"
},
{
"kind": "field",
"name": "alertType",
"type": {
"text": "\"info\" | \"warning\" | \"error\" | \"success\""
},
"privacy": "public",
"default": "\"info\"",
"description": "The type of alert to display. Defaults to \"info\". Determines the styling and icon used.",
"attribute": "alert-type"
},
{
"kind": "field",
"name": "dismissable",
"type": {
"text": "boolean"
},
"privacy": "public",
"default": "false",
"description": "Whether the alert can be dismissed. Defaults to `false`. If `true`, a dismiss button is displayed.",
"attribute": "dismissable"
},
{
"kind": "field",
"name": "narrow",
"type": {
"text": "boolean"
},
"privacy": "public",
"default": "false",
"description": "Whether the alert should use a narrow layout. Defaults to `false`.",
"attribute": "narrow"
},
{
"kind": "method",
"name": "_dismissClicked",
"privacy": "private"
}
],
"events": [
{
"description": "Fired when the dismiss button is clicked.",
"name": "alert-dismissed-clicked"
}
],
"attributes": [
{
"name": "title",
"type": {
"text": "string"
},
"default": "\"\"",
"description": "The title of the alert. Defaults to an empty string.",
"fieldName": "title"
},
{
"name": "alert-type",
"type": {
"text": "\"info\" | \"warning\" | \"error\" | \"success\""
},
"default": "\"info\"",
"description": "The type of alert to display. Defaults to \"info\". Determines the styling and icon used.",
"fieldName": "alertType"
},
{
"name": "dismissable",
"type": {
"text": "boolean"
},
"default": "false",
"description": "Whether the alert can be dismissed. Defaults to `false`. If `true`, a dismiss button is displayed.",
"fieldName": "dismissable"
},
{
"name": "narrow",
"type": {
"text": "boolean"
},
"default": "false",
"description": "Whether the alert should use a narrow layout. Defaults to `false`.",
"fieldName": "narrow"
}
],
"superclass": {
"name": "LitElement",
"package": "lit"
},
"tagName": "ha-alert",
"customElement": true
}
],
"exports": [
{
"kind": "custom-element-definition",
"name": "ha-alert",
"declaration": {
"name": "HaAlert",
"module": "src/components/ha-alert.ts"
}
}
]
}
]
}

View File

@@ -6,4 +6,4 @@ set -e
cd "$(dirname "$0")/../.."
./node_modules/.bin/gulp build-demo
yarn run-task build-demo

View File

@@ -6,4 +6,4 @@ set -e
cd "$(dirname "$0")/../.."
./node_modules/.bin/gulp develop-demo
yarn run-task develop-demo

View File

@@ -6,4 +6,4 @@ set -e
cd "$(dirname "$0")/../.."
./node_modules/.bin/gulp analyze-demo
yarn run-task analyze-demo

View File

@@ -68,7 +68,7 @@
}
#ha-launch-screen .ha-launch-screen-spacer-top {
flex: 1;
margin-top: calc( 2 * max(env(safe-area-inset-bottom), 48px) + 46px );
margin-top: calc( 2 * max(var(--safe-area-inset-bottom), 48px) + 46px );
padding-top: 48px;
}
#ha-launch-screen .ha-launch-screen-spacer-bottom {
@@ -76,7 +76,7 @@
padding-top: 48px;
}
.ohf-logo {
margin: max(env(safe-area-inset-bottom), 48px) 0;
margin: max(var(--safe-area-inset-bottom), 48px) 0;
display: flex;
flex-direction: column;
align-items: center;

View File

@@ -1,7 +1,30 @@
import type { MockHomeAssistant } from "../../../src/fake_data/provide_hass";
let changeFunction;
export const mockFrontend = (hass: MockHomeAssistant) => {
hass.mockWS("frontend/get_user_data", () => ({
value: null,
}));
hass.mockWS("frontend/set_user_data", ({ key, value }) => {
if (key === "sidebar") {
changeFunction?.({
value: {
panelOrder: value.panelOrder || [],
hiddenPanels: value.hiddenPanels || [],
},
});
}
});
hass.mockWS("frontend/subscribe_user_data", (_msg, _hass, onChange) => {
changeFunction = onChange;
onChange?.({
value: {
panelOrder: [],
hiddenPanels: [],
},
});
// eslint-disable-next-line @typescript-eslint/no-empty-function
return () => {};
});
};

View File

@@ -11,6 +11,7 @@ import tseslint from "typescript-eslint";
import eslintConfigPrettier from "eslint-config-prettier";
import { configs as litConfigs } from "eslint-plugin-lit";
import { configs as wcConfigs } from "eslint-plugin-wc";
import { configs as a11yConfigs } from "eslint-plugin-lit-a11y";
const _filename = fileURLToPath(import.meta.url);
const _dirname = path.dirname(_filename);
@@ -21,13 +22,14 @@ const compat = new FlatCompat({
});
export default tseslint.config(
...compat.extends("airbnb-base", "plugin:lit-a11y/recommended"),
...compat.extends("airbnb-base"),
eslintConfigPrettier,
litConfigs["flat/all"],
tseslint.configs.recommended,
tseslint.configs.strict,
tseslint.configs.stylistic,
wcConfigs["flat/recommended"],
a11yConfigs.recommended,
{
plugins: {
"unused-imports": unusedImports,
@@ -54,15 +56,6 @@ export default tseslint.config(
},
},
},
settings: {
"import/resolver": {
webpack: {
config: "./rspack.config.cjs",
},
},
},
rules: {
"class-methods-use-this": "off",
"new-cap": "off",
@@ -185,5 +178,12 @@ export default tseslint.config(
],
"no-use-before-define": "off",
},
settings: {
"import/resolver": {
node: {
extensions: [".ts", ".js"],
},
},
},
}
);

View File

@@ -6,4 +6,4 @@ set -e
cd "$(dirname "$0")/../.."
./node_modules/.bin/gulp build-gallery
yarn run-task build-gallery

View File

@@ -6,4 +6,4 @@ set -e
cd "$(dirname "$0")/../.."
./node_modules/.bin/gulp develop-gallery
yarn run-task develop-gallery

View File

@@ -38,12 +38,12 @@ class PageDescription extends HaMarkdown {
}
.title {
font-size: 42px;
line-height: 56px;
line-height: var(--ha-line-height-condensed);
padding-bottom: 8px;
}
.subtitle {
font-size: var(--ha-font-size-l);
line-height: 24px;
line-height: var(--ha-line-height-normal);
}
.root {
max-width: 800px;

View File

@@ -252,12 +252,12 @@ class HaGallery extends LitElement {
.page-footer .header {
font-size: var(--ha-font-size-l);
font-weight: var(--ha-font-weight-medium);
line-height: 28px;
line-height: var(--ha-line-height-normal);
text-align: center;
}
.page-footer .secondary {
line-height: 23px;
line-height: var(--ha-line-height-normal);
text-align: center;
}

View File

@@ -135,7 +135,7 @@ export class DemoHaControlSelect extends LitElement {
.options=${options}
class=${ifDefined(config.class)}
@value-changed=${this.handleValueChanged}
aria-labelledby=${id}
.label=${label}
?disabled=${config.disabled}
>
</ha-control-select>
@@ -156,7 +156,7 @@ export class DemoHaControlSelect extends LitElement {
vertical
class=${ifDefined(config.class)}
@value-changed=${this.handleValueChanged}
aria-labelledby=${id}
.label=${label}
?disabled=${config.disabled}
>
</ha-control-select>

View File

@@ -97,7 +97,7 @@ export class DemoHaBarSlider extends LitElement {
class=${ifDefined(config.class)}
@value-changed=${this.handleValueChanged}
@slider-moved=${this.handleSliderMoved}
aria-labelledby=${id}
.label=${label}
.unit=${config.unit}
>
</ha-control-slider>
@@ -119,7 +119,7 @@ export class DemoHaBarSlider extends LitElement {
class=${ifDefined(config.class)}
@value-changed=${this.handleValueChanged}
@slider-moved=${this.handleSliderMoved}
aria-label=${label}
.label=${label}
.unit=${config.unit}
>
</ha-control-slider>

View File

@@ -63,7 +63,7 @@ export class DemoHaControlSwitch extends LitElement {
@change=${this.handleValueChanged}
.pathOn=${mdiLightbulb}
.pathOff=${mdiLightbulbOff}
aria-labelledby=${id}
.label=${label}
?disabled=${config.disabled}
?reversed=${config.reversed}
>
@@ -84,7 +84,7 @@ export class DemoHaControlSwitch extends LitElement {
vertical
class=${ifDefined(config.class)}
@change=${this.handleValueChanged}
aria-label=${label}
.label=${label}
.pathOn=${mdiGarageOpen}
.pathOff=${mdiGarage}
?disabled=${config.disabled}

View File

@@ -416,6 +416,34 @@ const SCHEMAS: {
},
},
},
items: {
name: "Items",
selector: {
object: {
label_field: "name",
description_field: "value",
multiple: true,
fields: {
name: {
label: "Name",
selector: { text: {} },
required: true,
},
value: {
label: "Value",
selector: {
number: {
mode: "slider",
min: 0,
max: 100,
unit_of_measurement: "%",
},
},
},
},
},
},
},
},
},
];

View File

@@ -1,4 +0,0 @@
import { availableParallelism } from "node:os";
import "./build-scripts/gulp/index.mjs";
process.env.UV_THREADPOOL_SIZE = availableParallelism();

View File

@@ -6,4 +6,4 @@ set -e
cd "$(dirname "$0")/../.."
./node_modules/.bin/gulp build-hassio
yarn run-task build-hassio

View File

@@ -6,4 +6,4 @@ set -e
cd "$(dirname "$0")/../.."
./node_modules/.bin/gulp develop-hassio
yarn run-task develop-hassio

View File

@@ -430,7 +430,7 @@ class HassioAddonConfig extends LitElement {
font-family: var(--ha-card-header-font-family, inherit);
font-size: var(--ha-card-header-font-size, var(--ha-font-size-2xl));
letter-spacing: -0.012em;
line-height: 48px;
line-height: var(--ha-line-height-expanded);
padding: 12px 16px 16px;
display: block;
margin-block: 0px;

View File

@@ -101,7 +101,7 @@ class HassioCardContent extends LitElement {
overflow: hidden;
position: relative;
height: 2.4em;
line-height: 1.2em;
line-height: var(--ha-line-height-condensed);
}
.icon_image img {
max-height: 40px;

View File

@@ -132,9 +132,9 @@ class HassioDashboard extends LitElement {
}
ha-fab.non-tabs {
position: fixed;
right: calc(16px + env(safe-area-inset-right));
bottom: calc(16px + env(safe-area-inset-bottom));
inset-inline-end: calc(16px + env(safe-area-inset-right));
right: calc(16px + var(--safe-area-inset-right));
bottom: calc(16px + var(--safe-area-inset-bottom));
inset-inline-end: calc(16px + var(--safe-area-inset-right));
inset-inline-start: initial;
z-index: 1;
}

View File

@@ -610,7 +610,7 @@ export class DialogHassioNetwork
display: flex;
justify-content: space-between;
padding: 8px;
padding-bottom: max(env(safe-area-inset-bottom), 8px);
padding-bottom: max(var(--safe-area-inset-bottom), 8px);
background-color: var(--mdc-theme-surface, #fff);
}
.warning {

View File

@@ -249,6 +249,8 @@ class HassioRepositoriesDialog extends LitElement {
await addStoreRepository(this.hass, input.value);
await this._loadData();
fireEvent(this, "supervisor-collection-refresh", { collection: "store" });
input.value = "";
} catch (err: any) {
this._error = extractApiErrorMessage(err);
@@ -261,6 +263,8 @@ class HassioRepositoriesDialog extends LitElement {
try {
await removeStoreRepository(this.hass, slug);
await this._loadData();
fireEvent(this, "supervisor-collection-refresh", { collection: "store" });
} catch (err: any) {
this._error = extractApiErrorMessage(err);
}

View File

@@ -354,7 +354,7 @@ class HassioIngressView extends LitElement {
.main-title {
margin: var(--margin-title);
line-height: 20px;
line-height: var(--ha-line-height-condensed);
flex-grow: 1;
}

View File

@@ -6,4 +6,4 @@ set -e
cd "$(dirname "$0")/../.."
./node_modules/.bin/gulp build-landing-page
yarn run-task build-landing-page

View File

@@ -6,4 +6,4 @@ set -e
cd "$(dirname "$0")/../.."
./node_modules/.bin/gulp develop-landing-page
yarn run-task develop-landing-page

View File

@@ -1,5 +1,6 @@
import "@material/mwc-linear-progress/mwc-linear-progress";
import { mdiArrowCollapseDown, mdiDownload } from "@mdi/js";
// eslint-disable-next-line import/extensions
import { IntersectionController } from "@lit-labs/observers/intersection-controller.js";
import { LitElement, type PropertyValues, css, html, nothing } from "lit";

View File

@@ -21,22 +21,21 @@
"postpack": "pinst --enable",
"test": "vitest run --config test/vitest.config.ts",
"test:coverage": "vitest run --config test/vitest.config.ts --coverage",
"analyze": "cem analyze --litelement --globs \"src/components/ha-alert.ts\" --dev",
"doc": "gulp generate-component-docs"
"run-task": "tsx ./build-scripts/runTask.ts"
},
"author": "Paulus Schoutsen <Paulus@PaulusSchoutsen.nl> (http://paulusschoutsen.nl)",
"license": "Apache-2.0",
"type": "module",
"dependencies": {
"@babel/runtime": "7.27.1",
"@babel/runtime": "7.27.6",
"@braintree/sanitize-url": "7.1.1",
"@codemirror/autocomplete": "6.18.6",
"@codemirror/commands": "6.8.1",
"@codemirror/language": "6.11.0",
"@codemirror/language": "6.11.2",
"@codemirror/legacy-modes": "6.5.1",
"@codemirror/search": "6.5.10",
"@codemirror/search": "6.5.11",
"@codemirror/state": "6.5.2",
"@codemirror/view": "6.36.7",
"@codemirror/view": "6.38.1",
"@egjs/hammerjs": "2.0.17",
"@formatjs/intl-datetimeformat": "6.18.0",
"@formatjs/intl-displaynames": "6.8.11",
@@ -47,18 +46,18 @@
"@formatjs/intl-numberformat": "8.15.4",
"@formatjs/intl-pluralrules": "5.4.4",
"@formatjs/intl-relativetimeformat": "11.4.11",
"@fullcalendar/core": "6.1.17",
"@fullcalendar/daygrid": "6.1.17",
"@fullcalendar/interaction": "6.1.17",
"@fullcalendar/list": "6.1.17",
"@fullcalendar/luxon3": "6.1.17",
"@fullcalendar/timegrid": "6.1.17",
"@fullcalendar/core": "6.1.18",
"@fullcalendar/daygrid": "6.1.18",
"@fullcalendar/interaction": "6.1.18",
"@fullcalendar/list": "6.1.18",
"@fullcalendar/luxon3": "6.1.18",
"@fullcalendar/timegrid": "6.1.18",
"@lezer/highlight": "1.2.1",
"@lit-labs/motion": "1.0.8",
"@lit-labs/observers": "2.0.5",
"@lit-labs/virtualizer": "2.1.0",
"@lit/context": "1.1.5",
"@lit/reactive-element": "2.1.0",
"@lit-labs/motion": "1.0.9",
"@lit-labs/observers": "2.0.6",
"@lit-labs/virtualizer": "2.1.1",
"@lit/context": "1.1.6",
"@lit/reactive-element": "2.1.1",
"@material/chips": "=14.0.0-canary.53b3cad2f.0",
"@material/data-table": "=14.0.0-canary.53b3cad2f.0",
"@material/mwc-base": "0.27.0",
@@ -91,17 +90,17 @@
"@thomasloven/round-slider": "0.6.0",
"@tsparticles/engine": "3.8.1",
"@tsparticles/preset-links": "3.2.0",
"@vaadin/combo-box": "24.7.5",
"@vaadin/vaadin-themable-mixin": "24.7.5",
"@vaadin/combo-box": "24.7.9",
"@vaadin/vaadin-themable-mixin": "24.7.9",
"@vibrant/color": "4.0.0",
"@vue/web-component-wrapper": "1.3.0",
"@webcomponents/scoped-custom-element-registry": "0.0.10",
"@webcomponents/webcomponentsjs": "2.8.0",
"app-datepicker": "5.1.1",
"barcode-detector": "3.0.4",
"barcode-detector": "3.0.5",
"color-name": "2.0.0",
"comlink": "4.4.2",
"core-js": "3.42.0",
"core-js": "3.44.0",
"cropperjs": "1.6.2",
"date-fns": "4.1.0",
"date-fns-tz": "3.2.0",
@@ -113,7 +112,7 @@
"fuse.js": "7.1.0",
"google-timezones-json": "1.2.0",
"gulp-zopfli-green": "6.0.2",
"hls.js": "1.6.2",
"hls.js": "1.6.7",
"home-assistant-js-websocket": "9.5.0",
"idb-keyval": "6.2.2",
"intl-messageformat": "10.7.16",
@@ -121,10 +120,10 @@
"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.0",
"lit-html": "3.3.0",
"luxon": "3.6.1",
"marked": "15.0.11",
"lit": "3.3.1",
"lit-html": "3.3.1",
"luxon": "3.7.1",
"marked": "16.1.1",
"memoize-one": "6.0.0",
"node-vibrant": "4.0.3",
"object-hash": "3.0.0",
@@ -137,9 +136,7 @@
"stacktrace-js": "2.0.2",
"superstruct": "2.0.2",
"tinykeys": "3.0.0",
"ua-parser-js": "2.0.3",
"vis-data": "7.1.9",
"vis-network": "9.1.9",
"ua-parser-js": "2.0.4",
"vue": "2.7.16",
"vue2-daterange-picker": "0.6.8",
"weekstart": "2.0.0",
@@ -152,94 +149,92 @@
"xss": "1.0.15"
},
"devDependencies": {
"@babel/core": "7.27.1",
"@babel/helper-define-polyfill-provider": "0.6.4",
"@babel/plugin-transform-runtime": "7.27.1",
"@babel/preset-env": "7.27.2",
"@bundle-stats/plugin-webpack-filter": "4.20.1",
"@custom-elements-manifest/analyzer": "0.10.4",
"@custom-elements-manifest/to-markdown": "0.1.0",
"@lokalise/node-api": "14.7.0",
"@octokit/auth-oauth-device": "7.1.5",
"@octokit/plugin-retry": "7.2.1",
"@octokit/rest": "21.1.1",
"@rsdoctor/rspack-plugin": "1.1.2",
"@rspack/cli": "1.3.9",
"@rspack/core": "1.3.9",
"@babel/core": "7.28.0",
"@babel/helper-define-polyfill-provider": "0.6.5",
"@babel/plugin-transform-runtime": "7.28.0",
"@babel/preset-env": "7.28.0",
"@bundle-stats/plugin-webpack-filter": "4.21.0",
"@lokalise/node-api": "14.9.1",
"@octokit/auth-oauth-device": "8.0.1",
"@octokit/plugin-retry": "8.0.1",
"@octokit/rest": "22.0.0",
"@rsdoctor/rspack-plugin": "1.1.8",
"@rspack/cli": "1.4.8",
"@rspack/core": "1.4.8",
"@types/babel__plugin-transform-runtime": "7.9.5",
"@types/chromecast-caf-receiver": "6.0.21",
"@types/chromecast-caf-receiver": "6.0.22",
"@types/chromecast-caf-sender": "1.0.11",
"@types/color-name": "2.0.0",
"@types/glob": "8.1.0",
"@types/html-minifier-terser": "7.0.2",
"@types/js-yaml": "4.0.9",
"@types/leaflet": "1.9.17",
"@types/leaflet": "1.9.20",
"@types/leaflet-draw": "1.0.12",
"@types/leaflet.markercluster": "1.5.5",
"@types/lodash.merge": "4.6.9",
"@types/luxon": "3.6.2",
"@types/mocha": "10.0.10",
"@types/node": "22.15.16",
"@types/qrcode": "1.5.5",
"@types/sortablejs": "1.15.8",
"@types/tar": "6.1.13",
"@types/ua-parser-js": "0.7.39",
"@types/webspeechapi": "0.0.29",
"@vitest/coverage-v8": "3.1.3",
"@vitest/coverage-v8": "3.2.4",
"babel-loader": "10.0.0",
"babel-plugin-template-html-minifier": "4.1.0",
"browserslist-useragent-regexp": "4.1.3",
"del": "8.0.0",
"eslint": "9.26.0",
"eslint": "9.31.0",
"eslint-config-airbnb-base": "15.0.0",
"eslint-config-prettier": "10.1.5",
"eslint-import-resolver-webpack": "0.13.10",
"eslint-plugin-import": "2.31.0",
"eslint-config-prettier": "10.1.8",
"eslint-plugin-import": "2.32.0",
"eslint-plugin-lit": "2.1.1",
"eslint-plugin-lit-a11y": "4.1.4",
"eslint-plugin-lit-a11y": "5.1.0",
"eslint-plugin-unused-imports": "4.1.4",
"eslint-plugin-wc": "3.0.1",
"fancy-log": "2.0.0",
"fs-extra": "11.3.0",
"glob": "11.0.2",
"gulp": "5.0.0",
"glob": "11.0.3",
"gulp": "5.0.1",
"gulp-brotli": "3.0.0",
"gulp-json-transform": "0.5.0",
"gulp-rename": "2.0.0",
"gulp-rename": "2.1.0",
"html-minifier-terser": "7.2.0",
"husky": "9.1.7",
"jsdom": "26.1.0",
"jszip": "3.10.1",
"lint-staged": "15.5.2",
"lint-staged": "16.1.2",
"lit-analyzer": "2.0.3",
"lodash.merge": "4.6.2",
"lodash.template": "4.5.0",
"map-stream": "0.0.7",
"pinst": "3.0.0",
"prettier": "3.5.3",
"prettier": "3.6.2",
"rspack-manifest-plugin": "5.0.3",
"serve": "14.2.4",
"sinon": "20.0.0",
"sinon": "21.0.0",
"tar": "7.4.3",
"terser-webpack-plugin": "5.3.14",
"ts-lit-plugin": "2.0.2",
"tsx": "4.19.4",
"typescript": "5.8.3",
"typescript-eslint": "8.32.0",
"typescript-eslint": "8.37.0",
"vite-tsconfig-paths": "5.1.4",
"vitest": "3.1.3",
"vitest": "3.2.4",
"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.0",
"lit-html": "3.3.0",
"lit": "3.3.1",
"lit-html": "3.3.1",
"clean-css": "5.3.3",
"@lit/reactive-element": "2.1.0",
"@fullcalendar/daygrid": "6.1.17",
"globals": "16.1.0",
"@lit/reactive-element": "2.1.1",
"@fullcalendar/daygrid": "6.1.18",
"globals": "16.3.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"
},
"packageManager": "yarn@4.9.1"
"packageManager": "yarn@4.9.2"
}

View File

@@ -0,0 +1,32 @@
<svg width="160" height="160" viewBox="0 0 160 160" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_3969_57097)">
<path d="M0 4C0 1.79086 1.79086 0 4 0H16C18.2091 0 20 1.79086 20 4V4C20 6.20914 18.2091 8 16 8H4C1.79086 8 0 6.20914 0 4V4Z" fill="white" fill-opacity="0.48"/>
<path d="M0 20C0 15.5817 3.58172 12 8 12H68C72.4183 12 76 15.5817 76 20V36C76 40.4183 72.4183 44 68 44H8C3.58172 44 0 40.4183 0 36V20Z" fill="#1C1C1C"/>
<path d="M8 12.5H68C72.1421 12.5 75.5 15.8579 75.5 20V36C75.5 40.1421 72.1421 43.5 68 43.5H8C3.85786 43.5 0.5 40.1421 0.5 36V20C0.5 15.8579 3.85786 12.5 8 12.5Z" stroke="white" stroke-opacity="0.24"/>
<path d="M32.9844 27.0156C32.9844 26.0781 32.7031 25.2656 32.1406 24.5781C31.5781 23.8594 30.8594 23.375 29.9844 23.125V22C29.9844 21.4375 30.125 20.9375 30.4062 20.5C30.6875 20.0312 31.0469 19.6719 31.4844 19.4219C31.9531 19.1406 32.4531 19 32.9844 19H43.0156C43.5469 19 44.0312 19.1406 44.4688 19.4219C44.9375 19.6719 45.3125 20.0312 45.5938 20.5C45.875 20.9375 46.0156 21.4375 46.0156 22V23.125C45.1406 23.375 44.4219 23.8594 43.8594 24.5781C43.2969 25.2656 43.0156 26.0781 43.0156 27.0156V28.9844H32.9844V27.0156ZM47 25C47.5625 25 48.0312 25.2031 48.4062 25.6094C48.8125 25.9844 49.0156 26.4531 49.0156 27.0156V31.9844C49.0156 32.5469 48.875 33.0625 48.5938 33.5312C48.3125 33.9688 47.9375 34.3281 47.4688 34.6094C47.0312 34.8594 46.5469 34.9844 46.0156 34.9844V36.0156C46.0156 36.2656 45.9062 36.5 45.6875 36.7188C45.5 36.9062 45.2656 37 44.9844 37C44.7344 37 44.5 36.9062 44.2812 36.7188C44.0938 36.5 44 36.2656 44 36.0156V34.9844H32V36.0156C32 36.2656 31.8906 36.5 31.6719 36.7188C31.4844 36.9062 31.2656 37 31.0156 37C30.7344 37 30.4844 36.9062 30.2656 36.7188C30.0781 36.5 29.9844 36.2656 29.9844 36.0156V34.9844C29.4531 34.9844 28.9531 34.8594 28.4844 34.6094C28.0469 34.3281 27.6875 33.9688 27.4062 33.5312C27.125 33.0625 26.9844 32.5469 26.9844 31.9844V27.0156C26.9844 26.4531 27.1719 25.9844 27.5469 25.6094C27.9531 25.2031 28.4375 25 29 25C29.5625 25 30.0312 25.2031 30.4062 25.6094C30.8125 25.9844 31.0156 26.4531 31.0156 27.0156V31H44.9844V27.0156C44.9844 26.4531 45.1719 25.9844 45.5469 25.6094C45.9531 25.2031 46.4375 25 47 25Z" fill="#03A9F4"/>
<path d="M0 56C0 51.5817 3.58172 48 8 48H68C72.4183 48 76 51.5817 76 56V72C76 76.4183 72.4183 80 68 80H8C3.58172 80 0 76.4183 0 72V56Z" fill="#1C1C1C"/>
<path d="M8 48.5H68C72.1421 48.5 75.5 51.8579 75.5 56V72C75.5 76.1421 72.1421 79.5 68 79.5H8C3.85786 79.5 0.5 76.1421 0.5 72V56C0.5 51.8579 3.85786 48.5 8 48.5Z" stroke="white" stroke-opacity="0.24"/>
<path d="M44 61.9844H47.9844V64H46.0156V72.0156H29.9844V64H28.0156V61.9844H32C31.4375 61.9844 30.9531 61.7969 30.5469 61.4219C30.1719 61.0156 29.9844 60.5469 29.9844 60.0156V55.9844H35.9844V60.0156C35.9844 60.5469 35.7812 61.0156 35.375 61.4219C35 61.7969 34.5469 61.9844 34.0156 61.9844H41.9844V58.9844C41.9844 58.7344 41.8906 58.5156 41.7031 58.3281C41.5156 58.1094 41.2812 58 41 58C40.7188 58 40.4844 58.1094 40.2969 58.3281C40.1094 58.5156 40.0156 58.7344 40.0156 58.9844H38C38 58.4531 38.125 57.9688 38.375 57.5312C38.6562 57.0625 39.0156 56.6875 39.4531 56.4062C39.9219 56.125 40.4375 55.9844 41 55.9844C41.5625 55.9844 42.0625 56.125 42.5 56.4062C42.9688 56.6875 43.3281 57.0625 43.5781 57.5312C43.8594 57.9688 44 58.4531 44 58.9844V61.9844ZM38.9844 70V64H37.0156V70H38.9844Z" fill="#03A9F4"/>
<path d="M0 92C0 87.5817 3.58172 84 8 84H68C72.4183 84 76 87.5817 76 92V108C76 112.418 72.4183 116 68 116H8C3.58172 116 0 112.418 0 108V92Z" fill="#1C1C1C"/>
<path d="M8 84.5H68C72.1421 84.5 75.5 87.8579 75.5 92V108C75.5 112.142 72.1421 115.5 68 115.5H8C3.85786 115.5 0.5 112.142 0.5 108V92C0.5 87.8579 3.85786 84.5 8 84.5Z" stroke="white" stroke-opacity="0.24"/>
<path d="M44.9844 94.9844C46.0781 94.9844 47.0156 95.3906 47.7969 96.2031C48.6094 96.9844 49.0156 97.9219 49.0156 99.0156V108.016H47V105.016H29V108.016H26.9844V93.0156H29V102.016H37.0156V94.9844H44.9844ZM35.0938 100.094C34.5 100.688 33.7969 100.984 32.9844 100.984C32.1719 100.984 31.4688 100.688 30.875 100.094C30.2812 99.5 29.9844 98.7969 29.9844 97.9844C29.9844 97.1719 30.2812 96.4688 30.875 95.875C31.4688 95.2812 32.1719 94.9844 32.9844 94.9844C33.7969 94.9844 34.5 95.2812 35.0938 95.875C35.6875 96.4688 35.9844 97.1719 35.9844 97.9844C35.9844 98.7969 35.6875 99.5 35.0938 100.094Z" fill="#03A9F4"/>
<path d="M0 128C0 123.582 3.58172 120 8 120H68C72.4183 120 76 123.582 76 128V144C76 148.418 72.4183 152 68 152H8C3.58172 152 0 148.418 0 144V128Z" fill="#1C1C1C"/>
<path d="M8 120.5H68C72.1421 120.5 75.5 123.858 75.5 128V144C75.5 148.142 72.1421 151.5 68 151.5H8C3.85786 151.5 0.5 148.142 0.5 144V128C0.5 123.858 3.85786 120.5 8 120.5Z" stroke="white" stroke-opacity="0.24"/>
<path d="M46.0156 136.984H47.9844V142.984C47.9844 143.516 47.7812 143.984 47.375 144.391C47 144.797 46.5469 145 46.0156 145C46.0156 145.281 45.9062 145.516 45.6875 145.703C45.5 145.891 45.2656 145.984 44.9844 145.984H31.0156C30.7344 145.984 30.4844 145.891 30.2656 145.703C30.0781 145.516 29.9844 145.281 29.9844 145C29.4531 145 28.9844 144.797 28.5781 144.391C28.2031 143.984 28.0156 143.516 28.0156 142.984V136.984H31.0156V136.234C31.0156 135.641 31.2344 135.125 31.6719 134.688C32.1406 134.219 32.6719 133.984 33.2656 133.984C33.8906 133.984 34.4531 134.234 34.9531 134.734L36.3125 136.281C36.5 136.5 36.7812 136.734 37.1562 136.984H44V128.828C44 128.609 43.9219 128.422 43.7656 128.266C43.6094 128.078 43.4062 127.984 43.1562 127.984C42.9375 127.984 42.75 128.062 42.5938 128.219L41.3281 129.484C41.3906 129.734 41.4219 129.906 41.4219 130C41.4219 130.344 41.3125 130.703 41.0938 131.078L38.3281 128.312C38.7031 128.094 39.0625 127.984 39.4062 127.984C39.5625 127.984 39.7344 128.016 39.9219 128.078L41.1875 126.812C41.7188 126.281 42.375 126.016 43.1562 126.016C43.9375 126.016 44.6094 126.297 45.1719 126.859C45.7344 127.391 46.0156 128.047 46.0156 128.828V136.984ZM31.5781 132.438C31.2031 132.031 31.0156 131.547 31.0156 130.984C31.0156 130.422 31.2031 129.953 31.5781 129.578C31.9531 129.203 32.4219 129.016 32.9844 129.016C33.5469 129.016 34.0156 129.203 34.3906 129.578C34.7969 129.953 35 130.422 35 130.984C35 131.547 34.7969 132.031 34.3906 132.438C34.0156 132.812 33.5469 133 32.9844 133C32.4219 133 31.9531 132.812 31.5781 132.438Z" fill="#03A9F4"/>
<path d="M84 4C84 1.79086 85.7909 0 88 0H100C102.209 0 104 1.79086 104 4V4C104 6.20914 102.209 8 100 8H88C85.7909 8 84 6.20914 84 4V4Z" fill="white" fill-opacity="0.48"/>
<path d="M84 20C84 15.5817 87.5817 12 92 12H152C156.418 12 160 15.5817 160 20V36C160 40.4183 156.418 44 152 44H92C87.5817 44 84 40.4183 84 36V20Z" fill="#1C1C1C"/>
<path d="M92 12.5H152C156.142 12.5 159.5 15.8579 159.5 20V36C159.5 40.1421 156.142 43.5 152 43.5H92C87.8579 43.5 84.5 40.1421 84.5 36V20C84.5 15.8579 87.8579 12.5 92 12.5Z" stroke="white" stroke-opacity="0.24"/>
<path d="M131.984 30.0156C131.984 30.7656 131.797 31.4531 131.422 32.0781C131.047 32.6719 130.562 33.1406 129.969 33.4844C129.844 34.2031 129.5 34.8125 128.938 35.3125C128.406 35.7812 127.766 36.0156 127.016 36.0156C126.359 36.0156 125.766 35.8281 125.234 35.4531C124.734 35.0781 124.391 34.5938 124.203 34H119.797C119.609 34.5938 119.25 35.0781 118.719 35.4531C118.219 35.8281 117.641 36.0156 116.984 36.0156C116.234 36.0156 115.578 35.7812 115.016 35.3125C114.484 34.8125 114.156 34.2031 114.031 33.4844C113.438 33.1406 112.953 32.6719 112.578 32.0781C112.203 31.4531 112.016 30.7656 112.016 30.0156C112.016 29.1094 112.266 28.3125 112.766 27.625C113.297 26.9375 113.969 26.4688 114.781 26.2188L113 24.3906L112.719 24.7188C112.5 24.9062 112.25 25 111.969 25C111.719 25 111.5 24.9062 111.312 24.7188C111.094 24.5312 110.984 24.2969 110.984 24.0156C110.984 23.7344 111.094 23.5 111.312 23.3125L113.281 21.2969C113.469 21.1094 113.703 21.0156 113.984 21.0156C114.266 21.0156 114.5 21.1094 114.688 21.2969C114.906 21.4844 115.016 21.7188 115.016 22C115.016 22.2812 114.906 22.5156 114.688 22.7031L114.406 22.9844L115.812 24.3906L116.609 22.0469C116.797 21.4219 117.156 20.9219 117.688 20.5469C118.219 20.1719 118.797 19.9844 119.422 19.9844H124.578C125.203 19.9844 125.781 20.1719 126.312 20.5469C126.844 20.9219 127.203 21.4219 127.391 22.0469L128.75 26.0781C129.375 26.2031 129.922 26.4531 130.391 26.8281C130.891 27.2031 131.281 27.6719 131.562 28.2344C131.844 28.7656 131.984 29.3594 131.984 30.0156ZM116.984 34C117.266 34 117.5 33.9062 117.688 33.7188C117.906 33.5 118.016 33.2656 118.016 33.0156C118.016 32.7344 117.906 32.5 117.688 32.3125C117.5 32.0938 117.266 31.9844 116.984 31.9844C116.734 31.9844 116.5 32.0938 116.281 32.3125C116.094 32.5 116 32.7344 116 33.0156C116 33.2656 116.094 33.5 116.281 33.7188C116.5 33.9062 116.734 34 116.984 34ZM121.016 25.9844V22H119.422C118.953 22 118.641 22.2344 118.484 22.7031L117.406 25.9844H121.016ZM122.984 22V25.9844H126.594L125.516 22.7031C125.359 22.2344 125.047 22 124.578 22H122.984ZM127.016 34C127.266 34 127.484 33.9062 127.672 33.7188C127.891 33.5 128 33.2656 128 33.0156C128 32.7344 127.891 32.5 127.672 32.3125C127.484 32.0938 127.266 31.9844 127.016 31.9844C126.734 31.9844 126.484 32.0938 126.266 32.3125C126.078 32.5 125.984 32.7344 125.984 33.0156C125.984 33.2656 126.078 33.5 126.266 33.7188C126.484 33.9062 126.734 34 127.016 34Z" fill="#03A9F4"/>
<path d="M84 56C84 51.5817 87.5817 48 92 48H152C156.418 48 160 51.5817 160 56V72C160 76.4183 156.418 80 152 80H92C87.5817 80 84 76.4183 84 72V56Z" fill="#1C1C1C"/>
<path d="M92 48.5H152C156.142 48.5 159.5 51.8579 159.5 56V72C159.5 76.1421 156.142 79.5 152 79.5H92C87.8579 79.5 84.5 76.1421 84.5 72V56C84.5 51.8579 87.8579 48.5 92 48.5Z" stroke="white" stroke-opacity="0.24"/>
<path d="M128.984 58.9844C130.078 58.9844 131.016 59.3906 131.797 60.2031C132.609 60.9844 133.016 61.9219 133.016 63.0156V72.0156H131V69.0156H113V72.0156H110.984V57.0156H113V66.0156H121.016V58.9844H128.984ZM119.094 64.0938C118.5 64.6875 117.797 64.9844 116.984 64.9844C116.172 64.9844 115.469 64.6875 114.875 64.0938C114.281 63.5 113.984 62.7969 113.984 61.9844C113.984 61.1719 114.281 60.4688 114.875 59.875C115.469 59.2812 116.172 58.9844 116.984 58.9844C117.797 58.9844 118.5 59.2812 119.094 59.875C119.688 60.4688 119.984 61.1719 119.984 61.9844C119.984 62.7969 119.688 63.5 119.094 64.0938Z" fill="#03A9F4"/>
<path d="M84 92C84 87.5817 87.5817 84 92 84H152C156.418 84 160 87.5817 160 92V108C160 112.418 156.418 116 152 116H92C87.5817 116 84 112.418 84 108V92Z" fill="#1C1C1C"/>
<path d="M92 84.5H152C156.142 84.5 159.5 87.8579 159.5 92V108C159.5 112.142 156.142 115.5 152 115.5H92C87.8579 115.5 84.5 112.142 84.5 108V92C84.5 87.8579 87.8579 84.5 92 84.5Z" stroke="white" stroke-opacity="0.24"/>
<path d="M112.016 94H131.984V106H130.016V103.984H125.984V106H124.016V96.0156H113.984V106H112.016V94ZM130.016 96.0156H125.984V97.9844H130.016V96.0156ZM125.984 102.016H130.016V100H125.984V102.016Z" fill="#03A9F4"/>
</g>
<defs>
<clipPath id="clip0_3969_57097">
<rect width="160" height="160" fill="white"/>
</clipPath>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 11 KiB

View File

@@ -0,0 +1,63 @@
<svg width="160" height="160" viewBox="0 0 160 160" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_1738_5534)">
<path d="M0 8C0 3.58172 3.58172 0 8 0H42.6667C47.0849 0 50.6667 3.58172 50.6667 8V64C50.6667 68.4183 47.0849 72 42.6667 72H8.00001C3.58173 72 0 68.4183 0 64V8Z" fill="#1C1C1C"/>
<path d="M8 0.5H42.667C46.809 0.500178 50.167 3.85798 50.167 8V64C50.167 68.142 46.809 71.4998 42.667 71.5H8C3.85787 71.5 0.5 68.1421 0.5 64V8C0.5 3.85786 3.85786 0.5 8 0.5Z" stroke="white" stroke-opacity="0.24"/>
<path d="M8 12C8 9.79086 9.79086 8 12 8H38.6667C40.8758 8 42.6667 9.79086 42.6667 12V12C42.6667 14.2091 40.8758 16 38.6667 16H12C9.79086 16 8 14.2091 8 12V12Z" fill="white" fill-opacity="0.48"/>
<path d="M8 27C8 25.3431 9.34315 24 11 24H27.6667C29.3235 24 30.6667 25.3431 30.6667 27V29C30.6667 30.6569 29.3235 32 27.6667 32H11C9.34314 32 8 30.6569 8 29V27Z" fill="white" fill-opacity="0.24"/>
<path d="M34.6667 28C34.6667 25.7909 36.4575 24 38.6667 24V24C40.8758 24 42.6667 25.7909 42.6667 28V28C42.6667 30.2091 40.8758 32 38.6667 32V32C36.4575 32 34.6667 30.2091 34.6667 28V28Z" fill="white" fill-opacity="0.24"/>
<path d="M8 43C8 41.3431 9.34315 40 11 40H27.6667C29.3235 40 30.6667 41.3431 30.6667 43V45C30.6667 46.6569 29.3235 48 27.6667 48H11C9.34314 48 8 46.6569 8 45V43Z" fill="white" fill-opacity="0.24"/>
<path d="M34.6667 44C34.6667 41.7909 36.4575 40 38.6667 40V40C40.8758 40 42.6667 41.7909 42.6667 44V44C42.6667 46.2091 40.8758 48 38.6667 48V48C36.4575 48 34.6667 46.2091 34.6667 44V44Z" fill="white" fill-opacity="0.24"/>
<path d="M8 59C8 57.3431 9.34315 56 11 56H27.6667C29.3235 56 30.6667 57.3431 30.6667 59V61C30.6667 62.6569 29.3235 64 27.6667 64H11C9.34314 64 8 62.6569 8 61V59Z" fill="white" fill-opacity="0.24"/>
<path d="M34.6667 60C34.6667 57.7909 36.4575 56 38.6667 56V56C40.8758 56 42.6667 57.7909 42.6667 60V60C42.6667 62.2091 40.8758 64 38.6667 64V64C36.4575 64 34.6667 62.2091 34.6667 60V60Z" fill="white" fill-opacity="0.24"/>
<path d="M0 84C0 79.5817 3.58172 76 8 76H42.6667C47.0849 76 50.6667 79.5817 50.6667 84V124C50.6667 128.418 47.0849 132 42.6667 132H8.00001C3.58173 132 0 128.418 0 124V84Z" fill="#1C1C1C"/>
<path d="M8 76.5H42.667C46.809 76.5002 50.167 79.858 50.167 84V124C50.167 128.142 46.809 131.5 42.667 131.5H8C3.85787 131.5 0.5 128.142 0.5 124V84C0.5 79.8579 3.85786 76.5 8 76.5Z" stroke="white" stroke-opacity="0.24"/>
<path d="M8 88C8 85.7909 9.79086 84 12 84H38.6667C40.8758 84 42.6667 85.7909 42.6667 88V88C42.6667 90.2091 40.8758 92 38.6667 92H12C9.79086 92 8 90.2091 8 88V88Z" fill="white" fill-opacity="0.48"/>
<path d="M8 103C8 101.343 9.34315 100 11 100H27.6667C29.3235 100 30.6667 101.343 30.6667 103V105C30.6667 106.657 29.3235 108 27.6667 108H11C9.34314 108 8 106.657 8 105V103Z" fill="white" fill-opacity="0.24"/>
<path d="M34.6667 104C34.6667 101.791 36.4575 100 38.6667 100V100C40.8758 100 42.6667 101.791 42.6667 104V104C42.6667 106.209 40.8758 108 38.6667 108V108C36.4575 108 34.6667 106.209 34.6667 104V104Z" fill="white" fill-opacity="0.24"/>
<path d="M8 119C8 117.343 9.34315 116 11 116H27.6667C29.3235 116 30.6667 117.343 30.6667 119V121C30.6667 122.657 29.3235 124 27.6667 124H11C9.34314 124 8 122.657 8 121V119Z" fill="white" fill-opacity="0.24"/>
<path d="M34.6667 120C34.6667 117.791 36.4575 116 38.6667 116V116C40.8758 116 42.6667 117.791 42.6667 120V120C42.6667 122.209 40.8758 124 38.6667 124V124C36.4575 124 34.6667 122.209 34.6667 120V120Z" fill="white" fill-opacity="0.24"/>
<path d="M0 144C0 139.582 3.58172 136 8 136H42.6667C47.0849 136 50.6667 139.582 50.6667 144V152C50.6667 156.418 47.0849 160 42.6667 160H8.00001C3.58173 160 0 156.418 0 152V144Z" fill="#1C1C1C"/>
<path d="M8 136.5H42.667C46.809 136.5 50.167 139.858 50.167 144V152C50.167 156.142 46.809 159.5 42.667 159.5H8C3.85787 159.5 0.5 156.142 0.5 152V144C0.5 139.858 3.85786 136.5 8 136.5Z" stroke="white" stroke-opacity="0.24"/>
<path d="M8 148C8 145.791 9.79086 144 12 144H38.6667C40.8758 144 42.6667 145.791 42.6667 148V148C42.6667 150.209 40.8758 152 38.6667 152H12C9.79086 152 8 150.209 8 148V148Z" fill="white" fill-opacity="0.48"/>
<path d="M54.6667 8C54.6667 3.58172 58.2484 0 62.6667 0H97.3333C101.752 0 105.333 3.58172 105.333 8V48C105.333 52.4183 101.752 56 97.3334 56H62.6667C58.2484 56 54.6667 52.4183 54.6667 48V8Z" fill="#1C1C1C"/>
<path d="M62.6667 0.5H97.3337C101.476 0.50018 104.834 3.85798 104.834 8V48C104.834 52.142 101.476 55.4998 97.3337 55.5H62.6667C58.5246 55.5 55.1667 52.1421 55.1667 48V8C55.1667 3.85786 58.5246 0.5 62.6667 0.5Z" stroke="white" stroke-opacity="0.24"/>
<path d="M62.6667 12C62.6667 9.79086 64.4575 8 66.6667 8H93.3334C95.5425 8 97.3334 9.79086 97.3334 12V12C97.3334 14.2091 95.5425 16 93.3334 16H66.6667C64.4576 16 62.6667 14.2091 62.6667 12V12Z" fill="white" fill-opacity="0.48"/>
<path d="M62.6667 27C62.6667 25.3431 64.0098 24 65.6667 24H82.3334C83.9902 24 85.3334 25.3431 85.3334 27V29C85.3334 30.6569 83.9902 32 82.3334 32H65.6667C64.0098 32 62.6667 30.6569 62.6667 29V27Z" fill="white" fill-opacity="0.24"/>
<path d="M89.3333 28C89.3333 25.7909 91.1242 24 93.3333 24V24C95.5425 24 97.3333 25.7909 97.3333 28V28C97.3333 30.2091 95.5425 32 93.3333 32V32C91.1242 32 89.3333 30.2091 89.3333 28V28Z" fill="white" fill-opacity="0.24"/>
<path d="M62.6667 43C62.6667 41.3431 64.0098 40 65.6667 40H82.3334C83.9902 40 85.3334 41.3431 85.3334 43V45C85.3334 46.6569 83.9902 48 82.3334 48H65.6667C64.0098 48 62.6667 46.6569 62.6667 45V43Z" fill="white" fill-opacity="0.24"/>
<path d="M89.3333 44C89.3333 41.7909 91.1242 40 93.3333 40V40C95.5425 40 97.3333 41.7909 97.3333 44V44C97.3333 46.2091 95.5425 48 93.3333 48V48C91.1242 48 89.3333 46.2091 89.3333 44V44Z" fill="white" fill-opacity="0.24"/>
<path d="M54.6667 68C54.6667 63.5817 58.2484 60 62.6667 60H97.3333C101.752 60 105.333 63.5817 105.333 68V76C105.333 80.4183 101.752 84 97.3334 84H62.6667C58.2484 84 54.6667 80.4183 54.6667 76V68Z" fill="#1C1C1C"/>
<path d="M62.6667 60.5H97.3337C101.476 60.5002 104.834 63.858 104.834 68V76C104.834 80.142 101.476 83.4998 97.3337 83.5H62.6667C58.5246 83.5 55.1667 80.1421 55.1667 76V68C55.1667 63.8579 58.5246 60.5 62.6667 60.5Z" stroke="white" stroke-opacity="0.24"/>
<path d="M62.6667 72C62.6667 69.7909 64.4575 68 66.6667 68H93.3334C95.5425 68 97.3334 69.7909 97.3334 72V72C97.3334 74.2091 95.5425 76 93.3334 76H66.6667C64.4576 76 62.6667 74.2091 62.6667 72V72Z" fill="white" fill-opacity="0.48"/>
<path d="M54.6667 96C54.6667 91.5817 58.2484 88 62.6667 88H97.3333C101.752 88 105.333 91.5817 105.333 96V136C105.333 140.418 101.752 144 97.3334 144H62.6667C58.2484 144 54.6667 140.418 54.6667 136V96Z" fill="#1C1C1C"/>
<path d="M62.6667 88.5H97.3337C101.476 88.5002 104.834 91.858 104.834 96V136C104.834 140.142 101.476 143.5 97.3337 143.5H62.6667C58.5246 143.5 55.1667 140.142 55.1667 136V96C55.1667 91.8579 58.5246 88.5 62.6667 88.5Z" stroke="white" stroke-opacity="0.24"/>
<path d="M62.6667 100C62.6667 97.7909 64.4575 96 66.6667 96H93.3334C95.5425 96 97.3334 97.7909 97.3334 100V100C97.3334 102.209 95.5425 104 93.3334 104H66.6667C64.4576 104 62.6667 102.209 62.6667 100V100Z" fill="white" fill-opacity="0.48"/>
<path d="M62.6667 115C62.6667 113.343 64.0098 112 65.6667 112H82.3334C83.9902 112 85.3334 113.343 85.3334 115V117C85.3334 118.657 83.9902 120 82.3334 120H65.6667C64.0098 120 62.6667 118.657 62.6667 117V115Z" fill="white" fill-opacity="0.24"/>
<path d="M89.3333 116C89.3333 113.791 91.1242 112 93.3333 112V112C95.5425 112 97.3333 113.791 97.3333 116V116C97.3333 118.209 95.5425 120 93.3333 120V120C91.1242 120 89.3333 118.209 89.3333 116V116Z" fill="white" fill-opacity="0.24"/>
<path d="M62.6667 131C62.6667 129.343 64.0098 128 65.6667 128H82.3334C83.9902 128 85.3334 129.343 85.3334 131V133C85.3334 134.657 83.9902 136 82.3334 136H65.6667C64.0098 136 62.6667 134.657 62.6667 133V131Z" fill="white" fill-opacity="0.24"/>
<path d="M89.3333 132C89.3333 129.791 91.1242 128 93.3333 128V128C95.5425 128 97.3333 129.791 97.3333 132V132C97.3333 134.209 95.5425 136 93.3333 136V136C91.1242 136 89.3333 134.209 89.3333 132V132Z" fill="white" fill-opacity="0.24"/>
<path d="M109.333 8C109.333 3.58172 112.915 0 117.333 0H152C156.418 0 160 3.58172 160 8V112C160 116.418 156.418 120 152 120H117.333C112.915 120 109.333 116.418 109.333 112V8Z" fill="#1C1C1C"/>
<path d="M117.333 0.5H152C156.142 0.50018 159.5 3.85798 159.5 8V112C159.5 116.142 156.142 119.5 152 119.5H117.333C113.191 119.5 109.833 116.142 109.833 112V8C109.833 3.85786 113.191 0.5 117.333 0.5Z" stroke="white" stroke-opacity="0.24"/>
<path d="M117.333 12C117.333 9.79086 119.124 8 121.333 8H148C150.209 8 152 9.79086 152 12V12C152 14.2091 150.209 16 148 16H121.333C119.124 16 117.333 14.2091 117.333 12V12Z" fill="white" fill-opacity="0.48"/>
<path d="M117.333 27C117.333 25.3431 118.676 24 120.333 24H137C138.657 24 140 25.3431 140 27V29C140 30.6569 138.657 32 137 32H120.333C118.676 32 117.333 30.6569 117.333 29V27Z" fill="white" fill-opacity="0.24"/>
<path d="M144 28C144 25.7909 145.791 24 148 24V24C150.209 24 152 25.7909 152 28V28C152 30.2091 150.209 32 148 32V32C145.791 32 144 30.2091 144 28V28Z" fill="white" fill-opacity="0.24"/>
<path d="M117.333 43C117.333 41.3431 118.676 40 120.333 40H137C138.657 40 140 41.3431 140 43V45C140 46.6569 138.657 48 137 48H120.333C118.676 48 117.333 46.6569 117.333 45V43Z" fill="white" fill-opacity="0.24"/>
<path d="M144 44C144 41.7909 145.791 40 148 40V40C150.209 40 152 41.7909 152 44V44C152 46.2091 150.209 48 148 48V48C145.791 48 144 46.2091 144 44V44Z" fill="white" fill-opacity="0.24"/>
<path d="M117.333 59C117.333 57.3431 118.676 56 120.333 56H137C138.657 56 140 57.3431 140 59V61C140 62.6569 138.657 64 137 64H120.333C118.676 64 117.333 62.6569 117.333 61V59Z" fill="white" fill-opacity="0.24"/>
<path d="M144 60C144 57.7909 145.791 56 148 56V56C150.209 56 152 57.7909 152 60V60C152 62.2091 150.209 64 148 64V64C145.791 64 144 62.2091 144 60V60Z" fill="white" fill-opacity="0.24"/>
<path d="M117.333 75C117.333 73.3431 118.676 72 120.333 72H137C138.657 72 140 73.3431 140 75V77C140 78.6569 138.657 80 137 80H120.333C118.676 80 117.333 78.6569 117.333 77V75Z" fill="white" fill-opacity="0.24"/>
<path d="M144 76C144 73.7909 145.791 72 148 72V72C150.209 72 152 73.7909 152 76V76C152 78.2091 150.209 80 148 80V80C145.791 80 144 78.2091 144 76V76Z" fill="white" fill-opacity="0.24"/>
<path d="M117.333 91C117.333 89.3431 118.676 88 120.333 88H137C138.657 88 140 89.3431 140 91V93C140 94.6569 138.657 96 137 96H120.333C118.676 96 117.333 94.6569 117.333 93V91Z" fill="white" fill-opacity="0.24"/>
<path d="M144 92C144 89.7909 145.791 88 148 88V88C150.209 88 152 89.7909 152 92V92C152 94.2091 150.209 96 148 96V96C145.791 96 144 94.2091 144 92V92Z" fill="white" fill-opacity="0.24"/>
<path d="M117.333 107C117.333 105.343 118.676 104 120.333 104H137C138.657 104 140 105.343 140 107V109C140 110.657 138.657 112 137 112H120.333C118.676 112 117.333 110.657 117.333 109V107Z" fill="white" fill-opacity="0.24"/>
<path d="M144 108C144 105.791 145.791 104 148 104V104C150.209 104 152 105.791 152 108V108C152 110.209 150.209 112 148 112V112C145.791 112 144 110.209 144 108V108Z" fill="white" fill-opacity="0.24"/>
<path d="M109.333 132C109.333 127.582 112.915 124 117.333 124H152C156.418 124 160 127.582 160 132V140C160 144.418 156.418 148 152 148H117.333C112.915 148 109.333 144.418 109.333 140V132Z" fill="#1C1C1C"/>
<path d="M117.333 124.5H152C156.142 124.5 159.5 127.858 159.5 132V140C159.5 144.142 156.142 147.5 152 147.5H117.333C113.191 147.5 109.833 144.142 109.833 140V132C109.833 127.858 113.191 124.5 117.333 124.5Z" stroke="white" stroke-opacity="0.24"/>
<path d="M117.333 136C117.333 133.791 119.124 132 121.333 132H148C150.209 132 152 133.791 152 136V136C152 138.209 150.209 140 148 140H121.333C119.124 140 117.333 138.209 117.333 136V136Z" fill="white" fill-opacity="0.48"/>
</g>
<defs>
<clipPath id="clip0_1738_5534">
<rect width="160" height="160" fill="white"/>
</clipPath>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 12 KiB

View File

@@ -0,0 +1,16 @@
<svg width="160" height="160" viewBox="0 0 160 160" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_1738_5540)">
<path d="M0 8C0 3.58172 3.58172 0 8 0H152C156.418 0 160 3.58172 160 8V152C160 156.418 156.418 160 152 160H8C3.58172 160 0 156.418 0 152V8Z" fill="#1C1C1C"/>
<path d="M8 0.5H152C156.142 0.500001 159.5 3.85787 159.5 8V152C159.5 156.142 156.142 159.5 152 159.5H8C3.85787 159.5 0.5 156.142 0.5 152V8C0.500001 3.85787 3.85787 0.5 8 0.5Z" stroke="white" stroke-opacity="0.24"/>
<path d="M83 86.9844V75.125L77 73.0156V84.875L83 86.9844ZM88.4844 71C88.8281 71 89 71.1719 89 71.5156V86.6094C89 86.8594 88.875 87.0156 88.625 87.0781L83 89L77 86.8906L71.6562 88.9531L71.5156 89C71.1719 89 71 88.8281 71 88.4844V73.3906C71 73.1406 71.125 72.9844 71.375 72.9219L77 71L83 73.1094L88.3438 71.0469L88.4844 71Z" fill="#03A9F4"/>
<path d="M148 77.0508L139.288 85.8983M139.288 85.8983L116.852 108.684C115.724 109.83 114.184 110.475 112.576 110.475H81.6939M139.288 85.8983V69.4322M21.1957 82.9492H12M21.1957 82.9492L32.3274 71.6441M21.1957 82.9492L44.427 106.542M81.6939 110.475V124.237M81.6939 110.475H54.5907M81.6939 138V124.237M81.6939 124.237H148M32.3274 71.6441L43.4591 60.339L54.5907 49.0339L70.4941 32.8828C74.2533 29.0651 79.3871 26.9153 84.7451 26.9153H128.641V26.9153C134.521 26.9153 139.288 31.6824 139.288 37.5629V37.7288V49.0339M32.3274 71.6441L24.8569 64.0572C22.5573 61.7218 22.5573 57.9732 24.8569 55.6377L57.9786 22M139.288 49.0339H126.313C124.706 49.0339 123.166 48.389 122.038 47.2436L116.057 41.1695M139.288 49.0339V69.4322M139.288 69.4322H126.313C124.706 69.4322 123.166 68.7873 122.038 67.6419L116.057 61.5678M54.5907 110.475V110.475C54.5907 107.488 52.17 105.068 49.184 105.068H49.0249C45.951 105.068 43.4591 107.56 43.4591 110.634V110.807C43.4591 113.881 45.951 116.373 49.0249 116.373V116.373C52.0988 116.373 54.5907 113.881 54.5907 110.807V110.475ZM44.427 115.39L22.1637 138" stroke="white" stroke-opacity="0.24" stroke-width="5" stroke-linecap="round"/>
<circle cx="41" cy="39" r="14" fill="white" fill-opacity="0.48"/>
<circle cx="89" cy="117" r="14" fill="white" fill-opacity="0.48"/>
<path d="M116 62.325C115.767 62.325 115.533 62.2833 115.3 62.2C115.067 62.1167 114.858 61.9917 114.675 61.825C113.592 60.825 112.633 59.85 111.8 58.9C110.967 57.95 110.267 57.0333 109.7 56.15C109.15 55.25 108.725 54.3917 108.425 53.575C108.142 52.7417 108 51.95 108 51.2C108 48.7 108.8 46.7083 110.4 45.225C112.017 43.7417 113.883 43 116 43C118.117 43 119.975 43.7417 121.575 45.225C123.192 46.7083 124 48.7 124 51.2C124 51.95 123.85 52.7417 123.55 53.575C123.267 54.3917 122.842 55.25 122.275 56.15C121.725 57.0333 121.033 57.95 120.2 58.9C119.367 59.85 118.408 60.825 117.325 61.825C117.142 61.9917 116.933 62.1167 116.7 62.2C116.467 62.2833 116.233 62.325 116 62.325Z" fill="white" fill-opacity="0.48"/>
</g>
<defs>
<clipPath id="clip0_1738_5540">
<rect width="160" height="160" fill="white"/>
</clipPath>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 2.9 KiB

View File

@@ -0,0 +1,13 @@
<svg width="160" height="72" viewBox="0 0 160 72" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_1738_5536)">
<path d="M0 4C0 1.79086 1.79086 0 4 0H28C30.2091 0 32 1.79086 32 4V4C32 6.20914 30.2091 8 28 8H4C1.79086 8 0 6.20914 0 4V4Z" fill="white" fill-opacity="0.48"/>
<path d="M0 20C0 15.5817 3.58172 12 8 12H42.6667C47.0849 12 50.6667 15.5817 50.6667 20V64C50.6667 68.4183 47.0849 72 42.6667 72H8.00001C3.58173 72 0 68.4183 0 64V20Z" fill="#1C1C1C"/>
<path d="M8 12.5H42.667C46.809 12.5002 50.167 15.858 50.167 20V64C50.167 68.142 46.809 71.4998 42.667 71.5H8C3.85787 71.5 0.5 68.1421 0.5 64V20L0.509766 19.6143C0.710536 15.6514 3.98724 12.5 8 12.5Z" stroke="white" stroke-opacity="0.24"/>
<path d="M32.3177 42.9844H26.3177V48.9844H24.349V42.9844H18.349V41.0156H24.349V35.0156H26.3177V41.0156H32.3177V42.9844Z" fill="#03A9F4"/>
</g>
<defs>
<clipPath id="clip0_1738_5536">
<rect width="160" height="72" fill="white"/>
</clipPath>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 973 B

View File

@@ -0,0 +1,19 @@
<svg width="160" height="160" viewBox="0 0 160 160" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_1738_5538)">
<path d="M0 8C0 3.58172 3.58172 0 8 0H152C156.418 0 160 3.58172 160 8V152C160 156.418 156.418 160 152 160H8C3.58172 160 0 156.418 0 152V8Z" fill="#1C1C1C"/>
<path d="M8 0.5H152C156.142 0.500001 159.5 3.85787 159.5 8V152C159.5 156.142 156.142 159.5 152 159.5H8C3.85787 159.5 0.5 156.142 0.5 152V8C0.500001 3.85787 3.85787 0.5 8 0.5Z" stroke="white" stroke-opacity="0.24"/>
<path d="M8 13.5C8 10.4624 10.4624 8 13.5 8H146.5C149.538 8 152 10.4624 152 13.5V13.5C152 16.5376 149.538 19 146.5 19H13.5C10.4624 19 8 16.5376 8 13.5V13.5Z" fill="white" fill-opacity="0.48"/>
<path d="M8 35C8 30.5817 11.5817 27 16 27H45.3333C49.7516 27 53.3333 30.5817 53.3333 35V125C53.3333 129.418 49.7516 133 45.3333 133H16C11.5817 133 8 129.418 8 125V35Z" fill="#1C1C1C"/>
<path d="M16 27.5H45.333C49.4751 27.5 52.833 30.8579 52.833 35V125C52.833 129.142 49.4751 132.5 45.333 132.5H16C11.8579 132.5 8.5 129.142 8.5 125V35C8.5 30.8579 11.8579 27.5 16 27.5Z" stroke="white" stroke-opacity="0.24"/>
<path d="M57.3333 35C57.3333 30.5817 60.9151 27 65.3333 27H94.6667C99.0849 27 102.667 30.5817 102.667 35V49C102.667 53.4183 99.0849 57 94.6667 57H65.3333C60.915 57 57.3333 53.4183 57.3333 49V35Z" fill="#1C1C1C"/>
<path d="M65.3333 27.5H94.6663C98.8085 27.5 102.166 30.8579 102.166 35V49C102.166 53.1421 98.8085 56.5 94.6663 56.5H65.3333C61.1912 56.5 57.8333 53.1421 57.8333 49V35C57.8333 30.8579 61.1912 27.5 65.3333 27.5Z" stroke="white" stroke-opacity="0.24"/>
<path d="M106.667 35C106.667 30.5817 110.248 27 114.667 27H144C148.418 27 152 30.5817 152 35V87C152 91.4183 148.418 95 144 95H114.667C110.248 95 106.667 91.4183 106.667 87V35Z" fill="#1C1C1C"/>
<path d="M114.667 27.5H144C148.142 27.5 151.5 30.8579 151.5 35V87C151.5 91.1421 148.142 94.5 144 94.5H114.667C110.525 94.5 107.167 91.1421 107.167 87V35C107.167 30.8579 110.525 27.5 114.667 27.5Z" stroke="white" stroke-opacity="0.24"/>
<path d="M84.3594 82.0156H87.7344C87.9219 81.1406 88.0156 80.4688 88.0156 80C88.0156 79.5312 87.9219 78.8594 87.7344 77.9844H84.3594C84.4531 78.6406 84.5 79.3125 84.5 80C84.5 80.6875 84.4531 81.3594 84.3594 82.0156ZM82.5781 87.5469C83.3594 87.2969 84.1719 86.8281 85.0156 86.1406C85.8594 85.4219 86.5 84.7031 86.9375 83.9844H83.9844C83.6719 85.2344 83.2031 86.4219 82.5781 87.5469ZM82.3438 82.0156C82.4375 81.3594 82.4844 80.6875 82.4844 80C82.4844 79.3125 82.4375 78.6406 82.3438 77.9844H77.6562C77.5625 78.6406 77.5156 79.3125 77.5156 80C77.5156 80.6875 77.5625 81.3594 77.6562 82.0156H82.3438ZM80 87.9688C80.875 86.6875 81.5156 85.3594 81.9219 83.9844H78.0781C78.4844 85.3594 79.125 86.6875 80 87.9688ZM76.0156 76.0156C76.3906 74.6719 76.8594 73.4844 77.4219 72.4531C76.6406 72.7031 75.8125 73.1875 74.9375 73.9062C74.0938 74.5938 73.4688 75.2969 73.0625 76.0156H76.0156ZM73.0625 83.9844C73.4688 84.7031 74.0938 85.4219 74.9375 86.1406C75.8125 86.8281 76.6406 87.2969 77.4219 87.5469C76.7969 86.4219 76.3281 85.2344 76.0156 83.9844H73.0625ZM72.2656 82.0156H75.6406C75.5469 81.3594 75.5 80.6875 75.5 80C75.5 79.3125 75.5469 78.6406 75.6406 77.9844H72.2656C72.0781 78.8594 71.9844 79.5312 71.9844 80C71.9844 80.4688 72.0781 81.1406 72.2656 82.0156ZM80 72.0312C79.125 73.3125 78.4844 74.6406 78.0781 76.0156H81.9219C81.5156 74.6406 80.875 73.3125 80 72.0312ZM86.9375 76.0156C86.5 75.2969 85.8594 74.5938 85.0156 73.9062C84.1719 73.1875 83.3594 72.7031 82.5781 72.4531C83.1406 73.4844 83.6094 74.6719 83.9844 76.0156H86.9375ZM72.9219 72.9688C74.8906 71 77.25 70.0156 80 70.0156C82.75 70.0156 85.0938 71 87.0312 72.9688C89 74.9062 89.9844 77.25 89.9844 80C89.9844 82.75 89 85.1094 87.0312 87.0781C85.0938 89.0156 82.75 89.9844 80 89.9844C77.25 89.9844 74.8906 89.0156 72.9219 87.0781C70.9844 85.1094 70.0156 82.75 70.0156 80C70.0156 77.25 70.9844 74.9062 72.9219 72.9688Z" fill="#03A9F4"/>
</g>
<defs>
<clipPath id="clip0_1738_5538">
<rect width="160" height="160" fill="white"/>
</clipPath>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 3.9 KiB

View File

@@ -0,0 +1,32 @@
<svg width="160" height="160" viewBox="0 0 160 160" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_3969_50764)">
<path d="M0 4C0 1.79086 1.79086 0 4 0H16C18.2091 0 20 1.79086 20 4V4C20 6.20914 18.2091 8 16 8H4C1.79086 8 0 6.20914 0 4V4Z" fill="black" fill-opacity="0.32"/>
<path d="M0 20C0 15.5817 3.58172 12 8 12H68C72.4183 12 76 15.5817 76 20V36C76 40.4183 72.4183 44 68 44H8C3.58172 44 0 40.4183 0 36V20Z" fill="white"/>
<path d="M8 12.5H68C72.1421 12.5 75.5 15.8579 75.5 20V36C75.5 40.1421 72.1421 43.5 68 43.5H8C3.85786 43.5 0.5 40.1421 0.5 36V20C0.5 15.8579 3.85786 12.5 8 12.5Z" stroke="black" stroke-opacity="0.12"/>
<path d="M32.9844 27.0156C32.9844 26.0781 32.7031 25.2656 32.1406 24.5781C31.5781 23.8594 30.8594 23.375 29.9844 23.125V22C29.9844 21.4375 30.125 20.9375 30.4062 20.5C30.6875 20.0312 31.0469 19.6719 31.4844 19.4219C31.9531 19.1406 32.4531 19 32.9844 19H43.0156C43.5469 19 44.0312 19.1406 44.4688 19.4219C44.9375 19.6719 45.3125 20.0312 45.5938 20.5C45.875 20.9375 46.0156 21.4375 46.0156 22V23.125C45.1406 23.375 44.4219 23.8594 43.8594 24.5781C43.2969 25.2656 43.0156 26.0781 43.0156 27.0156V28.9844H32.9844V27.0156ZM47 25C47.5625 25 48.0312 25.2031 48.4062 25.6094C48.8125 25.9844 49.0156 26.4531 49.0156 27.0156V31.9844C49.0156 32.5469 48.875 33.0625 48.5938 33.5312C48.3125 33.9688 47.9375 34.3281 47.4688 34.6094C47.0312 34.8594 46.5469 34.9844 46.0156 34.9844V36.0156C46.0156 36.2656 45.9062 36.5 45.6875 36.7188C45.5 36.9062 45.2656 37 44.9844 37C44.7344 37 44.5 36.9062 44.2812 36.7188C44.0938 36.5 44 36.2656 44 36.0156V34.9844H32V36.0156C32 36.2656 31.8906 36.5 31.6719 36.7188C31.4844 36.9062 31.2656 37 31.0156 37C30.7344 37 30.4844 36.9062 30.2656 36.7188C30.0781 36.5 29.9844 36.2656 29.9844 36.0156V34.9844C29.4531 34.9844 28.9531 34.8594 28.4844 34.6094C28.0469 34.3281 27.6875 33.9688 27.4062 33.5312C27.125 33.0625 26.9844 32.5469 26.9844 31.9844V27.0156C26.9844 26.4531 27.1719 25.9844 27.5469 25.6094C27.9531 25.2031 28.4375 25 29 25C29.5625 25 30.0312 25.2031 30.4062 25.6094C30.8125 25.9844 31.0156 26.4531 31.0156 27.0156V31H44.9844V27.0156C44.9844 26.4531 45.1719 25.9844 45.5469 25.6094C45.9531 25.2031 46.4375 25 47 25Z" fill="#03A9F4"/>
<path d="M0 56C0 51.5817 3.58172 48 8 48H68C72.4183 48 76 51.5817 76 56V72C76 76.4183 72.4183 80 68 80H8C3.58172 80 0 76.4183 0 72V56Z" fill="white"/>
<path d="M8 48.5H68C72.1421 48.5 75.5 51.8579 75.5 56V72C75.5 76.1421 72.1421 79.5 68 79.5H8C3.85786 79.5 0.5 76.1421 0.5 72V56C0.5 51.8579 3.85786 48.5 8 48.5Z" stroke="black" stroke-opacity="0.12"/>
<path d="M44 61.9844H47.9844V64H46.0156V72.0156H29.9844V64H28.0156V61.9844H32C31.4375 61.9844 30.9531 61.7969 30.5469 61.4219C30.1719 61.0156 29.9844 60.5469 29.9844 60.0156V55.9844H35.9844V60.0156C35.9844 60.5469 35.7812 61.0156 35.375 61.4219C35 61.7969 34.5469 61.9844 34.0156 61.9844H41.9844V58.9844C41.9844 58.7344 41.8906 58.5156 41.7031 58.3281C41.5156 58.1094 41.2812 58 41 58C40.7188 58 40.4844 58.1094 40.2969 58.3281C40.1094 58.5156 40.0156 58.7344 40.0156 58.9844H38C38 58.4531 38.125 57.9688 38.375 57.5312C38.6562 57.0625 39.0156 56.6875 39.4531 56.4062C39.9219 56.125 40.4375 55.9844 41 55.9844C41.5625 55.9844 42.0625 56.125 42.5 56.4062C42.9688 56.6875 43.3281 57.0625 43.5781 57.5312C43.8594 57.9688 44 58.4531 44 58.9844V61.9844ZM38.9844 70V64H37.0156V70H38.9844Z" fill="#03A9F4"/>
<path d="M0 92C0 87.5817 3.58172 84 8 84H68C72.4183 84 76 87.5817 76 92V108C76 112.418 72.4183 116 68 116H8C3.58172 116 0 112.418 0 108V92Z" fill="white"/>
<path d="M8 84.5H68C72.1421 84.5 75.5 87.8579 75.5 92V108C75.5 112.142 72.1421 115.5 68 115.5H8C3.85786 115.5 0.5 112.142 0.5 108V92C0.5 87.8579 3.85786 84.5 8 84.5Z" stroke="black" stroke-opacity="0.12"/>
<path d="M44.9844 94.9844C46.0781 94.9844 47.0156 95.3906 47.7969 96.2031C48.6094 96.9844 49.0156 97.9219 49.0156 99.0156V108.016H47V105.016H29V108.016H26.9844V93.0156H29V102.016H37.0156V94.9844H44.9844ZM35.0938 100.094C34.5 100.688 33.7969 100.984 32.9844 100.984C32.1719 100.984 31.4688 100.688 30.875 100.094C30.2812 99.5 29.9844 98.7969 29.9844 97.9844C29.9844 97.1719 30.2812 96.4688 30.875 95.875C31.4688 95.2812 32.1719 94.9844 32.9844 94.9844C33.7969 94.9844 34.5 95.2812 35.0938 95.875C35.6875 96.4688 35.9844 97.1719 35.9844 97.9844C35.9844 98.7969 35.6875 99.5 35.0938 100.094Z" fill="#03A9F4"/>
<path d="M0 128C0 123.582 3.58172 120 8 120H68C72.4183 120 76 123.582 76 128V144C76 148.418 72.4183 152 68 152H8C3.58172 152 0 148.418 0 144V128Z" fill="white"/>
<path d="M8 120.5H68C72.1421 120.5 75.5 123.858 75.5 128V144C75.5 148.142 72.1421 151.5 68 151.5H8C3.85786 151.5 0.5 148.142 0.5 144V128C0.5 123.858 3.85786 120.5 8 120.5Z" stroke="black" stroke-opacity="0.12"/>
<path d="M46.0156 136.984H47.9844V142.984C47.9844 143.516 47.7812 143.984 47.375 144.391C47 144.797 46.5469 145 46.0156 145C46.0156 145.281 45.9062 145.516 45.6875 145.703C45.5 145.891 45.2656 145.984 44.9844 145.984H31.0156C30.7344 145.984 30.4844 145.891 30.2656 145.703C30.0781 145.516 29.9844 145.281 29.9844 145C29.4531 145 28.9844 144.797 28.5781 144.391C28.2031 143.984 28.0156 143.516 28.0156 142.984V136.984H31.0156V136.234C31.0156 135.641 31.2344 135.125 31.6719 134.688C32.1406 134.219 32.6719 133.984 33.2656 133.984C33.8906 133.984 34.4531 134.234 34.9531 134.734L36.3125 136.281C36.5 136.5 36.7812 136.734 37.1562 136.984H44V128.828C44 128.609 43.9219 128.422 43.7656 128.266C43.6094 128.078 43.4062 127.984 43.1562 127.984C42.9375 127.984 42.75 128.062 42.5938 128.219L41.3281 129.484C41.3906 129.734 41.4219 129.906 41.4219 130C41.4219 130.344 41.3125 130.703 41.0938 131.078L38.3281 128.312C38.7031 128.094 39.0625 127.984 39.4062 127.984C39.5625 127.984 39.7344 128.016 39.9219 128.078L41.1875 126.812C41.7188 126.281 42.375 126.016 43.1562 126.016C43.9375 126.016 44.6094 126.297 45.1719 126.859C45.7344 127.391 46.0156 128.047 46.0156 128.828V136.984ZM31.5781 132.438C31.2031 132.031 31.0156 131.547 31.0156 130.984C31.0156 130.422 31.2031 129.953 31.5781 129.578C31.9531 129.203 32.4219 129.016 32.9844 129.016C33.5469 129.016 34.0156 129.203 34.3906 129.578C34.7969 129.953 35 130.422 35 130.984C35 131.547 34.7969 132.031 34.3906 132.438C34.0156 132.812 33.5469 133 32.9844 133C32.4219 133 31.9531 132.812 31.5781 132.438Z" fill="#03A9F4"/>
<path d="M84 4C84 1.79086 85.7909 0 88 0H100C102.209 0 104 1.79086 104 4V4C104 6.20914 102.209 8 100 8H88C85.7909 8 84 6.20914 84 4V4Z" fill="black" fill-opacity="0.32"/>
<path d="M84 20C84 15.5817 87.5817 12 92 12H152C156.418 12 160 15.5817 160 20V36C160 40.4183 156.418 44 152 44H92C87.5817 44 84 40.4183 84 36V20Z" fill="white"/>
<path d="M92 12.5H152C156.142 12.5 159.5 15.8579 159.5 20V36C159.5 40.1421 156.142 43.5 152 43.5H92C87.8579 43.5 84.5 40.1421 84.5 36V20C84.5 15.8579 87.8579 12.5 92 12.5Z" stroke="black" stroke-opacity="0.12"/>
<path d="M131.984 30.0156C131.984 30.7656 131.797 31.4531 131.422 32.0781C131.047 32.6719 130.562 33.1406 129.969 33.4844C129.844 34.2031 129.5 34.8125 128.938 35.3125C128.406 35.7812 127.766 36.0156 127.016 36.0156C126.359 36.0156 125.766 35.8281 125.234 35.4531C124.734 35.0781 124.391 34.5938 124.203 34H119.797C119.609 34.5938 119.25 35.0781 118.719 35.4531C118.219 35.8281 117.641 36.0156 116.984 36.0156C116.234 36.0156 115.578 35.7812 115.016 35.3125C114.484 34.8125 114.156 34.2031 114.031 33.4844C113.438 33.1406 112.953 32.6719 112.578 32.0781C112.203 31.4531 112.016 30.7656 112.016 30.0156C112.016 29.1094 112.266 28.3125 112.766 27.625C113.297 26.9375 113.969 26.4688 114.781 26.2188L113 24.3906L112.719 24.7188C112.5 24.9062 112.25 25 111.969 25C111.719 25 111.5 24.9062 111.312 24.7188C111.094 24.5312 110.984 24.2969 110.984 24.0156C110.984 23.7344 111.094 23.5 111.312 23.3125L113.281 21.2969C113.469 21.1094 113.703 21.0156 113.984 21.0156C114.266 21.0156 114.5 21.1094 114.688 21.2969C114.906 21.4844 115.016 21.7188 115.016 22C115.016 22.2812 114.906 22.5156 114.688 22.7031L114.406 22.9844L115.812 24.3906L116.609 22.0469C116.797 21.4219 117.156 20.9219 117.688 20.5469C118.219 20.1719 118.797 19.9844 119.422 19.9844H124.578C125.203 19.9844 125.781 20.1719 126.312 20.5469C126.844 20.9219 127.203 21.4219 127.391 22.0469L128.75 26.0781C129.375 26.2031 129.922 26.4531 130.391 26.8281C130.891 27.2031 131.281 27.6719 131.562 28.2344C131.844 28.7656 131.984 29.3594 131.984 30.0156ZM116.984 34C117.266 34 117.5 33.9062 117.688 33.7188C117.906 33.5 118.016 33.2656 118.016 33.0156C118.016 32.7344 117.906 32.5 117.688 32.3125C117.5 32.0938 117.266 31.9844 116.984 31.9844C116.734 31.9844 116.5 32.0938 116.281 32.3125C116.094 32.5 116 32.7344 116 33.0156C116 33.2656 116.094 33.5 116.281 33.7188C116.5 33.9062 116.734 34 116.984 34ZM121.016 25.9844V22H119.422C118.953 22 118.641 22.2344 118.484 22.7031L117.406 25.9844H121.016ZM122.984 22V25.9844H126.594L125.516 22.7031C125.359 22.2344 125.047 22 124.578 22H122.984ZM127.016 34C127.266 34 127.484 33.9062 127.672 33.7188C127.891 33.5 128 33.2656 128 33.0156C128 32.7344 127.891 32.5 127.672 32.3125C127.484 32.0938 127.266 31.9844 127.016 31.9844C126.734 31.9844 126.484 32.0938 126.266 32.3125C126.078 32.5 125.984 32.7344 125.984 33.0156C125.984 33.2656 126.078 33.5 126.266 33.7188C126.484 33.9062 126.734 34 127.016 34Z" fill="#03A9F4"/>
<path d="M84 56C84 51.5817 87.5817 48 92 48H152C156.418 48 160 51.5817 160 56V72C160 76.4183 156.418 80 152 80H92C87.5817 80 84 76.4183 84 72V56Z" fill="white"/>
<path d="M92 48.5H152C156.142 48.5 159.5 51.8579 159.5 56V72C159.5 76.1421 156.142 79.5 152 79.5H92C87.8579 79.5 84.5 76.1421 84.5 72V56C84.5 51.8579 87.8579 48.5 92 48.5Z" stroke="black" stroke-opacity="0.12"/>
<path d="M128.984 58.9844C130.078 58.9844 131.016 59.3906 131.797 60.2031C132.609 60.9844 133.016 61.9219 133.016 63.0156V72.0156H131V69.0156H113V72.0156H110.984V57.0156H113V66.0156H121.016V58.9844H128.984ZM119.094 64.0938C118.5 64.6875 117.797 64.9844 116.984 64.9844C116.172 64.9844 115.469 64.6875 114.875 64.0938C114.281 63.5 113.984 62.7969 113.984 61.9844C113.984 61.1719 114.281 60.4688 114.875 59.875C115.469 59.2812 116.172 58.9844 116.984 58.9844C117.797 58.9844 118.5 59.2812 119.094 59.875C119.688 60.4688 119.984 61.1719 119.984 61.9844C119.984 62.7969 119.688 63.5 119.094 64.0938Z" fill="#03A9F4"/>
<path d="M84 92C84 87.5817 87.5817 84 92 84H152C156.418 84 160 87.5817 160 92V108C160 112.418 156.418 116 152 116H92C87.5817 116 84 112.418 84 108V92Z" fill="white"/>
<path d="M92 84.5H152C156.142 84.5 159.5 87.8579 159.5 92V108C159.5 112.142 156.142 115.5 152 115.5H92C87.8579 115.5 84.5 112.142 84.5 108V92C84.5 87.8579 87.8579 84.5 92 84.5Z" stroke="black" stroke-opacity="0.12"/>
<path d="M112.016 94H131.984V106H130.016V103.984H125.984V106H124.016V96.0156H113.984V106H112.016V94ZM130.016 96.0156H125.984V97.9844H130.016V96.0156ZM125.984 102.016H130.016V100H125.984V102.016Z" fill="#03A9F4"/>
</g>
<defs>
<clipPath id="clip0_3969_50764">
<rect width="160" height="160" fill="white"/>
</clipPath>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 11 KiB

View File

@@ -0,0 +1,63 @@
<svg width="160" height="160" viewBox="0 0 160 160" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_1738_5533)">
<path d="M0 8C0 3.58172 3.58172 0 8 0H42.6667C47.0849 0 50.6667 3.58172 50.6667 8V64C50.6667 68.4183 47.0849 72 42.6667 72H8.00001C3.58173 72 0 68.4183 0 64V8Z" fill="white"/>
<path d="M8 0.5H42.667C46.809 0.500178 50.167 3.85798 50.167 8V64C50.167 68.142 46.809 71.4998 42.667 71.5H8C3.85787 71.5 0.5 68.1421 0.5 64V8C0.5 3.85786 3.85786 0.5 8 0.5Z" stroke="black" stroke-opacity="0.12"/>
<path d="M8 12C8 9.79086 9.79086 8 12 8H38.6667C40.8758 8 42.6667 9.79086 42.6667 12V12C42.6667 14.2091 40.8758 16 38.6667 16H12C9.79086 16 8 14.2091 8 12V12Z" fill="black" fill-opacity="0.32"/>
<path d="M8 27C8 25.3431 9.34315 24 11 24H27.6667C29.3235 24 30.6667 25.3431 30.6667 27V29C30.6667 30.6569 29.3235 32 27.6667 32H11C9.34314 32 8 30.6569 8 29V27Z" fill="black" fill-opacity="0.12"/>
<rect x="34.6667" y="24" width="8" height="8" rx="4" fill="black" fill-opacity="0.12"/>
<path d="M8 43C8 41.3431 9.34315 40 11 40H27.6667C29.3235 40 30.6667 41.3431 30.6667 43V45C30.6667 46.6569 29.3235 48 27.6667 48H11C9.34314 48 8 46.6569 8 45V43Z" fill="black" fill-opacity="0.12"/>
<rect x="34.6667" y="40" width="8" height="8" rx="4" fill="black" fill-opacity="0.12"/>
<path d="M8 59C8 57.3431 9.34315 56 11 56H27.6667C29.3235 56 30.6667 57.3431 30.6667 59V61C30.6667 62.6569 29.3235 64 27.6667 64H11C9.34314 64 8 62.6569 8 61V59Z" fill="black" fill-opacity="0.12"/>
<rect x="34.6667" y="56" width="8" height="8" rx="4" fill="black" fill-opacity="0.12"/>
<path d="M0 84C0 79.5817 3.58172 76 8 76H42.6667C47.0849 76 50.6667 79.5817 50.6667 84V124C50.6667 128.418 47.0849 132 42.6667 132H8.00001C3.58173 132 0 128.418 0 124V84Z" fill="white"/>
<path d="M8 76.5H42.667C46.809 76.5002 50.167 79.858 50.167 84V124C50.167 128.142 46.809 131.5 42.667 131.5H8C3.85787 131.5 0.5 128.142 0.5 124V84C0.5 79.8579 3.85786 76.5 8 76.5Z" stroke="black" stroke-opacity="0.12"/>
<path d="M8 88C8 85.7909 9.79086 84 12 84H38.6667C40.8758 84 42.6667 85.7909 42.6667 88V88C42.6667 90.2091 40.8758 92 38.6667 92H12C9.79086 92 8 90.2091 8 88V88Z" fill="black" fill-opacity="0.32"/>
<path d="M8 103C8 101.343 9.34315 100 11 100H27.6667C29.3235 100 30.6667 101.343 30.6667 103V105C30.6667 106.657 29.3235 108 27.6667 108H11C9.34314 108 8 106.657 8 105V103Z" fill="black" fill-opacity="0.12"/>
<rect x="34.6667" y="100" width="8" height="8" rx="4" fill="black" fill-opacity="0.12"/>
<path d="M8 119C8 117.343 9.34315 116 11 116H27.6667C29.3235 116 30.6667 117.343 30.6667 119V121C30.6667 122.657 29.3235 124 27.6667 124H11C9.34314 124 8 122.657 8 121V119Z" fill="black" fill-opacity="0.12"/>
<rect x="34.6667" y="116" width="8" height="8" rx="4" fill="black" fill-opacity="0.12"/>
<path d="M0 144C0 139.582 3.58172 136 8 136H42.6667C47.0849 136 50.6667 139.582 50.6667 144V152C50.6667 156.418 47.0849 160 42.6667 160H8.00001C3.58173 160 0 156.418 0 152V144Z" fill="white"/>
<path d="M8 136.5H42.667C46.809 136.5 50.167 139.858 50.167 144V152C50.167 156.142 46.809 159.5 42.667 159.5H8C3.85787 159.5 0.5 156.142 0.5 152V144C0.5 139.858 3.85786 136.5 8 136.5Z" stroke="black" stroke-opacity="0.12"/>
<path d="M8 148C8 145.791 9.79086 144 12 144H38.6667C40.8758 144 42.6667 145.791 42.6667 148V148C42.6667 150.209 40.8758 152 38.6667 152H12C9.79086 152 8 150.209 8 148V148Z" fill="black" fill-opacity="0.32"/>
<path d="M54.6667 8C54.6667 3.58172 58.2484 0 62.6667 0H97.3333C101.752 0 105.333 3.58172 105.333 8V48C105.333 52.4183 101.752 56 97.3334 56H62.6667C58.2484 56 54.6667 52.4183 54.6667 48V8Z" fill="white"/>
<path d="M62.6667 0.5H97.3337C101.476 0.50018 104.834 3.85798 104.834 8V48C104.834 52.142 101.476 55.4998 97.3337 55.5H62.6667C58.5246 55.5 55.1667 52.1421 55.1667 48V8C55.1667 3.85786 58.5246 0.5 62.6667 0.5Z" stroke="black" stroke-opacity="0.12"/>
<path d="M62.6667 12C62.6667 9.79086 64.4575 8 66.6667 8H93.3334C95.5425 8 97.3334 9.79086 97.3334 12V12C97.3334 14.2091 95.5425 16 93.3334 16H66.6667C64.4576 16 62.6667 14.2091 62.6667 12V12Z" fill="black" fill-opacity="0.32"/>
<path d="M62.6667 27C62.6667 25.3431 64.0098 24 65.6667 24H82.3334C83.9902 24 85.3334 25.3431 85.3334 27V29C85.3334 30.6569 83.9902 32 82.3334 32H65.6667C64.0098 32 62.6667 30.6569 62.6667 29V27Z" fill="black" fill-opacity="0.12"/>
<rect x="89.3333" y="24" width="8" height="8" rx="4" fill="black" fill-opacity="0.12"/>
<path d="M62.6667 43C62.6667 41.3431 64.0098 40 65.6667 40H82.3334C83.9902 40 85.3334 41.3431 85.3334 43V45C85.3334 46.6569 83.9902 48 82.3334 48H65.6667C64.0098 48 62.6667 46.6569 62.6667 45V43Z" fill="black" fill-opacity="0.12"/>
<rect x="89.3333" y="40" width="8" height="8" rx="4" fill="black" fill-opacity="0.12"/>
<path d="M54.6667 68C54.6667 63.5817 58.2484 60 62.6667 60H97.3333C101.752 60 105.333 63.5817 105.333 68V76C105.333 80.4183 101.752 84 97.3334 84H62.6667C58.2484 84 54.6667 80.4183 54.6667 76V68Z" fill="white"/>
<path d="M62.6667 60.5H97.3337C101.476 60.5002 104.834 63.858 104.834 68V76C104.834 80.142 101.476 83.4998 97.3337 83.5H62.6667C58.5246 83.5 55.1667 80.1421 55.1667 76V68C55.1667 63.8579 58.5246 60.5 62.6667 60.5Z" stroke="black" stroke-opacity="0.12"/>
<path d="M62.6667 72C62.6667 69.7909 64.4575 68 66.6667 68H93.3334C95.5425 68 97.3334 69.7909 97.3334 72V72C97.3334 74.2091 95.5425 76 93.3334 76H66.6667C64.4576 76 62.6667 74.2091 62.6667 72V72Z" fill="black" fill-opacity="0.32"/>
<path d="M54.6667 96C54.6667 91.5817 58.2484 88 62.6667 88H97.3333C101.752 88 105.333 91.5817 105.333 96V136C105.333 140.418 101.752 144 97.3334 144H62.6667C58.2484 144 54.6667 140.418 54.6667 136V96Z" fill="white"/>
<path d="M62.6667 88.5H97.3337C101.476 88.5002 104.834 91.858 104.834 96V136C104.834 140.142 101.476 143.5 97.3337 143.5H62.6667C58.5246 143.5 55.1667 140.142 55.1667 136V96C55.1667 91.8579 58.5246 88.5 62.6667 88.5Z" stroke="black" stroke-opacity="0.12"/>
<path d="M62.6667 100C62.6667 97.7909 64.4575 96 66.6667 96H93.3334C95.5425 96 97.3334 97.7909 97.3334 100V100C97.3334 102.209 95.5425 104 93.3334 104H66.6667C64.4576 104 62.6667 102.209 62.6667 100V100Z" fill="black" fill-opacity="0.32"/>
<path d="M62.6667 115C62.6667 113.343 64.0098 112 65.6667 112H82.3334C83.9902 112 85.3334 113.343 85.3334 115V117C85.3334 118.657 83.9902 120 82.3334 120H65.6667C64.0098 120 62.6667 118.657 62.6667 117V115Z" fill="black" fill-opacity="0.12"/>
<rect x="89.3333" y="112" width="8" height="8" rx="4" fill="black" fill-opacity="0.12"/>
<path d="M62.6667 131C62.6667 129.343 64.0098 128 65.6667 128H82.3334C83.9902 128 85.3334 129.343 85.3334 131V133C85.3334 134.657 83.9902 136 82.3334 136H65.6667C64.0098 136 62.6667 134.657 62.6667 133V131Z" fill="black" fill-opacity="0.12"/>
<rect x="89.3333" y="128" width="8" height="8" rx="4" fill="black" fill-opacity="0.12"/>
<path d="M109.333 8C109.333 3.58172 112.915 0 117.333 0H152C156.418 0 160 3.58172 160 8V112C160 116.418 156.418 120 152 120H117.333C112.915 120 109.333 116.418 109.333 112V8Z" fill="white"/>
<path d="M117.333 0.5H152C156.142 0.50018 159.5 3.85798 159.5 8V112C159.5 116.142 156.142 119.5 152 119.5H117.333C113.191 119.5 109.833 116.142 109.833 112V8C109.833 3.85786 113.191 0.5 117.333 0.5Z" stroke="black" stroke-opacity="0.12"/>
<path d="M117.333 12C117.333 9.79086 119.124 8 121.333 8H148C150.209 8 152 9.79086 152 12V12C152 14.2091 150.209 16 148 16H121.333C119.124 16 117.333 14.2091 117.333 12V12Z" fill="black" fill-opacity="0.32"/>
<path d="M117.333 27C117.333 25.3431 118.676 24 120.333 24H137C138.657 24 140 25.3431 140 27V29C140 30.6569 138.657 32 137 32H120.333C118.676 32 117.333 30.6569 117.333 29V27Z" fill="black" fill-opacity="0.12"/>
<rect x="144" y="24" width="8" height="8" rx="4" fill="black" fill-opacity="0.12"/>
<path d="M117.333 43C117.333 41.3431 118.676 40 120.333 40H137C138.657 40 140 41.3431 140 43V45C140 46.6569 138.657 48 137 48H120.333C118.676 48 117.333 46.6569 117.333 45V43Z" fill="black" fill-opacity="0.12"/>
<rect x="144" y="40" width="8" height="8" rx="4" fill="black" fill-opacity="0.12"/>
<path d="M117.333 59C117.333 57.3431 118.676 56 120.333 56H137C138.657 56 140 57.3431 140 59V61C140 62.6569 138.657 64 137 64H120.333C118.676 64 117.333 62.6569 117.333 61V59Z" fill="black" fill-opacity="0.12"/>
<rect x="144" y="56" width="8" height="8" rx="4" fill="black" fill-opacity="0.12"/>
<path d="M117.333 75C117.333 73.3431 118.676 72 120.333 72H137C138.657 72 140 73.3431 140 75V77C140 78.6569 138.657 80 137 80H120.333C118.676 80 117.333 78.6569 117.333 77V75Z" fill="black" fill-opacity="0.12"/>
<rect x="144" y="72" width="8" height="8" rx="4" fill="black" fill-opacity="0.12"/>
<path d="M117.333 91C117.333 89.3431 118.676 88 120.333 88H137C138.657 88 140 89.3431 140 91V93C140 94.6569 138.657 96 137 96H120.333C118.676 96 117.333 94.6569 117.333 93V91Z" fill="black" fill-opacity="0.12"/>
<rect x="144" y="88" width="8" height="8" rx="4" fill="black" fill-opacity="0.12"/>
<path d="M117.333 107C117.333 105.343 118.676 104 120.333 104H137C138.657 104 140 105.343 140 107V109C140 110.657 138.657 112 137 112H120.333C118.676 112 117.333 110.657 117.333 109V107Z" fill="black" fill-opacity="0.12"/>
<rect x="144" y="104" width="8" height="8" rx="4" fill="black" fill-opacity="0.12"/>
<path d="M109.333 132C109.333 127.582 112.915 124 117.333 124H152C156.418 124 160 127.582 160 132V140C160 144.418 156.418 148 152 148H117.333C112.915 148 109.333 144.418 109.333 140V132Z" fill="white"/>
<path d="M117.333 124.5H152C156.142 124.5 159.5 127.858 159.5 132V140C159.5 144.142 156.142 147.5 152 147.5H117.333C113.191 147.5 109.833 144.142 109.833 140V132C109.833 127.858 113.191 124.5 117.333 124.5Z" stroke="black" stroke-opacity="0.12"/>
<path d="M117.333 136C117.333 133.791 119.124 132 121.333 132H148C150.209 132 152 133.791 152 136V136C152 138.209 150.209 140 148 140H121.333C119.124 140 117.333 138.209 117.333 136V136Z" fill="black" fill-opacity="0.32"/>
</g>
<defs>
<clipPath id="clip0_1738_5533">
<rect width="160" height="160" fill="white"/>
</clipPath>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 9.8 KiB

View File

@@ -0,0 +1,16 @@
<svg width="160" height="160" viewBox="0 0 160 160" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_1738_5539)">
<rect width="160" height="160" rx="8" fill="white"/>
<rect x="0.5" y="0.5" width="159" height="159" rx="7.5" stroke="black" stroke-opacity="0.12"/>
<path d="M83 86.9844V75.125L77 73.0156V84.875L83 86.9844ZM88.4844 71C88.8281 71 89 71.1719 89 71.5156V86.6094C89 86.8594 88.875 87.0156 88.625 87.0781L83 89L77 86.8906L71.6562 88.9531L71.5156 89C71.1719 89 71 88.8281 71 88.4844V73.3906C71 73.1406 71.125 72.9844 71.375 72.9219L77 71L83 73.1094L88.3438 71.0469L88.4844 71Z" fill="#03A9F4"/>
<path d="M148 77.0508L139.288 85.8983M139.288 85.8983L116.852 108.684C115.724 109.83 114.184 110.475 112.576 110.475H81.6939M139.288 85.8983V69.4322M21.1957 82.9492H12M21.1957 82.9492L32.3274 71.6441M21.1957 82.9492L44.427 106.542M81.6939 110.475V124.237M81.6939 110.475H54.5907M81.6939 138V124.237M81.6939 124.237H148M32.3274 71.6441L43.4591 60.339L54.5907 49.0339L70.4941 32.8828C74.2533 29.0651 79.3871 26.9153 84.7451 26.9153H128.641V26.9153C134.521 26.9153 139.288 31.6824 139.288 37.5629V37.7288V49.0339M32.3274 71.6441L24.8569 64.0572C22.5573 61.7218 22.5573 57.9732 24.8569 55.6377L57.9786 22M139.288 49.0339H126.313C124.706 49.0339 123.166 48.389 122.038 47.2436L116.057 41.1695M139.288 49.0339V69.4322M139.288 69.4322H126.313C124.706 69.4322 123.166 68.7873 122.038 67.6419L116.057 61.5678M54.5907 110.475V110.475C54.5907 107.488 52.17 105.068 49.184 105.068H49.0249C45.951 105.068 43.4591 107.56 43.4591 110.634V110.807C43.4591 113.881 45.951 116.373 49.0249 116.373V116.373C52.0988 116.373 54.5907 113.881 54.5907 110.807V110.475ZM44.427 115.39L22.1637 138" stroke="black" stroke-opacity="0.12" stroke-width="5" stroke-linecap="round"/>
<circle cx="41" cy="39" r="14" fill="black" fill-opacity="0.32"/>
<circle cx="89" cy="117" r="14" fill="black" fill-opacity="0.32"/>
<path d="M116 62.325C115.767 62.325 115.533 62.2833 115.3 62.2C115.067 62.1167 114.858 61.9917 114.675 61.825C113.592 60.825 112.633 59.85 111.8 58.9C110.967 57.95 110.267 57.0333 109.7 56.15C109.15 55.25 108.725 54.3917 108.425 53.575C108.142 52.7417 108 51.95 108 51.2C108 48.7 108.8 46.7083 110.4 45.225C112.017 43.7417 113.883 43 116 43C118.117 43 119.975 43.7417 121.575 45.225C123.192 46.7083 124 48.7 124 51.2C124 51.95 123.85 52.7417 123.55 53.575C123.267 54.3917 122.842 55.25 122.275 56.15C121.725 57.0333 121.033 57.95 120.2 58.9C119.367 59.85 118.408 60.825 117.325 61.825C117.142 61.9917 116.933 62.1167 116.7 62.2C116.467 62.2833 116.233 62.325 116 62.325Z" fill="black" fill-opacity="0.32"/>
</g>
<defs>
<clipPath id="clip0_1738_5539">
<rect width="160" height="160" fill="white"/>
</clipPath>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 2.7 KiB

View File

@@ -0,0 +1,13 @@
<svg width="160" height="72" viewBox="0 0 160 72" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_1738_5535)">
<path d="M0 4C0 1.79086 1.79086 0 4 0H28C30.2091 0 32 1.79086 32 4V4C32 6.20914 30.2091 8 28 8H4C1.79086 8 0 6.20914 0 4V4Z" fill="black" fill-opacity="0.32"/>
<rect y="12" width="50.6667" height="60" rx="8" fill="white"/>
<rect x="0.5" y="12.5" width="49.6667" height="59" rx="7.5" stroke="black" stroke-opacity="0.12"/>
<path d="M32.3177 42.9844H26.3177V48.9844H24.349V42.9844H18.349V41.0156H24.349V35.0156H26.3177V41.0156H32.3177V42.9844Z" fill="#03A9F4"/>
</g>
<defs>
<clipPath id="clip0_1738_5535">
<rect width="160" height="72" fill="white"/>
</clipPath>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 712 B

View File

@@ -0,0 +1,16 @@
<svg width="160" height="160" viewBox="0 0 160 160" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_1738_5537)">
<rect width="160" height="160" rx="6" fill="white"/>
<rect x="0.5" y="0.5" width="159" height="159" rx="5.5" stroke="black" stroke-opacity="0.12"/>
<rect x="8" y="8" width="144" height="11" rx="5.5" fill="black" fill-opacity="0.32"/>
<rect x="8" y="27" width="45.3333" height="106" rx="4" fill="#E9E9E9"/>
<rect x="57.3333" y="27" width="45.3333" height="30" rx="4" fill="#E9E9E9"/>
<rect x="106.667" y="27" width="45.3333" height="68" rx="4" fill="#E9E9E9"/>
<path d="M84.3594 82.0156H87.7344C87.9219 81.1406 88.0156 80.4688 88.0156 80C88.0156 79.5312 87.9219 78.8594 87.7344 77.9844H84.3594C84.4531 78.6406 84.5 79.3125 84.5 80C84.5 80.6875 84.4531 81.3594 84.3594 82.0156ZM82.5781 87.5469C83.3594 87.2969 84.1719 86.8281 85.0156 86.1406C85.8594 85.4219 86.5 84.7031 86.9375 83.9844H83.9844C83.6719 85.2344 83.2031 86.4219 82.5781 87.5469ZM82.3438 82.0156C82.4375 81.3594 82.4844 80.6875 82.4844 80C82.4844 79.3125 82.4375 78.6406 82.3438 77.9844H77.6562C77.5625 78.6406 77.5156 79.3125 77.5156 80C77.5156 80.6875 77.5625 81.3594 77.6562 82.0156H82.3438ZM80 87.9688C80.875 86.6875 81.5156 85.3594 81.9219 83.9844H78.0781C78.4844 85.3594 79.125 86.6875 80 87.9688ZM76.0156 76.0156C76.3906 74.6719 76.8594 73.4844 77.4219 72.4531C76.6406 72.7031 75.8125 73.1875 74.9375 73.9062C74.0938 74.5938 73.4688 75.2969 73.0625 76.0156H76.0156ZM73.0625 83.9844C73.4688 84.7031 74.0938 85.4219 74.9375 86.1406C75.8125 86.8281 76.6406 87.2969 77.4219 87.5469C76.7969 86.4219 76.3281 85.2344 76.0156 83.9844H73.0625ZM72.2656 82.0156H75.6406C75.5469 81.3594 75.5 80.6875 75.5 80C75.5 79.3125 75.5469 78.6406 75.6406 77.9844H72.2656C72.0781 78.8594 71.9844 79.5312 71.9844 80C71.9844 80.4688 72.0781 81.1406 72.2656 82.0156ZM80 72.0312C79.125 73.3125 78.4844 74.6406 78.0781 76.0156H81.9219C81.5156 74.6406 80.875 73.3125 80 72.0312ZM86.9375 76.0156C86.5 75.2969 85.8594 74.5938 85.0156 73.9062C84.1719 73.1875 83.3594 72.7031 82.5781 72.4531C83.1406 73.4844 83.6094 74.6719 83.9844 76.0156H86.9375ZM72.9219 72.9688C74.8906 71 77.25 70.0156 80 70.0156C82.75 70.0156 85.0938 71 87.0312 72.9688C89 74.9062 89.9844 77.25 89.9844 80C89.9844 82.75 89 85.1094 87.0312 87.0781C85.0938 89.0156 82.75 89.9844 80 89.9844C77.25 89.9844 74.8906 89.0156 72.9219 87.0781C70.9844 85.1094 70.0156 82.75 70.0156 80C70.0156 77.25 70.9844 74.9062 72.9219 72.9688Z" fill="#03A9F4"/>
</g>
<defs>
<clipPath id="clip0_1738_5537">
<rect width="160" height="160" fill="white"/>
</clipPath>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 2.5 KiB

View File

@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
[project]
name = "home-assistant-frontend"
version = "20250430.0"
version = "20250625.0"
license = "Apache-2.0"
license-files = ["LICENSE*"]
description = "The Home Assistant frontend"

View File

@@ -1,28 +0,0 @@
/* eslint-disable @typescript-eslint/no-require-imports */
// Needs to remain CommonJS until eslint-import-resolver-webpack supports ES modules
const rspack = require("./build-scripts/rspack.cjs");
const env = require("./build-scripts/env.cjs");
// This file exists because we haven't migrated the stats script yet
const configs = [
rspack.createAppConfig({
isProdBuild: env.isProdBuild(),
isStatsBuild: env.isStatsBuild(),
isTestBuild: env.isTestBuild(),
latestBuild: true,
}),
];
if (env.isProdBuild() && !env.isStatsBuild()) {
configs.push(
rspack.createAppConfig({
isProdBuild: env.isProdBuild(),
isStatsBuild: env.isStatsBuild(),
isTestBuild: env.isTestBuild(),
latestBuild: false,
})
);
}
module.exports = configs;

View File

@@ -6,4 +6,4 @@ set -e
cd "$(dirname "$0")/.."
./node_modules/.bin/gulp build-app
yarn run-task build-app

View File

@@ -6,4 +6,4 @@ set -e
cd "$(dirname "$0")/.."
./node_modules/.bin/gulp develop-app
yarn run-task develop-app

View File

@@ -6,4 +6,4 @@ set -e
cd "$(dirname "$0")/.."
./node_modules/.bin/gulp setup-and-fetch-nightly-translations
yarn run-task setup-and-fetch-nightly-translations

View File

@@ -6,4 +6,4 @@ set -e
cd "$(dirname "$0")/.."
./node_modules/.bin/gulp analyze-app
yarn run-task analyze-app

View File

@@ -8,4 +8,4 @@ set -eu -o pipefail
cd "$(dirname "$0")/.."
./node_modules/.bin/gulp download-translations
yarn run-task download-translations

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