├── .browserslistrc
├── .devcontainer
├── Dockerfile
├── devcontainer.json
└── post_create.sh
├── .gitattributes
├── .github
├── ISSUE_TEMPLATE.md
├── ISSUE_TEMPLATE
│ ├── bug_report.yml
│ └── config.yml
├── PULL_REQUEST_TEMPLATE.md
├── dependabot.yml
├── labeler.yml
├── move.yml
├── release-drafter.yml
└── workflows
│ ├── cast_deployment.yaml
│ ├── ci.yaml
│ ├── codeql-analysis.yml
│ ├── demo_deployment.yaml
│ ├── design_deployment.yaml
│ ├── design_preview.yaml
│ ├── labeler.yaml
│ ├── lock.yml
│ ├── nightly.yaml
│ ├── relative-ci.yaml
│ ├── release-drafter.yaml
│ ├── release.yaml
│ ├── stale.yml
│ └── translations.yaml
├── .gitignore
├── .gitmodules
├── .husky
└── pre-commit
├── .nvmrc
├── .prettierignore
├── .vscode
├── extensions.json
├── launch.json
└── tasks.json
├── .yarn
├── patches
│ ├── @material-mwc-formfield-npm-0.27.0-9528cb60f6.patch
│ ├── @material-mwc-list-npm-0.27.0-5344fc9de4.patch
│ ├── leaflet-draw-npm-1.0.4-0ca0ebcf65.patch
│ ├── sortablejs-npm-1.15.6-3235a8f83b.patch
│ └── workbox-build-npm-7.1.1-a854f3faae.patch
└── releases
│ └── yarn-4.9.1.cjs
├── .yarnrc.yml
├── CLA.md
├── CODE_OF_CONDUCT.md
├── LICENSE.md
├── MANIFEST.in
├── README.md
├── build-scripts
├── README.md
├── babel-plugins
│ ├── custom-polyfill-plugin.js
│ └── inline-constants-plugin.cjs
├── bundle.cjs
├── env.cjs
├── eslint.config.mjs
├── gulp
│ ├── app.js
│ ├── cast.js
│ ├── clean.js
│ ├── compress.js
│ ├── demo.js
│ ├── download-translations.js
│ ├── entry-html.js
│ ├── fetch-nightly-translations.js
│ ├── gallery.js
│ ├── gather-static.js
│ ├── gen-icons-json.js
│ ├── hassio.js
│ ├── index.mjs
│ ├── landing-page.js
│ ├── locale-data.js
│ ├── rspack.js
│ ├── service-worker.js
│ └── translations.js
├── list-plugins-and-polyfills.js
├── paths.cjs
├── removedIcons.json
└── rspack.cjs
├── cast
├── README.md
├── public
│ ├── _headers
│ ├── _redirects
│ ├── images
│ │ ├── arsaboo.jpg
│ │ ├── favicon.ico
│ │ ├── google-nest-hub.png
│ │ ├── ha-cast-icon.png
│ │ ├── melody.jpg
│ │ └── nabu-loves-hass.png
│ ├── manifest.json
│ ├── sw-legacy.js
│ └── sw-modern.js
├── script
│ ├── build_cast
│ ├── develop_cast
│ └── upload
└── src
│ ├── html
│ ├── _social_meta.html.template
│ ├── faq.html.template
│ ├── index.html.template
│ ├── media.html.template
│ └── receiver.html.template
│ ├── launcher
│ ├── entrypoint.ts
│ └── layout
│ │ ├── hc-cast.ts
│ │ ├── hc-connect.ts
│ │ └── hc-layout.ts
│ ├── media
│ └── entrypoint.ts
│ └── receiver
│ ├── cast_context.ts
│ ├── cast_framework.ts
│ ├── demo
│ ├── cast-demo-entities.ts
│ └── cast-demo-lovelace.ts
│ ├── entrypoint.ts
│ ├── layout
│ ├── hc-demo.ts
│ ├── hc-launch-screen.ts
│ ├── hc-lovelace.ts
│ └── hc-main.ts
│ └── types.ts
├── demo
├── public
│ ├── _headers
│ ├── assets
│ │ ├── arsaboo
│ │ │ ├── floorplans
│ │ │ │ ├── ecobee_blank.png
│ │ │ │ ├── main.png
│ │ │ │ └── second.png
│ │ │ ├── icons
│ │ │ │ ├── Harmony.png
│ │ │ │ ├── abode_disabled.png
│ │ │ │ ├── abode_enabled.png
│ │ │ │ ├── automation_disabled.png
│ │ │ │ ├── automation_enabled.png
│ │ │ │ ├── camera_backyard_recording.png
│ │ │ │ ├── camera_backyard_streaming.png
│ │ │ │ ├── camera_driveway_recording.png
│ │ │ │ ├── camera_driveway_streaming.png
│ │ │ │ ├── camera_patio_recording.png
│ │ │ │ ├── camera_patio_streaming.png
│ │ │ │ ├── camera_porch_recording.png
│ │ │ │ ├── camera_porch_streaming.png
│ │ │ │ ├── ecobee_blank.png
│ │ │ │ ├── garage_door_closed.png
│ │ │ │ ├── garage_door_open.png
│ │ │ │ ├── light_bulb_off.png
│ │ │ │ ├── light_bulb_on.png
│ │ │ │ ├── light_off.png
│ │ │ │ ├── light_on.png
│ │ │ │ ├── security_armed_red.png
│ │ │ │ ├── security_disarmed.png
│ │ │ │ ├── tv_disabled.png
│ │ │ │ ├── tv_enabled.png
│ │ │ │ ├── tv_off2.png
│ │ │ │ └── tv_on2.png
│ │ │ └── images
│ │ │ │ ├── arsaboo.jpg
│ │ │ │ ├── camera.backyard.jpg
│ │ │ │ ├── camera.driveway.jpg
│ │ │ │ ├── camera.patio.jpg
│ │ │ │ ├── camera.porch.jpg
│ │ │ │ ├── media_player_family_room.jpg
│ │ │ │ └── melody.jpg
│ │ ├── jimpower
│ │ │ ├── background-15.jpg
│ │ │ ├── cardbackK.png
│ │ │ ├── home
│ │ │ │ ├── bus_10.jpg
│ │ │ │ ├── git.png
│ │ │ │ ├── house_4.png
│ │ │ │ ├── james_10.jpg
│ │ │ │ └── tina_4.jpg
│ │ │ └── security
│ │ │ │ ├── air_8.jpg
│ │ │ │ ├── alarm_3.jpg
│ │ │ │ ├── door_3.png
│ │ │ │ ├── leak_2.png
│ │ │ │ ├── motion_3.jpg
│ │ │ │ ├── smoke_4.jpg
│ │ │ │ └── window_2.jpg
│ │ ├── kernehed
│ │ │ ├── bella.jpg
│ │ │ ├── camera.entre.jpg
│ │ │ └── oscar.jpg
│ │ ├── sections
│ │ │ └── images
│ │ │ │ └── media_player_family_room.jpg
│ │ └── teachingbirds
│ │ │ ├── House_square.jpg
│ │ │ ├── Stefan_square.jpg
│ │ │ ├── background_square.png
│ │ │ ├── cleaning_square.jpg
│ │ │ ├── clothes_drying_square.jpg
│ │ │ ├── dryer_square.jpg
│ │ │ ├── folded_clothes_square.jpg
│ │ │ ├── guests_square.jpg
│ │ │ ├── isa_square.jpg
│ │ │ ├── laundry_clean_2_square.jpg
│ │ │ ├── laundry_running_square.jpg
│ │ │ ├── mailbox_bw_square.jpg
│ │ │ ├── mailbox_square.jpg
│ │ │ ├── meteogram.png
│ │ │ ├── plants.png
│ │ │ ├── radiator_off.jpg
│ │ │ ├── radiator_on.jpg
│ │ │ ├── roomba_bw_square.jpg
│ │ │ ├── roomba_square.jpg
│ │ │ ├── trash_bear_bw_square.jpg
│ │ │ ├── trash_square.jpg
│ │ │ └── washer_square.jpg
│ ├── manifest.json
│ ├── stub_config
│ │ ├── bedroom.png
│ │ ├── floorplan.png
│ │ ├── kitchen.png
│ │ └── t-shirt-promo.png
│ ├── sw-legacy.js
│ └── sw-modern.js
├── script
│ ├── build_demo
│ ├── develop_demo
│ └── size_stats
└── src
│ ├── configs
│ ├── arsaboo
│ │ ├── entities.ts
│ │ ├── index.ts
│ │ ├── lovelace.ts
│ │ └── theme.ts
│ ├── demo-configs.ts
│ ├── jimpower
│ │ ├── entities.ts
│ │ ├── index.ts
│ │ ├── lovelace.ts
│ │ └── theme.ts
│ ├── kernehed
│ │ ├── entities.ts
│ │ ├── index.ts
│ │ ├── lovelace.ts
│ │ └── theme.ts
│ ├── sections
│ │ ├── entities.ts
│ │ ├── index.ts
│ │ └── lovelace.ts
│ ├── teachingbirds
│ │ ├── entities.ts
│ │ ├── index.ts
│ │ ├── lovelace.ts
│ │ └── theme.ts
│ └── types.ts
│ ├── custom-cards
│ ├── card-modder.js
│ ├── card-tools.js
│ ├── cast-demo-row.ts
│ └── ha-demo-card.ts
│ ├── entrypoint.ts
│ ├── ha-demo.ts
│ ├── html
│ ├── _social_meta.html.template
│ └── index.html.template
│ ├── stubs
│ ├── area_registry.ts
│ ├── auth.ts
│ ├── config.ts
│ ├── config_entries.ts
│ ├── device_registry.ts
│ ├── energy.ts
│ ├── entities.ts
│ ├── entity_registry.ts
│ ├── events.ts
│ ├── floor_registry.ts
│ ├── frontend.ts
│ ├── hassio_supervisor.ts
│ ├── history.ts
│ ├── icons.ts
│ ├── label_registry.ts
│ ├── lovelace.ts
│ ├── media_player.ts
│ ├── persistent_notification.ts
│ ├── recorder.ts
│ ├── sensor.ts
│ ├── system_log.ts
│ ├── tags.ts
│ ├── template.ts
│ ├── todo.ts
│ └── translations.ts
│ └── util
│ └── is_frontpage.ts
├── docs
└── screenshot.png
├── eslint.config.mjs
├── gallery
├── eslint.config.mjs
├── public
│ ├── api
│ │ ├── hassio
│ │ │ └── addons
│ │ │ │ └── core_zwave_js
│ │ │ │ └── icon
│ │ └── media_player_proxy
│ │ │ ├── media_player.bedroom
│ │ │ ├── media_player.living_room
│ │ │ └── media_player.walkman
│ └── images
│ │ ├── album_cover.jpg
│ │ ├── album_cover_2.jpg
│ │ ├── bed.png
│ │ ├── brand
│ │ ├── README.md
│ │ ├── logo-exclusion-zone.png
│ │ ├── logo-layout-variants.png
│ │ └── logo.png
│ │ ├── clearspace.png
│ │ ├── divider.png
│ │ ├── floorplan.png
│ │ ├── frenck.jpg
│ │ ├── kitchen.png
│ │ ├── light_bulb_off.png
│ │ ├── light_bulb_on.png
│ │ ├── living_room.png
│ │ ├── logo-variants.png
│ │ ├── logo-with-text.png
│ │ ├── netflix.jpg
│ │ ├── office.jpg
│ │ ├── paulus.jpg
│ │ ├── select_box
│ │ ├── card.svg
│ │ └── text_only.svg
│ │ └── sunflowers.jpg
├── script
│ ├── build_gallery
│ └── develop_gallery
├── sidebar.js
└── src
│ ├── components
│ ├── demo-black-white-row.ts
│ ├── demo-card.ts
│ ├── demo-cards.ts
│ ├── demo-more-info.ts
│ ├── demo-more-infos.ts
│ └── page-description.ts
│ ├── data
│ ├── date-options.ts
│ ├── demo_states.js
│ ├── hass.js
│ ├── media_players.ts
│ ├── plants.ts
│ ├── text.ts
│ └── traces
│ │ ├── basic_trace.ts
│ │ ├── mock-demo-trace.ts
│ │ ├── motion-light-trace.ts
│ │ └── types.ts
│ ├── entrypoint.js
│ ├── ha-demo-options.ts
│ ├── ha-gallery.ts
│ ├── html
│ └── index.html.template
│ └── pages
│ ├── Text
│ └── remove-delete-add-create.markdown
│ ├── automation
│ ├── describe-action.markdown
│ ├── describe-action.ts
│ ├── describe-condition.markdown
│ ├── describe-condition.ts
│ ├── describe-trigger.markdown
│ ├── describe-trigger.ts
│ ├── editor-action.markdown
│ ├── editor-action.ts
│ ├── editor-condition.markdown
│ ├── editor-condition.ts
│ ├── editor-trigger.markdown
│ ├── editor-trigger.ts
│ ├── trace-timeline.markdown
│ ├── trace-timeline.ts
│ ├── trace.markdown
│ └── trace.ts
│ ├── brand
│ ├── logo.markdown
│ └── our-story.markdown
│ ├── components
│ ├── ha-alert.markdown
│ ├── ha-alert.ts
│ ├── ha-badge.markdown
│ ├── ha-badge.ts
│ ├── ha-bar.markdown
│ ├── ha-bar.ts
│ ├── ha-chips.markdown
│ ├── ha-chips.ts
│ ├── ha-control-button.markdown
│ ├── ha-control-button.ts
│ ├── ha-control-circular-slider.markdown
│ ├── ha-control-circular-slider.ts
│ ├── ha-control-number-buttons.markdown
│ ├── ha-control-number-buttons.ts
│ ├── ha-control-select-menu.markdown
│ ├── ha-control-select-menu.ts
│ ├── ha-control-select.markdown
│ ├── ha-control-select.ts
│ ├── ha-control-slider.markdown
│ ├── ha-control-slider.ts
│ ├── ha-control-switch.markdown
│ ├── ha-control-switch.ts
│ ├── ha-dialogs.markdown
│ ├── ha-expansion-panel.markdown
│ ├── ha-expansion-panel.ts
│ ├── ha-faded.markdown
│ ├── ha-faded.ts
│ ├── ha-form.markdown
│ ├── ha-form.ts
│ ├── ha-gauge.markdown
│ ├── ha-gauge.ts
│ ├── ha-hs-color-picker.markdown
│ ├── ha-hs-color-picker.ts
│ ├── ha-label-badge.markdown
│ ├── ha-label-badge.ts
│ ├── ha-select-box.markdown
│ ├── ha-select-box.ts
│ ├── ha-selector.markdown
│ ├── ha-selector.ts
│ ├── ha-spinner.markdown
│ ├── ha-spinner.ts
│ ├── ha-switch.markdown
│ ├── ha-switch.ts
│ ├── ha-tip.markdown
│ ├── ha-tip.ts
│ ├── ha-tooltip.markdown
│ └── ha-tooltip.ts
│ ├── concepts
│ └── home.markdown
│ ├── date-time
│ ├── date-time-numeric.markdown
│ ├── date-time-numeric.ts
│ ├── date-time-seconds.markdown
│ ├── date-time-seconds.ts
│ ├── date-time-short-year.markdown
│ ├── date-time-short-year.ts
│ ├── date-time-short.markdown
│ ├── date-time-short.ts
│ ├── date-time.markdown
│ ├── date-time.ts
│ ├── date.markdown
│ ├── date.ts
│ ├── time-seconds.markdown
│ ├── time-seconds.ts
│ ├── time-weekday.markdown
│ ├── time-weekday.ts
│ ├── time.markdown
│ └── time.ts
│ ├── design.home-assistant.io
│ └── editing.markdown
│ ├── lovelace
│ ├── alarm-panel-card.markdown
│ ├── alarm-panel-card.ts
│ ├── area-card.markdown
│ ├── area-card.ts
│ ├── conditional-card.markdown
│ ├── conditional-card.ts
│ ├── entities-card.markdown
│ ├── entities-card.ts
│ ├── entity-button-card.markdown
│ ├── entity-button-card.ts
│ ├── entity-filter-card.markdown
│ ├── entity-filter-card.ts
│ ├── gauge-card.markdown
│ ├── gauge-card.ts
│ ├── glance-card.markdown
│ ├── glance-card.ts
│ ├── grid-and-stack-card.markdown
│ ├── grid-and-stack-card.ts
│ ├── iframe-card.markdown
│ ├── iframe-card.ts
│ ├── introduction.markdown
│ ├── light-card.markdown
│ ├── light-card.ts
│ ├── map-card.markdown
│ ├── map-card.ts
│ ├── markdown-card.markdown
│ ├── markdown-card.ts
│ ├── media-control-card.markdown
│ ├── media-control-card.ts
│ ├── media-player-row.markdown
│ ├── media-player-row.ts
│ ├── picture-card.markdown
│ ├── picture-card.ts
│ ├── picture-elements-card.markdown
│ ├── picture-elements-card.ts
│ ├── picture-entity-card.markdown
│ ├── picture-entity-card.ts
│ ├── picture-glance-card.markdown
│ ├── picture-glance-card.ts
│ ├── plant-card.markdown
│ ├── plant-card.ts
│ ├── thermostat-card.markdown
│ ├── thermostat-card.ts
│ ├── tile-card.markdown
│ ├── tile-card.ts
│ ├── todo-list-card.markdown
│ └── todo-list-card.ts
│ ├── misc
│ ├── entity-state.markdown
│ ├── entity-state.ts
│ ├── ha-markdown.markdown
│ ├── ha-markdown.ts
│ ├── integration-card.markdown
│ ├── integration-card.ts
│ ├── util-long-press.markdown
│ └── util-long-press.ts
│ ├── more-info
│ ├── climate.markdown
│ ├── climate.ts
│ ├── cover.markdown
│ ├── cover.ts
│ ├── humidifier.markdown
│ ├── humidifier.ts
│ ├── input-number.markdown
│ ├── input-number.ts
│ ├── input-text.markdown
│ ├── input-text.ts
│ ├── light.markdown
│ ├── light.ts
│ ├── lock.markdown
│ ├── lock.ts
│ ├── media-player.markdown
│ ├── media-player.ts
│ ├── number.markdown
│ ├── number.ts
│ ├── scene.markdown
│ ├── scene.ts
│ ├── timer.markdown
│ ├── timer.ts
│ ├── update.markdown
│ ├── update.ts
│ ├── vacuum.markdown
│ ├── vacuum.ts
│ ├── water-heater.markdown
│ └── water-heater.ts
│ └── user-test
│ ├── configuration-menu.markdown
│ └── user-types.markdown
├── gulpfile.js
├── hassio
├── config.cjs
├── script
│ ├── build_hassio
│ └── develop
└── src
│ ├── addon-store
│ ├── hassio-addon-repository.ts
│ └── hassio-addon-store.ts
│ ├── addon-view
│ ├── config
│ │ ├── hassio-addon-audio.ts
│ │ ├── hassio-addon-config-tab.ts
│ │ ├── hassio-addon-config.ts
│ │ └── hassio-addon-network.ts
│ ├── documentation
│ │ └── hassio-addon-documentation-tab.ts
│ ├── hassio-addon-dashboard.ts
│ ├── hassio-addon-router.ts
│ ├── info
│ │ ├── hassio-addon-info-tab.ts
│ │ ├── hassio-addon-info.ts
│ │ └── hassio-addon-system-managed.ts
│ └── log
│ │ └── hassio-addon-log-tab.ts
│ ├── backups
│ └── hassio-backups.ts
│ ├── components
│ ├── hassio-card-content.ts
│ ├── hassio-filter-addons.ts
│ ├── hassio-upload-backup.ts
│ ├── supervisor-backup-content.ts
│ ├── supervisor-formfield-label.ts
│ └── supervisor-metric.ts
│ ├── dashboard
│ ├── hassio-addons.ts
│ ├── hassio-dashboard.ts
│ └── hassio-update.ts
│ ├── dialogs
│ ├── backup
│ │ ├── dialog-hassio-backup-location.ts
│ │ ├── dialog-hassio-backup-upload.ts
│ │ ├── dialog-hassio-backup.ts
│ │ ├── dialog-hassio-create-backup.ts
│ │ ├── show-dialog-backup-upload.ts
│ │ ├── show-dialog-hassio-backu-location.ts
│ │ ├── show-dialog-hassio-backup.ts
│ │ └── show-dialog-hassio-create-backup.ts
│ ├── datadisk
│ │ ├── dialog-hassio-datadisk.ts
│ │ └── show-dialog-hassio-datadisk.ts
│ ├── hardware
│ │ ├── dialog-hassio-hardware.ts
│ │ └── show-dialog-hassio-hardware.ts
│ ├── markdown
│ │ ├── dialog-hassio-markdown.ts
│ │ └── show-dialog-hassio-markdown.ts
│ ├── network
│ │ ├── dialog-hassio-network.ts
│ │ └── show-dialog-network.ts
│ ├── registries
│ │ ├── dialog-hassio-registries.ts
│ │ └── show-dialog-registries.ts
│ ├── repositories
│ │ ├── dialog-hassio-repositories.ts
│ │ └── show-dialog-repositories.ts
│ ├── suggestAddonRestart.ts
│ └── system-managed
│ │ ├── dialog-system-managed.ts
│ │ └── show-dialog-system-managed.ts
│ ├── entrypoint.js.template
│ ├── entrypoint.ts
│ ├── hassio-main.ts
│ ├── hassio-my-redirect.ts
│ ├── hassio-panel-router.ts
│ ├── hassio-panel.ts
│ ├── hassio-router.ts
│ ├── hassio-tabs.ts
│ ├── ingress-view
│ └── hassio-ingress-view.ts
│ ├── resources
│ └── hassio-style.ts
│ ├── supervisor-base-element.ts
│ ├── system
│ ├── hassio-core-info.ts
│ ├── hassio-host-info.ts
│ ├── hassio-supervisor-info.ts
│ ├── hassio-supervisor-log.ts
│ └── hassio-system.ts
│ ├── update-available
│ ├── update-available-card.ts
│ └── update-available-dashboard.ts
│ └── util
│ └── addon.ts
├── landing-page
├── README.md
├── eslintrc.config.mjs
├── public
│ └── static
│ │ ├── icons
│ │ ├── favicon-192x192.png
│ │ ├── favicon.ico
│ │ ├── logo_ohf.svg
│ │ └── ohf.svg
│ │ └── images
│ │ ├── appstore.svg
│ │ ├── logo_discord.png
│ │ ├── logo_mastodon.svg
│ │ ├── logo_x.svg
│ │ ├── playstore.svg
│ │ ├── qr-appstore.svg
│ │ └── qr-playstore.svg
├── script
│ ├── build_landing_page
│ └── develop
└── src
│ ├── components
│ ├── landing-page-logs.ts
│ └── landing-page-network.ts
│ ├── data
│ ├── observer.ts
│ └── supervisor.ts
│ ├── entrypoint.js
│ ├── ha-landing-page.ts
│ ├── html
│ └── index.html.template
│ └── landing-page-base-element.ts
├── lint-staged.config.js
├── netlify.toml
├── package.json
├── prettier.config.js
├── public
├── __init__.py
├── py.typed
├── robots.txt
└── static
│ ├── icons
│ ├── browserconfig.xml
│ ├── favicon-1024x1024.png
│ ├── favicon-16x16.png
│ ├── favicon-192x192.png
│ ├── favicon-32x32.png
│ ├── favicon-384x384.png
│ ├── favicon-512x512.png
│ ├── favicon-apple-180x180.png
│ ├── favicon.ico
│ ├── logo_ohf.svg
│ ├── mask-icon.svg
│ ├── maskable_icon-128x128.png
│ ├── maskable_icon-192x192.png
│ ├── maskable_icon-384x384.png
│ ├── maskable_icon-48x48.png
│ ├── maskable_icon-512x512.png
│ ├── maskable_icon-72x72.png
│ ├── maskable_icon-96x96.png
│ ├── ohf.svg
│ ├── tile-win-150x150.png
│ ├── tile-win-310x150.png
│ ├── tile-win-310x310.png
│ └── tile-win-70x70.png
│ └── images
│ ├── appstore.svg
│ ├── card_media_player_bg.png
│ ├── color_wheel.png
│ ├── config_ecobee_thermostat.png
│ ├── config_fitbit_app.png
│ ├── config_flows
│ └── config_homematicip_cloud.png
│ ├── config_freebox.png
│ ├── config_icloud.png
│ ├── config_insteon.png
│ ├── config_philips_hue.jpg
│ ├── config_webos.png
│ ├── config_wink.png
│ ├── darksky
│ ├── weather-cloudy.svg
│ ├── weather-fog.svg
│ ├── weather-hail.svg
│ ├── weather-night.svg
│ ├── weather-partlycloudy.svg
│ ├── weather-pouring.svg
│ ├── weather-rainy.svg
│ ├── weather-snowy.svg
│ ├── weather-sunny.svg
│ └── weather-windy.svg
│ ├── form
│ ├── markdown_card.svg
│ ├── markdown_card_dark.svg
│ ├── markdown_text_only.svg
│ ├── markdown_text_only_dark.svg
│ ├── tile_content_layout_horizontal.svg
│ ├── tile_content_layout_horizontal_dark.svg
│ ├── tile_content_layout_vertical.svg
│ ├── tile_content_layout_vertical_dark.svg
│ ├── tile_features_position_bottom.svg
│ ├── tile_features_position_bottom_dark.svg
│ ├── tile_features_position_inline.svg
│ ├── tile_features_position_inline_dark.svg
│ ├── view_header_badges_position_bottom.svg
│ ├── view_header_badges_position_bottom_dark.svg
│ ├── view_header_badges_position_top.svg
│ ├── view_header_badges_position_top_dark.svg
│ ├── view_header_badges_wrap_scroll.svg
│ ├── view_header_badges_wrap_scroll_dark.svg
│ ├── view_header_badges_wrap_wrap.svg
│ ├── view_header_badges_wrap_wrap_dark.svg
│ ├── view_header_layout_center.svg
│ ├── view_header_layout_center_dark.svg
│ ├── view_header_layout_responsive.svg
│ ├── view_header_layout_responsive_dark.svg
│ ├── view_header_layout_start.svg
│ └── view_header_layout_start_dark.svg
│ ├── image-broken.svg
│ ├── logo_apple_home.png
│ ├── logo_automatic.png
│ ├── logo_axis.png
│ ├── logo_deconz.jpeg
│ ├── logo_discord.png
│ ├── logo_google_home.png
│ ├── logo_mastodon.svg
│ ├── logo_nabu_casa.png
│ ├── logo_nabu_casa_dark.png
│ ├── logo_philips_hue.png
│ ├── logo_plex_mediaserver.png
│ ├── logo_x.svg
│ ├── notification-badge.png
│ ├── ohf-badge.svg
│ ├── playstore.svg
│ ├── qr-appstore.svg
│ ├── qr-playstore.svg
│ ├── screenshots
│ └── screenshot-1.png
│ ├── smart-tv.png
│ ├── voice-assistant
│ ├── area.png
│ ├── change-wake-word.png
│ ├── error.png
│ ├── great-job.png
│ ├── heart.png
│ ├── hi.png
│ ├── ok-nabu.png
│ ├── sleep.png
│ └── update.png
│ └── z-wave-add-node
│ ├── long-range.svg
│ ├── long-range_dark.svg
│ ├── mesh.svg
│ └── mesh_dark.svg
├── pyproject.toml
├── renovate.json
├── rspack.config.cjs
├── script
├── bootstrap
├── build_frontend
├── core
├── develop
├── develop_and_serve
├── release
├── serve-config.json
├── setup
├── setup_translations
├── size_stats
├── translations_download
├── translations_upload_base
└── version_bump.js
├── src
├── auth
│ ├── ha-auth-flow.ts
│ ├── ha-auth-form-string.ts
│ ├── ha-auth-form.ts
│ ├── ha-auth-textfield.ts
│ ├── ha-authorize.ts
│ └── ha-pick-auth-provider.ts
├── cast
│ ├── cast_framework.ts
│ ├── cast_manager.ts
│ ├── const.ts
│ ├── dev_const.ts
│ ├── receiver_messages.ts
│ ├── sender_messages.ts
│ └── types.ts
├── common
│ ├── array
│ │ ├── combinations.ts
│ │ ├── ensure-array.ts
│ │ └── literal-includes.ts
│ ├── auth
│ │ └── token_storage.ts
│ ├── color
│ │ ├── colors.ts
│ │ ├── compute-color.ts
│ │ ├── convert-color.ts
│ │ ├── convert-light-color.ts
│ │ ├── hex.ts
│ │ ├── lab.ts
│ │ └── rgb.ts
│ ├── config
│ │ ├── can_show_page.ts
│ │ ├── components_with_service.ts
│ │ ├── is_component_loaded.ts
│ │ ├── is_pwa.ts
│ │ ├── is_service_loaded.ts
│ │ ├── location_name.ts
│ │ └── version.ts
│ ├── const.ts
│ ├── controllers
│ │ └── drag-scroll-controller.ts
│ ├── datetime
│ │ ├── absolute_time.ts
│ │ ├── calc_date.ts
│ │ ├── calc_date_range.ts
│ │ ├── check_valid_date.ts
│ │ ├── create_duration_data.ts
│ │ ├── duration_to_seconds.ts
│ │ ├── first_weekday.ts
│ │ ├── format_date.ts
│ │ ├── format_date_time.ts
│ │ ├── format_duration.ts
│ │ ├── format_time.ts
│ │ ├── localize_date.ts
│ │ ├── milliseconds_to_duration.ts
│ │ ├── relative_time.ts
│ │ ├── resolve-time-zone.ts
│ │ ├── seconds_to_duration.ts
│ │ └── use_am_pm.ts
│ ├── decorators
│ │ ├── restore-scroll.ts
│ │ ├── storage.ts
│ │ └── transform.ts
│ ├── dom
│ │ ├── ancestors-with-property.ts
│ │ ├── apply_themes_on_element.ts
│ │ ├── can-override-input.ts
│ │ ├── deep-active-element.ts
│ │ ├── dynamic-element-directive.ts
│ │ ├── fire_event.ts
│ │ ├── get_main_window.ts
│ │ ├── is-navigation-click.ts
│ │ ├── load_resource.ts
│ │ ├── media_query.ts
│ │ ├── prevent_default.ts
│ │ ├── scroll-to-target.ts
│ │ ├── setup-leaflet-map.ts
│ │ ├── stop_propagation.ts
│ │ └── toggle_attribute.ts
│ ├── empty_image_base64.ts
│ ├── entity
│ │ ├── attribute_class_names.ts
│ │ ├── battery_icon.ts
│ │ ├── can_toggle_domain.ts
│ │ ├── can_toggle_state.ts
│ │ ├── color
│ │ │ └── battery_color.ts
│ │ ├── compute_area_name.ts
│ │ ├── compute_attribute_display.ts
│ │ ├── compute_device_name.ts
│ │ ├── compute_domain.ts
│ │ ├── compute_entity_name.ts
│ │ ├── compute_floor_name.ts
│ │ ├── compute_object_id.ts
│ │ ├── compute_state_display.ts
│ │ ├── compute_state_domain.ts
│ │ ├── compute_state_name.ts
│ │ ├── context
│ │ │ ├── get_area_context.ts
│ │ │ ├── get_device_context.ts
│ │ │ └── get_entity_context.ts
│ │ ├── cover_icon.ts
│ │ ├── delete_entity.ts
│ │ ├── device_tracker_icon.ts
│ │ ├── entity_domain_filter.ts
│ │ ├── entity_filter.ts
│ │ ├── extract_views.ts
│ │ ├── feature_class_names.ts
│ │ ├── get_group_entities.ts
│ │ ├── get_states.ts
│ │ ├── get_view_entities.ts
│ │ ├── has_location.ts
│ │ ├── split_by_groups.ts
│ │ ├── state_active.ts
│ │ ├── state_card_type.ts
│ │ ├── state_color.ts
│ │ ├── state_icon.ts
│ │ ├── states_sort_by_name.ts
│ │ ├── strip_prefix_from_entity_name.ts
│ │ ├── supports-feature.ts
│ │ ├── update_icon.ts
│ │ ├── valid_entity_id.ts
│ │ └── valid_service_id.ts
│ ├── feature-detect
│ │ └── support-web-components.ts
│ ├── image
│ │ └── extract_color.ts
│ ├── integrations
│ │ └── protocolIntegrationPicked.ts
│ ├── language
│ │ └── format_language.ts
│ ├── location
│ │ └── add_distance_to_coord.ts
│ ├── map
│ │ └── decorated_marker.ts
│ ├── mwc
│ │ └── handle-request-selected-event.ts
│ ├── navigate.ts
│ ├── number
│ │ ├── clamp.ts
│ │ ├── format_number.ts
│ │ └── round.ts
│ ├── string
│ │ ├── capitalize-first-letter.ts
│ │ ├── compare.ts
│ │ ├── escape_regexp.ts
│ │ ├── filter
│ │ │ ├── char-code.ts
│ │ │ ├── filter.ts
│ │ │ └── sequence-matching.ts
│ │ ├── format-list.ts
│ │ ├── get_duplicates.ts
│ │ ├── has-template.ts
│ │ ├── is_date.ts
│ │ ├── is_ip_address.ts
│ │ ├── is_timestamp.ts
│ │ ├── slugify.ts
│ │ ├── starts-with.ts
│ │ ├── strip-diacritics.ts
│ │ └── title-case.ts
│ ├── structs
│ │ ├── handle-errors.ts
│ │ ├── is-custom-type.ts
│ │ └── is-icon.ts
│ ├── style
│ │ ├── derived-css-vars.ts
│ │ └── icon_color_css.ts
│ ├── translations
│ │ ├── auto_case_noun.ts
│ │ ├── blank_before_percent.ts
│ │ ├── blank_before_unit.ts
│ │ ├── day_names.ts
│ │ ├── entity-state.ts
│ │ ├── localize.ts
│ │ ├── markdown_support.ts
│ │ └── month_names.ts
│ ├── url
│ │ ├── construct-url.ts
│ │ └── search-params.ts
│ └── util
│ │ ├── compute_rtl.ts
│ │ ├── copy-clipboard.ts
│ │ ├── debounce.ts
│ │ ├── deep-equal.ts
│ │ ├── group-by.ts
│ │ ├── parse-aspect-ratio.ts
│ │ ├── patch.ts
│ │ ├── promise-all-settled-results.ts
│ │ ├── promise-timeout.ts
│ │ ├── render-status.ts
│ │ ├── select-unit.ts
│ │ ├── shallow-equal.ts
│ │ ├── subscribe-one.ts
│ │ ├── subscribe-polling.ts
│ │ ├── throttle.ts
│ │ ├── time-cache-entity-promise-func.ts
│ │ ├── time-cache-function-promise.ts
│ │ ├── uid.ts
│ │ └── wait.ts
├── components
│ ├── buttons
│ │ ├── ha-call-service-button.ts
│ │ └── ha-progress-button.ts
│ ├── chart
│ │ ├── axis-label.ts
│ │ ├── down-sample.ts
│ │ ├── ha-chart-base.ts
│ │ ├── ha-network-graph.ts
│ │ ├── ha-sankey-chart.ts
│ │ ├── state-history-chart-line.ts
│ │ ├── state-history-chart-timeline.ts
│ │ ├── state-history-charts.ts
│ │ ├── statistics-chart.ts
│ │ └── timeline-color.ts
│ ├── chips
│ │ ├── ha-assist-chip.ts
│ │ ├── ha-chip-set.ts
│ │ ├── ha-filter-chip.ts
│ │ └── ha-input-chip.ts
│ ├── data-table
│ │ ├── dialog-data-table-settings.ts
│ │ ├── ha-data-table-icon.ts
│ │ ├── ha-data-table-labels.ts
│ │ ├── ha-data-table.ts
│ │ ├── show-dialog-data-table-settings.ts
│ │ ├── sort-filter-worker.ts
│ │ └── sort-filter.ts
│ ├── date-range-picker.ts
│ ├── device
│ │ ├── ha-device-action-picker.ts
│ │ ├── ha-device-automation-picker.ts
│ │ ├── ha-device-condition-picker.ts
│ │ ├── ha-device-picker.ts
│ │ ├── ha-device-trigger-picker.ts
│ │ └── ha-devices-picker.ts
│ ├── entity
│ │ ├── ha-battery-icon.ts
│ │ ├── ha-entities-picker.ts
│ │ ├── ha-entity-attribute-picker.ts
│ │ ├── ha-entity-picker.ts
│ │ ├── ha-entity-state-content-picker.ts
│ │ ├── ha-entity-state-picker.ts
│ │ ├── ha-entity-toggle.ts
│ │ ├── ha-state-label-badge.ts
│ │ ├── ha-statistic-picker.ts
│ │ ├── ha-statistics-picker.ts
│ │ ├── state-badge.ts
│ │ └── state-info.ts
│ ├── ha-absolute-time.ts
│ ├── ha-addon-picker.ts
│ ├── ha-alert.ts
│ ├── ha-aliases-editor.ts
│ ├── ha-analytics.ts
│ ├── ha-ansi-to-html.ts
│ ├── ha-area-floor-picker.ts
│ ├── ha-area-picker.ts
│ ├── ha-areas-display-editor.ts
│ ├── ha-areas-picker.ts
│ ├── ha-assist-chat.ts
│ ├── ha-assist-pipeline-picker.ts
│ ├── ha-attribute-icon.ts
│ ├── ha-attribute-value.ts
│ ├── ha-attributes.ts
│ ├── ha-badge.ts
│ ├── ha-bar.ts
│ ├── ha-base-time-input.ts
│ ├── ha-big-number.ts
│ ├── ha-blueprint-picker.ts
│ ├── ha-button-menu.ts
│ ├── ha-button-toggle-group.ts
│ ├── ha-button.ts
│ ├── ha-camera-stream.ts
│ ├── ha-card.ts
│ ├── ha-check-list-item.ts
│ ├── ha-checkbox.ts
│ ├── ha-climate-state.ts
│ ├── ha-code-editor.ts
│ ├── ha-color-picker.ts
│ ├── ha-combo-box-item.ts
│ ├── ha-combo-box-textfield.ts
│ ├── ha-combo-box.ts
│ ├── ha-config-entry-picker.ts
│ ├── ha-control-button-group.ts
│ ├── ha-control-button.ts
│ ├── ha-control-circular-slider.ts
│ ├── ha-control-number-buttons.ts
│ ├── ha-control-select-menu.ts
│ ├── ha-control-select.ts
│ ├── ha-control-slider.ts
│ ├── ha-control-switch.ts
│ ├── ha-conversation-agent-picker.ts
│ ├── ha-copy-textfield.ts
│ ├── ha-country-picker.ts
│ ├── ha-cover-controls.ts
│ ├── ha-cover-tilt-controls.ts
│ ├── ha-currency-picker.ts
│ ├── ha-date-input.ts
│ ├── ha-date-range-picker.ts
│ ├── ha-dialog-date-picker.ts
│ ├── ha-dialog-header.ts
│ ├── ha-dialog.ts
│ ├── ha-divider.ts
│ ├── ha-domain-icon.ts
│ ├── ha-drawer.ts
│ ├── ha-duration-input.ts
│ ├── ha-entities-display-editor.ts
│ ├── ha-expansion-panel.ts
│ ├── ha-fab.ts
│ ├── ha-fade-in.ts
│ ├── ha-faded.ts
│ ├── ha-file-upload.ts
│ ├── ha-filter-blueprints.ts
│ ├── ha-filter-categories.ts
│ ├── ha-filter-devices.ts
│ ├── ha-filter-domains.ts
│ ├── ha-filter-entities.ts
│ ├── ha-filter-floor-areas.ts
│ ├── ha-filter-integrations.ts
│ ├── ha-filter-labels.ts
│ ├── ha-filter-states.ts
│ ├── ha-floor-icon.ts
│ ├── ha-floor-picker.ts
│ ├── ha-floors-picker.ts
│ ├── ha-form
│ │ ├── compute-initial-ha-form-data.ts
│ │ ├── ha-form-boolean.ts
│ │ ├── ha-form-constant.ts
│ │ ├── ha-form-expandable.ts
│ │ ├── ha-form-float.ts
│ │ ├── ha-form-grid.ts
│ │ ├── ha-form-integer.ts
│ │ ├── ha-form-multi_select.ts
│ │ ├── ha-form-optional_actions.ts
│ │ ├── ha-form-positive_time_period_dict.ts
│ │ ├── ha-form-select.ts
│ │ ├── ha-form-string.ts
│ │ ├── ha-form.ts
│ │ └── types.ts
│ ├── ha-formfield.ts
│ ├── ha-gauge.ts
│ ├── ha-generic-picker.ts
│ ├── ha-grid-size-picker.ts
│ ├── ha-header-bar.ts
│ ├── ha-heading-badge.ts
│ ├── ha-help-tooltip.ts
│ ├── ha-hls-player.ts
│ ├── ha-hs-color-picker.ts
│ ├── ha-humidifier-state.ts
│ ├── ha-icon-button-arrow-next.ts
│ ├── ha-icon-button-arrow-prev.ts
│ ├── ha-icon-button-group.ts
│ ├── ha-icon-button-next.ts
│ ├── ha-icon-button-prev.ts
│ ├── ha-icon-button-toggle.ts
│ ├── ha-icon-button.ts
│ ├── ha-icon-next.ts
│ ├── ha-icon-overflow-menu.ts
│ ├── ha-icon-picker.ts
│ ├── ha-icon-prev.ts
│ ├── ha-icon.ts
│ ├── ha-input-helper-text.ts
│ ├── ha-items-display-editor.ts
│ ├── ha-label-badge.ts
│ ├── ha-label-picker.ts
│ ├── ha-label.ts
│ ├── ha-labeled-slider.ts
│ ├── ha-labels-picker.ts
│ ├── ha-language-picker.ts
│ ├── ha-lawn_mower-action-button.ts
│ ├── ha-list-item.ts
│ ├── ha-list.ts
│ ├── ha-logo-svg.ts
│ ├── ha-markdown-element.ts
│ ├── ha-markdown.ts
│ ├── ha-md-button-menu.ts
│ ├── ha-md-dialog.ts
│ ├── ha-md-divider.ts
│ ├── ha-md-list-item.ts
│ ├── ha-md-list.ts
│ ├── ha-md-menu-item.ts
│ ├── ha-md-menu.ts
│ ├── ha-md-select-option.ts
│ ├── ha-md-select.ts
│ ├── ha-md-textfield.ts
│ ├── ha-menu-button.ts
│ ├── ha-menu.ts
│ ├── ha-metric.ts
│ ├── ha-mount-picker.ts
│ ├── ha-multi-textfield.ts
│ ├── ha-navigation-list.ts
│ ├── ha-navigation-picker.ts
│ ├── ha-network.ts
│ ├── ha-outlined-button.ts
│ ├── ha-outlined-field.ts
│ ├── ha-outlined-icon-button.ts
│ ├── ha-outlined-text-field.ts
│ ├── ha-password-field.ts
│ ├── ha-picker-combo-box.ts
│ ├── ha-picker-field.ts
│ ├── ha-picture-upload.ts
│ ├── ha-progress-ring.ts
│ ├── ha-push-notifications-toggle.ts
│ ├── ha-qr-code.ts
│ ├── ha-qr-scanner.ts
│ ├── ha-radio-list-item.ts
│ ├── ha-radio.ts
│ ├── ha-related-items.ts
│ ├── ha-relative-time.ts
│ ├── ha-ripple.ts
│ ├── ha-select-box.ts
│ ├── ha-select.ts
│ ├── ha-selector
│ │ ├── ha-selector-action.ts
│ │ ├── ha-selector-addon.ts
│ │ ├── ha-selector-area.ts
│ │ ├── ha-selector-areas-display.ts
│ │ ├── ha-selector-assist-pipeline.ts
│ │ ├── ha-selector-attribute.ts
│ │ ├── ha-selector-background.ts
│ │ ├── ha-selector-backup-location.ts
│ │ ├── ha-selector-boolean.ts
│ │ ├── ha-selector-button-toggle.ts
│ │ ├── ha-selector-color-rgb.ts
│ │ ├── ha-selector-color-temp.ts
│ │ ├── ha-selector-condition.ts
│ │ ├── ha-selector-config-entry.ts
│ │ ├── ha-selector-constant.ts
│ │ ├── ha-selector-conversation-agent.ts
│ │ ├── ha-selector-country.ts
│ │ ├── ha-selector-date.ts
│ │ ├── ha-selector-datetime.ts
│ │ ├── ha-selector-device.ts
│ │ ├── ha-selector-duration.ts
│ │ ├── ha-selector-entity.ts
│ │ ├── ha-selector-file.ts
│ │ ├── ha-selector-floor.ts
│ │ ├── ha-selector-icon.ts
│ │ ├── ha-selector-image.ts
│ │ ├── ha-selector-label.ts
│ │ ├── ha-selector-language.ts
│ │ ├── ha-selector-location.ts
│ │ ├── ha-selector-media.ts
│ │ ├── ha-selector-navigation.ts
│ │ ├── ha-selector-number.ts
│ │ ├── ha-selector-object.ts
│ │ ├── ha-selector-qr-code.ts
│ │ ├── ha-selector-select.ts
│ │ ├── ha-selector-selector.ts
│ │ ├── ha-selector-state.ts
│ │ ├── ha-selector-statistic.ts
│ │ ├── ha-selector-stt.ts
│ │ ├── ha-selector-target.ts
│ │ ├── ha-selector-template.ts
│ │ ├── ha-selector-text.ts
│ │ ├── ha-selector-theme.ts
│ │ ├── ha-selector-time.ts
│ │ ├── ha-selector-trigger.ts
│ │ ├── ha-selector-tts-voice.ts
│ │ ├── ha-selector-tts.ts
│ │ ├── ha-selector-ui-action.ts
│ │ ├── ha-selector-ui-color.ts
│ │ ├── ha-selector-ui-state-content.ts
│ │ └── ha-selector.ts
│ ├── ha-service-control.ts
│ ├── ha-service-icon.ts
│ ├── ha-service-picker.ts
│ ├── ha-service-section-icon.ts
│ ├── ha-settings-row.ts
│ ├── ha-sidebar.ts
│ ├── ha-slider.ts
│ ├── ha-sortable.ts
│ ├── ha-spinner.ts
│ ├── ha-state-icon.ts
│ ├── ha-stt-picker.ts
│ ├── ha-sub-menu.ts
│ ├── ha-svg-icon.ts
│ ├── ha-switch.ts
│ ├── ha-tab.ts
│ ├── ha-target-picker.ts
│ ├── ha-textarea.ts
│ ├── ha-textfield.ts
│ ├── ha-theme-picker.ts
│ ├── ha-time-input.ts
│ ├── ha-timezone-picker.ts
│ ├── ha-tip.ts
│ ├── ha-toast.ts
│ ├── ha-tooltip.ts
│ ├── ha-top-app-bar-fixed.ts
│ ├── ha-top-app-bar.ts
│ ├── ha-tree-indicator.ts
│ ├── ha-tts-picker.ts
│ ├── ha-tts-voice-picker.ts
│ ├── ha-two-pane-top-app-bar-fixed.ts
│ ├── ha-vacuum-state.ts
│ ├── ha-valve-controls.ts
│ ├── ha-water_heater-state.ts
│ ├── ha-web-rtc-player.ts
│ ├── ha-yaml-editor.ts
│ ├── map
│ │ ├── ha-entity-marker.ts
│ │ ├── ha-locations-editor.ts
│ │ └── ha-map.ts
│ ├── media-player
│ │ ├── dialog-join-media-players.ts
│ │ ├── dialog-media-manage.ts
│ │ ├── dialog-media-player-browse.ts
│ │ ├── ha-browse-media-tts.ts
│ │ ├── ha-media-manage-button.ts
│ │ ├── ha-media-player-browse.ts
│ │ ├── ha-media-player-toggle.ts
│ │ ├── ha-media-upload-button.ts
│ │ ├── show-join-media-players-dialog.ts
│ │ ├── show-media-browser-dialog.ts
│ │ └── show-media-manage-dialog.ts
│ ├── search-input-outlined.ts
│ ├── search-input.ts
│ ├── sl-tab-group.ts
│ ├── tile
│ │ ├── ha-tile-badge.ts
│ │ ├── ha-tile-icon.ts
│ │ └── ha-tile-info.ts
│ ├── timezone-datalist.ts
│ ├── trace
│ │ ├── ha-timeline.ts
│ │ ├── ha-trace-blueprint-config.ts
│ │ ├── ha-trace-config.ts
│ │ ├── ha-trace-logbook.ts
│ │ ├── ha-trace-path-details.ts
│ │ ├── ha-trace-timeline.ts
│ │ ├── hat-graph-branch.ts
│ │ ├── hat-graph-const.ts
│ │ ├── hat-graph-node.ts
│ │ ├── hat-graph-spacer.ts
│ │ ├── hat-logbook-note.ts
│ │ ├── hat-script-graph.ts
│ │ ├── hat-trace-timeline.ts
│ │ └── trace-tab-styles.ts
│ └── user
│ │ ├── ha-person-badge.ts
│ │ ├── ha-user-badge.ts
│ │ ├── ha-user-picker.ts
│ │ └── ha-users-picker.ts
├── data
│ ├── action.ts
│ ├── alarm_control_panel.ts
│ ├── alexa.ts
│ ├── analytics.ts
│ ├── application_credential.ts
│ ├── area_registry.ts
│ ├── assist_pipeline.ts
│ ├── assist_satellite.ts
│ ├── auth.ts
│ ├── automation.ts
│ ├── automation_i18n.ts
│ ├── backup.ts
│ ├── backup_manager.ts
│ ├── backup_onboarding.ts
│ ├── blueprint.ts
│ ├── bluetooth.ts
│ ├── bootstrap_integrations.ts
│ ├── calendar.ts
│ ├── camera.ts
│ ├── category_registry.ts
│ ├── climate.ts
│ ├── cloud.ts
│ ├── cloud
│ │ └── tts.ts
│ ├── collection.ts
│ ├── condition.ts
│ ├── config.ts
│ ├── config_entries.ts
│ ├── config_flow.ts
│ ├── connection-status.ts
│ ├── context.ts
│ ├── conversation.ts
│ ├── core.ts
│ ├── counter.ts
│ ├── cover.ts
│ ├── currency.ts
│ ├── custom_icons.ts
│ ├── custom_iconsets.ts
│ ├── data_entry_flow.ts
│ ├── data_table_filters.ts
│ ├── date.ts
│ ├── datetime.ts
│ ├── device_automation.ts
│ ├── device_registry.ts
│ ├── dhcp.ts
│ ├── diagnostics.ts
│ ├── energy.ts
│ ├── entity.ts
│ ├── entity_attributes.ts
│ ├── entity_registry.ts
│ ├── entity_sources.ts
│ ├── error_log.ts
│ ├── expose.ts
│ ├── external.ts
│ ├── fan.ts
│ ├── file_upload.ts
│ ├── floor_registry.ts
│ ├── frontend.ts
│ ├── google_assistant.ts
│ ├── graph.ts
│ ├── group.ts
│ ├── haptics.ts
│ ├── hardware.ts
│ ├── hassio
│ │ ├── addon.ts
│ │ ├── backup.ts
│ │ ├── common.ts
│ │ ├── docker.ts
│ │ ├── hardware.ts
│ │ ├── host.ts
│ │ ├── ingress.ts
│ │ ├── network.ts
│ │ ├── resolution.ts
│ │ └── supervisor.ts
│ ├── helpers_crud.ts
│ ├── history.ts
│ ├── humidifier.ts
│ ├── icons.ts
│ ├── iconsets.ts
│ ├── image.ts
│ ├── image_upload.ts
│ ├── input_boolean.ts
│ ├── input_button.ts
│ ├── input_datetime.ts
│ ├── input_number.ts
│ ├── input_select.ts
│ ├── input_text.ts
│ ├── integration.ts
│ ├── integration_quality_scale.ts
│ ├── integrations.ts
│ ├── label_registry.ts
│ ├── lawn_mower.ts
│ ├── light.ts
│ ├── lock.ts
│ ├── logbook.ts
│ ├── lovelace.ts
│ ├── lovelace
│ │ ├── action_handler.ts
│ │ ├── config
│ │ │ ├── action.ts
│ │ │ ├── badge.ts
│ │ │ ├── card.ts
│ │ │ ├── section.ts
│ │ │ ├── strategy.ts
│ │ │ ├── types.ts
│ │ │ └── view.ts
│ │ ├── dashboard.ts
│ │ └── resource.ts
│ ├── lovelace_custom_cards.ts
│ ├── main_window.ts
│ ├── matter.ts
│ ├── media-player.ts
│ ├── media_source.ts
│ ├── mqtt.ts
│ ├── network.ts
│ ├── notify_html5.ts
│ ├── number.ts
│ ├── onboarding.ts
│ ├── openstreetmap.ts
│ ├── options_flow.ts
│ ├── otbr.ts
│ ├── panel.ts
│ ├── panel_custom.ts
│ ├── persistent_notification.ts
│ ├── person.ts
│ ├── preloads.ts
│ ├── preview.ts
│ ├── recorder.ts
│ ├── refresh_token.ts
│ ├── regenerate_entity_ids.ts
│ ├── registry.ts
│ ├── remote.ts
│ ├── repairs.ts
│ ├── scene.ts
│ ├── schedule.ts
│ ├── script.ts
│ ├── script_i18n.ts
│ ├── search.ts
│ ├── select.ts
│ ├── selector.ts
│ ├── sensor.ts
│ ├── service.ts
│ ├── siren.ts
│ ├── ssdp.ts
│ ├── stt.ts
│ ├── sub_config_flow.ts
│ ├── supervisor
│ │ ├── common.ts
│ │ ├── core.ts
│ │ ├── mounts.ts
│ │ ├── store.ts
│ │ ├── supervisor.ts
│ │ └── update.ts
│ ├── system_health.ts
│ ├── system_log.ts
│ ├── tag.ts
│ ├── text.ts
│ ├── thread.ts
│ ├── time.ts
│ ├── timer.ts
│ ├── todo.ts
│ ├── trace.ts
│ ├── translation.ts
│ ├── trigger.ts
│ ├── tts.ts
│ ├── update.ts
│ ├── usb.ts
│ ├── user.ts
│ ├── vacuum.ts
│ ├── valve.ts
│ ├── wake_word.ts
│ ├── water_heater.ts
│ ├── weather.ts
│ ├── webhook.ts
│ ├── websocket_api.ts
│ ├── ws-area_registry.ts
│ ├── ws-device_registry.ts
│ ├── ws-entity_registry_display.ts
│ ├── ws-floor_registry.ts
│ ├── ws-panels.ts
│ ├── ws-templates.ts
│ ├── ws-themes.ts
│ ├── ws-user.ts
│ ├── wyoming.ts
│ ├── zeroconf.ts
│ ├── zha.ts
│ ├── zone.ts
│ └── zwave_js.ts
├── dialogs
│ ├── config-entry-system-options
│ │ ├── dialog-config-entry-system-options.ts
│ │ └── show-dialog-config-entry-system-options.ts
│ ├── config-flow
│ │ ├── dialog-data-entry-flow.ts
│ │ ├── previews
│ │ │ ├── entity-preview-row.ts
│ │ │ ├── flow-preview-generic.ts
│ │ │ ├── flow-preview-generic_camera.ts
│ │ │ └── flow-preview-template.ts
│ │ ├── show-dialog-config-flow.ts
│ │ ├── show-dialog-data-entry-flow.ts
│ │ ├── show-dialog-options-flow.ts
│ │ ├── show-dialog-sub-config-flow.ts
│ │ ├── step-flow-abort.ts
│ │ ├── step-flow-create-entry.ts
│ │ ├── step-flow-external.ts
│ │ ├── step-flow-form.ts
│ │ ├── step-flow-loading.ts
│ │ ├── step-flow-menu.ts
│ │ ├── step-flow-progress.ts
│ │ └── styles.ts
│ ├── enter-code
│ │ ├── dialog-enter-code.ts
│ │ └── show-enter-code-dialog.ts
│ ├── generic
│ │ ├── dialog-box.ts
│ │ └── show-dialog-box.ts
│ ├── image-cropper-dialog
│ │ ├── image-cropper-dialog.ts
│ │ └── show-image-cropper-dialog.ts
│ ├── make-dialog-manager.ts
│ ├── more-info
│ │ ├── components
│ │ │ ├── ha-more-info-control-select-container.ts
│ │ │ ├── ha-more-info-state-header.ts
│ │ │ ├── lights
│ │ │ │ ├── dialog-light-color-favorite.ts
│ │ │ │ ├── ha-favorite-color-button.ts
│ │ │ │ ├── ha-more-info-light-favorite-colors.ts
│ │ │ │ ├── light-color-rgb-picker.ts
│ │ │ │ ├── light-color-temp-picker.ts
│ │ │ │ └── show-dialog-light-color-favorite.ts
│ │ │ ├── more-info-control-style.ts
│ │ │ ├── siren
│ │ │ │ ├── ha-more-info-siren-advanced-controls.ts
│ │ │ │ └── show-dialog-siren-advanced-controls.ts
│ │ │ └── voice
│ │ │ │ ├── ha-more-info-view-voice-assistants.ts
│ │ │ │ └── show-view-voice-assistants.ts
│ │ ├── const.ts
│ │ ├── controls
│ │ │ ├── more-info-alarm_control_panel.ts
│ │ │ ├── more-info-automation.ts
│ │ │ ├── more-info-camera.ts
│ │ │ ├── more-info-climate.ts
│ │ │ ├── more-info-configurator.ts
│ │ │ ├── more-info-conversation.ts
│ │ │ ├── more-info-counter.ts
│ │ │ ├── more-info-cover.ts
│ │ │ ├── more-info-date.ts
│ │ │ ├── more-info-datetime.ts
│ │ │ ├── more-info-default.ts
│ │ │ ├── more-info-fan.ts
│ │ │ ├── more-info-group.ts
│ │ │ ├── more-info-humidifier.ts
│ │ │ ├── more-info-image.ts
│ │ │ ├── more-info-input_boolean.ts
│ │ │ ├── more-info-input_datetime.ts
│ │ │ ├── more-info-lawn_mower.ts
│ │ │ ├── more-info-light.ts
│ │ │ ├── more-info-lock.ts
│ │ │ ├── more-info-media_player.ts
│ │ │ ├── more-info-person.ts
│ │ │ ├── more-info-remote.ts
│ │ │ ├── more-info-script.ts
│ │ │ ├── more-info-siren.ts
│ │ │ ├── more-info-sun.ts
│ │ │ ├── more-info-switch.ts
│ │ │ ├── more-info-time.ts
│ │ │ ├── more-info-timer.ts
│ │ │ ├── more-info-update.ts
│ │ │ ├── more-info-vacuum.ts
│ │ │ ├── more-info-valve.ts
│ │ │ ├── more-info-water_heater.ts
│ │ │ └── more-info-weather.ts
│ │ ├── ha-more-info-dialog.ts
│ │ ├── ha-more-info-history-and-logbook.ts
│ │ ├── ha-more-info-history.ts
│ │ ├── ha-more-info-info.ts
│ │ ├── ha-more-info-logbook.ts
│ │ ├── ha-more-info-settings.ts
│ │ ├── more-info-content.ts
│ │ ├── show-ha-more-info-dialog.ts
│ │ └── state_more_info_control.ts
│ ├── notifications
│ │ ├── configurator-notification-item.ts
│ │ ├── notification-drawer.ts
│ │ ├── notification-item-template.ts
│ │ ├── notification-item.ts
│ │ ├── persistent-notification-item.ts
│ │ └── show-notification-drawer.ts
│ ├── quick-bar
│ │ ├── ha-quick-bar.ts
│ │ └── show-dialog-quick-bar.ts
│ ├── restart
│ │ ├── dialog-restart-wait.ts
│ │ ├── dialog-restart.ts
│ │ └── show-dialog-restart.ts
│ ├── shortcuts
│ │ ├── dialog-shortcuts.ts
│ │ └── show-shortcuts-dialog.ts
│ ├── sidebar
│ │ ├── dialog-edit-sidebar.ts
│ │ └── show-dialog-edit-sidebar.ts
│ ├── tts-try
│ │ ├── dialog-tts-try.ts
│ │ └── show-dialog-tts-try.ts
│ ├── update_backup
│ │ ├── dialog-update-backup.ts
│ │ └── show-update-backup-dialog.ts
│ ├── voice-assistant-setup
│ │ ├── cloud
│ │ │ ├── cloud-step-intro.ts
│ │ │ ├── cloud-step-signin.ts
│ │ │ └── cloud-step-signup.ts
│ │ ├── show-voice-assistant-setup-dialog.ts
│ │ ├── styles.ts
│ │ ├── voice-assistant-setup-dialog.ts
│ │ ├── voice-assistant-setup-step-area.ts
│ │ ├── voice-assistant-setup-step-change-wake-word.ts
│ │ ├── voice-assistant-setup-step-check.ts
│ │ ├── voice-assistant-setup-step-cloud.ts
│ │ ├── voice-assistant-setup-step-local.ts
│ │ ├── voice-assistant-setup-step-pipeline.ts
│ │ ├── voice-assistant-setup-step-success.ts
│ │ ├── voice-assistant-setup-step-update.ts
│ │ └── voice-assistant-setup-step-wake-word.ts
│ └── voice-command-dialog
│ │ ├── ha-voice-command-dialog.ts
│ │ └── show-ha-voice-command-dialog.ts
├── entrypoints
│ ├── app.ts
│ ├── authorize.ts
│ ├── core.ts
│ ├── custom-panel.ts
│ ├── onboarding.ts
│ └── service-worker.ts
├── external_app
│ ├── external_app_entrypoint.ts
│ ├── external_auth.ts
│ └── external_messaging.ts
├── fake_data
│ ├── demo_config.ts
│ ├── demo_panels.ts
│ ├── demo_services.ts
│ ├── entity.ts
│ ├── entity_component_icons.ts
│ └── provide_hass.ts
├── html
│ ├── _header.html.template
│ ├── _js_base.html.template
│ ├── _preload_roboto.html.template
│ ├── _script_loader.html.template
│ ├── _style_base.html.template
│ ├── authorize.html.template
│ ├── index.html.template
│ └── onboarding.html.template
├── layouts
│ ├── ha-init-page.ts
│ ├── hass-error-screen.ts
│ ├── hass-loading-screen.ts
│ ├── hass-router-page.ts
│ ├── hass-subpage.ts
│ ├── hass-tabs-subpage-data-table.ts
│ ├── hass-tabs-subpage.ts
│ ├── home-assistant-main.ts
│ ├── home-assistant.ts
│ ├── partial-panel-resolver.ts
│ └── supervisor-error-screen.ts
├── managers
│ └── notification-manager.ts
├── mixins
│ ├── keyboard-shortcut-mixin.ts
│ ├── lit-localize-lite-mixin.ts
│ ├── prevent-unsaved-mixin.ts
│ ├── provide-hass-lit-mixin.ts
│ ├── subscribe-mixin.ts
│ └── wakelock-mixin.ts
├── onboarding
│ ├── dialogs
│ │ ├── app-dialog.ts
│ │ ├── community-dialog.ts
│ │ ├── show-app-dialog.ts
│ │ └── show-community-dialog.ts
│ ├── ha-onboarding.ts
│ ├── integration-badge.ts
│ ├── onboarding-analytics.ts
│ ├── onboarding-core-config.ts
│ ├── onboarding-create-user.ts
│ ├── onboarding-integrations.ts
│ ├── onboarding-loading.ts
│ ├── onboarding-location.ts
│ ├── onboarding-restore-backup.ts
│ ├── onboarding-welcome-link.ts
│ ├── onboarding-welcome-links.ts
│ ├── onboarding-welcome.ts
│ ├── restore-backup
│ │ ├── onboarding-restore-backup-cloud-login.ts
│ │ ├── onboarding-restore-backup-no-cloud-backup.ts
│ │ ├── onboarding-restore-backup-restore.ts
│ │ ├── onboarding-restore-backup-status.ts
│ │ └── onboarding-restore-backup-upload.ts
│ └── styles.ts
├── panels
│ ├── calendar
│ │ ├── confirm-event-dialog-box.ts
│ │ ├── dialog-calendar-event-detail.ts
│ │ ├── dialog-calendar-event-editor.ts
│ │ ├── ha-full-calendar.ts
│ │ ├── ha-panel-calendar.ts
│ │ ├── ha-recurrence-rule-editor.ts
│ │ ├── recurrence.ts
│ │ ├── show-confirm-event-dialog-box.ts
│ │ ├── show-dialog-calendar-event-detail.ts
│ │ └── show-dialog-calendar-event-editor.ts
│ ├── config
│ │ ├── application_credentials
│ │ │ ├── dialog-add-application-credential.ts
│ │ │ ├── ha-config-application-credentials.ts
│ │ │ └── show-dialog-add-application-credential.ts
│ │ ├── areas
│ │ │ ├── dialog-area-registry-detail.ts
│ │ │ ├── dialog-floor-registry-detail.ts
│ │ │ ├── ha-config-area-page.ts
│ │ │ ├── ha-config-areas-dashboard.ts
│ │ │ ├── ha-config-areas.ts
│ │ │ ├── show-dialog-area-registry-detail.ts
│ │ │ └── show-dialog-floor-registry-detail.ts
│ │ ├── automation
│ │ │ ├── action
│ │ │ │ ├── ha-automation-action-row.ts
│ │ │ │ ├── ha-automation-action.ts
│ │ │ │ └── types
│ │ │ │ │ ├── ha-automation-action-choose.ts
│ │ │ │ │ ├── ha-automation-action-condition.ts
│ │ │ │ │ ├── ha-automation-action-delay.ts
│ │ │ │ │ ├── ha-automation-action-device_id.ts
│ │ │ │ │ ├── ha-automation-action-event.ts
│ │ │ │ │ ├── ha-automation-action-if.ts
│ │ │ │ │ ├── ha-automation-action-parallel.ts
│ │ │ │ │ ├── ha-automation-action-play_media.ts
│ │ │ │ │ ├── ha-automation-action-repeat.ts
│ │ │ │ │ ├── ha-automation-action-sequence.ts
│ │ │ │ │ ├── ha-automation-action-service.ts
│ │ │ │ │ ├── ha-automation-action-set_conversation_response.ts
│ │ │ │ │ ├── ha-automation-action-stop.ts
│ │ │ │ │ ├── ha-automation-action-wait_for_trigger.ts
│ │ │ │ │ └── ha-automation-action-wait_template.ts
│ │ │ ├── add-automation-element-dialog.ts
│ │ │ ├── automation-mode-dialog
│ │ │ │ ├── dialog-automation-mode.ts
│ │ │ │ └── show-dialog-automation-mode.ts
│ │ │ ├── automation-save-dialog
│ │ │ │ ├── dialog-automation-save.ts
│ │ │ │ └── show-dialog-automation-save.ts
│ │ │ ├── blueprint-automation-editor.ts
│ │ │ ├── condition
│ │ │ │ ├── ha-automation-condition-editor.ts
│ │ │ │ ├── ha-automation-condition-row.ts
│ │ │ │ ├── ha-automation-condition.ts
│ │ │ │ └── types
│ │ │ │ │ ├── ha-automation-condition-and.ts
│ │ │ │ │ ├── ha-automation-condition-device.ts
│ │ │ │ │ ├── ha-automation-condition-logical.ts
│ │ │ │ │ ├── ha-automation-condition-not.ts
│ │ │ │ │ ├── ha-automation-condition-numeric_state.ts
│ │ │ │ │ ├── ha-automation-condition-or.ts
│ │ │ │ │ ├── ha-automation-condition-state.ts
│ │ │ │ │ ├── ha-automation-condition-sun.ts
│ │ │ │ │ ├── ha-automation-condition-template.ts
│ │ │ │ │ ├── ha-automation-condition-time.ts
│ │ │ │ │ ├── ha-automation-condition-trigger.ts
│ │ │ │ │ └── ha-automation-condition-zone.ts
│ │ │ ├── dialog-new-automation.ts
│ │ │ ├── ha-automation-editor.ts
│ │ │ ├── ha-automation-picker.ts
│ │ │ ├── ha-automation-trace.ts
│ │ │ ├── ha-config-automation.ts
│ │ │ ├── manual-automation-editor.ts
│ │ │ ├── option
│ │ │ │ ├── ha-automation-option-row.ts
│ │ │ │ └── ha-automation-option.ts
│ │ │ ├── paste-replace-dialog
│ │ │ │ ├── dialog-paste-replace.ts
│ │ │ │ └── show-dialog-paste-replace.ts
│ │ │ ├── show-add-automation-element-dialog.ts
│ │ │ ├── show-dialog-new-automation.ts
│ │ │ ├── structs.ts
│ │ │ └── trigger
│ │ │ │ ├── ha-automation-trigger-row.ts
│ │ │ │ ├── ha-automation-trigger.ts
│ │ │ │ └── types
│ │ │ │ ├── ha-automation-trigger-calendar.ts
│ │ │ │ ├── ha-automation-trigger-conversation.ts
│ │ │ │ ├── ha-automation-trigger-device.ts
│ │ │ │ ├── ha-automation-trigger-event.ts
│ │ │ │ ├── ha-automation-trigger-geo_location.ts
│ │ │ │ ├── ha-automation-trigger-homeassistant.ts
│ │ │ │ ├── ha-automation-trigger-list.ts
│ │ │ │ ├── ha-automation-trigger-mqtt.ts
│ │ │ │ ├── ha-automation-trigger-numeric_state.ts
│ │ │ │ ├── ha-automation-trigger-persistent_notification.ts
│ │ │ │ ├── ha-automation-trigger-state.ts
│ │ │ │ ├── ha-automation-trigger-sun.ts
│ │ │ │ ├── ha-automation-trigger-tag.ts
│ │ │ │ ├── ha-automation-trigger-template.ts
│ │ │ │ ├── ha-automation-trigger-time.ts
│ │ │ │ ├── ha-automation-trigger-time_pattern.ts
│ │ │ │ ├── ha-automation-trigger-webhook.ts
│ │ │ │ └── ha-automation-trigger-zone.ts
│ │ ├── backup
│ │ │ ├── components
│ │ │ │ ├── config
│ │ │ │ │ ├── ha-backup-config-addon.ts
│ │ │ │ │ ├── ha-backup-config-agents.ts
│ │ │ │ │ ├── ha-backup-config-data.ts
│ │ │ │ │ ├── ha-backup-config-encryption-key.ts
│ │ │ │ │ ├── ha-backup-config-retention.ts
│ │ │ │ │ └── ha-backup-config-schedule.ts
│ │ │ │ ├── ha-backup-addons-picker.ts
│ │ │ │ ├── ha-backup-agents-picker.ts
│ │ │ │ ├── ha-backup-data-picker.ts
│ │ │ │ ├── ha-backup-details-restore.ts
│ │ │ │ ├── ha-backup-details-summary.ts
│ │ │ │ ├── ha-backup-formfield-label.ts
│ │ │ │ ├── ha-backup-summary-card.ts
│ │ │ │ └── overview
│ │ │ │ │ ├── ha-backup-overview-backups.ts
│ │ │ │ │ ├── ha-backup-overview-onboarding.ts
│ │ │ │ │ ├── ha-backup-overview-progress.ts
│ │ │ │ │ ├── ha-backup-overview-settings.ts
│ │ │ │ │ └── ha-backup-overview-summary.ts
│ │ │ ├── dialogs
│ │ │ │ ├── dialog-backup-onboarding.ts
│ │ │ │ ├── dialog-change-backup-encryption-key.ts
│ │ │ │ ├── dialog-download-decrypted-backup.ts
│ │ │ │ ├── dialog-generate-backup.ts
│ │ │ │ ├── dialog-local-backup-location.ts
│ │ │ │ ├── dialog-new-backup.ts
│ │ │ │ ├── dialog-restore-backup.ts
│ │ │ │ ├── dialog-set-backup-encryption-key.ts
│ │ │ │ ├── dialog-show-backup-encryption-key.ts
│ │ │ │ ├── dialog-upload-backup.ts
│ │ │ │ ├── show-dialog-backup_onboarding.ts
│ │ │ │ ├── show-dialog-change-backup-encryption-key.ts
│ │ │ │ ├── show-dialog-download-decrypted-backup.ts
│ │ │ │ ├── show-dialog-generate-backup.ts
│ │ │ │ ├── show-dialog-local-backup-location.ts
│ │ │ │ ├── show-dialog-new-backup.ts
│ │ │ │ ├── show-dialog-restore-backup.ts
│ │ │ │ ├── show-dialog-set-backup-encryption-key.ts
│ │ │ │ ├── show-dialog-show-backup-encryption-key.ts
│ │ │ │ └── show-dialog-upload-backup.ts
│ │ │ ├── ha-config-backup-backups.ts
│ │ │ ├── ha-config-backup-details.ts
│ │ │ ├── ha-config-backup-location.ts
│ │ │ ├── ha-config-backup-overview.ts
│ │ │ ├── ha-config-backup-settings.ts
│ │ │ ├── ha-config-backup.ts
│ │ │ └── helper
│ │ │ │ └── download_backup.ts
│ │ ├── blueprint
│ │ │ ├── blueprint-generic-editor.ts
│ │ │ ├── dialog-import-blueprint.ts
│ │ │ ├── ha-blueprint-overview.ts
│ │ │ ├── ha-config-blueprint.ts
│ │ │ └── show-dialog-import-blueprint.ts
│ │ ├── category
│ │ │ ├── dialog-assign-category.ts
│ │ │ ├── dialog-category-registry-detail.ts
│ │ │ ├── ha-category-picker.ts
│ │ │ ├── show-dialog-assign-category.ts
│ │ │ └── show-dialog-category-registry-detail.ts
│ │ ├── cloud
│ │ │ ├── account
│ │ │ │ ├── cloud-account.ts
│ │ │ │ ├── cloud-ice-servers-pref.ts
│ │ │ │ ├── cloud-remote-pref.ts
│ │ │ │ ├── cloud-tts-pref.ts
│ │ │ │ ├── cloud-webhooks.ts
│ │ │ │ ├── dialog-cloud-support-package.ts
│ │ │ │ ├── dialog-cloud-tts-try.ts
│ │ │ │ ├── show-dialog-cloud-support-package.ts
│ │ │ │ └── show-dialog-cloud-tts-try.ts
│ │ │ ├── dialog-cloud-already-connected
│ │ │ │ ├── dialog-cloud-already-connected.ts
│ │ │ │ └── show-dialog-cloud-already-connected.ts
│ │ │ ├── dialog-cloud-certificate
│ │ │ │ ├── dialog-cloud-certificate.ts
│ │ │ │ └── show-dialog-cloud-certificate.ts
│ │ │ ├── dialog-manage-cloudhook
│ │ │ │ ├── dialog-manage-cloudhook.ts
│ │ │ │ └── show-dialog-manage-cloudhook.ts
│ │ │ ├── forgot-password
│ │ │ │ ├── cloud-forgot-password-card.ts
│ │ │ │ └── cloud-forgot-password.ts
│ │ │ ├── ha-config-cloud.ts
│ │ │ ├── login
│ │ │ │ ├── cloud-login-panel.ts
│ │ │ │ └── cloud-login.ts
│ │ │ └── register
│ │ │ │ └── cloud-register.ts
│ │ ├── core
│ │ │ ├── ha-config-analytics.ts
│ │ │ ├── ha-config-section-analytics.ts
│ │ │ ├── ha-config-section-general.ts
│ │ │ ├── ha-config-section-updates.ts
│ │ │ ├── ha-config-system-navigation.ts
│ │ │ └── updates
│ │ │ │ ├── dialog-join-beta.ts
│ │ │ │ └── show-dialog-join-beta.ts
│ │ ├── dashboard
│ │ │ ├── dialog-new-dashboard.ts
│ │ │ ├── ha-config-dashboard.ts
│ │ │ ├── ha-config-navigation.ts
│ │ │ ├── ha-config-updates.ts
│ │ │ └── show-dialog-new-dashboard.ts
│ │ ├── devices
│ │ │ ├── device-detail
│ │ │ │ ├── ha-device-automation-dialog.ts
│ │ │ │ ├── ha-device-entities-card.ts
│ │ │ │ ├── ha-device-info-card.ts
│ │ │ │ ├── ha-device-via-devices-card.ts
│ │ │ │ ├── integration-elements
│ │ │ │ │ ├── matter
│ │ │ │ │ │ ├── device-actions.ts
│ │ │ │ │ │ └── ha-device-info-matter.ts
│ │ │ │ │ ├── mqtt
│ │ │ │ │ │ ├── device-actions.ts
│ │ │ │ │ │ ├── dialog-mqtt-device-debug-info.ts
│ │ │ │ │ │ ├── mqtt-discovery-payload.ts
│ │ │ │ │ │ ├── mqtt-messages.ts
│ │ │ │ │ │ └── show-dialog-mqtt-device-debug-info.ts
│ │ │ │ │ ├── zha
│ │ │ │ │ │ ├── device-actions.ts
│ │ │ │ │ │ └── ha-device-info-zha.ts
│ │ │ │ │ └── zwave_js
│ │ │ │ │ │ ├── device-actions.ts
│ │ │ │ │ │ ├── device-alerts.ts
│ │ │ │ │ │ └── ha-device-info-zwave_js.ts
│ │ │ │ └── show-dialog-device-automation.ts
│ │ │ ├── device-registry-detail
│ │ │ │ ├── dialog-device-registry-detail.ts
│ │ │ │ └── show-dialog-device-registry-detail.ts
│ │ │ ├── ha-config-device-page.ts
│ │ │ ├── ha-config-devices-dashboard.ts
│ │ │ └── ha-config-devices.ts
│ │ ├── energy
│ │ │ ├── components
│ │ │ │ ├── ha-energy-battery-settings.ts
│ │ │ │ ├── ha-energy-device-settings.ts
│ │ │ │ ├── ha-energy-gas-settings.ts
│ │ │ │ ├── ha-energy-grid-settings.ts
│ │ │ │ ├── ha-energy-solar-settings.ts
│ │ │ │ ├── ha-energy-validation-result.ts
│ │ │ │ ├── ha-energy-water-settings.ts
│ │ │ │ └── styles.ts
│ │ │ ├── dialogs
│ │ │ │ ├── dialog-energy-battery-settings.ts
│ │ │ │ ├── dialog-energy-device-settings.ts
│ │ │ │ ├── dialog-energy-gas-settings.ts
│ │ │ │ ├── dialog-energy-grid-flow-settings.ts
│ │ │ │ ├── dialog-energy-solar-settings.ts
│ │ │ │ ├── dialog-energy-water-settings.ts
│ │ │ │ └── show-dialogs-energy.ts
│ │ │ └── ha-config-energy.ts
│ │ ├── entities
│ │ │ ├── const.ts
│ │ │ ├── editor-tabs
│ │ │ │ └── settings
│ │ │ │ │ └── entity-settings-helper-tab.ts
│ │ │ ├── entity-registry-settings-editor.ts
│ │ │ ├── entity-registry-settings.ts
│ │ │ └── ha-config-entities.ts
│ │ ├── ha-config-section.ts
│ │ ├── ha-panel-config.ts
│ │ ├── hardware
│ │ │ ├── dialog-hardware-available.ts
│ │ │ ├── ha-config-hardware.ts
│ │ │ └── show-dialog-hardware-available.ts
│ │ ├── helpers
│ │ │ ├── const.ts
│ │ │ ├── dialog-helper-detail.ts
│ │ │ ├── forms
│ │ │ │ ├── dialog-schedule-block-info.ts
│ │ │ │ ├── ha-counter-form.ts
│ │ │ │ ├── ha-input_boolean-form.ts
│ │ │ │ ├── ha-input_button-form.ts
│ │ │ │ ├── ha-input_datetime-form.ts
│ │ │ │ ├── ha-input_number-form.ts
│ │ │ │ ├── ha-input_select-form.ts
│ │ │ │ ├── ha-input_text-form.ts
│ │ │ │ ├── ha-schedule-form.ts
│ │ │ │ ├── ha-timer-form.ts
│ │ │ │ └── show-dialog-schedule-block-info.ts
│ │ │ ├── ha-config-helpers.ts
│ │ │ └── show-dialog-helper-detail.ts
│ │ ├── info
│ │ │ └── ha-config-info.ts
│ │ ├── integrations
│ │ │ ├── dialog-add-integration.ts
│ │ │ ├── dialog-yaml-integration.ts
│ │ │ ├── ha-config-flow-card.ts
│ │ │ ├── ha-config-integration-page.ts
│ │ │ ├── ha-config-integrations-dashboard.ts
│ │ │ ├── ha-config-integrations.ts
│ │ │ ├── ha-disabled-config-entry-card.ts
│ │ │ ├── ha-domain-integrations.ts
│ │ │ ├── ha-ignored-config-entry-card.ts
│ │ │ ├── ha-integration-action-card.ts
│ │ │ ├── ha-integration-card.ts
│ │ │ ├── ha-integration-header.ts
│ │ │ ├── ha-integration-list-item.ts
│ │ │ ├── ha-integration-overflow-menu.ts
│ │ │ ├── integration-panels
│ │ │ │ ├── bluetooth
│ │ │ │ │ ├── bluetooth-advertisement-monitor.ts
│ │ │ │ │ ├── bluetooth-config-dashboard-router.ts
│ │ │ │ │ ├── bluetooth-config-dashboard.ts
│ │ │ │ │ ├── bluetooth-connection-monitor.ts
│ │ │ │ │ ├── bluetooth-network-visualization.ts
│ │ │ │ │ ├── dialog-bluetooth-device-info.ts
│ │ │ │ │ └── show-dialog-bluetooth-device-info.ts
│ │ │ │ ├── dhcp
│ │ │ │ │ └── dhcp-config-panel.ts
│ │ │ │ ├── matter
│ │ │ │ │ ├── dialog-matter-add-device.ts
│ │ │ │ │ ├── dialog-matter-manage-fabrics.ts
│ │ │ │ │ ├── dialog-matter-open-commissioning-window.ts
│ │ │ │ │ ├── dialog-matter-ping-node.ts
│ │ │ │ │ ├── dialog-matter-reinterview-node.ts
│ │ │ │ │ ├── matter-add-device.ts
│ │ │ │ │ ├── matter-add-device
│ │ │ │ │ │ ├── matter-add-device-apple-home.ts
│ │ │ │ │ │ ├── matter-add-device-commissioning.ts
│ │ │ │ │ │ ├── matter-add-device-existing.ts
│ │ │ │ │ │ ├── matter-add-device-generic.ts
│ │ │ │ │ │ ├── matter-add-device-google-home-fallback.ts
│ │ │ │ │ │ ├── matter-add-device-google-home.ts
│ │ │ │ │ │ ├── matter-add-device-main.ts
│ │ │ │ │ │ ├── matter-add-device-new.ts
│ │ │ │ │ │ └── matter-add-device-shared-styles.ts
│ │ │ │ │ ├── matter-config-dashboard.ts
│ │ │ │ │ ├── matter-config-panel.ts
│ │ │ │ │ ├── show-dialog-add-matter-device.ts
│ │ │ │ │ ├── show-dialog-matter-manage-fabrics.ts
│ │ │ │ │ ├── show-dialog-matter-open-commissioning-window.ts
│ │ │ │ │ ├── show-dialog-matter-ping-node.ts
│ │ │ │ │ └── show-dialog-matter-reinterview-node.ts
│ │ │ │ ├── mqtt
│ │ │ │ │ ├── mqtt-config-panel.ts
│ │ │ │ │ └── mqtt-subscribe-card.ts
│ │ │ │ ├── ssdp
│ │ │ │ │ ├── dialog-ssdp-discovery-info.ts
│ │ │ │ │ ├── dialog-ssdp-raw-data.ts
│ │ │ │ │ ├── show-dialog-ssdp-discovery-info.ts
│ │ │ │ │ ├── show-dialog-ssdp-raw-data.ts
│ │ │ │ │ └── ssdp-config-panel.ts
│ │ │ │ ├── thread
│ │ │ │ │ ├── dialog-thread-dataset.ts
│ │ │ │ │ ├── show-dialog-thread-dataset.ts
│ │ │ │ │ └── thread-config-panel.ts
│ │ │ │ ├── zeroconf
│ │ │ │ │ ├── dialog-zeroconf-discovery-info.ts
│ │ │ │ │ ├── show-dialog-zeroconf-discovery-info.ts
│ │ │ │ │ └── zeroconf-config-panel.ts
│ │ │ │ ├── zha
│ │ │ │ │ ├── dialog-zha-change-channel.ts
│ │ │ │ │ ├── dialog-zha-manage-zigbee-device.ts
│ │ │ │ │ ├── dialog-zha-reconfigure-device.ts
│ │ │ │ │ ├── functions.ts
│ │ │ │ │ ├── show-dialog-zha-change-channel.ts
│ │ │ │ │ ├── show-dialog-zha-manage-zigbee-device.ts
│ │ │ │ │ ├── show-dialog-zha-reconfigure-device.ts
│ │ │ │ │ ├── types.ts
│ │ │ │ │ ├── zha-add-devices-page.ts
│ │ │ │ │ ├── zha-add-group-page.ts
│ │ │ │ │ ├── zha-cluster-attributes.ts
│ │ │ │ │ ├── zha-cluster-commands.ts
│ │ │ │ │ ├── zha-clusters-data-table.ts
│ │ │ │ │ ├── zha-config-dashboard-router.ts
│ │ │ │ │ ├── zha-config-dashboard.ts
│ │ │ │ │ ├── zha-device-binding.ts
│ │ │ │ │ ├── zha-device-card.ts
│ │ │ │ │ ├── zha-device-endpoint-data-table.ts
│ │ │ │ │ ├── zha-device-neighbors.ts
│ │ │ │ │ ├── zha-device-pairing-status-card.ts
│ │ │ │ │ ├── zha-device-signature.ts
│ │ │ │ │ ├── zha-group-binding.ts
│ │ │ │ │ ├── zha-group-page.ts
│ │ │ │ │ ├── zha-groups-dashboard.ts
│ │ │ │ │ ├── zha-manage-clusters.ts
│ │ │ │ │ └── zha-network-visualization-page.ts
│ │ │ │ └── zwave_js
│ │ │ │ │ ├── add-node
│ │ │ │ │ ├── data.ts
│ │ │ │ │ ├── dialog-zwave_js-add-node.ts
│ │ │ │ │ ├── show-dialog-zwave_js-add-node.ts
│ │ │ │ │ ├── zwave-js-add-node-added-insecure.ts
│ │ │ │ │ ├── zwave-js-add-node-code-input.ts
│ │ │ │ │ ├── zwave-js-add-node-configure-device.ts
│ │ │ │ │ ├── zwave-js-add-node-failed.ts
│ │ │ │ │ ├── zwave-js-add-node-grant-security-classes.ts
│ │ │ │ │ ├── zwave-js-add-node-loading.ts
│ │ │ │ │ ├── zwave-js-add-node-searching-devices.ts
│ │ │ │ │ ├── zwave-js-add-node-select-method.ts
│ │ │ │ │ ├── zwave-js-add-node-select-security-strategy.ts
│ │ │ │ │ └── zwave_js-add-node.ts
│ │ │ │ │ ├── capability-controls
│ │ │ │ │ ├── zwave_js-capability-control-color-switch.ts
│ │ │ │ │ ├── zwave_js-capability-control-door-lock.ts
│ │ │ │ │ ├── zwave_js-capability-control-multilevel-switch.ts
│ │ │ │ │ └── zwave_js-capability-control-thermostat-setback.ts
│ │ │ │ │ ├── dialog-zwave_js-hard-reset-controller.ts
│ │ │ │ │ ├── dialog-zwave_js-node-statistics.ts
│ │ │ │ │ ├── dialog-zwave_js-rebuild-network-routes.ts
│ │ │ │ │ ├── dialog-zwave_js-rebuild-node-routes.ts
│ │ │ │ │ ├── dialog-zwave_js-reinterview-node.ts
│ │ │ │ │ ├── dialog-zwave_js-remove-failed-node.ts
│ │ │ │ │ ├── dialog-zwave_js-remove-node.ts
│ │ │ │ │ ├── dialog-zwave_js-update-firmware-node.ts
│ │ │ │ │ ├── show-dialog-zwave_js-hard-reset-controller.ts
│ │ │ │ │ ├── show-dialog-zwave_js-node-statistics.ts
│ │ │ │ │ ├── show-dialog-zwave_js-rebuild-network-routes.ts
│ │ │ │ │ ├── show-dialog-zwave_js-rebuild-node-routes.ts
│ │ │ │ │ ├── show-dialog-zwave_js-reinterview-node.ts
│ │ │ │ │ ├── show-dialog-zwave_js-remove-failed-node.ts
│ │ │ │ │ ├── show-dialog-zwave_js-remove-node.ts
│ │ │ │ │ ├── show-dialog-zwave_js-update-firmware-node.ts
│ │ │ │ │ ├── zwave_js-config-dashboard.ts
│ │ │ │ │ ├── zwave_js-config-router.ts
│ │ │ │ │ ├── zwave_js-custom-param.ts
│ │ │ │ │ ├── zwave_js-logs.ts
│ │ │ │ │ ├── zwave_js-node-config.ts
│ │ │ │ │ ├── zwave_js-node-installer.ts
│ │ │ │ │ └── zwave_js-provisioned.ts
│ │ │ └── show-add-integration-dialog.ts
│ │ ├── labels
│ │ │ ├── dialog-label-detail.ts
│ │ │ ├── ha-config-labels.ts
│ │ │ └── show-dialog-label-detail.ts
│ │ ├── logs
│ │ │ ├── dialog-download-logs.ts
│ │ │ ├── dialog-system-log-detail.ts
│ │ │ ├── error-log-card.ts
│ │ │ ├── ha-config-logs.ts
│ │ │ ├── show-dialog-download-logs.ts
│ │ │ ├── show-dialog-system-log-detail.ts
│ │ │ ├── system-log-card.ts
│ │ │ └── util.ts
│ │ ├── lovelace
│ │ │ ├── dashboards
│ │ │ │ ├── dialog-lovelace-dashboard-configure-strategy.ts
│ │ │ │ ├── dialog-lovelace-dashboard-detail.ts
│ │ │ │ ├── ha-config-lovelace-dashboards.ts
│ │ │ │ ├── show-dialog-lovelace-dashboard-configure-strategy.ts
│ │ │ │ └── show-dialog-lovelace-dashboard-detail.ts
│ │ │ ├── ha-config-lovelace.ts
│ │ │ └── resources
│ │ │ │ ├── dialog-lovelace-resource-detail.ts
│ │ │ │ ├── ha-config-lovelace-resources.ts
│ │ │ │ └── show-dialog-lovelace-resource-detail.ts
│ │ ├── network
│ │ │ ├── ha-config-network.ts
│ │ │ ├── ha-config-section-network.ts
│ │ │ ├── ha-config-url-form.ts
│ │ │ ├── supervisor-hostname.ts
│ │ │ └── supervisor-network.ts
│ │ ├── person
│ │ │ ├── dialog-person-detail.ts
│ │ │ ├── ha-config-person.ts
│ │ │ └── show-dialog-person-detail.ts
│ │ ├── repairs
│ │ │ ├── dialog-integration-startup.ts
│ │ │ ├── dialog-repairs-issue-subtitle.ts
│ │ │ ├── dialog-repairs-issue.ts
│ │ │ ├── dialog-system-information.ts
│ │ │ ├── ha-config-repairs-dashboard.ts
│ │ │ ├── ha-config-repairs.ts
│ │ │ ├── integrations-startup-time.ts
│ │ │ ├── show-dialog-repair-flow.ts
│ │ │ ├── show-integration-startup-dialog.ts
│ │ │ ├── show-repair-issue-dialog.ts
│ │ │ └── show-system-information-dialog.ts
│ │ ├── scene
│ │ │ ├── ha-config-scene.ts
│ │ │ ├── ha-scene-dashboard.ts
│ │ │ └── ha-scene-editor.ts
│ │ ├── script
│ │ │ ├── blueprint-script-editor.ts
│ │ │ ├── ha-config-script.ts
│ │ │ ├── ha-script-editor.ts
│ │ │ ├── ha-script-field-row.ts
│ │ │ ├── ha-script-fields.ts
│ │ │ ├── ha-script-picker.ts
│ │ │ ├── ha-script-trace.ts
│ │ │ └── manual-script-editor.ts
│ │ ├── storage
│ │ │ ├── dialog-mount-view.ts
│ │ │ ├── dialog-move-datadisk.ts
│ │ │ ├── ha-config-section-storage.ts
│ │ │ ├── show-dialog-move-datadisk.ts
│ │ │ └── show-dialog-view-mount.ts
│ │ ├── tags
│ │ │ ├── dialog-tag-detail.ts
│ │ │ ├── ha-config-tags.ts
│ │ │ ├── show-dialog-tag-detail.ts
│ │ │ └── tag-image.ts
│ │ ├── users
│ │ │ ├── dialog-add-user.ts
│ │ │ ├── dialog-admin-change-password.ts
│ │ │ ├── dialog-user-detail.ts
│ │ │ ├── ha-config-users.ts
│ │ │ ├── show-dialog-add-user.ts
│ │ │ ├── show-dialog-admin-change-password.ts
│ │ │ └── show-dialog-user-detail.ts
│ │ ├── voice-assistants
│ │ │ ├── assist-pipeline-detail
│ │ │ │ ├── assist-pipeline-detail-config.ts
│ │ │ │ ├── assist-pipeline-detail-conversation.ts
│ │ │ │ ├── assist-pipeline-detail-stt.ts
│ │ │ │ ├── assist-pipeline-detail-tts.ts
│ │ │ │ └── assist-pipeline-detail-wakeword.ts
│ │ │ ├── assist-pref.ts
│ │ │ ├── assist
│ │ │ │ └── ha-config-voice-assistants-assist-devices.ts
│ │ │ ├── cloud-alexa-pref.ts
│ │ │ ├── cloud-discover.ts
│ │ │ ├── cloud-google-pref.ts
│ │ │ ├── debug
│ │ │ │ ├── assist-debug.ts
│ │ │ │ ├── assist-pipeline-debug.ts
│ │ │ │ ├── assist-pipeline-run-debug.ts
│ │ │ │ ├── assist-render-pipeline-events.ts
│ │ │ │ └── assist-render-pipeline-run.ts
│ │ │ ├── dialog-expose-entity.ts
│ │ │ ├── dialog-voice-assistant-pipeline-detail.ts
│ │ │ ├── dialog-voice-settings.ts
│ │ │ ├── entity-voice-settings.ts
│ │ │ ├── expose
│ │ │ │ └── expose-assistant-icon.ts
│ │ │ ├── ha-config-voice-assistants-assistants.ts
│ │ │ ├── ha-config-voice-assistants-expose.ts
│ │ │ ├── ha-config-voice-assistants.ts
│ │ │ ├── show-dialog-expose-entity.ts
│ │ │ ├── show-dialog-voice-assistant-pipeline-detail.ts
│ │ │ └── show-dialog-voice-settings.ts
│ │ └── zone
│ │ │ ├── dialog-home-zone-detail.ts
│ │ │ ├── dialog-zone-detail.ts
│ │ │ ├── ha-config-zone.ts
│ │ │ ├── show-dialog-home-zone-detail.ts
│ │ │ └── show-dialog-zone-detail.ts
│ ├── custom
│ │ └── ha-panel-custom.ts
│ ├── developer-tools
│ │ ├── action
│ │ │ └── developer-tools-action.ts
│ │ ├── assist
│ │ │ └── developer-tools-assist.ts
│ │ ├── debug
│ │ │ ├── developer-tools-debug.ts
│ │ │ └── ha-debug-connection-row.ts
│ │ ├── developer-tools-router.ts
│ │ ├── event
│ │ │ ├── developer-tools-event.ts
│ │ │ ├── event-subscribe-card.ts
│ │ │ └── events-list.ts
│ │ ├── ha-panel-developer-tools.ts
│ │ ├── state
│ │ │ └── developer-tools-state.ts
│ │ ├── statistics
│ │ │ ├── developer-tools-statistics.ts
│ │ │ ├── dialog-statistics-adjust-sum.ts
│ │ │ ├── dialog-statistics-fix-units-changed.ts
│ │ │ ├── dialog-statistics-fix.ts
│ │ │ ├── fix-statistics.ts
│ │ │ ├── show-dialog-statistics-adjust-sum.ts
│ │ │ ├── show-dialog-statistics-fix-units-changed.ts
│ │ │ └── show-dialog-statistics-fix.ts
│ │ ├── template
│ │ │ └── developer-tools-template.ts
│ │ └── yaml_configuration
│ │ │ └── developer-yaml-config.ts
│ ├── energy
│ │ ├── cards
│ │ │ └── energy-setup-wizard-card.ts
│ │ ├── ha-panel-energy.ts
│ │ └── strategies
│ │ │ └── energy-view-strategy.ts
│ ├── history
│ │ └── ha-panel-history.ts
│ ├── iframe
│ │ └── ha-panel-iframe.ts
│ ├── logbook
│ │ ├── ha-logbook-renderer.ts
│ │ ├── ha-logbook.ts
│ │ └── ha-panel-logbook.ts
│ ├── lovelace
│ │ ├── badges
│ │ │ ├── hui-badge.ts
│ │ │ ├── hui-entity-badge.ts
│ │ │ ├── hui-entity-filter-badge.ts
│ │ │ ├── hui-error-badge.ts
│ │ │ ├── hui-state-label-badge.ts
│ │ │ ├── hui-view-badges.ts
│ │ │ └── types.ts
│ │ ├── card-features
│ │ │ ├── common
│ │ │ │ ├── card-feature-styles.ts
│ │ │ │ └── filter-modes.ts
│ │ │ ├── hui-alarm-modes-card-feature.ts
│ │ │ ├── hui-card-feature.ts
│ │ │ ├── hui-card-features.ts
│ │ │ ├── hui-climate-fan-modes-card-feature.ts
│ │ │ ├── hui-climate-hvac-modes-card-feature.ts
│ │ │ ├── hui-climate-preset-modes-card-feature.ts
│ │ │ ├── hui-climate-swing-horizontal-modes-card-feature.ts
│ │ │ ├── hui-climate-swing-modes-card-feature.ts
│ │ │ ├── hui-counter-actions-card-feature.ts
│ │ │ ├── hui-cover-open-close-card-feature.ts
│ │ │ ├── hui-cover-position-card-feature.ts
│ │ │ ├── hui-cover-tilt-card-feature.ts
│ │ │ ├── hui-cover-tilt-position-card-feature.ts
│ │ │ ├── hui-fan-preset-modes-card-feature.ts
│ │ │ ├── hui-fan-speed-card-feature.ts
│ │ │ ├── hui-humidifier-modes-card-feature.ts
│ │ │ ├── hui-humidifier-toggle-card-feature.ts
│ │ │ ├── hui-lawn-mower-commands-card-feature.ts
│ │ │ ├── hui-light-brightness-card-feature.ts
│ │ │ ├── hui-light-color-temp-card-feature.ts
│ │ │ ├── hui-lock-commands-card-feature.ts
│ │ │ ├── hui-lock-open-door-card-feature.ts
│ │ │ ├── hui-media-player-volume-slider-card-feature.ts
│ │ │ ├── hui-numeric-input-card-feature.ts
│ │ │ ├── hui-select-options-card-feature.ts
│ │ │ ├── hui-target-humidity-card-feature.ts
│ │ │ ├── hui-target-temperature-card-feature.ts
│ │ │ ├── hui-toggle-card-feature.ts
│ │ │ ├── hui-update-actions-card-feature.ts
│ │ │ ├── hui-vacuum-commands-card-feature.ts
│ │ │ ├── hui-water-heater-operation-modes-card-feature.ts
│ │ │ └── types.ts
│ │ ├── cards
│ │ │ ├── energy
│ │ │ │ ├── common
│ │ │ │ │ ├── color.ts
│ │ │ │ │ └── energy-chart-options.ts
│ │ │ │ ├── hui-energy-carbon-consumed-gauge-card.ts
│ │ │ │ ├── hui-energy-compare-card.ts
│ │ │ │ ├── hui-energy-date-selection-card.ts
│ │ │ │ ├── hui-energy-devices-detail-graph-card.ts
│ │ │ │ ├── hui-energy-devices-graph-card.ts
│ │ │ │ ├── hui-energy-distribution-card.ts
│ │ │ │ ├── hui-energy-gas-graph-card.ts
│ │ │ │ ├── hui-energy-grid-neutrality-gauge-card.ts
│ │ │ │ ├── hui-energy-sankey-card.ts
│ │ │ │ ├── hui-energy-self-sufficiency-gauge-card.ts
│ │ │ │ ├── hui-energy-solar-consumed-gauge-card.ts
│ │ │ │ ├── hui-energy-solar-graph-card.ts
│ │ │ │ ├── hui-energy-sources-table-card.ts
│ │ │ │ ├── hui-energy-usage-graph-card.ts
│ │ │ │ └── hui-energy-water-graph-card.ts
│ │ │ ├── hui-alarm-panel-card.ts
│ │ │ ├── hui-area-card.ts
│ │ │ ├── hui-button-card.ts
│ │ │ ├── hui-calendar-card.ts
│ │ │ ├── hui-card.ts
│ │ │ ├── hui-clock-card.ts
│ │ │ ├── hui-conditional-card.ts
│ │ │ ├── hui-empty-state-card.ts
│ │ │ ├── hui-entities-card.ts
│ │ │ ├── hui-entity-button-card.ts
│ │ │ ├── hui-entity-card.ts
│ │ │ ├── hui-entity-filter-card.ts
│ │ │ ├── hui-error-card.ts
│ │ │ ├── hui-gauge-card.ts
│ │ │ ├── hui-glance-card.ts
│ │ │ ├── hui-grid-card.ts
│ │ │ ├── hui-heading-card.ts
│ │ │ ├── hui-history-graph-card.ts
│ │ │ ├── hui-horizontal-stack-card.ts
│ │ │ ├── hui-humidifier-card.ts
│ │ │ ├── hui-iframe-card.ts
│ │ │ ├── hui-light-card.ts
│ │ │ ├── hui-logbook-card.ts
│ │ │ ├── hui-map-card.ts
│ │ │ ├── hui-markdown-card.ts
│ │ │ ├── hui-media-control-card.ts
│ │ │ ├── hui-picture-card.ts
│ │ │ ├── hui-picture-elements-card.ts
│ │ │ ├── hui-picture-entity-card.ts
│ │ │ ├── hui-picture-glance-card.ts
│ │ │ ├── hui-plant-status-card.ts
│ │ │ ├── hui-recovery-mode-card.ts
│ │ │ ├── hui-sensor-card.ts
│ │ │ ├── hui-shopping-list-card.ts
│ │ │ ├── hui-stack-card.ts
│ │ │ ├── hui-starting-card.ts
│ │ │ ├── hui-statistic-card.ts
│ │ │ ├── hui-statistics-graph-card.ts
│ │ │ ├── hui-thermostat-card.ts
│ │ │ ├── hui-tile-card.ts
│ │ │ ├── hui-todo-list-card.ts
│ │ │ ├── hui-vertical-stack-card.ts
│ │ │ ├── hui-weather-forecast-card.ts
│ │ │ ├── picture-elements
│ │ │ │ └── create-styled-hui-element.ts
│ │ │ ├── tile
│ │ │ │ └── badges
│ │ │ │ │ ├── tile-badge-climate.ts
│ │ │ │ │ ├── tile-badge-humidifier.ts
│ │ │ │ │ ├── tile-badge-person.ts
│ │ │ │ │ └── tile-badge.ts
│ │ │ └── types.ts
│ │ ├── common
│ │ │ ├── check-lovelace-config.ts
│ │ │ ├── compute-card-grid-size.ts
│ │ │ ├── compute-card-size.ts
│ │ │ ├── compute-tooltip.ts
│ │ │ ├── compute-unused-entities.ts
│ │ │ ├── confirm-action.ts
│ │ │ ├── directives
│ │ │ │ └── action-handler-directive.ts
│ │ │ ├── entity
│ │ │ │ ├── toggle-entity.ts
│ │ │ │ ├── turn-on-off-entities.ts
│ │ │ │ └── turn-on-off-entity.ts
│ │ │ ├── evaluate-filter.ts
│ │ │ ├── find-entities.ts
│ │ │ ├── generate-lovelace-config.ts
│ │ │ ├── graph
│ │ │ │ ├── coordinates.ts
│ │ │ │ └── get-path.ts
│ │ │ ├── handle-action.ts
│ │ │ ├── has-action.ts
│ │ │ ├── has-changed.ts
│ │ │ ├── icon-condition.ts
│ │ │ ├── is-valid-object.ts
│ │ │ ├── load-resources.ts
│ │ │ ├── process-config-entities.ts
│ │ │ └── validate-condition.ts
│ │ ├── components
│ │ │ ├── hui-action-editor.ts
│ │ │ ├── hui-badge-edit-mode.ts
│ │ │ ├── hui-buttons-base.ts
│ │ │ ├── hui-card-edit-mode.ts
│ │ │ ├── hui-card-options.ts
│ │ │ ├── hui-conditional-base.ts
│ │ │ ├── hui-energy-period-selector.ts
│ │ │ ├── hui-entities-toggle.ts
│ │ │ ├── hui-entity-editor.ts
│ │ │ ├── hui-generic-entity-row.ts
│ │ │ ├── hui-graph-base.ts
│ │ │ ├── hui-image.ts
│ │ │ ├── hui-marquee.ts
│ │ │ ├── hui-timestamp-display.ts
│ │ │ ├── hui-warning-element.ts
│ │ │ ├── hui-warning.ts
│ │ │ └── types.ts
│ │ ├── create-element
│ │ │ ├── create-badge-element.ts
│ │ │ ├── create-card-element.ts
│ │ │ ├── create-card-feature-element.ts
│ │ │ ├── create-element-base.ts
│ │ │ ├── create-header-footer-element.ts
│ │ │ ├── create-heading-badge-element.ts
│ │ │ ├── create-hui-element.ts
│ │ │ ├── create-picture-element.ts
│ │ │ ├── create-row-element.ts
│ │ │ ├── create-section-element.ts
│ │ │ └── create-view-element.ts
│ │ ├── custom-card-helpers.ts
│ │ ├── editor
│ │ │ ├── add-entities-to-view.ts
│ │ │ ├── badge-editor
│ │ │ │ ├── hui-badge-element-editor.ts
│ │ │ │ ├── hui-badge-picker.ts
│ │ │ │ ├── hui-badge-visibility-editor.ts
│ │ │ │ ├── hui-dialog-create-badge.ts
│ │ │ │ ├── hui-dialog-edit-badge.ts
│ │ │ │ ├── hui-dialog-suggest-badge.ts
│ │ │ │ ├── show-create-badge-dialog.ts
│ │ │ │ ├── show-edit-badge-dialog.ts
│ │ │ │ └── show-suggest-badge-dialog.ts
│ │ │ ├── card-editor
│ │ │ │ ├── ha-grid-layout-slider.ts
│ │ │ │ ├── hui-card-element-editor.ts
│ │ │ │ ├── hui-card-layout-editor.ts
│ │ │ │ ├── hui-card-picker.ts
│ │ │ │ ├── hui-card-visibility-editor.ts
│ │ │ │ ├── hui-dialog-create-card.ts
│ │ │ │ ├── hui-dialog-delete-card.ts
│ │ │ │ ├── hui-dialog-edit-card.ts
│ │ │ │ ├── hui-dialog-suggest-card.ts
│ │ │ │ ├── hui-entity-picker-table.ts
│ │ │ │ ├── show-create-card-dialog.ts
│ │ │ │ ├── show-delete-card-dialog.ts
│ │ │ │ ├── show-edit-card-dialog.ts
│ │ │ │ └── show-suggest-card-dialog.ts
│ │ │ ├── conditions
│ │ │ │ ├── ha-card-condition-editor.ts
│ │ │ │ ├── ha-card-conditions-editor.ts
│ │ │ │ ├── types.ts
│ │ │ │ └── types
│ │ │ │ │ ├── ha-card-condition-and.ts
│ │ │ │ │ ├── ha-card-condition-numeric_state.ts
│ │ │ │ │ ├── ha-card-condition-or.ts
│ │ │ │ │ ├── ha-card-condition-screen.ts
│ │ │ │ │ ├── ha-card-condition-state.ts
│ │ │ │ │ └── ha-card-condition-user.ts
│ │ │ ├── config-elements
│ │ │ │ ├── config-elements-style.ts
│ │ │ │ ├── elements
│ │ │ │ │ ├── hui-conditional-element-editor.ts
│ │ │ │ │ ├── hui-icon-element-editor.ts
│ │ │ │ │ ├── hui-image-element-editor.ts
│ │ │ │ │ ├── hui-service-button-element-editor.ts
│ │ │ │ │ ├── hui-state-badge-element-editor.ts
│ │ │ │ │ ├── hui-state-icon-element-editor.ts
│ │ │ │ │ └── hui-state-label-element-editor.ts
│ │ │ │ ├── hui-alarm-modes-card-feature-editor.ts
│ │ │ │ ├── hui-alarm-panel-card-editor.ts
│ │ │ │ ├── hui-area-card-editor.ts
│ │ │ │ ├── hui-button-card-editor.ts
│ │ │ │ ├── hui-calendar-card-editor.ts
│ │ │ │ ├── hui-card-features-editor.ts
│ │ │ │ ├── hui-climate-fan-modes-card-feature-editor.ts
│ │ │ │ ├── hui-climate-hvac-modes-card-feature-editor.ts
│ │ │ │ ├── hui-climate-preset-modes-card-feature-editor.ts
│ │ │ │ ├── hui-climate-swing-horizontal-modes-card-feature-editor.ts
│ │ │ │ ├── hui-climate-swing-modes-card-feature-editor.ts
│ │ │ │ ├── hui-clock-card-editor.ts
│ │ │ │ ├── hui-conditional-card-editor.ts
│ │ │ │ ├── hui-counter-actions-card-feature-editor.ts
│ │ │ │ ├── hui-entities-card-editor.ts
│ │ │ │ ├── hui-entity-badge-editor.ts
│ │ │ │ ├── hui-entity-card-editor.ts
│ │ │ │ ├── hui-fan-preset-modes-card-feature-editor.ts
│ │ │ │ ├── hui-form-editor.ts
│ │ │ │ ├── hui-gauge-card-editor.ts
│ │ │ │ ├── hui-generic-entity-row-editor.ts
│ │ │ │ ├── hui-glance-card-editor.ts
│ │ │ │ ├── hui-graph-footer-editor.ts
│ │ │ │ ├── hui-grid-card-editor.ts
│ │ │ │ ├── hui-heading-badges-editor.ts
│ │ │ │ ├── hui-heading-card-editor.ts
│ │ │ │ ├── hui-history-graph-card-editor.ts
│ │ │ │ ├── hui-humidifier-card-editor.ts
│ │ │ │ ├── hui-humidifier-modes-card-feature-editor.ts
│ │ │ │ ├── hui-iframe-card-editor.ts
│ │ │ │ ├── hui-lawn-mower-commands-card-feature-editor.ts
│ │ │ │ ├── hui-light-card-editor.ts
│ │ │ │ ├── hui-logbook-card-editor.ts
│ │ │ │ ├── hui-map-card-editor.ts
│ │ │ │ ├── hui-markdown-card-editor.ts
│ │ │ │ ├── hui-media-control-card-editor.ts
│ │ │ │ ├── hui-numeric-input-card-feature-editor.ts
│ │ │ │ ├── hui-picture-card-editor.ts
│ │ │ │ ├── hui-picture-elements-card-editor.ts
│ │ │ │ ├── hui-picture-entity-card-editor.ts
│ │ │ │ ├── hui-picture-glance-card-editor.ts
│ │ │ │ ├── hui-plant-status-card-editor.ts
│ │ │ │ ├── hui-select-options-card-feature-editor.ts
│ │ │ │ ├── hui-sensor-card-editor.ts
│ │ │ │ ├── hui-stack-card-editor.ts
│ │ │ │ ├── hui-state-label-badge-editor.ts
│ │ │ │ ├── hui-statistic-card-editor.ts
│ │ │ │ ├── hui-statistics-graph-card-editor.ts
│ │ │ │ ├── hui-thermostat-card-editor.ts
│ │ │ │ ├── hui-tile-card-editor.ts
│ │ │ │ ├── hui-todo-list-editor.ts
│ │ │ │ ├── hui-update-actions-card-feature-editor.ts
│ │ │ │ ├── hui-vacuum-commands-card-feature-editor.ts
│ │ │ │ ├── hui-water-heater-operation-modes-card-feature-editor.ts
│ │ │ │ └── hui-weather-forecast-card-editor.ts
│ │ │ ├── config-util.ts
│ │ │ ├── dashboard-strategy-editor
│ │ │ │ ├── dialogs
│ │ │ │ │ ├── dialog-dashboard-strategy-editor.ts
│ │ │ │ │ └── show-dialog-dashboard-strategy-editor.ts
│ │ │ │ ├── hui-dashboard-strategy-element-editor.ts
│ │ │ │ ├── hui-iframe-dashboard-strategy-editor.ts
│ │ │ │ └── hui-original-states-dashboard-strategy-editor.ts
│ │ │ ├── delete-badge.ts
│ │ │ ├── delete-card.ts
│ │ │ ├── entity-row-editor
│ │ │ │ └── hui-row-element-editor.ts
│ │ │ ├── feature-editor
│ │ │ │ └── hui-card-feature-element-editor.ts
│ │ │ ├── get-badge-stub-config.ts
│ │ │ ├── get-card-stub-config.ts
│ │ │ ├── get-dashboard-documentation-url.ts
│ │ │ ├── get-element-stub-config.ts
│ │ │ ├── gui-support-error.ts
│ │ │ ├── header-footer-editor
│ │ │ │ ├── get-headerfooter-stub-config.ts
│ │ │ │ ├── hui-dialog-create-headerfooter.ts
│ │ │ │ ├── hui-header-footer-editor.ts
│ │ │ │ ├── hui-header-footer-element-editor.ts
│ │ │ │ └── show-create-headerfooter-dialog.ts
│ │ │ ├── heading-badge-editor
│ │ │ │ ├── hui-entity-heading-badge-editor.ts
│ │ │ │ └── hui-heading-badge-element-editor.ts
│ │ │ ├── hui-dialog-save-config.ts
│ │ │ ├── hui-element-editor.ts
│ │ │ ├── hui-entities-card-row-editor.ts
│ │ │ ├── hui-picture-elements-card-row-editor.ts
│ │ │ ├── hui-sub-element-editor.ts
│ │ │ ├── hui-typed-element-editor.ts
│ │ │ ├── lovelace-badges.ts
│ │ │ ├── lovelace-cards.ts
│ │ │ ├── lovelace-headerfooters.ts
│ │ │ ├── lovelace-path.ts
│ │ │ ├── picture-element-editor
│ │ │ │ └── hui-picture-element-element-editor.ts
│ │ │ ├── process-editor-entities.ts
│ │ │ ├── section-editor
│ │ │ │ ├── hui-dialog-edit-section.ts
│ │ │ │ ├── hui-section-settings-editor.ts
│ │ │ │ ├── hui-section-visibility-editor.ts
│ │ │ │ └── show-edit-section-dialog.ts
│ │ │ ├── select-dashboard
│ │ │ │ ├── hui-dialog-select-dashboard.ts
│ │ │ │ └── show-select-dashboard-dialog.ts
│ │ │ ├── select-view
│ │ │ │ ├── hui-dialog-select-view.ts
│ │ │ │ └── show-select-view-dialog.ts
│ │ │ ├── show-save-config-dialog.ts
│ │ │ ├── structs
│ │ │ │ ├── action-struct.ts
│ │ │ │ ├── base-badge-struct.ts
│ │ │ │ ├── base-card-struct.ts
│ │ │ │ ├── button-entity-struct.ts
│ │ │ │ └── entities-struct.ts
│ │ │ ├── types.ts
│ │ │ ├── unused-entities
│ │ │ │ └── hui-unused-entities.ts
│ │ │ ├── view-editor
│ │ │ │ ├── hui-dialog-edit-view.ts
│ │ │ │ ├── hui-view-background-editor.ts
│ │ │ │ ├── hui-view-editor.ts
│ │ │ │ ├── hui-view-visibility-editor.ts
│ │ │ │ └── show-edit-view-dialog.ts
│ │ │ └── view-header
│ │ │ │ ├── hui-dialog-edit-view-header.ts
│ │ │ │ ├── hui-view-header-settings-editor.ts
│ │ │ │ └── show-edit-view-header-dialog.ts
│ │ ├── elements
│ │ │ ├── hui-conditional-element.ts
│ │ │ ├── hui-icon-element.ts
│ │ │ ├── hui-image-element.ts
│ │ │ ├── hui-service-button-element.ts
│ │ │ ├── hui-state-badge-element.ts
│ │ │ ├── hui-state-icon-element.ts
│ │ │ ├── hui-state-label-element.ts
│ │ │ └── types.ts
│ │ ├── entity-rows
│ │ │ ├── hui-button-entity-row.ts
│ │ │ ├── hui-climate-entity-row.ts
│ │ │ ├── hui-cover-entity-row.ts
│ │ │ ├── hui-date-entity-row.ts
│ │ │ ├── hui-datetime-entity-row.ts
│ │ │ ├── hui-event-entity-row.ts
│ │ │ ├── hui-group-entity-row.ts
│ │ │ ├── hui-humidifier-entity-row.ts
│ │ │ ├── hui-input-button-entity-row.ts
│ │ │ ├── hui-input-datetime-entity-row.ts
│ │ │ ├── hui-input-number-entity-row.ts
│ │ │ ├── hui-input-select-entity-row.ts
│ │ │ ├── hui-input-text-entity-row.ts
│ │ │ ├── hui-lock-entity-row.ts
│ │ │ ├── hui-media-player-entity-row.ts
│ │ │ ├── hui-number-entity-row.ts
│ │ │ ├── hui-scene-entity-row.ts
│ │ │ ├── hui-script-entity-row.ts
│ │ │ ├── hui-select-entity-row.ts
│ │ │ ├── hui-sensor-entity-row.ts
│ │ │ ├── hui-simple-entity-row.ts
│ │ │ ├── hui-text-entity-row.ts
│ │ │ ├── hui-time-entity-row.ts
│ │ │ ├── hui-timer-entity-row.ts
│ │ │ ├── hui-toggle-entity-row.ts
│ │ │ ├── hui-update-entity-row.ts
│ │ │ ├── hui-valve-entity-row.ts
│ │ │ ├── hui-weather-entity-row.ts
│ │ │ └── types.ts
│ │ ├── ha-panel-lovelace.ts
│ │ ├── header-footer
│ │ │ ├── hui-buttons-header-footer.ts
│ │ │ ├── hui-graph-header-footer.ts
│ │ │ ├── hui-picture-header-footer.ts
│ │ │ ├── structs.ts
│ │ │ └── types.ts
│ │ ├── heading-badges
│ │ │ ├── hui-entity-heading-badge.ts
│ │ │ ├── hui-error-heading-badge.ts
│ │ │ ├── hui-heading-badge.ts
│ │ │ └── types.ts
│ │ ├── hui-editor.ts
│ │ ├── hui-root.ts
│ │ ├── sections
│ │ │ ├── const.ts
│ │ │ ├── hui-error-section.ts
│ │ │ ├── hui-grid-section.ts
│ │ │ └── hui-section.ts
│ │ ├── special-rows
│ │ │ ├── hui-attribute-row.ts
│ │ │ ├── hui-button-row.ts
│ │ │ ├── hui-buttons-row.ts
│ │ │ ├── hui-call-service-row.ts
│ │ │ ├── hui-cast-row.ts
│ │ │ ├── hui-conditional-row.ts
│ │ │ ├── hui-divider-row.ts
│ │ │ ├── hui-section-row.ts
│ │ │ ├── hui-text-row.ts
│ │ │ └── hui-weblink-row.ts
│ │ ├── strategies
│ │ │ ├── areas
│ │ │ │ ├── area-view-strategy.ts
│ │ │ │ ├── areas-dashboard-strategy.ts
│ │ │ │ ├── areas-overview-view-strategy.ts
│ │ │ │ ├── editor
│ │ │ │ │ └── hui-areas-dashboard-strategy-editor.ts
│ │ │ │ └── helpers
│ │ │ │ │ └── areas-strategy-helper.ts
│ │ │ ├── get-strategy.ts
│ │ │ ├── iframe
│ │ │ │ ├── iframe-dashboard-strategy.ts
│ │ │ │ └── iframe-view-strategy.ts
│ │ │ ├── legacy-strategy.ts
│ │ │ ├── map
│ │ │ │ ├── map-dashboard-strategy.ts
│ │ │ │ └── map-view-strategy.ts
│ │ │ ├── original-states
│ │ │ │ ├── original-states-dashboard-strategy.ts
│ │ │ │ └── original-states-view-strategy.ts
│ │ │ └── types.ts
│ │ ├── types.ts
│ │ └── views
│ │ │ ├── const.ts
│ │ │ ├── default-section.ts
│ │ │ ├── default-view-editable.ts
│ │ │ ├── get-view-type.ts
│ │ │ ├── hui-masonry-view.ts
│ │ │ ├── hui-panel-view.ts
│ │ │ ├── hui-sections-view.ts
│ │ │ ├── hui-sidebar-view.ts
│ │ │ ├── hui-view-background.ts
│ │ │ ├── hui-view-container.ts
│ │ │ ├── hui-view-header.ts
│ │ │ └── hui-view.ts
│ ├── map
│ │ └── ha-panel-map.ts
│ ├── media-browser
│ │ ├── browser-media-player.ts
│ │ ├── ha-bar-media-player.ts
│ │ ├── ha-panel-media-browser.ts
│ │ ├── hui-dialog-web-browser-play-media.ts
│ │ └── show-media-player-dialog.ts
│ ├── my
│ │ └── ha-panel-my.ts
│ ├── profile
│ │ ├── dialog-ha-mfa-module-setup-flow.ts
│ │ ├── ha-advanced-mode-row.ts
│ │ ├── ha-change-password-card.ts
│ │ ├── ha-enable-shortcuts-row.ts
│ │ ├── ha-entity-id-picker-row.ts
│ │ ├── ha-force-narrow-row.ts
│ │ ├── ha-long-lived-access-token-dialog.ts
│ │ ├── ha-long-lived-access-tokens-card.ts
│ │ ├── ha-mfa-modules-card.ts
│ │ ├── ha-panel-profile.ts
│ │ ├── ha-pick-dashboard-row.ts
│ │ ├── ha-pick-date-format-row.ts
│ │ ├── ha-pick-first-weekday-row.ts
│ │ ├── ha-pick-language-row.ts
│ │ ├── ha-pick-number-format-row.ts
│ │ ├── ha-pick-theme-row.ts
│ │ ├── ha-pick-time-format-row.ts
│ │ ├── ha-pick-time-zone-row.ts
│ │ ├── ha-profile-section-general.ts
│ │ ├── ha-profile-section-security.ts
│ │ ├── ha-push-notifications-row.ts
│ │ ├── ha-refresh-tokens-card.ts
│ │ ├── ha-set-suspend-row.ts
│ │ ├── ha-set-vibrate-row.ts
│ │ ├── show-ha-mfa-module-setup-flow-dialog.ts
│ │ └── show-long-lived-access-token-dialog.ts
│ └── todo
│ │ ├── dialog-todo-item-editor.ts
│ │ ├── ha-panel-todo.ts
│ │ └── show-dialog-todo-item-editor.ts
├── resources
│ ├── append-ha-style.ts
│ ├── codemirror.ts
│ ├── css-variables.ts
│ ├── custom-card-support.ts
│ ├── echarts.ts
│ ├── fuse.ts
│ ├── hammer.ts
│ ├── home-assistant-logo-svg.ts
│ ├── icon-metadata.ts
│ ├── log-message.ts
│ ├── markdown-worker.ts
│ ├── particles.ts
│ ├── polyfills
│ │ ├── element-getattributenames.ts
│ │ ├── element-toggleattribute.ts
│ │ ├── intl-polyfill.ts
│ │ ├── locale-data-polyfill.ts
│ │ └── resize-observer.ts
│ ├── render-markdown.ts
│ ├── roboto.ts
│ ├── sortable.ts
│ ├── styles.ts
│ ├── svg-arc.ts
│ ├── theme
│ │ ├── color.globals.ts
│ │ ├── main.globals.ts
│ │ ├── theme.ts
│ │ └── typography.globals.ts
│ ├── translations-metadata.ts
│ └── virtualizer.ts
├── state-control
│ ├── alarm_control_panel
│ │ └── ha-state-control-alarm_control_panel-modes.ts
│ ├── climate
│ │ ├── ha-state-control-climate-humidity.ts
│ │ └── ha-state-control-climate-temperature.ts
│ ├── cover
│ │ ├── ha-state-control-cover-buttons.ts
│ │ ├── ha-state-control-cover-position.ts
│ │ ├── ha-state-control-cover-tilt-position.ts
│ │ └── ha-state-control-cover-toggle.ts
│ ├── fan
│ │ └── ha-state-control-fan-speed.ts
│ ├── ha-state-control-toggle.ts
│ ├── humidifier
│ │ └── ha-state-control-humidifier-humidity.ts
│ ├── light
│ │ └── ha-state-control-light-brightness.ts
│ ├── lock
│ │ └── ha-state-control-lock-toggle.ts
│ ├── state-control-circular-slider-style.ts
│ ├── valve
│ │ ├── ha-state-control-valve-buttons.ts
│ │ ├── ha-state-control-valve-position.ts
│ │ └── ha-state-control-valve-toggle.ts
│ └── water_heater
│ │ └── ha-state-control-water_heater-temperature.ts
├── state-display
│ ├── ha-timer-remaining-time.ts
│ └── state-display.ts
├── state-summary
│ ├── state-card-alert.ts
│ ├── state-card-button.ts
│ ├── state-card-climate.ts
│ ├── state-card-configurator.ts
│ ├── state-card-content.ts
│ ├── state-card-cover.ts
│ ├── state-card-display.ts
│ ├── state-card-event.ts
│ ├── state-card-humidifier.ts
│ ├── state-card-input_button.ts
│ ├── state-card-input_number.ts
│ ├── state-card-input_select.ts
│ ├── state-card-input_text.ts
│ ├── state-card-lawn_mower.ts
│ ├── state-card-lock.ts
│ ├── state-card-media_player.ts
│ ├── state-card-number.ts
│ ├── state-card-scene.ts
│ ├── state-card-script.ts
│ ├── state-card-select.ts
│ ├── state-card-text.ts
│ ├── state-card-timer.ts
│ ├── state-card-toggle.ts
│ ├── state-card-update.ts
│ ├── state-card-vacuum.ts
│ └── state-card-water_heater.ts
├── state
│ ├── action-mixin.ts
│ ├── auth-mixin.ts
│ ├── connection-mixin.ts
│ ├── context-mixin.ts
│ ├── dialog-manager-mixin.ts
│ ├── disconnect-toast-mixin.ts
│ ├── haptic-mixin.ts
│ ├── hass-base-mixin.ts
│ ├── hass-element.ts
│ ├── logging-mixin.ts
│ ├── more-info-mixin.ts
│ ├── notification-mixin.ts
│ ├── panel-title-mixin.ts
│ ├── quick-bar-mixin.ts
│ ├── sidebar-mixin.ts
│ ├── state-display-mixin.ts
│ ├── themes-mixin.ts
│ ├── translations-mixin.ts
│ └── url-sync-mixin.ts
├── translations
│ ├── en.json
│ └── translationMetadata.json
├── types.ts
├── types
│ ├── audio.d.ts
│ ├── echarts.d.ts
│ ├── node-vibrant.d.ts
│ └── service-worker.d.ts
└── util
│ ├── audio-recorder.ts
│ ├── brands-url.ts
│ ├── bytes-to-string.ts
│ ├── cache-manager.ts
│ ├── calculate.ts
│ ├── common-translation.ts
│ ├── custom-panel
│ ├── create-custom-panel-element.ts
│ ├── load-custom-panel.ts
│ └── set-custom-panel-properties.ts
│ ├── documentation-url.ts
│ ├── empty.js
│ ├── fetch-with-auth.ts
│ ├── file_download.ts
│ ├── ha-pref-storage.ts
│ ├── hass-call-api.ts
│ ├── hass-media-player-model.ts
│ ├── iframe.ts
│ ├── is_ios.ts
│ ├── is_mac.ts
│ ├── is_mobile.ts
│ ├── is_safari.ts
│ ├── is_touch.ts
│ ├── launch-screen.ts
│ ├── recorder-worklet.js
│ ├── register-service-worker.ts
│ ├── text.ts
│ ├── toast-saved-success.ts
│ ├── toast.ts
│ └── url.ts
├── test
├── common
│ ├── array
│ │ ├── combination.test.ts
│ │ ├── ensure-array.test.ts
│ │ └── literal-includes.test.ts
│ ├── auth
│ │ └── token_storage
│ │ │ ├── askWrite.test.ts
│ │ │ ├── saveTokens.test.ts
│ │ │ └── token_storage.test.ts
│ ├── color
│ │ ├── colors.test.ts
│ │ ├── compute-color.test.ts
│ │ ├── convert-color.test.ts
│ │ ├── convert-light-color.test.ts
│ │ ├── hex.test.ts
│ │ ├── lab.test.ts
│ │ └── rgb.test.ts
│ ├── config
│ │ ├── can_show_page.test.ts
│ │ ├── components_with_service.test.ts
│ │ ├── is_component_loaded.test.ts
│ │ ├── is_pwa.test.ts
│ │ ├── is_service_loaded.test.ts
│ │ ├── location_name.test.ts
│ │ └── version.test.ts
│ ├── datetime
│ │ ├── absolute_time.test.ts
│ │ ├── calc_date.test.ts
│ │ ├── check_valid_date.test.ts
│ │ ├── create_duration_data.test.ts
│ │ ├── duration_to_seconds.test.ts
│ │ ├── first_weekday.test.ts
│ │ ├── format_date.test.ts
│ │ ├── format_date_time.test.ts
│ │ ├── format_duration.test.ts
│ │ ├── format_time.test.ts
│ │ ├── localize_date.test.ts
│ │ ├── milliseconds_to_duration.test.ts
│ │ ├── relative_time.test.ts
│ │ ├── resolve-time-zone.test.ts
│ │ ├── seconds_to_duration.test.ts
│ │ ├── shift_date_range.test.ts
│ │ └── use_am_pm.test.ts
│ ├── entity
│ │ ├── attribute_class_names.test.ts
│ │ ├── battery_icon.test.ts
│ │ ├── can_toggle_domain.test.ts
│ │ ├── can_toggle_state.test.ts
│ │ ├── color
│ │ │ └── battery_color.test.ts
│ │ ├── compute_area_name.test.ts
│ │ ├── compute_attribute_display.test.ts
│ │ ├── compute_device_name.test.ts
│ │ ├── compute_domain.test.ts
│ │ ├── compute_entity_name.test.ts
│ │ ├── compute_floor_name.test.ts
│ │ ├── compute_state_display.test.ts
│ │ ├── compute_state_domain.test.ts
│ │ ├── compute_state_name.test.ts
│ │ ├── context
│ │ │ ├── context-mock.ts
│ │ │ ├── get_area_context.test.ts
│ │ │ ├── get_device_context.test.ts
│ │ │ └── get_entity_context.test.ts
│ │ ├── cover_icon.test.ts
│ │ ├── delete_entity.test.ts
│ │ ├── entity_domain_filter.test.ts
│ │ ├── extract_views.test.ts
│ │ ├── feature_class_names.test.ts
│ │ ├── get_group_entities.test.ts
│ │ ├── get_view_entities.test.ts
│ │ ├── has_location.test.ts
│ │ ├── split_by_groups.test.ts
│ │ ├── state_card_type.test.ts
│ │ ├── state_color.ts
│ │ ├── state_more_info_type.test.ts
│ │ ├── test_util.ts
│ │ └── timer_time_remaining.test.ts
│ ├── string
│ │ ├── format_number.test.ts
│ │ ├── get_duplicate.test.ts
│ │ ├── is_date.test.ts
│ │ ├── sequence_matching.test.ts
│ │ └── slugify.test.ts
│ └── util
│ │ └── parse_aspect_ratio.test.ts
├── data
│ ├── energy.test.ts
│ └── image_upload.test.ts
├── external_app
│ ├── external_app_entrypoint.test.ts
│ └── external_messaging.test.ts
├── hassio
│ └── create_session.test.ts
├── panels
│ └── lovelace
│ │ └── editor
│ │ └── config-util.test.ts
├── setup.ts
├── test_helper
│ ├── local-storage-fallback.test.ts
│ └── local-storage-fallback.ts
├── util
│ ├── cache-manager.test.ts
│ ├── calculate.test.ts
│ ├── generate-brands-url.test.ts
│ ├── generate-documentation-url.test.ts
│ └── ha-pref-storage.test.ts
└── vitest.config.ts
├── tsconfig.json
└── yarn.lock
/.devcontainer/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM mcr.microsoft.com/devcontainers/python:1-3.13
2 |
3 | ENV \
4 | DEBIAN_FRONTEND=noninteractive \
5 | DEVCONTAINER=true \
6 | PATH=$PATH:./node_modules/.bin
7 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Ensure Docker script files uses LF to support Docker for Windows.
2 | # Ensure "git config --global core.autocrlf input" before you clone
3 | * text eol=lf
4 | *.ts whitespace=error
5 | *.js whitespace=error
6 |
7 | *.ico binary
8 | *.jpg binary
9 | *.png binary
10 | *.zip binary
11 | *.mp3 binary
12 |
13 | demo/public/api/camera_proxy_stream/* binary
14 | demo/public/api/media_player_proxy/* binary
15 |
--------------------------------------------------------------------------------
/.github/dependabot.yml:
--------------------------------------------------------------------------------
1 | version: 2
2 | updates:
3 | - package-ecosystem: "github-actions"
4 | directory: "/"
5 | schedule:
6 | interval: weekly
7 | time: "06:00"
8 | open-pull-requests-limit: 10
9 | labels:
10 | - Dependencies
11 | - GitHub Actions
12 |
--------------------------------------------------------------------------------
/.github/move.yml:
--------------------------------------------------------------------------------
1 | # Configuration for move-issues - https://github.com/dessant/move-issues
2 |
3 | # Delete the command comment. Ignored when the comment also contains other content
4 | deleteCommand: true
5 | # Close the source issue after moving
6 | closeSourceIssue: true
7 | # Lock the source issue after moving
8 | lockSourceIssue: false
9 | # Set custom aliases for targets
10 | # aliases:
11 | # r: repo
12 | # or: owner/repo
13 |
14 |
--------------------------------------------------------------------------------
/.github/release-drafter.yml:
--------------------------------------------------------------------------------
1 | categories:
2 | - title: "Dependency updates"
3 | collapse-after: 3
4 | labels:
5 | - "Dependencies"
6 | template: |
7 | ## What's Changed
8 |
9 | $CHANGES
10 |
--------------------------------------------------------------------------------
/.github/workflows/labeler.yaml:
--------------------------------------------------------------------------------
1 | name: "Pull Request Labeler"
2 |
3 | on: pull_request_target
4 |
5 | jobs:
6 | triage:
7 | permissions:
8 | contents: read
9 | pull-requests: write
10 | runs-on: ubuntu-latest
11 | steps:
12 | - name: Apply labels
13 | uses: actions/labeler@v5.0.0
14 | with:
15 | sync-labels: true
16 |
--------------------------------------------------------------------------------
/.github/workflows/lock.yml:
--------------------------------------------------------------------------------
1 | name: Lock
2 |
3 | # yamllint disable-line rule:truthy
4 | on:
5 | schedule:
6 | - cron: "0 * * * *"
7 |
8 | jobs:
9 | lock:
10 | runs-on: ubuntu-latest
11 | steps:
12 | - uses: dessant/lock-threads@v5.0.1
13 | with:
14 | github-token: ${{ github.token }}
15 | process-only: "issues, prs"
16 | issue-lock-inactive-days: "30"
17 | issue-exclude-created-before: "2020-10-01T00:00:00Z"
18 | issue-lock-reason: ""
19 | pr-lock-inactive-days: "1"
20 | pr-exclude-created-before: "2020-11-01T00:00:00Z"
21 | pr-lock-reason: ""
22 |
--------------------------------------------------------------------------------
/.github/workflows/translations.yaml:
--------------------------------------------------------------------------------
1 | name: Translations
2 |
3 | on:
4 | push:
5 | branches:
6 | - dev
7 | paths:
8 | - src/translations/en.json
9 |
10 | jobs:
11 | upload:
12 | name: Upload
13 | runs-on: ubuntu-latest
14 | steps:
15 | - name: Checkout the repository
16 | uses: actions/checkout@v4.2.2
17 |
18 | - name: Upload Translations
19 | run: |
20 | export LOKALISE_TOKEN="${{ secrets.LOKALISE_TOKEN }}"
21 | ./script/translations_upload_base
22 |
--------------------------------------------------------------------------------
/.gitmodules:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/.gitmodules
--------------------------------------------------------------------------------
/.husky/pre-commit:
--------------------------------------------------------------------------------
1 | yarn run lint-staged --relative
2 |
--------------------------------------------------------------------------------
/.nvmrc:
--------------------------------------------------------------------------------
1 | lts/iron
2 |
--------------------------------------------------------------------------------
/.prettierignore:
--------------------------------------------------------------------------------
1 | CLA.md
2 | CODE_OF_CONDUCT.md
3 | LICENSE.md
4 | PULL_REQUEST_TEMPLATE.md
--------------------------------------------------------------------------------
/.vscode/extensions.json:
--------------------------------------------------------------------------------
1 | {
2 | "recommendations": [
3 | "dbaeumer.vscode-eslint",
4 | "esbenp.prettier-vscode",
5 | "runem.lit-plugin",
6 | "github.vscode-pull-request-github",
7 | "eamodio.gitlens",
8 | "vitest.explorer",
9 | "yeion7.styled-global-variables-autocomplete"
10 | ]
11 | }
12 |
--------------------------------------------------------------------------------
/.yarnrc.yml:
--------------------------------------------------------------------------------
1 | compressionLevel: mixed
2 |
3 | defaultSemverRangePrefix: ""
4 |
5 | enableGlobalCache: false
6 |
7 | nodeLinker: node-modules
8 |
9 | yarnPath: .yarn/releases/yarn-4.9.1.cjs
10 |
--------------------------------------------------------------------------------
/MANIFEST.in:
--------------------------------------------------------------------------------
1 | include README.md
2 | graft hass_frontend
3 | graft hass_frontend_es5
4 | recursive-exclude * *.py[co]
5 |
--------------------------------------------------------------------------------
/build-scripts/eslint.config.mjs:
--------------------------------------------------------------------------------
1 | // @ts-check
2 |
3 | import tseslint from "typescript-eslint";
4 | import rootConfig from "../eslint.config.mjs";
5 |
6 | export default tseslint.config(...rootConfig, {
7 | rules: {
8 | "no-console": "off",
9 | "import/no-extraneous-dependencies": "off",
10 | "import/extensions": "off",
11 | "import/no-dynamic-require": "off",
12 | "global-require": "off",
13 | "@typescript-eslint/no-require-imports": "off",
14 | "prefer-arrow-callback": "off",
15 | },
16 | });
17 |
--------------------------------------------------------------------------------
/build-scripts/gulp/index.mjs:
--------------------------------------------------------------------------------
1 | import "./app.js";
2 | import "./cast.js";
3 | import "./clean.js";
4 | import "./compress.js";
5 | import "./demo.js";
6 | import "./download-translations.js";
7 | import "./entry-html.js";
8 | import "./fetch-nightly-translations.js";
9 | import "./gallery.js";
10 | import "./gather-static.js";
11 | import "./gen-icons-json.js";
12 | import "./hassio.js";
13 | import "./landing-page.js";
14 | import "./locale-data.js";
15 | import "./rspack.js";
16 | import "./service-worker.js";
17 | import "./translations.js";
18 |
--------------------------------------------------------------------------------
/build-scripts/removedIcons.json:
--------------------------------------------------------------------------------
1 | []
2 |
--------------------------------------------------------------------------------
/cast/public/_redirects:
--------------------------------------------------------------------------------
1 | # These redirects are handled by Netlify
2 | #
3 |
4 | # Some custom cards are not prefixing the instance URL when fetching data
5 | # and can end up fetching the data from the Cast domain instead of HA.
6 | # This will make sure that some common ones are replaced with a placeholder.
7 | /api/camera_proxy/* /images/google-nest-hub.png
8 | /api/camera_proxy_stream/* /images/google-nest-hub.png
9 | /api/media_player_proxy/* /images/google-nest-hub.png
10 |
--------------------------------------------------------------------------------
/cast/public/images/arsaboo.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/cast/public/images/arsaboo.jpg
--------------------------------------------------------------------------------
/cast/public/images/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/cast/public/images/favicon.ico
--------------------------------------------------------------------------------
/cast/public/images/google-nest-hub.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/cast/public/images/google-nest-hub.png
--------------------------------------------------------------------------------
/cast/public/images/ha-cast-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/cast/public/images/ha-cast-icon.png
--------------------------------------------------------------------------------
/cast/public/images/melody.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/cast/public/images/melody.jpg
--------------------------------------------------------------------------------
/cast/public/images/nabu-loves-hass.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/cast/public/images/nabu-loves-hass.png
--------------------------------------------------------------------------------
/cast/public/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "background_color": "#FFFFFF",
3 | "description": "Show Home Assistant on your Chromecast or Google Assistant devices with a screen.",
4 | "dir": "ltr",
5 | "display": "standalone",
6 | "icons": [
7 | {
8 | "src": "/images/ha-cast-icon.png",
9 | "sizes": "512x512",
10 | "type": "image/png"
11 | }
12 | ],
13 | "lang": "en-US",
14 | "name": "Home Assistant Cast",
15 | "short_name": "HA Cast",
16 | "start_url": "/?homescreen=1",
17 | "theme_color": "#03A9F4"
18 | }
19 |
--------------------------------------------------------------------------------
/cast/public/sw-legacy.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | self.addEventListener("fetch", (event) => {
4 | event.respondWith(fetch(event.request));
5 | });
6 |
--------------------------------------------------------------------------------
/cast/public/sw-modern.js:
--------------------------------------------------------------------------------
1 | self.addEventListener("fetch", (event) => {
2 | event.respondWith(fetch(event.request));
3 | });
4 |
--------------------------------------------------------------------------------
/cast/script/build_cast:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | # Build the cast receiver
3 |
4 | # Stop on errors
5 | set -e
6 |
7 | cd "$(dirname "$0")/../.."
8 |
9 | ./node_modules/.bin/gulp build-cast
10 |
--------------------------------------------------------------------------------
/cast/script/develop_cast:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | # Develop the cast receiver
3 |
4 | # Stop on errors
5 | set -e
6 |
7 | cd "$(dirname "$0")/../.."
8 |
9 | ./node_modules/.bin/gulp develop-cast
10 |
--------------------------------------------------------------------------------
/cast/script/upload:
--------------------------------------------------------------------------------
1 | # Run it twice, second time we just delete.
2 | aws s3 sync dist s3://cast.home-assistant.io --acl public-read
3 | # Don't delete as it might break open sites that need to load code splitted things.
4 | # aws s3 sync dist s3://cast.home-assistant.io --acl public-read --delete
5 | # Todo : update JS first, HTML last.
6 |
--------------------------------------------------------------------------------
/cast/src/html/receiver.html.template:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | <% for (const entry of latestEntryJS) { %>
5 |
6 | <% } %>
7 | <%= renderTemplate("../../../src/html/_style_base.html.template") %>
8 |
13 |
14 |
--------------------------------------------------------------------------------
/cast/src/launcher/entrypoint.ts:
--------------------------------------------------------------------------------
1 | import "./layout/hc-connect";
2 |
3 | import("../../../src/resources/append-ha-style");
4 |
--------------------------------------------------------------------------------
/cast/src/receiver/cast_context.ts:
--------------------------------------------------------------------------------
1 | import { framework } from "./cast_framework";
2 |
3 | export const castContext = framework.CastReceiverContext.getInstance();
4 |
--------------------------------------------------------------------------------
/cast/src/receiver/cast_framework.ts:
--------------------------------------------------------------------------------
1 | import type { cast as ReceiverCast } from "chromecast-caf-receiver";
2 |
3 | export const framework = (cast as unknown as typeof ReceiverCast).framework;
4 |
--------------------------------------------------------------------------------
/cast/src/receiver/types.ts:
--------------------------------------------------------------------------------
1 | export interface ReceivedMessage {
2 | gj: boolean;
3 | data: T;
4 | senderId: string;
5 | type: "message";
6 | }
7 |
--------------------------------------------------------------------------------
/demo/public/_headers:
--------------------------------------------------------------------------------
1 | /*
2 | Cache-Control: public, max-age: 0, s-maxage=3600, must-revalidate
3 | Content-Security-Policy: form-action https:
4 | Referrer-Policy: no-referrer-when-downgrade
5 | X-Content-Type-Options: nosniff
6 | X-XSS-Protection: 1; mode=block
7 |
8 | /api/*
9 | Cache-Control: public, max-age: 604800, s-maxage=604800
10 |
11 | /assets/*
12 | Cache-Control: public, max-age: 604800, s-maxage=604800
13 |
14 | /frontend_es5/*
15 | Cache-Control: public, max-age: 604800, s-maxage=604800
16 |
17 | /frontend_latest/*
18 | Cache-Control: public, max-age: 604800, s-maxage=604800
19 |
--------------------------------------------------------------------------------
/demo/public/assets/arsaboo/floorplans/ecobee_blank.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/demo/public/assets/arsaboo/floorplans/ecobee_blank.png
--------------------------------------------------------------------------------
/demo/public/assets/arsaboo/floorplans/main.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/demo/public/assets/arsaboo/floorplans/main.png
--------------------------------------------------------------------------------
/demo/public/assets/arsaboo/floorplans/second.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/demo/public/assets/arsaboo/floorplans/second.png
--------------------------------------------------------------------------------
/demo/public/assets/arsaboo/icons/Harmony.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/demo/public/assets/arsaboo/icons/Harmony.png
--------------------------------------------------------------------------------
/demo/public/assets/arsaboo/icons/abode_disabled.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/demo/public/assets/arsaboo/icons/abode_disabled.png
--------------------------------------------------------------------------------
/demo/public/assets/arsaboo/icons/abode_enabled.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/demo/public/assets/arsaboo/icons/abode_enabled.png
--------------------------------------------------------------------------------
/demo/public/assets/arsaboo/icons/automation_disabled.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/demo/public/assets/arsaboo/icons/automation_disabled.png
--------------------------------------------------------------------------------
/demo/public/assets/arsaboo/icons/automation_enabled.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/demo/public/assets/arsaboo/icons/automation_enabled.png
--------------------------------------------------------------------------------
/demo/public/assets/arsaboo/icons/camera_backyard_recording.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/demo/public/assets/arsaboo/icons/camera_backyard_recording.png
--------------------------------------------------------------------------------
/demo/public/assets/arsaboo/icons/camera_backyard_streaming.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/demo/public/assets/arsaboo/icons/camera_backyard_streaming.png
--------------------------------------------------------------------------------
/demo/public/assets/arsaboo/icons/camera_driveway_recording.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/demo/public/assets/arsaboo/icons/camera_driveway_recording.png
--------------------------------------------------------------------------------
/demo/public/assets/arsaboo/icons/camera_driveway_streaming.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/demo/public/assets/arsaboo/icons/camera_driveway_streaming.png
--------------------------------------------------------------------------------
/demo/public/assets/arsaboo/icons/camera_patio_recording.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/demo/public/assets/arsaboo/icons/camera_patio_recording.png
--------------------------------------------------------------------------------
/demo/public/assets/arsaboo/icons/camera_patio_streaming.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/demo/public/assets/arsaboo/icons/camera_patio_streaming.png
--------------------------------------------------------------------------------
/demo/public/assets/arsaboo/icons/camera_porch_recording.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/demo/public/assets/arsaboo/icons/camera_porch_recording.png
--------------------------------------------------------------------------------
/demo/public/assets/arsaboo/icons/camera_porch_streaming.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/demo/public/assets/arsaboo/icons/camera_porch_streaming.png
--------------------------------------------------------------------------------
/demo/public/assets/arsaboo/icons/ecobee_blank.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/demo/public/assets/arsaboo/icons/ecobee_blank.png
--------------------------------------------------------------------------------
/demo/public/assets/arsaboo/icons/garage_door_closed.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/demo/public/assets/arsaboo/icons/garage_door_closed.png
--------------------------------------------------------------------------------
/demo/public/assets/arsaboo/icons/garage_door_open.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/demo/public/assets/arsaboo/icons/garage_door_open.png
--------------------------------------------------------------------------------
/demo/public/assets/arsaboo/icons/light_bulb_off.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/demo/public/assets/arsaboo/icons/light_bulb_off.png
--------------------------------------------------------------------------------
/demo/public/assets/arsaboo/icons/light_bulb_on.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/demo/public/assets/arsaboo/icons/light_bulb_on.png
--------------------------------------------------------------------------------
/demo/public/assets/arsaboo/icons/light_off.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/demo/public/assets/arsaboo/icons/light_off.png
--------------------------------------------------------------------------------
/demo/public/assets/arsaboo/icons/light_on.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/demo/public/assets/arsaboo/icons/light_on.png
--------------------------------------------------------------------------------
/demo/public/assets/arsaboo/icons/security_armed_red.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/demo/public/assets/arsaboo/icons/security_armed_red.png
--------------------------------------------------------------------------------
/demo/public/assets/arsaboo/icons/security_disarmed.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/demo/public/assets/arsaboo/icons/security_disarmed.png
--------------------------------------------------------------------------------
/demo/public/assets/arsaboo/icons/tv_disabled.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/demo/public/assets/arsaboo/icons/tv_disabled.png
--------------------------------------------------------------------------------
/demo/public/assets/arsaboo/icons/tv_enabled.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/demo/public/assets/arsaboo/icons/tv_enabled.png
--------------------------------------------------------------------------------
/demo/public/assets/arsaboo/icons/tv_off2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/demo/public/assets/arsaboo/icons/tv_off2.png
--------------------------------------------------------------------------------
/demo/public/assets/arsaboo/icons/tv_on2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/demo/public/assets/arsaboo/icons/tv_on2.png
--------------------------------------------------------------------------------
/demo/public/assets/arsaboo/images/arsaboo.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/demo/public/assets/arsaboo/images/arsaboo.jpg
--------------------------------------------------------------------------------
/demo/public/assets/arsaboo/images/camera.backyard.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/demo/public/assets/arsaboo/images/camera.backyard.jpg
--------------------------------------------------------------------------------
/demo/public/assets/arsaboo/images/camera.driveway.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/demo/public/assets/arsaboo/images/camera.driveway.jpg
--------------------------------------------------------------------------------
/demo/public/assets/arsaboo/images/camera.patio.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/demo/public/assets/arsaboo/images/camera.patio.jpg
--------------------------------------------------------------------------------
/demo/public/assets/arsaboo/images/camera.porch.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/demo/public/assets/arsaboo/images/camera.porch.jpg
--------------------------------------------------------------------------------
/demo/public/assets/arsaboo/images/media_player_family_room.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/demo/public/assets/arsaboo/images/media_player_family_room.jpg
--------------------------------------------------------------------------------
/demo/public/assets/arsaboo/images/melody.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/demo/public/assets/arsaboo/images/melody.jpg
--------------------------------------------------------------------------------
/demo/public/assets/jimpower/background-15.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/demo/public/assets/jimpower/background-15.jpg
--------------------------------------------------------------------------------
/demo/public/assets/jimpower/cardbackK.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/demo/public/assets/jimpower/cardbackK.png
--------------------------------------------------------------------------------
/demo/public/assets/jimpower/home/bus_10.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/demo/public/assets/jimpower/home/bus_10.jpg
--------------------------------------------------------------------------------
/demo/public/assets/jimpower/home/git.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/demo/public/assets/jimpower/home/git.png
--------------------------------------------------------------------------------
/demo/public/assets/jimpower/home/house_4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/demo/public/assets/jimpower/home/house_4.png
--------------------------------------------------------------------------------
/demo/public/assets/jimpower/home/james_10.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/demo/public/assets/jimpower/home/james_10.jpg
--------------------------------------------------------------------------------
/demo/public/assets/jimpower/home/tina_4.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/demo/public/assets/jimpower/home/tina_4.jpg
--------------------------------------------------------------------------------
/demo/public/assets/jimpower/security/air_8.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/demo/public/assets/jimpower/security/air_8.jpg
--------------------------------------------------------------------------------
/demo/public/assets/jimpower/security/alarm_3.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/demo/public/assets/jimpower/security/alarm_3.jpg
--------------------------------------------------------------------------------
/demo/public/assets/jimpower/security/door_3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/demo/public/assets/jimpower/security/door_3.png
--------------------------------------------------------------------------------
/demo/public/assets/jimpower/security/leak_2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/demo/public/assets/jimpower/security/leak_2.png
--------------------------------------------------------------------------------
/demo/public/assets/jimpower/security/motion_3.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/demo/public/assets/jimpower/security/motion_3.jpg
--------------------------------------------------------------------------------
/demo/public/assets/jimpower/security/smoke_4.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/demo/public/assets/jimpower/security/smoke_4.jpg
--------------------------------------------------------------------------------
/demo/public/assets/jimpower/security/window_2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/demo/public/assets/jimpower/security/window_2.jpg
--------------------------------------------------------------------------------
/demo/public/assets/kernehed/bella.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/demo/public/assets/kernehed/bella.jpg
--------------------------------------------------------------------------------
/demo/public/assets/kernehed/camera.entre.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/demo/public/assets/kernehed/camera.entre.jpg
--------------------------------------------------------------------------------
/demo/public/assets/kernehed/oscar.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/demo/public/assets/kernehed/oscar.jpg
--------------------------------------------------------------------------------
/demo/public/assets/sections/images/media_player_family_room.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/demo/public/assets/sections/images/media_player_family_room.jpg
--------------------------------------------------------------------------------
/demo/public/assets/teachingbirds/House_square.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/demo/public/assets/teachingbirds/House_square.jpg
--------------------------------------------------------------------------------
/demo/public/assets/teachingbirds/Stefan_square.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/demo/public/assets/teachingbirds/Stefan_square.jpg
--------------------------------------------------------------------------------
/demo/public/assets/teachingbirds/background_square.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/demo/public/assets/teachingbirds/background_square.png
--------------------------------------------------------------------------------
/demo/public/assets/teachingbirds/cleaning_square.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/demo/public/assets/teachingbirds/cleaning_square.jpg
--------------------------------------------------------------------------------
/demo/public/assets/teachingbirds/clothes_drying_square.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/demo/public/assets/teachingbirds/clothes_drying_square.jpg
--------------------------------------------------------------------------------
/demo/public/assets/teachingbirds/dryer_square.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/demo/public/assets/teachingbirds/dryer_square.jpg
--------------------------------------------------------------------------------
/demo/public/assets/teachingbirds/folded_clothes_square.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/demo/public/assets/teachingbirds/folded_clothes_square.jpg
--------------------------------------------------------------------------------
/demo/public/assets/teachingbirds/guests_square.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/demo/public/assets/teachingbirds/guests_square.jpg
--------------------------------------------------------------------------------
/demo/public/assets/teachingbirds/isa_square.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/demo/public/assets/teachingbirds/isa_square.jpg
--------------------------------------------------------------------------------
/demo/public/assets/teachingbirds/laundry_clean_2_square.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/demo/public/assets/teachingbirds/laundry_clean_2_square.jpg
--------------------------------------------------------------------------------
/demo/public/assets/teachingbirds/laundry_running_square.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/demo/public/assets/teachingbirds/laundry_running_square.jpg
--------------------------------------------------------------------------------
/demo/public/assets/teachingbirds/mailbox_bw_square.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/demo/public/assets/teachingbirds/mailbox_bw_square.jpg
--------------------------------------------------------------------------------
/demo/public/assets/teachingbirds/mailbox_square.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/demo/public/assets/teachingbirds/mailbox_square.jpg
--------------------------------------------------------------------------------
/demo/public/assets/teachingbirds/meteogram.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/demo/public/assets/teachingbirds/meteogram.png
--------------------------------------------------------------------------------
/demo/public/assets/teachingbirds/plants.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/demo/public/assets/teachingbirds/plants.png
--------------------------------------------------------------------------------
/demo/public/assets/teachingbirds/radiator_off.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/demo/public/assets/teachingbirds/radiator_off.jpg
--------------------------------------------------------------------------------
/demo/public/assets/teachingbirds/radiator_on.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/demo/public/assets/teachingbirds/radiator_on.jpg
--------------------------------------------------------------------------------
/demo/public/assets/teachingbirds/roomba_bw_square.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/demo/public/assets/teachingbirds/roomba_bw_square.jpg
--------------------------------------------------------------------------------
/demo/public/assets/teachingbirds/roomba_square.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/demo/public/assets/teachingbirds/roomba_square.jpg
--------------------------------------------------------------------------------
/demo/public/assets/teachingbirds/trash_bear_bw_square.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/demo/public/assets/teachingbirds/trash_bear_bw_square.jpg
--------------------------------------------------------------------------------
/demo/public/assets/teachingbirds/trash_square.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/demo/public/assets/teachingbirds/trash_square.jpg
--------------------------------------------------------------------------------
/demo/public/assets/teachingbirds/washer_square.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/demo/public/assets/teachingbirds/washer_square.jpg
--------------------------------------------------------------------------------
/demo/public/stub_config/bedroom.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/demo/public/stub_config/bedroom.png
--------------------------------------------------------------------------------
/demo/public/stub_config/floorplan.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/demo/public/stub_config/floorplan.png
--------------------------------------------------------------------------------
/demo/public/stub_config/kitchen.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/demo/public/stub_config/kitchen.png
--------------------------------------------------------------------------------
/demo/public/stub_config/t-shirt-promo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/demo/public/stub_config/t-shirt-promo.png
--------------------------------------------------------------------------------
/demo/public/sw-legacy.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | self.addEventListener("fetch", (event) => {
4 | event.respondWith(fetch(event.request));
5 | });
6 |
--------------------------------------------------------------------------------
/demo/public/sw-modern.js:
--------------------------------------------------------------------------------
1 | self.addEventListener("fetch", (event) => {
2 | event.respondWith(fetch(event.request));
3 | });
4 |
--------------------------------------------------------------------------------
/demo/script/build_demo:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | # Build the demo
3 |
4 | # Stop on errors
5 | set -e
6 |
7 | cd "$(dirname "$0")/../.."
8 |
9 | ./node_modules/.bin/gulp build-demo
10 |
--------------------------------------------------------------------------------
/demo/script/develop_demo:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | # Develop the demo
3 |
4 | # Stop on errors
5 | set -e
6 |
7 | cd "$(dirname "$0")/../.."
8 |
9 | ./node_modules/.bin/gulp develop-demo
10 |
--------------------------------------------------------------------------------
/demo/script/size_stats:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | # Analyze stats
3 |
4 | # Stop on errors
5 | set -e
6 |
7 | cd "$(dirname "$0")/../.."
8 |
9 | ./node_modules/.bin/gulp analyze-demo
--------------------------------------------------------------------------------
/demo/src/configs/arsaboo/index.ts:
--------------------------------------------------------------------------------
1 | import type { DemoConfig } from "../types";
2 | import { demoEntitiesArsaboo } from "./entities";
3 | import { demoLovelaceArsaboo } from "./lovelace";
4 | import { demoThemeArsaboo } from "./theme";
5 |
6 | export const demoArsaboo: DemoConfig = {
7 | authorName: "Arsaboo",
8 | authorUrl: "https://github.com/arsaboo/homeassistant-config/",
9 | name: "ARS Home",
10 | lovelace: demoLovelaceArsaboo,
11 | entities: demoEntitiesArsaboo,
12 | theme: demoThemeArsaboo,
13 | };
14 |
--------------------------------------------------------------------------------
/demo/src/configs/arsaboo/theme.ts:
--------------------------------------------------------------------------------
1 | export const demoThemeArsaboo = () => ({});
2 |
--------------------------------------------------------------------------------
/demo/src/configs/jimpower/index.ts:
--------------------------------------------------------------------------------
1 | import type { DemoConfig } from "../types";
2 | import { demoEntitiesJimpower } from "./entities";
3 | import { demoLovelaceJimpower } from "./lovelace";
4 | import { demoThemeJimpower } from "./theme";
5 |
6 | export const demoJimpower: DemoConfig = {
7 | authorName: "Jimpower",
8 | authorUrl: "https://github.com/JamesMcCarthy79/Home-Assistant-Config",
9 | name: "Kingia Castle",
10 | lovelace: demoLovelaceJimpower,
11 | entities: demoEntitiesJimpower,
12 | theme: demoThemeJimpower,
13 | };
14 |
--------------------------------------------------------------------------------
/demo/src/configs/kernehed/index.ts:
--------------------------------------------------------------------------------
1 | import type { DemoConfig } from "../types";
2 | import { demoEntitiesKernehed } from "./entities";
3 | import { demoLovelaceKernehed } from "./lovelace";
4 | import { demoThemeKernehed } from "./theme";
5 |
6 | export const demoKernehed: DemoConfig = {
7 | authorName: "Kernehed",
8 | authorUrl: "https://github.com/kernehed",
9 | name: "Hem",
10 | lovelace: demoLovelaceKernehed,
11 | entities: demoEntitiesKernehed,
12 | theme: demoThemeKernehed,
13 | };
14 |
--------------------------------------------------------------------------------
/demo/src/configs/sections/index.ts:
--------------------------------------------------------------------------------
1 | import type { DemoConfig } from "../types";
2 | import { demoEntitiesSections } from "./entities";
3 | import { demoLovelaceSections } from "./lovelace";
4 |
5 | export const demoSections: DemoConfig = {
6 | authorName: "Home Assistant",
7 | authorUrl: "https://github.com/home-assistant/frontend/",
8 | name: "Home Demo",
9 | lovelace: demoLovelaceSections,
10 | entities: demoEntitiesSections,
11 | theme: () => ({}),
12 | };
13 |
--------------------------------------------------------------------------------
/demo/src/configs/teachingbirds/index.ts:
--------------------------------------------------------------------------------
1 | import type { DemoConfig } from "../types";
2 | import { demoEntitiesTeachingbirds } from "./entities";
3 | import { demoLovelaceTeachingbirds } from "./lovelace";
4 | import { demoThemeTeachingbirds } from "./theme";
5 |
6 | export const demoTeachingbirds: DemoConfig = {
7 | authorName: "Isabella Gross Alström",
8 | authorUrl: "https://github.com/isabellaalstrom/",
9 | name: "Isa's mobile friendly LL",
10 | lovelace: demoLovelaceTeachingbirds,
11 | entities: demoEntitiesTeachingbirds,
12 | theme: demoThemeTeachingbirds,
13 | };
14 |
--------------------------------------------------------------------------------
/demo/src/entrypoint.ts:
--------------------------------------------------------------------------------
1 | import "./util/is_frontpage";
2 | import "./ha-demo";
3 |
4 | import("../../src/resources/append-ha-style");
5 |
--------------------------------------------------------------------------------
/demo/src/stubs/area_registry.ts:
--------------------------------------------------------------------------------
1 | import type { AreaRegistryEntry } from "../../../src/data/area_registry";
2 | import type { MockHomeAssistant } from "../../../src/fake_data/provide_hass";
3 |
4 | export const mockAreaRegistry = (
5 | hass: MockHomeAssistant,
6 | data: AreaRegistryEntry[] = []
7 | ) => {
8 | hass.mockWS("config/area_registry/list", () => data);
9 | const areas = {};
10 | data.forEach((area) => {
11 | areas[area.area_id] = area;
12 | });
13 | hass.updateHass({ areas });
14 | };
15 |
--------------------------------------------------------------------------------
/demo/src/stubs/auth.ts:
--------------------------------------------------------------------------------
1 | import type { MockHomeAssistant } from "../../../src/fake_data/provide_hass";
2 |
3 | export const mockAuth = (hass: MockHomeAssistant) => {
4 | hass.mockWS("config/auth/list", () => []);
5 | hass.mockWS("auth/refresh_tokens", () => []);
6 | };
7 |
--------------------------------------------------------------------------------
/demo/src/stubs/config.ts:
--------------------------------------------------------------------------------
1 | import type { validateConfig } from "../../../src/data/config";
2 | import type { MockHomeAssistant } from "../../../src/fake_data/provide_hass";
3 |
4 | export const mockConfig = (hass: MockHomeAssistant) => {
5 | hass.mockWS("validate_config", () => ({
6 | actions: { valid: true, error: null },
7 | conditions: { valid: true, error: null },
8 | triggers: { valid: true, error: null },
9 | }));
10 | };
11 |
--------------------------------------------------------------------------------
/demo/src/stubs/device_registry.ts:
--------------------------------------------------------------------------------
1 | import type { DeviceRegistryEntry } from "../../../src/data/device_registry";
2 | import type { MockHomeAssistant } from "../../../src/fake_data/provide_hass";
3 |
4 | export const mockDeviceRegistry = (
5 | hass: MockHomeAssistant,
6 | data: DeviceRegistryEntry[] = []
7 | ) => {
8 | hass.mockWS("config/device_registry/list", () => data);
9 | const devices = {};
10 | data.forEach((device) => {
11 | devices[device.id] = device;
12 | });
13 | hass.updateHass({ devices });
14 | };
15 |
--------------------------------------------------------------------------------
/demo/src/stubs/entity_registry.ts:
--------------------------------------------------------------------------------
1 | import type { EntityRegistryEntry } from "../../../src/data/entity_registry";
2 | import type { MockHomeAssistant } from "../../../src/fake_data/provide_hass";
3 |
4 | export const mockEntityRegistry = (
5 | hass: MockHomeAssistant,
6 | data: EntityRegistryEntry[] = []
7 | ) => {
8 | hass.mockWS("config/entity_registry/list", () => data);
9 | };
10 |
--------------------------------------------------------------------------------
/demo/src/stubs/events.ts:
--------------------------------------------------------------------------------
1 | import type { MockHomeAssistant } from "../../../src/fake_data/provide_hass";
2 |
3 | export const mockEvents = (hass: MockHomeAssistant) => {
4 | hass.mockAPI("events", () => []);
5 | };
6 |
--------------------------------------------------------------------------------
/demo/src/stubs/floor_registry.ts:
--------------------------------------------------------------------------------
1 | import type { FloorRegistryEntry } from "../../../src/data/floor_registry";
2 | import type { MockHomeAssistant } from "../../../src/fake_data/provide_hass";
3 |
4 | export const mockFloorRegistry = (
5 | hass: MockHomeAssistant,
6 | data: FloorRegistryEntry[] = []
7 | ) => hass.mockWS("config/floor_registry/list", () => data);
8 |
--------------------------------------------------------------------------------
/demo/src/stubs/label_registry.ts:
--------------------------------------------------------------------------------
1 | import type { LabelRegistryEntry } from "../../../src/data/label_registry";
2 | import type { MockHomeAssistant } from "../../../src/fake_data/provide_hass";
3 |
4 | export const mockLabelRegistry = (
5 | hass: MockHomeAssistant,
6 | data: LabelRegistryEntry[] = []
7 | ) => hass.mockWS("config/label_registry/list", () => data);
8 |
--------------------------------------------------------------------------------
/demo/src/stubs/media_player.ts:
--------------------------------------------------------------------------------
1 | import type { MockHomeAssistant } from "../../../src/fake_data/provide_hass";
2 |
3 | export const mockMediaPlayer = (hass: MockHomeAssistant) => {
4 | hass.mockWS("media_player_thumbnail", () => Promise.reject());
5 | };
6 |
--------------------------------------------------------------------------------
/demo/src/stubs/system_log.ts:
--------------------------------------------------------------------------------
1 | import type { MockHomeAssistant } from "../../../src/fake_data/provide_hass";
2 |
3 | export const mockSystemLog = (hass: MockHomeAssistant) => {
4 | hass.mockAPI("error/all", () => []);
5 | };
6 |
--------------------------------------------------------------------------------
/demo/src/stubs/tags.ts:
--------------------------------------------------------------------------------
1 | import type { Tag } from "../../../src/data/tag";
2 | import type { MockHomeAssistant } from "../../../src/fake_data/provide_hass";
3 |
4 | export const mockTags = (hass: MockHomeAssistant) => {
5 | hass.mockWS("tag/list", () => [{ id: "my-tag", name: "My Tag" }] as Tag[]);
6 | };
7 |
--------------------------------------------------------------------------------
/demo/src/stubs/template.ts:
--------------------------------------------------------------------------------
1 | import type { MockHomeAssistant } from "../../../src/fake_data/provide_hass";
2 |
3 | export const mockTemplate = (hass: MockHomeAssistant) => {
4 | hass.mockAPI("template", () =>
5 | Promise.reject({
6 | body: { message: "Template dev tool does not work in the demo." },
7 | })
8 | );
9 | hass.mockWS("render_template", (msg, _hass, onChange) => {
10 | onChange!({
11 | result: msg.template,
12 | listeners: { all: false, domains: [], entities: [], time: false },
13 | });
14 | // eslint-disable-next-line @typescript-eslint/no-empty-function
15 | return () => {};
16 | });
17 | };
18 |
--------------------------------------------------------------------------------
/demo/src/stubs/translations.ts:
--------------------------------------------------------------------------------
1 | import type { MockHomeAssistant } from "../../../src/fake_data/provide_hass";
2 |
3 | export const mockTranslations = (hass: MockHomeAssistant) => {
4 | hass.mockWS(
5 | "frontend/get_translations",
6 | (/* msg: {language: string, category: string} */) => ({ resources: {} })
7 | );
8 | };
9 |
--------------------------------------------------------------------------------
/demo/src/util/is_frontpage.ts:
--------------------------------------------------------------------------------
1 | export const isFrontpageEmbed = document.location.search === "?frontpage";
2 |
--------------------------------------------------------------------------------
/docs/screenshot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/docs/screenshot.png
--------------------------------------------------------------------------------
/gallery/eslint.config.mjs:
--------------------------------------------------------------------------------
1 | // @ts-check
2 |
3 | import tseslint from "typescript-eslint";
4 | import rootConfig from "../eslint.config.mjs";
5 |
6 | export default tseslint.config(...rootConfig, {
7 | rules: {
8 | "no-console": "off",
9 | },
10 | });
11 |
--------------------------------------------------------------------------------
/gallery/public/api/hassio/addons/core_zwave_js/icon:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/gallery/public/api/hassio/addons/core_zwave_js/icon
--------------------------------------------------------------------------------
/gallery/public/api/media_player_proxy/media_player.bedroom:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/gallery/public/api/media_player_proxy/media_player.bedroom
--------------------------------------------------------------------------------
/gallery/public/api/media_player_proxy/media_player.living_room:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/gallery/public/api/media_player_proxy/media_player.living_room
--------------------------------------------------------------------------------
/gallery/public/api/media_player_proxy/media_player.walkman:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/gallery/public/api/media_player_proxy/media_player.walkman
--------------------------------------------------------------------------------
/gallery/public/images/album_cover.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/gallery/public/images/album_cover.jpg
--------------------------------------------------------------------------------
/gallery/public/images/album_cover_2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/gallery/public/images/album_cover_2.jpg
--------------------------------------------------------------------------------
/gallery/public/images/bed.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/gallery/public/images/bed.png
--------------------------------------------------------------------------------
/gallery/public/images/brand/README.md:
--------------------------------------------------------------------------------
1 | # Note!
2 |
3 | Note, the assets in this folder, are not part of the CC license this repository is shipped in.
4 | All rights reserved.
5 |
--------------------------------------------------------------------------------
/gallery/public/images/brand/logo-exclusion-zone.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/gallery/public/images/brand/logo-exclusion-zone.png
--------------------------------------------------------------------------------
/gallery/public/images/brand/logo-layout-variants.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/gallery/public/images/brand/logo-layout-variants.png
--------------------------------------------------------------------------------
/gallery/public/images/brand/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/gallery/public/images/brand/logo.png
--------------------------------------------------------------------------------
/gallery/public/images/clearspace.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/gallery/public/images/clearspace.png
--------------------------------------------------------------------------------
/gallery/public/images/divider.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/gallery/public/images/divider.png
--------------------------------------------------------------------------------
/gallery/public/images/floorplan.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/gallery/public/images/floorplan.png
--------------------------------------------------------------------------------
/gallery/public/images/frenck.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/gallery/public/images/frenck.jpg
--------------------------------------------------------------------------------
/gallery/public/images/kitchen.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/gallery/public/images/kitchen.png
--------------------------------------------------------------------------------
/gallery/public/images/light_bulb_off.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/gallery/public/images/light_bulb_off.png
--------------------------------------------------------------------------------
/gallery/public/images/light_bulb_on.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/gallery/public/images/light_bulb_on.png
--------------------------------------------------------------------------------
/gallery/public/images/living_room.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/gallery/public/images/living_room.png
--------------------------------------------------------------------------------
/gallery/public/images/logo-variants.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/gallery/public/images/logo-variants.png
--------------------------------------------------------------------------------
/gallery/public/images/logo-with-text.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/gallery/public/images/logo-with-text.png
--------------------------------------------------------------------------------
/gallery/public/images/netflix.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/gallery/public/images/netflix.jpg
--------------------------------------------------------------------------------
/gallery/public/images/office.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/gallery/public/images/office.jpg
--------------------------------------------------------------------------------
/gallery/public/images/paulus.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/gallery/public/images/paulus.jpg
--------------------------------------------------------------------------------
/gallery/public/images/sunflowers.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/gallery/public/images/sunflowers.jpg
--------------------------------------------------------------------------------
/gallery/script/build_gallery:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | # Run the gallery
3 |
4 | # Stop on errors
5 | set -e
6 |
7 | cd "$(dirname "$0")/../.."
8 |
9 | ./node_modules/.bin/gulp build-gallery
10 |
--------------------------------------------------------------------------------
/gallery/script/develop_gallery:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | # Run the gallery
3 |
4 | # Stop on errors
5 | set -e
6 |
7 | cd "$(dirname "$0")/../.."
8 |
9 | ./node_modules/.bin/gulp develop-gallery
10 |
--------------------------------------------------------------------------------
/gallery/src/data/date-options.ts:
--------------------------------------------------------------------------------
1 | import type { ControlSelectOption } from "../../../src/components/ha-control-select";
2 |
3 | export const timeOptions: ControlSelectOption[] = [
4 | {
5 | value: "now",
6 | label: "Now",
7 | },
8 | {
9 | value: "00:15:30",
10 | label: "12:15:30 AM",
11 | },
12 | {
13 | value: "06:15:30",
14 | label: "06:15:30 AM",
15 | },
16 | {
17 | value: "12:15:30",
18 | label: "12:15:30 PM",
19 | },
20 | {
21 | value: "18:15:30",
22 | label: "06:15:30 PM",
23 | },
24 | ];
25 |
--------------------------------------------------------------------------------
/gallery/src/data/traces/types.ts:
--------------------------------------------------------------------------------
1 | import type { AutomationTraceExtended } from "../../../../src/data/trace";
2 | import type { LogbookEntry } from "../../../../src/data/logbook";
3 |
4 | export interface DemoTrace {
5 | trace: AutomationTraceExtended;
6 | logbookEntries: LogbookEntry[];
7 | }
8 |
--------------------------------------------------------------------------------
/gallery/src/entrypoint.js:
--------------------------------------------------------------------------------
1 | import "./ha-gallery";
2 |
3 | import("../../src/resources/append-ha-style");
4 |
5 | document.body.appendChild(document.createElement("ha-gallery"));
6 |
--------------------------------------------------------------------------------
/gallery/src/pages/automation/describe-action.markdown:
--------------------------------------------------------------------------------
1 | ---
2 | title: Describe Action
3 | ---
4 |
--------------------------------------------------------------------------------
/gallery/src/pages/automation/describe-condition.markdown:
--------------------------------------------------------------------------------
1 | ---
2 | title: Describe Condition
3 | ---
4 |
--------------------------------------------------------------------------------
/gallery/src/pages/automation/describe-trigger.markdown:
--------------------------------------------------------------------------------
1 | ---
2 | title: Describe Trigger
3 | ---
4 |
--------------------------------------------------------------------------------
/gallery/src/pages/automation/editor-action.markdown:
--------------------------------------------------------------------------------
1 | ---
2 | title: Actions
3 | ---
4 |
--------------------------------------------------------------------------------
/gallery/src/pages/automation/editor-condition.markdown:
--------------------------------------------------------------------------------
1 | ---
2 | title: Conditions
3 | ---
4 |
--------------------------------------------------------------------------------
/gallery/src/pages/automation/editor-trigger.markdown:
--------------------------------------------------------------------------------
1 | ---
2 | title: Triggers
3 | ---
4 |
--------------------------------------------------------------------------------
/gallery/src/pages/automation/trace-timeline.markdown:
--------------------------------------------------------------------------------
1 | ---
2 | title: Trace Timelines
3 | ---
4 |
--------------------------------------------------------------------------------
/gallery/src/pages/automation/trace.markdown:
--------------------------------------------------------------------------------
1 | ---
2 | title: Trace Graphs
3 | ---
4 |
--------------------------------------------------------------------------------
/gallery/src/pages/components/ha-bar.markdown:
--------------------------------------------------------------------------------
1 | ---
2 | title: Bar
3 | subtitle: Can be used to communicate progress of a task.
4 | ---
5 |
--------------------------------------------------------------------------------
/gallery/src/pages/components/ha-chips.markdown:
--------------------------------------------------------------------------------
1 | ---
2 | title: Chip
3 | ---
4 |
--------------------------------------------------------------------------------
/gallery/src/pages/components/ha-control-button.markdown:
--------------------------------------------------------------------------------
1 | ---
2 | title: Control Button
3 | ---
4 |
--------------------------------------------------------------------------------
/gallery/src/pages/components/ha-control-circular-slider.markdown:
--------------------------------------------------------------------------------
1 | ---
2 | title: Control Circular Slider
3 | ---
4 |
--------------------------------------------------------------------------------
/gallery/src/pages/components/ha-control-number-buttons.markdown:
--------------------------------------------------------------------------------
1 | ---
2 | title: Control Number Buttons
3 | ---
4 |
--------------------------------------------------------------------------------
/gallery/src/pages/components/ha-control-select-menu.markdown:
--------------------------------------------------------------------------------
1 | ---
2 | title: Control Select Menu
3 | ---
4 |
--------------------------------------------------------------------------------
/gallery/src/pages/components/ha-control-select.markdown:
--------------------------------------------------------------------------------
1 | ---
2 | title: Control Select
3 | ---
4 |
--------------------------------------------------------------------------------
/gallery/src/pages/components/ha-control-slider.markdown:
--------------------------------------------------------------------------------
1 | ---
2 | title: Control Slider
3 | ---
4 |
--------------------------------------------------------------------------------
/gallery/src/pages/components/ha-control-switch.markdown:
--------------------------------------------------------------------------------
1 | ---
2 | title: Control Switch
3 | ---
4 |
--------------------------------------------------------------------------------
/gallery/src/pages/components/ha-expansion-panel.markdown:
--------------------------------------------------------------------------------
1 | ---
2 | title: Expansion Panel
3 | ---
4 |
5 | Expansion panel following all the ARIA guidelines.
6 |
--------------------------------------------------------------------------------
/gallery/src/pages/components/ha-faded.markdown:
--------------------------------------------------------------------------------
1 | ---
2 | title: Faded Content
3 | ---
4 |
--------------------------------------------------------------------------------
/gallery/src/pages/components/ha-form.markdown:
--------------------------------------------------------------------------------
1 | ---
2 | title: Forms
3 | ---
4 |
--------------------------------------------------------------------------------
/gallery/src/pages/components/ha-gauge.ts:
--------------------------------------------------------------------------------
1 | import "../../../../src/components/ha-gauge";
2 |
--------------------------------------------------------------------------------
/gallery/src/pages/components/ha-hs-color-picker.markdown:
--------------------------------------------------------------------------------
1 | ---
2 | title: HS Color Picker
3 | ---
4 |
--------------------------------------------------------------------------------
/gallery/src/pages/components/ha-label-badge.markdown:
--------------------------------------------------------------------------------
1 | ---
2 | title: Label Badge
3 | ---
4 |
--------------------------------------------------------------------------------
/gallery/src/pages/components/ha-select-box.markdown:
--------------------------------------------------------------------------------
1 | ---
2 | title: Select box
3 | ---
4 |
--------------------------------------------------------------------------------
/gallery/src/pages/components/ha-selector.markdown:
--------------------------------------------------------------------------------
1 | ---
2 | title: Selector
3 | ---
4 |
5 | See the website for [list of available selectors](https://www.home-assistant.io/docs/blueprint/selectors/).
6 |
--------------------------------------------------------------------------------
/gallery/src/pages/components/ha-spinner.markdown:
--------------------------------------------------------------------------------
1 | ---
2 | title: Spinner
3 | subtitle: Can be used to indicate an ongoing task.
4 | ---
5 |
--------------------------------------------------------------------------------
/gallery/src/pages/components/ha-switch.ts:
--------------------------------------------------------------------------------
1 | import "../../../../src/components/ha-switch";
2 |
--------------------------------------------------------------------------------
/gallery/src/pages/components/ha-tip.markdown:
--------------------------------------------------------------------------------
1 | ---
2 | title: Tip
3 | ---
4 |
--------------------------------------------------------------------------------
/gallery/src/pages/components/ha-tooltip.ts:
--------------------------------------------------------------------------------
1 | import "../../../../src/components/ha-tooltip";
2 | import "../../../../src/components/ha-button";
3 |
--------------------------------------------------------------------------------
/gallery/src/pages/date-time/date-time-numeric.markdown:
--------------------------------------------------------------------------------
1 | ---
2 | title: Date-Time Format (Numeric)
3 | ---
4 |
5 | This pages lists all supported languages with their available date-time formats.
6 |
7 | Formatting function: `const formatDateTimeNumeric: (dateObj: Date, locale: FrontendLocaleData) => string`
8 |
--------------------------------------------------------------------------------
/gallery/src/pages/date-time/date-time-seconds.markdown:
--------------------------------------------------------------------------------
1 | ---
2 | title: Date-Time Format (Seconds)
3 | ---
4 |
5 | This pages lists all supported languages with their available date-time formats.
6 |
7 | Formatting function: `const formatDateTimeWithSeconds: (dateObj: Date, locale: FrontendLocaleData) => string`
8 |
--------------------------------------------------------------------------------
/gallery/src/pages/date-time/date-time-short-year.markdown:
--------------------------------------------------------------------------------
1 | ---
2 | title: Date-Time Format (Short w/ Year)
3 | ---
4 |
5 | This pages lists all supported languages with their available date-time formats.
6 |
7 | Formatting function: `const formatShortDateTimeWithYear: (dateObj: Date, locale: FrontendLocaleData) => string`
8 |
--------------------------------------------------------------------------------
/gallery/src/pages/date-time/date-time-short.markdown:
--------------------------------------------------------------------------------
1 | ---
2 | title: Date-Time Format (Short)
3 | ---
4 |
5 | This pages lists all supported languages with their available date-time formats.
6 |
7 | Formatting function: `const formatShortDateTime: (dateObj: Date, locale: FrontendLocaleData) => string`
8 |
--------------------------------------------------------------------------------
/gallery/src/pages/date-time/date-time.markdown:
--------------------------------------------------------------------------------
1 | ---
2 | title: Date-Time Format
3 | ---
4 |
5 | This pages lists all supported languages with their available date-time formats.
6 |
7 | Formatting function: `const formatDateTime: (dateObj: Date, locale: FrontendLocaleData) => string`
8 |
--------------------------------------------------------------------------------
/gallery/src/pages/date-time/date.markdown:
--------------------------------------------------------------------------------
1 | ---
2 | title: Date Format (Numeric)
3 | ---
4 |
5 | This pages lists all supported languages with their available (numeric) date formats.
6 |
7 | Formatting function: `const formatDateNumeric: (dateObj: Date, locale: FrontendLocaleData) => string`
8 |
--------------------------------------------------------------------------------
/gallery/src/pages/date-time/time-seconds.markdown:
--------------------------------------------------------------------------------
1 | ---
2 | title: Time Format (Seconds)
3 | ---
4 |
5 | This pages lists all supported languages with their available time formats.
6 |
7 | Formatting function: `const formatTimeWithSeconds: (dateObj: Date, locale: FrontendLocaleData) => string`
8 |
--------------------------------------------------------------------------------
/gallery/src/pages/date-time/time-weekday.markdown:
--------------------------------------------------------------------------------
1 | ---
2 | title: Time Format (Weekday)
3 | ---
4 |
5 | This pages lists all supported languages with their available time formats.
6 |
7 | Formatting function: `const formatTimeWeekday: (dateObj: Date, locale: FrontendLocaleData) => string`
8 |
--------------------------------------------------------------------------------
/gallery/src/pages/date-time/time.markdown:
--------------------------------------------------------------------------------
1 | ---
2 | title: Time Format
3 | ---
4 |
5 | This pages lists all supported languages with their available time formats.
6 |
7 | Formatting function: `const formatTime: (dateObj: Date, locale: FrontendLocaleData) => string`
8 |
--------------------------------------------------------------------------------
/gallery/src/pages/lovelace/alarm-panel-card.markdown:
--------------------------------------------------------------------------------
1 | ---
2 | title: Alarm Panel Card
3 | ---
4 |
--------------------------------------------------------------------------------
/gallery/src/pages/lovelace/area-card.markdown:
--------------------------------------------------------------------------------
1 | ---
2 | title: Area Card
3 | ---
4 |
--------------------------------------------------------------------------------
/gallery/src/pages/lovelace/conditional-card.markdown:
--------------------------------------------------------------------------------
1 | ---
2 | title: Conditional Card
3 | ---
4 |
--------------------------------------------------------------------------------
/gallery/src/pages/lovelace/entities-card.markdown:
--------------------------------------------------------------------------------
1 | ---
2 | title: Entities Card
3 | ---
4 |
--------------------------------------------------------------------------------
/gallery/src/pages/lovelace/entity-button-card.markdown:
--------------------------------------------------------------------------------
1 | ---
2 | title: Entity Button Card
3 | ---
4 |
--------------------------------------------------------------------------------
/gallery/src/pages/lovelace/entity-filter-card.markdown:
--------------------------------------------------------------------------------
1 | ---
2 | title: Entity Filter Card
3 | ---
4 |
--------------------------------------------------------------------------------
/gallery/src/pages/lovelace/gauge-card.markdown:
--------------------------------------------------------------------------------
1 | ---
2 | title: Gauge Card
3 | ---
4 |
--------------------------------------------------------------------------------
/gallery/src/pages/lovelace/glance-card.markdown:
--------------------------------------------------------------------------------
1 | ---
2 | title: Glance Card
3 | ---
4 |
--------------------------------------------------------------------------------
/gallery/src/pages/lovelace/grid-and-stack-card.markdown:
--------------------------------------------------------------------------------
1 | ---
2 | title: Grid and Stack Card
3 | ---
4 |
--------------------------------------------------------------------------------
/gallery/src/pages/lovelace/iframe-card.markdown:
--------------------------------------------------------------------------------
1 | ---
2 | title: Website Card
3 | ---
4 |
--------------------------------------------------------------------------------
/gallery/src/pages/lovelace/introduction.markdown:
--------------------------------------------------------------------------------
1 | ---
2 | title: Introduction
3 | ---
4 |
5 | Dashboards have many different cards. Each card allows the user to tell
6 | a different story about what is going on in their house. These cards
7 | are very customizable, as no household is the same.
8 |
9 | This gallery helps our developers and designers to see all the
10 | different states that each card can be in.
11 |
12 | Check [the Dashboards documentation](https://www.home-assistant.io/dashboards/) for instructions on how to get started with Dashboards.
13 |
--------------------------------------------------------------------------------
/gallery/src/pages/lovelace/light-card.markdown:
--------------------------------------------------------------------------------
1 | ---
2 | title: Light Card
3 | ---
4 |
--------------------------------------------------------------------------------
/gallery/src/pages/lovelace/map-card.markdown:
--------------------------------------------------------------------------------
1 | ---
2 | title: Map Card
3 | ---
4 |
--------------------------------------------------------------------------------
/gallery/src/pages/lovelace/markdown-card.markdown:
--------------------------------------------------------------------------------
1 | ---
2 | title: Markdown Card
3 | ---
4 |
--------------------------------------------------------------------------------
/gallery/src/pages/lovelace/media-control-card.markdown:
--------------------------------------------------------------------------------
1 | ---
2 | title: Media Control Card
3 | ---
4 |
--------------------------------------------------------------------------------
/gallery/src/pages/lovelace/media-player-row.markdown:
--------------------------------------------------------------------------------
1 | ---
2 | title: Media Player Row
3 | ---
4 |
--------------------------------------------------------------------------------
/gallery/src/pages/lovelace/picture-card.markdown:
--------------------------------------------------------------------------------
1 | ---
2 | title: Picture Card
3 | ---
4 |
--------------------------------------------------------------------------------
/gallery/src/pages/lovelace/picture-elements-card.markdown:
--------------------------------------------------------------------------------
1 | ---
2 | title: Picture Elements Card
3 | ---
4 |
--------------------------------------------------------------------------------
/gallery/src/pages/lovelace/picture-entity-card.markdown:
--------------------------------------------------------------------------------
1 | ---
2 | title: Picture Entity Card
3 | ---
4 |
--------------------------------------------------------------------------------
/gallery/src/pages/lovelace/picture-glance-card.markdown:
--------------------------------------------------------------------------------
1 | ---
2 | title: Picture Glance Card
3 | ---
4 |
--------------------------------------------------------------------------------
/gallery/src/pages/lovelace/plant-card.markdown:
--------------------------------------------------------------------------------
1 | ---
2 | title: Plant Card
3 | ---
4 |
--------------------------------------------------------------------------------
/gallery/src/pages/lovelace/thermostat-card.markdown:
--------------------------------------------------------------------------------
1 | ---
2 | title: Thermostat Card
3 | ---
4 |
--------------------------------------------------------------------------------
/gallery/src/pages/lovelace/tile-card.markdown:
--------------------------------------------------------------------------------
1 | ---
2 | title: Tile Card
3 | ---
4 |
--------------------------------------------------------------------------------
/gallery/src/pages/lovelace/todo-list-card.markdown:
--------------------------------------------------------------------------------
1 | ---
2 | title: Todo List Card
3 | ---
4 |
--------------------------------------------------------------------------------
/gallery/src/pages/misc/entity-state.markdown:
--------------------------------------------------------------------------------
1 | ---
2 | title: Entity State
3 | ---
4 |
--------------------------------------------------------------------------------
/gallery/src/pages/misc/ha-markdown.markdown:
--------------------------------------------------------------------------------
1 | ---
2 | title: Markdown
3 | ---
4 |
--------------------------------------------------------------------------------
/gallery/src/pages/misc/integration-card.markdown:
--------------------------------------------------------------------------------
1 | ---
2 | title: Integration Card
3 | ---
4 |
--------------------------------------------------------------------------------
/gallery/src/pages/misc/util-long-press.markdown:
--------------------------------------------------------------------------------
1 | ---
2 | title: Long Press Utility
3 | ---
4 |
--------------------------------------------------------------------------------
/gallery/src/pages/more-info/climate.markdown:
--------------------------------------------------------------------------------
1 | ---
2 | title: Climate
3 | ---
4 |
--------------------------------------------------------------------------------
/gallery/src/pages/more-info/cover.markdown:
--------------------------------------------------------------------------------
1 | ---
2 | title: Cover
3 | ---
4 |
--------------------------------------------------------------------------------
/gallery/src/pages/more-info/humidifier.markdown:
--------------------------------------------------------------------------------
1 | ---
2 | title: Humidifier
3 | ---
4 |
--------------------------------------------------------------------------------
/gallery/src/pages/more-info/input-number.markdown:
--------------------------------------------------------------------------------
1 | ---
2 | title: Input Number
3 | ---
4 |
--------------------------------------------------------------------------------
/gallery/src/pages/more-info/input-text.markdown:
--------------------------------------------------------------------------------
1 | ---
2 | title: Input Text
3 | ---
4 |
--------------------------------------------------------------------------------
/gallery/src/pages/more-info/light.markdown:
--------------------------------------------------------------------------------
1 | ---
2 | title: Light
3 | ---
4 |
--------------------------------------------------------------------------------
/gallery/src/pages/more-info/lock.markdown:
--------------------------------------------------------------------------------
1 | ---
2 | title: Lock
3 | ---
4 |
--------------------------------------------------------------------------------
/gallery/src/pages/more-info/media-player.markdown:
--------------------------------------------------------------------------------
1 | ---
2 | title: Media Player
3 | ---
4 |
--------------------------------------------------------------------------------
/gallery/src/pages/more-info/number.markdown:
--------------------------------------------------------------------------------
1 | ---
2 | title: Number
3 | ---
4 |
--------------------------------------------------------------------------------
/gallery/src/pages/more-info/scene.markdown:
--------------------------------------------------------------------------------
1 | ---
2 | title: Scene
3 | ---
4 |
--------------------------------------------------------------------------------
/gallery/src/pages/more-info/timer.markdown:
--------------------------------------------------------------------------------
1 | ---
2 | title: Timer
3 | ---
4 |
--------------------------------------------------------------------------------
/gallery/src/pages/more-info/update.markdown:
--------------------------------------------------------------------------------
1 | ---
2 | title: Update
3 | ---
4 |
--------------------------------------------------------------------------------
/gallery/src/pages/more-info/vacuum.markdown:
--------------------------------------------------------------------------------
1 | ---
2 | title: Vacuum
3 | ---
4 |
--------------------------------------------------------------------------------
/gallery/src/pages/more-info/water-heater.markdown:
--------------------------------------------------------------------------------
1 | ---
2 | title: Water Heater
3 | ---
4 |
--------------------------------------------------------------------------------
/gulpfile.js:
--------------------------------------------------------------------------------
1 | import { availableParallelism } from "node:os";
2 | import "./build-scripts/gulp/index.mjs";
3 |
4 | process.env.UV_THREADPOOL_SIZE = availableParallelism();
5 |
--------------------------------------------------------------------------------
/hassio/config.cjs:
--------------------------------------------------------------------------------
1 | const path = require("path");
2 |
3 | module.exports = {
4 | // Target directory for the build.
5 | buildDir: path.resolve(__dirname, "build"),
6 | nodeDir: path.resolve(__dirname, "../node_modules"),
7 | // Path where the Hass.io frontend will be publicly available.
8 | publicPath: "/api/hassio/app",
9 | };
10 |
--------------------------------------------------------------------------------
/hassio/script/build_hassio:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | # Builds the Hass.io app for production
3 |
4 | # Stop on errors
5 | set -e
6 |
7 | cd "$(dirname "$0")/../.."
8 |
9 | ./node_modules/.bin/gulp build-hassio
10 |
--------------------------------------------------------------------------------
/hassio/script/develop:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | # Run the Hass.io development server
3 |
4 | # Stop on errors
5 | set -e
6 |
7 | cd "$(dirname "$0")/../.."
8 |
9 | ./node_modules/.bin/gulp develop-hassio
10 |
--------------------------------------------------------------------------------
/hassio/src/components/hassio-filter-addons.ts:
--------------------------------------------------------------------------------
1 | import type { IFuseOptions } from "fuse.js";
2 | import Fuse from "fuse.js";
3 | import type { StoreAddon } from "../../../src/data/supervisor/store";
4 |
5 | export function filterAndSort(addons: StoreAddon[], filter: string) {
6 | const options: IFuseOptions = {
7 | keys: ["name", "description", "slug"],
8 | isCaseSensitive: false,
9 | minMatchCharLength: Math.min(filter.length, 2),
10 | threshold: 0.2,
11 | ignoreDiacritics: true,
12 | };
13 | const fuse = new Fuse(addons, options);
14 | return fuse.search(filter).map((result) => result.item);
15 | }
16 |
--------------------------------------------------------------------------------
/hassio/src/dialogs/datadisk/show-dialog-hassio-datadisk.ts:
--------------------------------------------------------------------------------
1 | import { fireEvent } from "../../../../src/common/dom/fire_event";
2 | import type { Supervisor } from "../../../../src/data/supervisor/supervisor";
3 |
4 | export interface HassioDatatiskDialogParams {
5 | supervisor: Supervisor;
6 | }
7 |
8 | export const showHassioDatadiskDialog = (
9 | element: HTMLElement,
10 | dialogParams: HassioDatatiskDialogParams
11 | ): void => {
12 | fireEvent(element, "show-dialog", {
13 | dialogTag: "dialog-hassio-datadisk",
14 | dialogImport: () => import("./dialog-hassio-datadisk"),
15 | dialogParams,
16 | });
17 | };
18 |
--------------------------------------------------------------------------------
/hassio/src/dialogs/markdown/show-dialog-hassio-markdown.ts:
--------------------------------------------------------------------------------
1 | import { fireEvent } from "../../../../src/common/dom/fire_event";
2 |
3 | export interface HassioMarkdownDialogParams {
4 | title: string;
5 | content: string;
6 | }
7 |
8 | export const showHassioMarkdownDialog = (
9 | element: HTMLElement,
10 | dialogParams: HassioMarkdownDialogParams
11 | ): void => {
12 | fireEvent(element, "show-dialog", {
13 | dialogTag: "dialog-hassio-markdown",
14 | dialogImport: () => import("./dialog-hassio-markdown"),
15 | dialogParams,
16 | });
17 | };
18 |
--------------------------------------------------------------------------------
/landing-page/eslintrc.config.mjs:
--------------------------------------------------------------------------------
1 | import rootConfig from "../eslint.config.mjs";
2 |
3 | export default [
4 | ...rootConfig,
5 | {
6 | rules: {},
7 | },
8 | ];
9 |
--------------------------------------------------------------------------------
/landing-page/public/static/icons/favicon-192x192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/landing-page/public/static/icons/favicon-192x192.png
--------------------------------------------------------------------------------
/landing-page/public/static/icons/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/landing-page/public/static/icons/favicon.ico
--------------------------------------------------------------------------------
/landing-page/public/static/images/logo_discord.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/landing-page/public/static/images/logo_discord.png
--------------------------------------------------------------------------------
/landing-page/public/static/images/logo_x.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/landing-page/script/build_landing_page:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | # Run the landing-page
3 |
4 | # Stop on errors
5 | set -e
6 |
7 | cd "$(dirname "$0")/../.."
8 |
9 | ./node_modules/.bin/gulp build-landing-page
10 |
--------------------------------------------------------------------------------
/landing-page/script/develop:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | # Run the landing-page
3 |
4 | # Stop on errors
5 | set -e
6 |
7 | cd "$(dirname "$0")/../.."
8 |
9 | ./node_modules/.bin/gulp develop-landing-page
10 |
--------------------------------------------------------------------------------
/landing-page/src/data/observer.ts:
--------------------------------------------------------------------------------
1 | export async function getObserverLogs() {
2 | return fetch("/observer/logs");
3 | }
4 |
5 | export const downloadUrl = "/observer/logs";
6 |
--------------------------------------------------------------------------------
/landing-page/src/entrypoint.js:
--------------------------------------------------------------------------------
1 | import "./ha-landing-page";
2 |
3 | import("../../src/resources/append-ha-style");
4 |
--------------------------------------------------------------------------------
/netlify.toml:
--------------------------------------------------------------------------------
1 | [build.environment]
2 | YARN_VERSION = "1.22.11"
3 | NODE_OPTIONS = "--max_old_space_size=6144"
4 |
--------------------------------------------------------------------------------
/prettier.config.js:
--------------------------------------------------------------------------------
1 | export default {
2 | trailingComma: "es5",
3 | };
4 |
--------------------------------------------------------------------------------
/public/__init__.py:
--------------------------------------------------------------------------------
1 | """Frontend for Home Assistant."""
2 | from pathlib import Path
3 |
4 |
5 | def where() -> Path:
6 | """Return path to the frontend."""
7 | return Path(__file__).parent
8 |
--------------------------------------------------------------------------------
/public/py.typed:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/public/py.typed
--------------------------------------------------------------------------------
/public/robots.txt:
--------------------------------------------------------------------------------
1 | User-agent: *
2 | Disallow: /
--------------------------------------------------------------------------------
/public/static/icons/browserconfig.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | #18bcf2
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/public/static/icons/favicon-1024x1024.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/public/static/icons/favicon-1024x1024.png
--------------------------------------------------------------------------------
/public/static/icons/favicon-16x16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/public/static/icons/favicon-16x16.png
--------------------------------------------------------------------------------
/public/static/icons/favicon-192x192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/public/static/icons/favicon-192x192.png
--------------------------------------------------------------------------------
/public/static/icons/favicon-32x32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/public/static/icons/favicon-32x32.png
--------------------------------------------------------------------------------
/public/static/icons/favicon-384x384.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/public/static/icons/favicon-384x384.png
--------------------------------------------------------------------------------
/public/static/icons/favicon-512x512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/public/static/icons/favicon-512x512.png
--------------------------------------------------------------------------------
/public/static/icons/favicon-apple-180x180.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/public/static/icons/favicon-apple-180x180.png
--------------------------------------------------------------------------------
/public/static/icons/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/public/static/icons/favicon.ico
--------------------------------------------------------------------------------
/public/static/icons/maskable_icon-128x128.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/public/static/icons/maskable_icon-128x128.png
--------------------------------------------------------------------------------
/public/static/icons/maskable_icon-192x192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/public/static/icons/maskable_icon-192x192.png
--------------------------------------------------------------------------------
/public/static/icons/maskable_icon-384x384.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/public/static/icons/maskable_icon-384x384.png
--------------------------------------------------------------------------------
/public/static/icons/maskable_icon-48x48.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/public/static/icons/maskable_icon-48x48.png
--------------------------------------------------------------------------------
/public/static/icons/maskable_icon-512x512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/public/static/icons/maskable_icon-512x512.png
--------------------------------------------------------------------------------
/public/static/icons/maskable_icon-72x72.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/public/static/icons/maskable_icon-72x72.png
--------------------------------------------------------------------------------
/public/static/icons/maskable_icon-96x96.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/public/static/icons/maskable_icon-96x96.png
--------------------------------------------------------------------------------
/public/static/icons/tile-win-150x150.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/public/static/icons/tile-win-150x150.png
--------------------------------------------------------------------------------
/public/static/icons/tile-win-310x150.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/public/static/icons/tile-win-310x150.png
--------------------------------------------------------------------------------
/public/static/icons/tile-win-310x310.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/public/static/icons/tile-win-310x310.png
--------------------------------------------------------------------------------
/public/static/icons/tile-win-70x70.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/public/static/icons/tile-win-70x70.png
--------------------------------------------------------------------------------
/public/static/images/card_media_player_bg.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/public/static/images/card_media_player_bg.png
--------------------------------------------------------------------------------
/public/static/images/color_wheel.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/public/static/images/color_wheel.png
--------------------------------------------------------------------------------
/public/static/images/config_ecobee_thermostat.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/public/static/images/config_ecobee_thermostat.png
--------------------------------------------------------------------------------
/public/static/images/config_fitbit_app.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/public/static/images/config_fitbit_app.png
--------------------------------------------------------------------------------
/public/static/images/config_flows/config_homematicip_cloud.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/public/static/images/config_flows/config_homematicip_cloud.png
--------------------------------------------------------------------------------
/public/static/images/config_freebox.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/public/static/images/config_freebox.png
--------------------------------------------------------------------------------
/public/static/images/config_icloud.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/public/static/images/config_icloud.png
--------------------------------------------------------------------------------
/public/static/images/config_insteon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/public/static/images/config_insteon.png
--------------------------------------------------------------------------------
/public/static/images/config_philips_hue.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/public/static/images/config_philips_hue.jpg
--------------------------------------------------------------------------------
/public/static/images/config_webos.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/public/static/images/config_webos.png
--------------------------------------------------------------------------------
/public/static/images/config_wink.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/public/static/images/config_wink.png
--------------------------------------------------------------------------------
/public/static/images/darksky/weather-cloudy.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/public/static/images/form/tile_features_position_bottom.svg:
--------------------------------------------------------------------------------
1 |
7 |
--------------------------------------------------------------------------------
/public/static/images/form/tile_features_position_bottom_dark.svg:
--------------------------------------------------------------------------------
1 |
7 |
--------------------------------------------------------------------------------
/public/static/images/form/tile_features_position_inline.svg:
--------------------------------------------------------------------------------
1 |
7 |
--------------------------------------------------------------------------------
/public/static/images/form/tile_features_position_inline_dark.svg:
--------------------------------------------------------------------------------
1 |
7 |
--------------------------------------------------------------------------------
/public/static/images/image-broken.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/public/static/images/logo_apple_home.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/public/static/images/logo_apple_home.png
--------------------------------------------------------------------------------
/public/static/images/logo_automatic.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/public/static/images/logo_automatic.png
--------------------------------------------------------------------------------
/public/static/images/logo_axis.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/public/static/images/logo_axis.png
--------------------------------------------------------------------------------
/public/static/images/logo_deconz.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/public/static/images/logo_deconz.jpeg
--------------------------------------------------------------------------------
/public/static/images/logo_discord.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/public/static/images/logo_discord.png
--------------------------------------------------------------------------------
/public/static/images/logo_google_home.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/public/static/images/logo_google_home.png
--------------------------------------------------------------------------------
/public/static/images/logo_nabu_casa.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/public/static/images/logo_nabu_casa.png
--------------------------------------------------------------------------------
/public/static/images/logo_nabu_casa_dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/public/static/images/logo_nabu_casa_dark.png
--------------------------------------------------------------------------------
/public/static/images/logo_philips_hue.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/public/static/images/logo_philips_hue.png
--------------------------------------------------------------------------------
/public/static/images/logo_plex_mediaserver.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/public/static/images/logo_plex_mediaserver.png
--------------------------------------------------------------------------------
/public/static/images/logo_x.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/public/static/images/notification-badge.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/public/static/images/notification-badge.png
--------------------------------------------------------------------------------
/public/static/images/screenshots/screenshot-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/public/static/images/screenshots/screenshot-1.png
--------------------------------------------------------------------------------
/public/static/images/smart-tv.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/public/static/images/smart-tv.png
--------------------------------------------------------------------------------
/public/static/images/voice-assistant/area.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/public/static/images/voice-assistant/area.png
--------------------------------------------------------------------------------
/public/static/images/voice-assistant/change-wake-word.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/public/static/images/voice-assistant/change-wake-word.png
--------------------------------------------------------------------------------
/public/static/images/voice-assistant/error.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/public/static/images/voice-assistant/error.png
--------------------------------------------------------------------------------
/public/static/images/voice-assistant/great-job.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/public/static/images/voice-assistant/great-job.png
--------------------------------------------------------------------------------
/public/static/images/voice-assistant/heart.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/public/static/images/voice-assistant/heart.png
--------------------------------------------------------------------------------
/public/static/images/voice-assistant/hi.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/public/static/images/voice-assistant/hi.png
--------------------------------------------------------------------------------
/public/static/images/voice-assistant/ok-nabu.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/public/static/images/voice-assistant/ok-nabu.png
--------------------------------------------------------------------------------
/public/static/images/voice-assistant/sleep.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/public/static/images/voice-assistant/sleep.png
--------------------------------------------------------------------------------
/public/static/images/voice-assistant/update.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/home-assistant/frontend/02bb7086e7206f053d94953935afde678ba378a0/public/static/images/voice-assistant/update.png
--------------------------------------------------------------------------------
/script/build_frontend:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | # Builds the frontend for production
3 |
4 | # Stop on errors
5 | set -e
6 |
7 | cd "$(dirname "$0")/.."
8 |
9 | ./node_modules/.bin/gulp build-app
10 |
--------------------------------------------------------------------------------
/script/develop:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | # Run the frontend development server
3 |
4 | # Stop on errors
5 | set -e
6 |
7 | cd "$(dirname "$0")/.."
8 |
9 | ./node_modules/.bin/gulp develop-app
10 |
--------------------------------------------------------------------------------
/script/release:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | # Pushes a new version to PyPi.
3 |
4 | # Stop on errors
5 | set -e
6 |
7 | cd "$(dirname "$0")/.."
8 |
9 | # Install node modules
10 | yarn install
11 |
12 | script/build_frontend
13 |
14 | rm -rf dist home_assistant_frontend.egg-info
15 | python3 -m build
16 | python3 -m twine upload dist/*.whl --skip-existing
17 |
--------------------------------------------------------------------------------
/script/serve-config.json:
--------------------------------------------------------------------------------
1 | {
2 | "cleanUrls": false
3 | }
4 |
--------------------------------------------------------------------------------
/script/setup:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | # Resolve all frontend dependencies that the application requires to develop.
3 |
4 | # Stop on errors
5 | set -e
6 |
7 | cd "$(dirname "$0")/.."
8 |
9 | script/bootstrap
10 |
11 |
--------------------------------------------------------------------------------
/script/setup_translations:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | # Setup translation fetching during development
3 |
4 | # Stop on errors
5 | set -e
6 |
7 | cd "$(dirname "$0")/.."
8 |
9 | ./node_modules/.bin/gulp setup-and-fetch-nightly-translations
--------------------------------------------------------------------------------
/script/size_stats:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | # Analyze stats
3 |
4 | # Stop on errors
5 | set -e
6 |
7 | cd "$(dirname "$0")/.."
8 |
9 | ./node_modules/.bin/gulp analyze-app
10 |
--------------------------------------------------------------------------------
/script/translations_download:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | # Safe bash settings
4 | # -e Exit on command fail
5 | # -u Exit on unset variable
6 | # -o pipefail Exit if piped command has error code
7 | set -eu -o pipefail
8 |
9 | cd "$(dirname "$0")/.."
10 |
11 | ./node_modules/.bin/gulp download-translations
--------------------------------------------------------------------------------
/src/cast/const.ts:
--------------------------------------------------------------------------------
1 | import { CAST_DEV_APP_ID } from "./dev_const";
2 |
3 | // Guard dev mode with `__dev__` so it can only ever be enabled in dev mode.
4 | export const CAST_DEV = __DEV__ && true;
5 |
6 | export const CAST_APP_ID = CAST_DEV ? CAST_DEV_APP_ID : "A078F6B0";
7 | export const CAST_NS = "urn:x-cast:com.nabucasa.hast";
8 |
--------------------------------------------------------------------------------
/src/cast/dev_const.ts:
--------------------------------------------------------------------------------
1 | // Replace this with your own unpublished cast app that points at your local dev
2 | export const CAST_DEV_APP_ID = "5FE44367";
3 |
4 | // Chromecast SDK will only load on localhost and HTTPS
5 | // So during local development we have to send our dev IP address,
6 | // but then run the UI on localhost.
7 | export const CAST_DEV_HASS_URL = "http://192.168.1.234:8123";
8 |
--------------------------------------------------------------------------------
/src/cast/types.ts:
--------------------------------------------------------------------------------
1 | export interface BaseCastMessage {
2 | type: string;
3 | senderId?: string;
4 | }
5 |
--------------------------------------------------------------------------------
/src/common/array/combinations.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Get all possible combinations of an array
3 | * @param arr - The array to get combinations of
4 | * @returns A multidimensional array of all possible combinations
5 | */
6 | export function getAllCombinations(arr: T[]) {
7 | return arr.reduce(
8 | (combinations, element) =>
9 | combinations.concat(
10 | combinations.map((combination) => [...combination, element])
11 | ),
12 | [[]]
13 | );
14 | }
15 |
--------------------------------------------------------------------------------
/src/common/array/literal-includes.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Creates a type predicate function for determining if an array literal includes a given value
3 | * @param array - The array to check
4 | * @returns A type predicate function
5 | */
6 | export const arrayLiteralIncludes =
7 | (array: T) =>
8 | (searchElement: unknown, fromIndex?: number): searchElement is T[number] =>
9 | array.includes(searchElement as T[number], fromIndex);
10 |
--------------------------------------------------------------------------------
/src/common/color/lab.ts:
--------------------------------------------------------------------------------
1 | // From https://github.com/gka/chroma.js
2 | // Copyright (c) 2011-2019, Gregor Aisch
3 |
4 | export type LabColor = [number, number, number];
5 |
6 | export const labDarken = (lab: LabColor, amount = 1): LabColor => [
7 | lab[0] - 18 * amount,
8 | lab[1],
9 | lab[2],
10 | ];
11 |
12 | export const labBrighten = (lab: LabColor, amount = 1): LabColor =>
13 | labDarken(lab, -amount);
14 |
--------------------------------------------------------------------------------
/src/common/config/components_with_service.ts:
--------------------------------------------------------------------------------
1 | import type { HomeAssistant } from "../../types";
2 |
3 | /** Return an array of domains with the service. */
4 | export const componentsWithService = (
5 | hass: HomeAssistant,
6 | service: string
7 | ): string[] =>
8 | hass &&
9 | Object.keys(hass.services).filter((key) => service in hass.services[key]);
10 |
--------------------------------------------------------------------------------
/src/common/config/is_component_loaded.ts:
--------------------------------------------------------------------------------
1 | import type { HomeAssistant } from "../../types";
2 |
3 | /** Return if a component is loaded. */
4 | export const isComponentLoaded = (
5 | hass: HomeAssistant,
6 | component: string
7 | ): boolean => hass && hass.config.components.includes(component);
8 |
--------------------------------------------------------------------------------
/src/common/config/is_pwa.ts:
--------------------------------------------------------------------------------
1 | /** Return if the displaymode is in standalone mode (PWA). */
2 | export default function isPwa(): boolean {
3 | return window.matchMedia("(display-mode: standalone)").matches;
4 | }
5 |
--------------------------------------------------------------------------------
/src/common/config/is_service_loaded.ts:
--------------------------------------------------------------------------------
1 | import type { HomeAssistant } from "../../types";
2 |
3 | /** Return if a service is loaded. */
4 | export const isServiceLoaded = (
5 | hass: HomeAssistant,
6 | domain: string,
7 | service: string
8 | ): boolean =>
9 | hass && domain in hass.services && service in hass.services[domain];
10 |
--------------------------------------------------------------------------------
/src/common/config/location_name.ts:
--------------------------------------------------------------------------------
1 | import type { HomeAssistant } from "../../types";
2 |
3 | /** Get the location name from a hass object. */
4 | export default function computeLocationName(hass: HomeAssistant): string {
5 | return hass && hass.config.location_name;
6 | }
7 |
--------------------------------------------------------------------------------
/src/common/datetime/check_valid_date.ts:
--------------------------------------------------------------------------------
1 | export default function checkValidDate(date?: Date): boolean {
2 | if (!date) {
3 | return false;
4 | }
5 |
6 | return date instanceof Date && !isNaN(date.valueOf());
7 | }
8 |
--------------------------------------------------------------------------------
/src/common/datetime/duration_to_seconds.ts:
--------------------------------------------------------------------------------
1 | export default function durationToSeconds(duration: string): number {
2 | const parts = duration.split(":").map(Number);
3 | return parts[0] * 3600 + parts[1] * 60 + parts[2];
4 | }
5 |
--------------------------------------------------------------------------------
/src/common/datetime/resolve-time-zone.ts:
--------------------------------------------------------------------------------
1 | import { TimeZone } from "../../data/translation";
2 |
3 | const RESOLVED_TIME_ZONE = Intl.DateTimeFormat?.().resolvedOptions?.().timeZone;
4 |
5 | // Browser time zone can be determined from Intl, with fallback to UTC for polyfill or no support.
6 | export const LOCAL_TIME_ZONE = RESOLVED_TIME_ZONE ?? "UTC";
7 |
8 | // Pick time zone based on user profile option. Core zone is used when local cannot be determined.
9 | export const resolveTimeZone = (option: TimeZone, serverTimeZone: string) =>
10 | option === TimeZone.local && RESOLVED_TIME_ZONE
11 | ? LOCAL_TIME_ZONE
12 | : serverTimeZone;
13 |
--------------------------------------------------------------------------------
/src/common/datetime/seconds_to_duration.ts:
--------------------------------------------------------------------------------
1 | const leftPad = (num: number) => (num < 10 ? `0${num}` : num);
2 |
3 | export default function secondsToDuration(d: number) {
4 | const h = Math.floor(d / 3600);
5 | const m = Math.floor((d % 3600) / 60);
6 | const s = Math.floor((d % 3600) % 60);
7 |
8 | if (h > 0) {
9 | return `${h}:${leftPad(m)}:${leftPad(s)}`;
10 | }
11 | if (m > 0) {
12 | return `${m}:${leftPad(s)}`;
13 | }
14 | if (s > 0) {
15 | return "" + s;
16 | }
17 | return null;
18 | }
19 |
--------------------------------------------------------------------------------
/src/common/dom/deep-active-element.ts:
--------------------------------------------------------------------------------
1 | export const deepActiveElement = (
2 | root: DocumentOrShadowRoot = document
3 | ): Element | null => {
4 | if (root.activeElement?.shadowRoot?.activeElement) {
5 | return deepActiveElement(root.activeElement.shadowRoot);
6 | }
7 | return root.activeElement;
8 | };
9 |
--------------------------------------------------------------------------------
/src/common/dom/get_main_window.ts:
--------------------------------------------------------------------------------
1 | import { MAIN_WINDOW_NAME } from "../../data/main_window";
2 |
3 | export const mainWindow = (() => {
4 | try {
5 | return window.name === MAIN_WINDOW_NAME
6 | ? window
7 | : parent.name === MAIN_WINDOW_NAME
8 | ? parent
9 | : top!;
10 | } catch {
11 | return window;
12 | }
13 | })();
14 |
--------------------------------------------------------------------------------
/src/common/dom/prevent_default.ts:
--------------------------------------------------------------------------------
1 | export const preventDefault = (ev) => ev.preventDefault();
2 |
--------------------------------------------------------------------------------
/src/common/dom/stop_propagation.ts:
--------------------------------------------------------------------------------
1 | export const stopPropagation = (ev) => ev.stopPropagation();
2 |
--------------------------------------------------------------------------------
/src/common/dom/toggle_attribute.ts:
--------------------------------------------------------------------------------
1 | // Toggle Attribute Polyfill because it's too new for some browsers
2 | export const toggleAttribute = (
3 | el: HTMLElement,
4 | name: string,
5 | force?: boolean
6 | ) => {
7 | if (force !== undefined) {
8 | force = !!force;
9 | }
10 |
11 | if (el.hasAttribute(name)) {
12 | if (force) {
13 | return true;
14 | }
15 |
16 | el.removeAttribute(name);
17 | return false;
18 | }
19 | if (force === false) {
20 | return false;
21 | }
22 |
23 | el.setAttribute(name, "");
24 | return true;
25 | };
26 |
--------------------------------------------------------------------------------
/src/common/empty_image_base64.ts:
--------------------------------------------------------------------------------
1 | /** An empty image which can be set as src of an img element. */
2 | export const emptyImageBase64 =
3 | "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7";
4 |
--------------------------------------------------------------------------------
/src/common/entity/attribute_class_names.ts:
--------------------------------------------------------------------------------
1 | import type { HassEntity } from "home-assistant-js-websocket";
2 |
3 | export const attributeClassNames = (
4 | stateObj: HassEntity,
5 | attributes: string[]
6 | ): string => {
7 | if (!stateObj) {
8 | return "";
9 | }
10 | return attributes
11 | .map((attribute) =>
12 | attribute in stateObj.attributes ? "has-" + attribute : ""
13 | )
14 | .filter((attr) => attr !== "")
15 | .join(" ");
16 | };
17 |
--------------------------------------------------------------------------------
/src/common/entity/can_toggle_domain.ts:
--------------------------------------------------------------------------------
1 | import type { HomeAssistant } from "../../types";
2 |
3 | export const canToggleDomain = (hass: HomeAssistant, domain: string) => {
4 | const services = hass.services[domain];
5 | if (!services) {
6 | return false;
7 | }
8 |
9 | if (domain === "lock") {
10 | return "lock" in services;
11 | }
12 | if (domain === "cover") {
13 | return "open_cover" in services;
14 | }
15 | return "turn_on" in services;
16 | };
17 |
--------------------------------------------------------------------------------
/src/common/entity/color/battery_color.ts:
--------------------------------------------------------------------------------
1 | export const batteryStateColorProperty = (
2 | state: string
3 | ): string | undefined => {
4 | const value = Number(state);
5 | if (isNaN(value)) {
6 | return undefined;
7 | }
8 | if (value >= 70) {
9 | return "--state-sensor-battery-high-color";
10 | }
11 | if (value >= 30) {
12 | return "--state-sensor-battery-medium-color";
13 | }
14 | return "--state-sensor-battery-low-color";
15 | };
16 |
--------------------------------------------------------------------------------
/src/common/entity/compute_area_name.ts:
--------------------------------------------------------------------------------
1 | import type { AreaRegistryEntry } from "../../data/area_registry";
2 |
3 | export const computeAreaName = (area: AreaRegistryEntry): string | undefined =>
4 | area.name?.trim();
5 |
--------------------------------------------------------------------------------
/src/common/entity/compute_domain.ts:
--------------------------------------------------------------------------------
1 | export const computeDomain = (entityId: string): string =>
2 | entityId.substring(0, entityId.indexOf("."));
3 |
--------------------------------------------------------------------------------
/src/common/entity/compute_floor_name.ts:
--------------------------------------------------------------------------------
1 | import type { FloorRegistryEntry } from "../../data/floor_registry";
2 |
3 | export const computeFloorName = (floor: FloorRegistryEntry): string =>
4 | floor.name?.trim();
5 |
--------------------------------------------------------------------------------
/src/common/entity/compute_object_id.ts:
--------------------------------------------------------------------------------
1 | /** Compute the object ID of a state. */
2 | export const computeObjectId = (entityId: string): string =>
3 | entityId.substr(entityId.indexOf(".") + 1);
4 |
--------------------------------------------------------------------------------
/src/common/entity/compute_state_domain.ts:
--------------------------------------------------------------------------------
1 | import type { HassEntity } from "home-assistant-js-websocket";
2 | import { computeDomain } from "./compute_domain";
3 |
4 | export const computeStateDomain = (stateObj: HassEntity) =>
5 | computeDomain(stateObj.entity_id);
6 |
--------------------------------------------------------------------------------
/src/common/entity/compute_state_name.ts:
--------------------------------------------------------------------------------
1 | import type { HassEntity } from "home-assistant-js-websocket";
2 | import { computeObjectId } from "./compute_object_id";
3 |
4 | export const computeStateNameFromEntityAttributes = (
5 | entityId: string,
6 | attributes: Record
7 | ): string =>
8 | attributes.friendly_name === undefined
9 | ? computeObjectId(entityId).replace(/_/g, " ")
10 | : (attributes.friendly_name ?? "").toString();
11 |
12 | export const computeStateName = (stateObj: HassEntity): string =>
13 | computeStateNameFromEntityAttributes(stateObj.entity_id, stateObj.attributes);
14 |
--------------------------------------------------------------------------------
/src/common/entity/get_group_entities.ts:
--------------------------------------------------------------------------------
1 | import type { HassEntities } from "home-assistant-js-websocket";
2 | import type { GroupEntity } from "../../data/group";
3 |
4 | export const getGroupEntities = (
5 | entities: HassEntities,
6 | group: GroupEntity
7 | ) => {
8 | const result = {};
9 |
10 | group.attributes.entity_id.forEach((entityId) => {
11 | const entity = entities[entityId];
12 |
13 | if (entity) {
14 | result[entity.entity_id] = entity;
15 | }
16 | });
17 |
18 | return result;
19 | };
20 |
--------------------------------------------------------------------------------
/src/common/entity/has_location.ts:
--------------------------------------------------------------------------------
1 | import type { HassEntity } from "home-assistant-js-websocket";
2 |
3 | export const hasLocation = (stateObj: HassEntity) =>
4 | "latitude" in stateObj.attributes && "longitude" in stateObj.attributes;
5 |
--------------------------------------------------------------------------------
/src/common/entity/states_sort_by_name.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Sort function to help sort states by name
3 | *
4 | * Usage:
5 | * const states = [state1, state2]
6 | * states.sort(statessortStatesByName);
7 | */
8 | import type { HassEntity } from "home-assistant-js-websocket";
9 | import { computeStateName } from "./compute_state_name";
10 |
11 | export const sortStatesByName = (entityA: HassEntity, entityB: HassEntity) => {
12 | const nameA = computeStateName(entityA);
13 | const nameB = computeStateName(entityB);
14 | if (nameA < nameB) {
15 | return -1;
16 | }
17 | if (nameA > nameB) {
18 | return 1;
19 | }
20 | return 0;
21 | };
22 |
--------------------------------------------------------------------------------
/src/common/entity/supports-feature.ts:
--------------------------------------------------------------------------------
1 | import type { HassEntity } from "home-assistant-js-websocket";
2 |
3 | export const supportsFeature = (
4 | stateObj: HassEntity,
5 | feature: number
6 | ): boolean => supportsFeatureFromAttributes(stateObj.attributes, feature);
7 |
8 | export const supportsFeatureFromAttributes = (
9 | attributes: Record,
10 | feature: number
11 | ): boolean =>
12 | // eslint-disable-next-line no-bitwise
13 | (attributes.supported_features! & feature) !== 0;
14 |
--------------------------------------------------------------------------------
/src/common/entity/update_icon.ts:
--------------------------------------------------------------------------------
1 | import type { HassEntity } from "home-assistant-js-websocket";
2 | import type { UpdateEntity } from "../../data/update";
3 | import { updateIsInstalling } from "../../data/update";
4 |
5 | export const updateIcon = (stateObj: HassEntity, state?: string) => {
6 | const compareState = state ?? stateObj.state;
7 | return compareState === "on"
8 | ? updateIsInstalling(stateObj as UpdateEntity)
9 | ? "mdi:package-down"
10 | : "mdi:package-up"
11 | : "mdi:package";
12 | };
13 |
--------------------------------------------------------------------------------
/src/common/entity/valid_entity_id.ts:
--------------------------------------------------------------------------------
1 | const validEntityId = /^(\w+)\.(\w+)$/;
2 |
3 | export const isValidEntityId = (entityId: string) =>
4 | validEntityId.test(entityId);
5 |
--------------------------------------------------------------------------------
/src/common/entity/valid_service_id.ts:
--------------------------------------------------------------------------------
1 | const validServiceId = /^(\w+)\.(\w+)$/;
2 |
3 | export const isValidServiceId = (actionId: string) =>
4 | validServiceId.test(actionId);
5 |
--------------------------------------------------------------------------------
/src/common/feature-detect/support-web-components.ts:
--------------------------------------------------------------------------------
1 | export const webComponentsSupported = "attachShadow" in Element.prototype;
2 |
--------------------------------------------------------------------------------
/src/common/language/format_language.ts:
--------------------------------------------------------------------------------
1 | import memoizeOne from "memoize-one";
2 | import type { FrontendLocaleData } from "../../data/translation";
3 |
4 | export const formatLanguageCode = (
5 | languageCode: string,
6 | locale: FrontendLocaleData
7 | ) => {
8 | try {
9 | return formatLanguageCodeMem(locale)?.of(languageCode) ?? languageCode;
10 | } catch {
11 | return languageCode;
12 | }
13 | };
14 |
15 | const formatLanguageCodeMem = memoizeOne(
16 | (locale: FrontendLocaleData) =>
17 | new Intl.DisplayNames(locale.language, {
18 | type: "language",
19 | fallback: "code",
20 | })
21 | );
22 |
--------------------------------------------------------------------------------
/src/common/location/add_distance_to_coord.ts:
--------------------------------------------------------------------------------
1 | export const addDistanceToCoord = (
2 | location: [number, number],
3 | dx: number,
4 | dy: number
5 | ): [number, number] => {
6 | const rEarth = 6378000;
7 | const newLatitude = location[0] + (dy / rEarth) * (180 / Math.PI);
8 | const newLongitude =
9 | location[1] +
10 | ((dx / rEarth) * (180 / Math.PI)) / Math.cos((location[0] * Math.PI) / 180);
11 | return [newLatitude, newLongitude];
12 | };
13 |
--------------------------------------------------------------------------------
/src/common/mwc/handle-request-selected-event.ts:
--------------------------------------------------------------------------------
1 | import type {
2 | ListItem,
3 | RequestSelectedDetail,
4 | } from "@material/mwc-list/mwc-list-item";
5 |
6 | export const shouldHandleRequestSelectedEvent = (
7 | ev: CustomEvent
8 | ): boolean => {
9 | if (!ev.detail.selected || ev.detail.source !== "property") {
10 | return false;
11 | }
12 | (ev.currentTarget as ListItem).selected = false;
13 | return true;
14 | };
15 |
--------------------------------------------------------------------------------
/src/common/number/clamp.ts:
--------------------------------------------------------------------------------
1 | export const clamp = (value: number, min: number, max: number) =>
2 | Math.min(Math.max(value, min), max);
3 |
4 | // Variant that only applies the clamping to a border if the border is defined
5 | export const conditionalClamp = (value: number, min?: number, max?: number) => {
6 | let result: number;
7 | result = min != null ? Math.max(value, min) : value;
8 | result = max != null ? Math.min(result, max) : result;
9 | return result;
10 | };
11 |
--------------------------------------------------------------------------------
/src/common/number/round.ts:
--------------------------------------------------------------------------------
1 | export const round = (value: number, precision = 2): number =>
2 | Math.round(value * 10 ** precision) / 10 ** precision;
3 |
--------------------------------------------------------------------------------
/src/common/string/capitalize-first-letter.ts:
--------------------------------------------------------------------------------
1 | export const capitalizeFirstLetter = (str: string) =>
2 | str.charAt(0).toUpperCase() + str.slice(1);
3 |
--------------------------------------------------------------------------------
/src/common/string/escape_regexp.ts:
--------------------------------------------------------------------------------
1 | export const escapeRegExp = (text: string): string =>
2 | text.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
3 |
--------------------------------------------------------------------------------
/src/common/string/get_duplicates.ts:
--------------------------------------------------------------------------------
1 | export function getDuplicates(array: string[]): Set {
2 | const duplicates = new Set();
3 | const seen = new Set();
4 |
5 | for (const item of array) {
6 | if (seen.has(item)) {
7 | duplicates.add(item);
8 | } else {
9 | seen.add(item);
10 | }
11 | }
12 |
13 | return duplicates;
14 | }
15 |
--------------------------------------------------------------------------------
/src/common/string/has-template.ts:
--------------------------------------------------------------------------------
1 | const isTemplateRegex = /{%|{{/;
2 |
3 | export const isTemplate = (value: string): boolean =>
4 | isTemplateRegex.test(value);
5 |
6 | export const hasTemplate = (value: unknown): boolean => {
7 | if (!value) {
8 | return false;
9 | }
10 | if (typeof value === "string") {
11 | return isTemplate(value);
12 | }
13 | if (typeof value === "object") {
14 | const values = Array.isArray(value) ? value : Object.values(value!);
15 | return values.some((val) => val && hasTemplate(val));
16 | }
17 | return false;
18 | };
19 |
--------------------------------------------------------------------------------
/src/common/string/is_date.ts:
--------------------------------------------------------------------------------
1 | // https://regex101.com/r/kc5C14/2
2 | const regExpString = "^\\d{4}-(0[1-9]|1[0-2])-([12]\\d|0[1-9]|3[01])";
3 |
4 | const regExp = new RegExp(regExpString + "$");
5 | // 2nd expression without the "end of string" enforced, so it can be used
6 | // to just verify the start of a string and then based on that result e.g.
7 | // check for a full timestamp string efficiently.
8 | const regExpNoStringEnd = new RegExp(regExpString);
9 |
10 | export const isDate = (input: string, allowCharsAfterDate = false): boolean =>
11 | allowCharsAfterDate ? regExpNoStringEnd.test(input) : regExp.test(input);
12 |
--------------------------------------------------------------------------------
/src/common/string/is_ip_address.ts:
--------------------------------------------------------------------------------
1 | const regexp =
2 | /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/;
3 |
4 | export const isIPAddress = (input: string): boolean => regexp.test(input);
5 |
--------------------------------------------------------------------------------
/src/common/string/starts-with.ts:
--------------------------------------------------------------------------------
1 | export const strStartsWith = (value: string, search: string) =>
2 | value.substring(0, search.length) === search;
3 |
--------------------------------------------------------------------------------
/src/common/string/strip-diacritics.ts:
--------------------------------------------------------------------------------
1 | export const stripDiacritics = (str: string) =>
2 | str.normalize("NFD").replace(/[\u0300-\u036F]/g, "");
3 |
--------------------------------------------------------------------------------
/src/common/string/title-case.ts:
--------------------------------------------------------------------------------
1 | export const titleCase = (s) =>
2 | s.replace(/^_*(.)|_+(.)/g, (_s, c, d) =>
3 | c ? c.toUpperCase() : " " + d.toUpperCase()
4 | );
5 |
--------------------------------------------------------------------------------
/src/common/structs/is-custom-type.ts:
--------------------------------------------------------------------------------
1 | import { refine, string } from "superstruct";
2 | import { isCustomType } from "../../data/lovelace_custom_cards";
3 |
4 | export const customType = () =>
5 | refine(string(), "custom element type", isCustomType);
6 |
--------------------------------------------------------------------------------
/src/common/structs/is-icon.ts:
--------------------------------------------------------------------------------
1 | import { refine, string } from "superstruct";
2 |
3 | const isIcon = (value: string) => value.includes(":");
4 |
5 | export const icon = () => refine(string(), "icon (mdi:icon-name)", isIcon);
6 |
--------------------------------------------------------------------------------
/src/common/translations/blank_before_percent.ts:
--------------------------------------------------------------------------------
1 | import type { FrontendLocaleData } from "../../data/translation";
2 |
3 | // Logic based on https://en.wikipedia.org/wiki/Percent_sign#Form_and_spacing
4 | export const blankBeforePercent = (
5 | localeOptions: FrontendLocaleData
6 | ): string => {
7 | switch (localeOptions.language) {
8 | case "cs":
9 | case "de":
10 | case "fi":
11 | case "fr":
12 | case "sk":
13 | case "sv":
14 | return " ";
15 | default:
16 | return "";
17 | }
18 | };
19 |
--------------------------------------------------------------------------------
/src/common/translations/blank_before_unit.ts:
--------------------------------------------------------------------------------
1 | import type { FrontendLocaleData } from "../../data/translation";
2 | import { blankBeforePercent } from "./blank_before_percent";
3 |
4 | export const blankBeforeUnit = (
5 | unit: string,
6 | localeOptions: FrontendLocaleData | undefined
7 | ): string => {
8 | if (unit === "°") {
9 | return "";
10 | }
11 | if (localeOptions && unit === "%") {
12 | return blankBeforePercent(localeOptions);
13 | }
14 | return " ";
15 | };
16 |
--------------------------------------------------------------------------------
/src/common/translations/day_names.ts:
--------------------------------------------------------------------------------
1 | import { addDays, startOfWeek } from "date-fns";
2 | import type { HassConfig } from "home-assistant-js-websocket";
3 | import memoizeOne from "memoize-one";
4 | import type { FrontendLocaleData } from "../../data/translation";
5 | import { formatDateWeekday } from "../datetime/format_date";
6 |
7 | export const dayNames = memoizeOne(
8 | (locale: FrontendLocaleData, config: HassConfig): string[] =>
9 | Array.from({ length: 7 }, (_, d) =>
10 | formatDateWeekday(addDays(startOfWeek(new Date()), d), locale, config)
11 | )
12 | );
13 |
--------------------------------------------------------------------------------
/src/common/translations/markdown_support.ts:
--------------------------------------------------------------------------------
1 | import { html } from "lit";
2 | import type { LocalizeFunc } from "./localize";
3 |
4 | const MARKDOWN_SUPPORT_URL = "https://commonmark.org/help/";
5 |
6 | export const supportsMarkdownHelper = (localize: LocalizeFunc) =>
7 | localize("ui.common.supports_markdown", {
8 | markdown_help_link: html`${localize("ui.common.markdown")}`,
14 | });
15 |
--------------------------------------------------------------------------------
/src/common/translations/month_names.ts:
--------------------------------------------------------------------------------
1 | import { addMonths, startOfYear } from "date-fns";
2 | import type { HassConfig } from "home-assistant-js-websocket";
3 | import memoizeOne from "memoize-one";
4 | import type { FrontendLocaleData } from "../../data/translation";
5 | import { formatDateMonth } from "../datetime/format_date";
6 |
7 | export const monthNames = memoizeOne(
8 | (locale: FrontendLocaleData, config: HassConfig): string[] =>
9 | Array.from({ length: 12 }, (_, m) =>
10 | formatDateMonth(addMonths(startOfYear(new Date()), m), locale, config)
11 | )
12 | );
13 |
--------------------------------------------------------------------------------
/src/common/url/construct-url.ts:
--------------------------------------------------------------------------------
1 | export const constructUrlCurrentPath = (searchParams: string): string => {
2 | const base = window.location.pathname;
3 | // Prevent trailing "?" if no parameters exist
4 | return searchParams ? base + "?" + searchParams : base;
5 | };
6 |
--------------------------------------------------------------------------------
/src/common/util/copy-clipboard.ts:
--------------------------------------------------------------------------------
1 | export const copyToClipboard = async (str, rootEl?: HTMLElement) => {
2 | if (navigator.clipboard) {
3 | try {
4 | await navigator.clipboard.writeText(str);
5 | return;
6 | } catch {
7 | // just continue with the fallback coding below
8 | }
9 | }
10 |
11 | const root = rootEl ?? document.body;
12 |
13 | const el = document.createElement("textarea");
14 | el.value = str;
15 | root.appendChild(el);
16 | el.select();
17 | document.execCommand("copy");
18 | root.removeChild(el);
19 | };
20 |
--------------------------------------------------------------------------------
/src/common/util/group-by.ts:
--------------------------------------------------------------------------------
1 | export const groupBy = (
2 | list: T[],
3 | keySelector: (item: T) => string
4 | ): Record => {
5 | const result = {};
6 | for (const item of list) {
7 | const key = keySelector(item);
8 | if (key in result) {
9 | result[key].push(item);
10 | } else {
11 | result[key] = [item];
12 | }
13 | }
14 | return result;
15 | };
16 |
--------------------------------------------------------------------------------
/src/common/util/patch.ts:
--------------------------------------------------------------------------------
1 | export const applyPatch = (data, path, value): void => {
2 | if (path.length === 1) {
3 | data[path[0]] = value;
4 | return;
5 | }
6 | if (!data[path[0]]) {
7 | data[path[0]] = {};
8 | }
9 | // eslint-disable-next-line consistent-return
10 | return applyPatch(data[path[0]], path.slice(1), value);
11 | };
12 |
13 | export const getPath = (data, path): any | undefined => {
14 | if (path.length === 1) {
15 | return data[path[0]];
16 | }
17 | if (data[path[0]] === undefined) {
18 | return undefined;
19 | }
20 | return getPath(data[path[0]], path.slice(1));
21 | };
22 |
--------------------------------------------------------------------------------
/src/common/util/promise-all-settled-results.ts:
--------------------------------------------------------------------------------
1 | export const hasRejectedItems = (results: PromiseSettledResult[]) =>
2 | results.some((result) => result.status === "rejected");
3 |
4 | export const rejectedItems = (
5 | results: PromiseSettledResult[]
6 | ): PromiseRejectedResult[] =>
7 | results.filter(
8 | (result) => result.status === "rejected"
9 | ) as PromiseRejectedResult[];
10 |
--------------------------------------------------------------------------------
/src/common/util/render-status.ts:
--------------------------------------------------------------------------------
1 | export const afterNextRender = (cb: (value: unknown) => void): void => {
2 | requestAnimationFrame(() => setTimeout(cb, 0));
3 | };
4 |
5 | export const nextRender = () =>
6 | new Promise((resolve) => {
7 | afterNextRender(resolve);
8 | });
9 |
--------------------------------------------------------------------------------
/src/common/util/subscribe-one.ts:
--------------------------------------------------------------------------------
1 | import type { Connection, UnsubscribeFunc } from "home-assistant-js-websocket";
2 |
3 | export const subscribeOne = async (
4 | conn: Connection,
5 | subscribe: (
6 | conn2: Connection,
7 | onChange: (items: T) => void
8 | ) => UnsubscribeFunc
9 | ) =>
10 | new Promise((resolve) => {
11 | const unsub = subscribe(conn, (items) => {
12 | unsub();
13 | resolve(items);
14 | });
15 | });
16 |
--------------------------------------------------------------------------------
/src/common/util/subscribe-polling.ts:
--------------------------------------------------------------------------------
1 | import type { HomeAssistant } from "../../types";
2 |
3 | export const subscribePollingCollection = (
4 | hass: HomeAssistant,
5 | updateData: (hass: HomeAssistant) => void,
6 | interval: number
7 | ) => {
8 | let timeout;
9 | const fetchData = async () => {
10 | try {
11 | await updateData(hass);
12 | } finally {
13 | timeout = setTimeout(() => fetchData(), interval);
14 | }
15 | };
16 | fetchData();
17 | return () => clearTimeout(timeout);
18 | };
19 |
--------------------------------------------------------------------------------
/src/common/util/uid.ts:
--------------------------------------------------------------------------------
1 | function s4() {
2 | return Math.floor((1 + Math.random()) * 0x10000)
3 | .toString(16)
4 | .substring(1);
5 | }
6 |
7 | export function uid() {
8 | return s4() + s4() + s4() + s4() + s4();
9 | }
10 |
--------------------------------------------------------------------------------
/src/common/util/wait.ts:
--------------------------------------------------------------------------------
1 | export const waitForMs = (ms: number) =>
2 | new Promise((resolve) => {
3 | setTimeout(resolve, ms);
4 | });
5 |
6 | export const waitForSeconds = (seconds: number) => waitForMs(seconds * 1000);
7 |
--------------------------------------------------------------------------------
/src/components/chips/ha-chip-set.ts:
--------------------------------------------------------------------------------
1 | import { MdChipSet } from "@material/web/chips/chip-set";
2 | import { customElement } from "lit/decorators";
3 |
4 | @customElement("ha-chip-set")
5 | export class HaChipSet extends MdChipSet {}
6 |
7 | declare global {
8 | interface HTMLElementTagNameMap {
9 | "ha-chip-set": HaChipSet;
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/src/components/ha-checkbox.ts:
--------------------------------------------------------------------------------
1 | import { CheckboxBase } from "@material/mwc-checkbox/mwc-checkbox-base";
2 | import { styles } from "@material/mwc-checkbox/mwc-checkbox.css";
3 | import { css } from "lit";
4 | import { customElement } from "lit/decorators";
5 |
6 | @customElement("ha-checkbox")
7 | export class HaCheckbox extends CheckboxBase {
8 | static override styles = [
9 | styles,
10 | css`
11 | :host {
12 | --mdc-theme-secondary: var(--primary-color);
13 | }
14 | `,
15 | ];
16 | }
17 |
18 | declare global {
19 | interface HTMLElementTagNameMap {
20 | "ha-checkbox": HaCheckbox;
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/src/components/ha-fade-in.ts:
--------------------------------------------------------------------------------
1 | import SlAnimation from "@shoelace-style/shoelace/dist/components/animation/animation.component";
2 | import { customElement, property } from "lit/decorators";
3 |
4 | @customElement("ha-fade-in")
5 | export class HaFadeIn extends SlAnimation {
6 | @property() public name = "fadeIn";
7 |
8 | @property() public fill: FillMode = "both";
9 |
10 | @property({ type: Boolean }) public play = true;
11 |
12 | @property({ type: Number }) public iterations = 1;
13 | }
14 |
15 | declare global {
16 | interface HTMLElementTagNameMap {
17 | "ha-fade-in": HaFadeIn;
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/src/components/ha-icon-next.ts:
--------------------------------------------------------------------------------
1 | import { mdiChevronLeft, mdiChevronRight } from "@mdi/js";
2 | import { customElement, property } from "lit/decorators";
3 | import { mainWindow } from "../common/dom/get_main_window";
4 | import { HaSvgIcon } from "./ha-svg-icon";
5 |
6 | @customElement("ha-icon-next")
7 | export class HaIconNext extends HaSvgIcon {
8 | @property() public override path =
9 | mainWindow.document.dir === "rtl" ? mdiChevronLeft : mdiChevronRight;
10 | }
11 |
12 | declare global {
13 | interface HTMLElementTagNameMap {
14 | "ha-icon-next": HaIconNext;
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/src/components/ha-icon-prev.ts:
--------------------------------------------------------------------------------
1 | import { mdiChevronLeft, mdiChevronRight } from "@mdi/js";
2 | import { customElement, property } from "lit/decorators";
3 | import { mainWindow } from "../common/dom/get_main_window";
4 | import { HaSvgIcon } from "./ha-svg-icon";
5 |
6 | @customElement("ha-icon-prev")
7 | export class HaIconPrev extends HaSvgIcon {
8 | @property() public override path =
9 | mainWindow.document.dir === "rtl" ? mdiChevronRight : mdiChevronLeft;
10 | }
11 |
12 | declare global {
13 | interface HTMLElementTagNameMap {
14 | "ha-icon-prev": HaIconPrev;
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/src/components/ha-list.ts:
--------------------------------------------------------------------------------
1 | import { ListBase } from "@material/mwc-list/mwc-list-base";
2 | import { styles } from "@material/mwc-list/mwc-list.css";
3 | import { customElement } from "lit/decorators";
4 |
5 | @customElement("ha-list")
6 | export class HaList extends ListBase {
7 | static styles = styles;
8 | }
9 |
10 | declare global {
11 | interface HTMLElementTagNameMap {
12 | "ha-list": HaList;
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/src/components/ha-md-divider.ts:
--------------------------------------------------------------------------------
1 | import { Divider } from "@material/web/divider/internal/divider";
2 | import { styles } from "@material/web/divider/internal/divider-styles";
3 | import { css } from "lit";
4 | import { customElement } from "lit/decorators";
5 |
6 | @customElement("ha-md-divider")
7 | export class HaMdDivider extends Divider {
8 | static override styles = [
9 | styles,
10 | css`
11 | :host {
12 | --md-divider-color: var(--divider-color);
13 | }
14 | `,
15 | ];
16 | }
17 |
18 | declare global {
19 | interface HTMLElementTagNameMap {
20 | "ha-md-divider": HaMdDivider;
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/src/components/ha-md-list.ts:
--------------------------------------------------------------------------------
1 | import { List } from "@material/web/list/internal/list";
2 | import { styles } from "@material/web/list/internal/list-styles";
3 | import { css } from "lit";
4 | import { customElement } from "lit/decorators";
5 |
6 | @customElement("ha-md-list")
7 | export class HaMdList extends List {
8 | static override styles = [
9 | styles,
10 | css`
11 | :host {
12 | --md-sys-color-surface: var(--card-background-color);
13 | }
14 | `,
15 | ];
16 | }
17 |
18 | declare global {
19 | interface HTMLElementTagNameMap {
20 | "ha-md-list": HaMdList;
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/src/components/ha-radio.ts:
--------------------------------------------------------------------------------
1 | import { RadioBase } from "@material/mwc-radio/mwc-radio-base";
2 | import { styles } from "@material/mwc-radio/mwc-radio.css";
3 | import { css } from "lit";
4 | import { customElement } from "lit/decorators";
5 |
6 | @customElement("ha-radio")
7 | export class HaRadio extends RadioBase {
8 | static override styles = [
9 | styles,
10 | css`
11 | :host {
12 | --mdc-theme-secondary: var(--primary-color);
13 | }
14 | `,
15 | ];
16 | }
17 |
18 | declare global {
19 | interface HTMLElementTagNameMap {
20 | "ha-radio": HaRadio;
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/src/components/media-player/show-join-media-players-dialog.ts:
--------------------------------------------------------------------------------
1 | import { fireEvent } from "../../common/dom/fire_event";
2 |
3 | export interface JoinMediaPlayersDialogParams {
4 | entityId: string;
5 | }
6 |
7 | export const showJoinMediaPlayersDialog = (
8 | element: HTMLElement,
9 | dialogParams: JoinMediaPlayersDialogParams
10 | ): void => {
11 | fireEvent(element, "show-dialog", {
12 | dialogTag: "dialog-join-media-players",
13 | dialogImport: () => import("./dialog-join-media-players"),
14 | dialogParams,
15 | });
16 | };
17 |
--------------------------------------------------------------------------------
/src/components/media-player/show-media-manage-dialog.ts:
--------------------------------------------------------------------------------
1 | import { fireEvent } from "../../common/dom/fire_event";
2 | import type { MediaPlayerItem } from "../../data/media-player";
3 |
4 | export interface MediaManageDialogParams {
5 | currentItem: MediaPlayerItem;
6 | onClose?: () => void;
7 | }
8 |
9 | export const showMediaManageDialog = (
10 | element: HTMLElement,
11 | dialogParams: MediaManageDialogParams
12 | ): void => {
13 | fireEvent(element, "show-dialog", {
14 | dialogTag: "dialog-media-manage",
15 | dialogImport: () => import("./dialog-media-manage"),
16 | dialogParams,
17 | });
18 | };
19 |
--------------------------------------------------------------------------------
/src/components/timezone-datalist.ts:
--------------------------------------------------------------------------------
1 | import timezones from "google-timezones-json";
2 |
3 | export const createTimezoneListEl = () => {
4 | const list = document.createElement("datalist");
5 | list.id = "timezones";
6 | Object.keys(timezones).forEach((key) => {
7 | const option = document.createElement("option");
8 | option.value = key;
9 | option.innerText = timezones[key];
10 | list.appendChild(option);
11 | });
12 | return list;
13 | };
14 |
--------------------------------------------------------------------------------
/src/components/trace/hat-graph-const.ts:
--------------------------------------------------------------------------------
1 | export const SPACING = 10;
2 | export const NODE_SIZE = 30;
3 | export const BRANCH_HEIGHT = 20;
4 |
--------------------------------------------------------------------------------
/src/data/bootstrap_integrations.ts:
--------------------------------------------------------------------------------
1 | import type { HomeAssistant } from "../types";
2 |
3 | export type BootstrapIntegrationsTimings = Record;
4 |
5 | export const subscribeBootstrapIntegrations = (
6 | hass: HomeAssistant,
7 | callback: (message: BootstrapIntegrationsTimings) => void
8 | ) => {
9 | const unsubProm =
10 | hass.connection.subscribeMessage(
11 | (message) => callback(message),
12 | {
13 | type: "subscribe_bootstrap_integrations",
14 | }
15 | );
16 |
17 | return unsubProm;
18 | };
19 |
--------------------------------------------------------------------------------
/src/data/config.ts:
--------------------------------------------------------------------------------
1 | import type { HomeAssistant } from "../types";
2 |
3 | interface ValidConfig {
4 | valid: true;
5 | error: null;
6 | }
7 |
8 | interface InvalidConfig {
9 | valid: false;
10 | error: string;
11 | }
12 |
13 | type ValidKeys = "triggers" | "actions" | "conditions";
14 |
15 | export const validateConfig = >>(
16 | hass: HomeAssistant,
17 | config: T
18 | ): Promise> =>
19 | hass.callWS({
20 | type: "validate_config",
21 | ...config,
22 | });
23 |
--------------------------------------------------------------------------------
/src/data/custom_iconsets.ts:
--------------------------------------------------------------------------------
1 | import type { CustomIcon } from "./custom_icons";
2 |
3 | interface CustomIconsetsWindow {
4 | customIconsets?: Record Promise>;
5 | }
6 |
7 | const customIconsetsWindow = window as CustomIconsetsWindow;
8 |
9 | if (!("customIconsets" in customIconsetsWindow)) {
10 | customIconsetsWindow.customIconsets = {};
11 | }
12 |
13 | export const customIconsets = customIconsetsWindow.customIconsets!;
14 |
--------------------------------------------------------------------------------
/src/data/date.ts:
--------------------------------------------------------------------------------
1 | import type { HassEntityBase } from "home-assistant-js-websocket";
2 | import type { HomeAssistant } from "../types";
3 |
4 | export const stateToIsoDateString = (entityState: HassEntityBase) =>
5 | `${entityState}T00:00:00`;
6 |
7 | export const setDateValue = (
8 | hass: HomeAssistant,
9 | entityId: string,
10 | date: string | undefined = undefined
11 | ) => {
12 | const param = { entity_id: entityId, date };
13 | hass.callService("date", "set_value", param);
14 | };
15 |
--------------------------------------------------------------------------------
/src/data/datetime.ts:
--------------------------------------------------------------------------------
1 | import type { HomeAssistant } from "../types";
2 |
3 | export const setDateTimeValue = (
4 | hass: HomeAssistant,
5 | entityId: string,
6 | datetime: Date
7 | ) => {
8 | hass.callService("datetime", "set_value", {
9 | entity_id: entityId,
10 | datetime: datetime.toISOString(),
11 | });
12 | };
13 |
--------------------------------------------------------------------------------
/src/data/entity.ts:
--------------------------------------------------------------------------------
1 | import { arrayLiteralIncludes } from "../common/array/literal-includes";
2 |
3 | export const UNAVAILABLE = "unavailable";
4 | export const UNKNOWN = "unknown";
5 | export const ON = "on";
6 | export const OFF = "off";
7 |
8 | export const UNAVAILABLE_STATES = [UNAVAILABLE, UNKNOWN] as const;
9 | export const OFF_STATES = [UNAVAILABLE, UNKNOWN, OFF] as const;
10 |
11 | export const isUnavailableState = arrayLiteralIncludes(UNAVAILABLE_STATES);
12 | export const isOffState = arrayLiteralIncludes(OFF_STATES);
13 |
--------------------------------------------------------------------------------
/src/data/error_log.ts:
--------------------------------------------------------------------------------
1 | import type { HomeAssistant } from "../types";
2 |
3 | export interface LogProvider {
4 | key: string;
5 | name: string;
6 | }
7 |
8 | export const fetchErrorLog = (hass: HomeAssistant) =>
9 | hass.callApi("GET", "error_log");
10 |
11 | export const getErrorLogDownloadUrl = "/api/error_log";
12 |
--------------------------------------------------------------------------------
/src/data/external.ts:
--------------------------------------------------------------------------------
1 | export const isExternal =
2 | window.externalApp ||
3 | window.webkit?.messageHandlers?.getExternalAuth ||
4 | location.search.includes("external_auth=1");
5 |
--------------------------------------------------------------------------------
/src/data/graph.ts:
--------------------------------------------------------------------------------
1 | export const strokeWidth = 5;
2 |
--------------------------------------------------------------------------------
/src/data/image.ts:
--------------------------------------------------------------------------------
1 | import type {
2 | HassEntityAttributeBase,
3 | HassEntityBase,
4 | } from "home-assistant-js-websocket";
5 |
6 | interface ImageEntityAttributes extends HassEntityAttributeBase {
7 | access_token: string;
8 | }
9 |
10 | export interface ImageEntity extends HassEntityBase {
11 | attributes: ImageEntityAttributes;
12 | }
13 |
14 | export const computeImageUrl = (entity: ImageEntity): string =>
15 | `/api/image_proxy/${entity.entity_id}?token=${entity.attributes.access_token}&state=${entity.state}`;
16 |
--------------------------------------------------------------------------------
/src/data/lovelace/action_handler.ts:
--------------------------------------------------------------------------------
1 | import type { HASSDomEvent } from "../../common/dom/fire_event";
2 |
3 | export interface ActionHandlerOptions {
4 | hasHold?: boolean;
5 | hasDoubleClick?: boolean;
6 | disabled?: boolean;
7 | }
8 |
9 | export interface ActionHandlerDetail {
10 | action: "hold" | "tap" | "double_tap";
11 | }
12 |
13 | export type ActionHandlerEvent = HASSDomEvent;
14 |
--------------------------------------------------------------------------------
/src/data/lovelace/config/card.ts:
--------------------------------------------------------------------------------
1 | import type { Condition } from "../../../panels/lovelace/common/validate-condition";
2 | import type {
3 | LovelaceGridOptions,
4 | LovelaceLayoutOptions,
5 | } from "../../../panels/lovelace/types";
6 |
7 | export interface LovelaceCardConfig {
8 | index?: number;
9 | view_index?: number;
10 | view_layout?: any;
11 | /** @deprecated Use `grid_options` instead */
12 | layout_options?: LovelaceLayoutOptions;
13 | grid_options?: LovelaceGridOptions;
14 | type: string;
15 | [key: string]: any;
16 | visibility?: Condition[];
17 | }
18 |
--------------------------------------------------------------------------------
/src/data/lovelace/config/strategy.ts:
--------------------------------------------------------------------------------
1 | export interface LovelaceStrategyConfig {
2 | type: string;
3 | [key: string]: any;
4 | }
5 |
--------------------------------------------------------------------------------
/src/data/main_window.ts:
--------------------------------------------------------------------------------
1 | export const MAIN_WINDOW_NAME = "ha-main-window";
2 |
--------------------------------------------------------------------------------
/src/data/number.ts:
--------------------------------------------------------------------------------
1 | import type { HomeAssistant } from "../types";
2 |
3 | export interface NumberDeviceClassUnits {
4 | units: string[];
5 | }
6 |
7 | export const getNumberDeviceClassConvertibleUnits = (
8 | hass: HomeAssistant,
9 | deviceClass: string
10 | ): Promise =>
11 | hass.callWS({
12 | type: "number/device_class_convertible_units",
13 | device_class: deviceClass,
14 | });
15 |
--------------------------------------------------------------------------------
/src/data/panel_custom.ts:
--------------------------------------------------------------------------------
1 | import type { PanelInfo } from "../types";
2 |
3 | export interface CustomPanelConfig {
4 | name: string;
5 | embed_iframe: boolean;
6 | trust_external: boolean;
7 | js_url?: string;
8 | module_url?: string;
9 | html_url?: string;
10 | }
11 |
12 | export type CustomPanelInfo> = PanelInfo<
13 | T & { _panel_custom: CustomPanelConfig }
14 | >;
15 |
--------------------------------------------------------------------------------
/src/data/preloads.ts:
--------------------------------------------------------------------------------
1 | import type { LovelaceRawConfig } from "./lovelace/config/types";
2 | import type { LovelaceResource } from "./lovelace/resource";
3 | import type { RecorderInfo } from "./recorder";
4 |
5 | export interface WindowWithPreloads extends Window {
6 | llConfProm?: Promise;
7 | llResProm?: Promise;
8 | recorderInfoProm?: Promise;
9 | }
10 |
--------------------------------------------------------------------------------
/src/data/refresh_token.ts:
--------------------------------------------------------------------------------
1 | declare global {
2 | interface HASSDomEvents {
3 | "hass-refresh-tokens": undefined;
4 | }
5 | }
6 |
7 | export type RefreshTokenType = "normal" | "long_lived_access_token";
8 |
9 | export interface RefreshToken {
10 | client_icon?: string;
11 | client_id: string;
12 | client_name?: string;
13 | created_at: string;
14 | expire_at?: string;
15 | id: string;
16 | is_current: boolean;
17 | last_used_at?: string;
18 | last_used_ip?: string;
19 | type: RefreshTokenType;
20 | }
21 |
--------------------------------------------------------------------------------
/src/data/registry.ts:
--------------------------------------------------------------------------------
1 | export interface RegistryEntry {
2 | created_at: number;
3 | modified_at: number;
4 | }
5 |
--------------------------------------------------------------------------------
/src/data/remote.ts:
--------------------------------------------------------------------------------
1 | import type {
2 | HassEntityAttributeBase,
3 | HassEntityBase,
4 | } from "home-assistant-js-websocket";
5 |
6 | export const REMOTE_SUPPORT_LEARN_COMMAND = 1;
7 | export const REMOTE_SUPPORT_DELETE_COMMAND = 2;
8 | export const REMOTE_SUPPORT_ACTIVITY = 4;
9 |
10 | export type RemoteEntity = HassEntityBase & {
11 | attributes: HassEntityAttributeBase & {
12 | current_activity: string | null;
13 | activity_list: string[] | null;
14 | [key: string]: any;
15 | };
16 | };
17 |
--------------------------------------------------------------------------------
/src/data/select.ts:
--------------------------------------------------------------------------------
1 | import type {
2 | HassEntityAttributeBase,
3 | HassEntityBase,
4 | } from "home-assistant-js-websocket";
5 | import type { HomeAssistant } from "../types";
6 |
7 | interface SelectEntityAttributes extends HassEntityAttributeBase {
8 | options: string[];
9 | }
10 |
11 | export interface SelectEntity extends HassEntityBase {
12 | attributes: SelectEntityAttributes;
13 | }
14 |
15 | export const setSelectOption = (
16 | hass: HomeAssistant,
17 | entity: string,
18 | option: string
19 | ) =>
20 | hass.callService(
21 | "select",
22 | "select_option",
23 | { option },
24 | { entity_id: entity }
25 | );
26 |
--------------------------------------------------------------------------------
/src/data/siren.ts:
--------------------------------------------------------------------------------
1 | export const SirenEntityFeature = {
2 | TURN_ON: 1,
3 | TURN_OFF: 2,
4 | TONES: 4,
5 | VOLUME_SET: 8,
6 | DURATION: 16,
7 | };
8 |
--------------------------------------------------------------------------------
/src/data/text.ts:
--------------------------------------------------------------------------------
1 | import type {
2 | HassEntityAttributeBase,
3 | HassEntityBase,
4 | } from "home-assistant-js-websocket";
5 | import type { HomeAssistant } from "../types";
6 |
7 | interface TextEntityAttributes extends HassEntityAttributeBase {
8 | min?: number;
9 | max?: number;
10 | pattern?: string;
11 | mode?: "text" | "password";
12 | }
13 |
14 | export interface TextEntity extends HassEntityBase {
15 | attributes: TextEntityAttributes;
16 | }
17 |
18 | export const setValue = (hass: HomeAssistant, entity: string, value: string) =>
19 | hass.callService("text", "set_value", { value }, { entity_id: entity });
20 |
--------------------------------------------------------------------------------
/src/data/time.ts:
--------------------------------------------------------------------------------
1 | import type { HomeAssistant } from "../types";
2 |
3 | export const setTimeValue = (
4 | hass: HomeAssistant,
5 | entityId: string,
6 | time: string | undefined = undefined
7 | ) => {
8 | const param = { entity_id: entityId, time: time };
9 | hass.callService("time", "set_value", param);
10 | };
11 |
--------------------------------------------------------------------------------
/src/data/usb.ts:
--------------------------------------------------------------------------------
1 | import type { HomeAssistant } from "../types";
2 |
3 | export const scanUSBDevices = (hass: HomeAssistant) =>
4 | hass.callWS({ type: "usb/scan" });
5 |
--------------------------------------------------------------------------------
/src/data/wake_word.ts:
--------------------------------------------------------------------------------
1 | import type { HomeAssistant } from "../types";
2 |
3 | export interface WakeWord {
4 | id: string;
5 | name: string;
6 | }
7 |
8 | export const fetchWakeWordInfo = (hass: HomeAssistant, entity_id: string) =>
9 | hass.callWS<{ wake_words: WakeWord[] }>({
10 | type: "wake_word/info",
11 | entity_id,
12 | });
13 |
--------------------------------------------------------------------------------
/src/data/webhook.ts:
--------------------------------------------------------------------------------
1 | import type { HomeAssistant } from "../types";
2 |
3 | export interface Webhook {
4 | webhook_id: string;
5 | domain: string;
6 | name: string;
7 | local_only: boolean;
8 | }
9 | export interface WebhookError {
10 | code: number;
11 | message: string;
12 | }
13 |
14 | export const fetchWebhooks = (hass: HomeAssistant): Promise =>
15 | hass.callWS({
16 | type: "webhook/list",
17 | });
18 |
--------------------------------------------------------------------------------
/src/data/websocket_api.ts:
--------------------------------------------------------------------------------
1 | export const ERR_ID_REUSE = "id_reuse";
2 | export const ERR_INVALID_FORMAT = "invalid_format";
3 | export const ERR_NOT_FOUND = "not_found";
4 | export const ERR_UNKNOWN_COMMAND = "unknown_command";
5 | export const ERR_UNKNOWN_ERROR = "unknown_error";
6 | export const ERR_UNAUTHORIZED = "unauthorized";
7 |
--------------------------------------------------------------------------------
/src/data/ws-user.ts:
--------------------------------------------------------------------------------
1 | import type { Connection } from "home-assistant-js-websocket";
2 | import { getCollection, getUser } from "home-assistant-js-websocket";
3 | import type { CurrentUser } from "../types";
4 |
5 | export const userCollection = (conn: Connection) =>
6 | getCollection(
7 | conn,
8 | "_usr",
9 | () => getUser(conn) as Promise,
10 | undefined
11 | );
12 |
13 | export const subscribeUser = (
14 | conn: Connection,
15 | onChange: (user: CurrentUser) => void
16 | ) => userCollection(conn).subscribe(onChange);
17 |
--------------------------------------------------------------------------------
/src/data/wyoming.ts:
--------------------------------------------------------------------------------
1 | import type { HomeAssistant } from "../types";
2 |
3 | export interface WyomingInfo {
4 | asr: WyomingAsrInfo[];
5 | handle: [];
6 | intent: [];
7 | tts: WyomingTtsInfo[];
8 | wake: [];
9 | }
10 |
11 | interface WyomingBaseInfo {
12 | name: string;
13 | version: string;
14 | attribution: Record;
15 | }
16 |
17 | interface WyomingTtsInfo extends WyomingBaseInfo {}
18 |
19 | interface WyomingAsrInfo extends WyomingBaseInfo {}
20 |
21 | export const fetchWyomingInfo = (hass: HomeAssistant) =>
22 | hass.callWS<{ info: Record }>({ type: "wyoming/info" });
23 |
--------------------------------------------------------------------------------
/src/dialogs/more-info/components/voice/show-view-voice-assistants.ts:
--------------------------------------------------------------------------------
1 | import { fireEvent } from "../../../../common/dom/fire_event";
2 |
3 | export const loadVoiceAssistantsView = () =>
4 | import("./ha-more-info-view-voice-assistants");
5 |
6 | export const showVoiceAssistantsView = (
7 | element: HTMLElement,
8 | title: string
9 | ): void => {
10 | fireEvent(element, "show-child-view", {
11 | viewTag: "ha-more-info-view-voice-assistants",
12 | viewImport: loadVoiceAssistantsView,
13 | viewTitle: title,
14 | viewParams: {},
15 | });
16 | };
17 |
--------------------------------------------------------------------------------
/src/dialogs/more-info/show-ha-more-info-dialog.ts:
--------------------------------------------------------------------------------
1 | import { fireEvent } from "../../common/dom/fire_event";
2 | import type { MoreInfoDialogParams } from "./ha-more-info-dialog";
3 |
4 | export const showMoreInfoDialog = (
5 | element: HTMLElement,
6 | params: MoreInfoDialogParams
7 | ) => fireEvent(element, "hass-more-info", params);
8 |
--------------------------------------------------------------------------------
/src/dialogs/notifications/show-notification-drawer.ts:
--------------------------------------------------------------------------------
1 | import { fireEvent } from "../../common/dom/fire_event";
2 |
3 | export interface NotificationDrawerParams {
4 | narrow: boolean;
5 | }
6 |
7 | export const showNotificationDrawer = (
8 | element: HTMLElement,
9 | dialogParams: NotificationDrawerParams
10 | ): void => {
11 | fireEvent(element, "show-dialog", {
12 | dialogTag: "notification-drawer",
13 | dialogImport: () => import("./notification-drawer"),
14 | dialogParams,
15 | });
16 | };
17 |
--------------------------------------------------------------------------------
/src/dialogs/shortcuts/show-shortcuts-dialog.ts:
--------------------------------------------------------------------------------
1 | import { fireEvent } from "../../common/dom/fire_event";
2 |
3 | export const showShortcutsDialog = (element: HTMLElement) =>
4 | fireEvent(element, "show-dialog", {
5 | dialogTag: "dialog-shortcuts",
6 | dialogImport: () => import("./dialog-shortcuts"),
7 | dialogParams: {},
8 | });
9 |
--------------------------------------------------------------------------------
/src/dialogs/sidebar/show-dialog-edit-sidebar.ts:
--------------------------------------------------------------------------------
1 | import { fireEvent } from "../../common/dom/fire_event";
2 |
3 | export const loadEditSidebarDialog = () => import("./dialog-edit-sidebar");
4 |
5 | export const showEditSidebarDialog = (element: HTMLElement): void => {
6 | fireEvent(element, "show-dialog", {
7 | dialogTag: "dialog-edit-sidebar",
8 | dialogImport: loadEditSidebarDialog,
9 | dialogParams: {},
10 | });
11 | };
12 |
--------------------------------------------------------------------------------
/src/dialogs/tts-try/show-dialog-tts-try.ts:
--------------------------------------------------------------------------------
1 | import { fireEvent } from "../../common/dom/fire_event";
2 |
3 | export interface TTSTryDialogParams {
4 | engine: string;
5 | language?: string;
6 | voice?: string;
7 | }
8 |
9 | export const loadTTSTryDialog = () => import("./dialog-tts-try");
10 |
11 | export const showTTSTryDialog = (
12 | element: HTMLElement,
13 | dialogParams: TTSTryDialogParams
14 | ): void => {
15 | fireEvent(element, "show-dialog", {
16 | addHistory: false,
17 | dialogTag: "dialog-tts-try",
18 | dialogImport: loadTTSTryDialog,
19 | dialogParams,
20 | });
21 | };
22 |
--------------------------------------------------------------------------------
/src/entrypoints/app.ts:
--------------------------------------------------------------------------------
1 | import "@webcomponents/scoped-custom-element-registry/scoped-custom-element-registry.min";
2 | import "../layouts/home-assistant";
3 |
4 | import("../resources/append-ha-style");
5 |
--------------------------------------------------------------------------------
/src/entrypoints/authorize.ts:
--------------------------------------------------------------------------------
1 | import "../auth/ha-authorize";
2 |
3 | import("../resources/append-ha-style");
4 |
--------------------------------------------------------------------------------
/src/entrypoints/onboarding.ts:
--------------------------------------------------------------------------------
1 | import "../onboarding/ha-onboarding";
2 |
3 | import("../resources/append-ha-style");
4 |
5 | declare global {
6 | interface Window {
7 | stepsPromise: Promise;
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/src/html/_header.html.template:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | <% for (const entry of latestEntryJS) { %>
5 |
6 | <% } %>
7 |
--------------------------------------------------------------------------------
/src/html/_preload_roboto.html.template:
--------------------------------------------------------------------------------
1 |
16 |
--------------------------------------------------------------------------------
/src/html/_script_loader.html.template:
--------------------------------------------------------------------------------
1 |
9 |
18 |
--------------------------------------------------------------------------------
/src/html/_style_base.html.template:
--------------------------------------------------------------------------------
1 |
2 |
13 |
--------------------------------------------------------------------------------
/src/onboarding/dialogs/show-app-dialog.ts:
--------------------------------------------------------------------------------
1 | import { fireEvent } from "../../common/dom/fire_event";
2 | import type { LocalizeFunc } from "../../common/translations/localize";
3 |
4 | export const loadAppDialog = () => import("./app-dialog");
5 |
6 | export const showAppDialog = (
7 | element: HTMLElement,
8 | params: { localize: LocalizeFunc }
9 | ): void => {
10 | fireEvent(element, "show-dialog", {
11 | dialogTag: "app-dialog",
12 | dialogImport: loadAppDialog,
13 | dialogParams: params,
14 | });
15 | };
16 |
--------------------------------------------------------------------------------
/src/onboarding/dialogs/show-community-dialog.ts:
--------------------------------------------------------------------------------
1 | import { fireEvent } from "../../common/dom/fire_event";
2 | import type { LocalizeFunc } from "../../common/translations/localize";
3 |
4 | export const loadCommunityDialog = () => import("./community-dialog");
5 |
6 | export const showCommunityDialog = (
7 | element: HTMLElement,
8 | params: { localize: LocalizeFunc }
9 | ): void => {
10 | fireEvent(element, "show-dialog", {
11 | dialogTag: "community-dialog",
12 | dialogImport: loadCommunityDialog,
13 | dialogParams: params,
14 | });
15 | };
16 |
--------------------------------------------------------------------------------
/src/panels/config/automation/structs.ts:
--------------------------------------------------------------------------------
1 | import { object, optional, number, string, boolean } from "superstruct";
2 |
3 | export const baseTriggerStruct = object({
4 | trigger: string(),
5 | id: optional(string()),
6 | enabled: optional(boolean()),
7 | });
8 |
9 | export const forDictStruct = object({
10 | days: optional(number()),
11 | hours: optional(number()),
12 | minutes: optional(number()),
13 | seconds: optional(number()),
14 | });
15 |
--------------------------------------------------------------------------------
/src/panels/config/backup/dialogs/show-dialog-local-backup-location.ts:
--------------------------------------------------------------------------------
1 | import { fireEvent } from "../../../../common/dom/fire_event";
2 |
3 | export interface LocalBackupLocationDialogParams {}
4 |
5 | export const showLocalBackupLocationDialog = (
6 | element: HTMLElement,
7 | dialogParams: LocalBackupLocationDialogParams
8 | ): void => {
9 | fireEvent(element, "show-dialog", {
10 | dialogTag: "dialog-local-backup-location",
11 | dialogImport: () => import("./dialog-local-backup-location"),
12 | dialogParams,
13 | });
14 | };
15 |
--------------------------------------------------------------------------------
/src/panels/config/backup/dialogs/show-dialog-show-backup-encryption-key.ts:
--------------------------------------------------------------------------------
1 | import { fireEvent } from "../../../../common/dom/fire_event";
2 |
3 | export interface ShowBackupEncryptionKeyDialogParams {
4 | currentKey: string;
5 | }
6 |
7 | const loadDialog = () => import("./dialog-show-backup-encryption-key");
8 |
9 | export const showShowBackupEncryptionKeyDialog = (
10 | element: HTMLElement,
11 | params?: ShowBackupEncryptionKeyDialogParams
12 | ) =>
13 | fireEvent(element, "show-dialog", {
14 | dialogTag: "ha-dialog-show-backup-encryption-key",
15 | dialogImport: loadDialog,
16 | dialogParams: params,
17 | });
18 |
--------------------------------------------------------------------------------
/src/panels/config/blueprint/show-dialog-import-blueprint.ts:
--------------------------------------------------------------------------------
1 | import { fireEvent } from "../../../common/dom/fire_event";
2 |
3 | export const loadImportBlueprintDialog = () =>
4 | import("./dialog-import-blueprint");
5 |
6 | export const showAddBlueprintDialog = (
7 | element: HTMLElement,
8 | dialogParams
9 | ): void => {
10 | fireEvent(element, "show-dialog", {
11 | dialogTag: "ha-dialog-import-blueprint",
12 | dialogImport: loadImportBlueprintDialog,
13 | dialogParams,
14 | });
15 | };
16 |
--------------------------------------------------------------------------------
/src/panels/config/cloud/account/show-dialog-cloud-support-package.ts:
--------------------------------------------------------------------------------
1 | import { fireEvent } from "../../../../common/dom/fire_event";
2 |
3 | export const loadSupportPackageDialog = () =>
4 | import("./dialog-cloud-support-package");
5 |
6 | export const showSupportPackageDialog = (element: HTMLElement): void => {
7 | fireEvent(element, "show-dialog", {
8 | dialogTag: "dialog-cloud-support-package",
9 | dialogImport: loadSupportPackageDialog,
10 | dialogParams: {},
11 | });
12 | };
13 |
--------------------------------------------------------------------------------
/src/panels/config/cloud/account/show-dialog-cloud-tts-try.ts:
--------------------------------------------------------------------------------
1 | import { fireEvent } from "../../../../common/dom/fire_event";
2 |
3 | export interface TryTtsDialogParams {
4 | defaultVoice: [string, string];
5 | }
6 |
7 | export const loadTryTtsDialog = () => import("./dialog-cloud-tts-try");
8 |
9 | export const showTryTtsDialog = (
10 | element: HTMLElement,
11 | dialogParams: TryTtsDialogParams
12 | ): void => {
13 | fireEvent(element, "show-dialog", {
14 | dialogTag: "dialog-cloud-try-tts",
15 | dialogImport: loadTryTtsDialog,
16 | dialogParams,
17 | });
18 | };
19 |
--------------------------------------------------------------------------------
/src/panels/config/core/updates/show-dialog-join-beta.ts:
--------------------------------------------------------------------------------
1 | import { fireEvent } from "../../../../common/dom/fire_event";
2 | import "./dialog-join-beta";
3 |
4 | export interface JoinBetaDialogParams {
5 | join?: () => any;
6 | cancel?: () => any;
7 | }
8 |
9 | export const showJoinBetaDialog = (
10 | element: HTMLElement,
11 | dialogParams: JoinBetaDialogParams
12 | ): void => {
13 | fireEvent(element, "show-dialog", {
14 | dialogTag: "dialog-join-beta",
15 | dialogImport: () => import("./dialog-join-beta"),
16 | dialogParams,
17 | });
18 | };
19 |
--------------------------------------------------------------------------------
/src/panels/config/entities/const.ts:
--------------------------------------------------------------------------------
1 | /** Platforms that have a settings tab. */
2 | export const PLATFORMS_WITH_SETTINGS_TAB = {
3 | input_number: "entity-settings-helper-tab",
4 | input_select: "entity-settings-helper-tab",
5 | input_text: "entity-settings-helper-tab",
6 | input_boolean: "entity-settings-helper-tab",
7 | input_datetime: "entity-settings-helper-tab",
8 | counter: "entity-settings-helper-tab",
9 | timer: "entity-settings-helper-tab",
10 | input_button: "entity-settings-helper-tab",
11 | schedule: "entity-settings-helper-tab",
12 | };
13 |
--------------------------------------------------------------------------------
/src/panels/config/hardware/show-dialog-hardware-available.ts:
--------------------------------------------------------------------------------
1 | import { fireEvent } from "../../../common/dom/fire_event";
2 |
3 | export const loadHardwareAvailableDialog = () =>
4 | import("./dialog-hardware-available");
5 |
6 | export const showhardwareAvailableDialog = (element: HTMLElement): void => {
7 | fireEvent(element, "show-dialog", {
8 | dialogTag: "ha-dialog-hardware-available",
9 | dialogImport: loadHardwareAvailableDialog,
10 | dialogParams: {},
11 | });
12 | };
13 |
--------------------------------------------------------------------------------
/src/panels/config/integrations/integration-panels/matter/show-dialog-add-matter-device.ts:
--------------------------------------------------------------------------------
1 | import { fireEvent } from "../../../../../common/dom/fire_event";
2 |
3 | export const loadAddDeviceDialog = () => import("./dialog-matter-add-device");
4 |
5 | export const showMatterAddDeviceDialog = (element: HTMLElement): void => {
6 | fireEvent(element, "show-dialog", {
7 | dialogTag: "dialog-matter-add-device",
8 | dialogImport: loadAddDeviceDialog,
9 | dialogParams: {},
10 | });
11 | };
12 |
--------------------------------------------------------------------------------
/src/panels/config/logs/show-dialog-download-logs.ts:
--------------------------------------------------------------------------------
1 | import { fireEvent } from "../../../common/dom/fire_event";
2 |
3 | export interface DownloadLogsDialogParams {
4 | header?: string;
5 | provider: string;
6 | defaultLineCount?: number;
7 | boot: number;
8 | }
9 |
10 | export const showDownloadLogsDialog = (
11 | element: HTMLElement,
12 | dialogParams: DownloadLogsDialogParams
13 | ): void => {
14 | fireEvent(element, "show-dialog", {
15 | dialogTag: "dialog-download-logs",
16 | dialogImport: () => import("./dialog-download-logs"),
17 | dialogParams,
18 | });
19 | };
20 |
--------------------------------------------------------------------------------
/src/panels/config/repairs/show-integration-startup-dialog.ts:
--------------------------------------------------------------------------------
1 | import { fireEvent } from "../../../common/dom/fire_event";
2 |
3 | export const loadIntegrationStartupDialog = () =>
4 | import("./dialog-integration-startup");
5 |
6 | export const showIntegrationStartupDialog = (element: HTMLElement): void => {
7 | fireEvent(element, "show-dialog", {
8 | dialogTag: "dialog-integration-startup",
9 | dialogImport: loadIntegrationStartupDialog,
10 | dialogParams: {},
11 | });
12 | };
13 |
--------------------------------------------------------------------------------
/src/panels/config/repairs/show-system-information-dialog.ts:
--------------------------------------------------------------------------------
1 | import { fireEvent } from "../../../common/dom/fire_event";
2 |
3 | export const loadSystemInformationDialog = () =>
4 | import("./dialog-system-information");
5 |
6 | export const showSystemInformationDialog = (element: HTMLElement): void => {
7 | fireEvent(element, "show-dialog", {
8 | dialogTag: "dialog-system-information",
9 | dialogImport: loadSystemInformationDialog,
10 | dialogParams: undefined,
11 | });
12 | };
13 |
--------------------------------------------------------------------------------
/src/panels/config/storage/show-dialog-move-datadisk.ts:
--------------------------------------------------------------------------------
1 | import { fireEvent } from "../../../common/dom/fire_event";
2 | import type { HassioHostInfo } from "../../../data/hassio/host";
3 |
4 | export interface MoveDatadiskDialogParams {
5 | hostInfo: HassioHostInfo;
6 | }
7 |
8 | export const showMoveDatadiskDialog = (
9 | element: HTMLElement,
10 | dialogParams: MoveDatadiskDialogParams
11 | ): void => {
12 | fireEvent(element, "show-dialog", {
13 | dialogTag: "dialog-move-datadisk",
14 | dialogImport: () => import("./dialog-move-datadisk"),
15 | dialogParams,
16 | });
17 | };
18 |
--------------------------------------------------------------------------------
/src/panels/config/storage/show-dialog-view-mount.ts:
--------------------------------------------------------------------------------
1 | import { fireEvent } from "../../../common/dom/fire_event";
2 | import type { SupervisorMount } from "../../../data/supervisor/mounts";
3 |
4 | export interface MountViewDialogParams {
5 | mount?: SupervisorMount;
6 | reloadMounts: () => void;
7 | }
8 |
9 | export const showMountViewDialog = (
10 | element: HTMLElement,
11 | dialogParams: MountViewDialogParams
12 | ): void => {
13 | fireEvent(element, "show-dialog", {
14 | dialogTag: "dialog-mount-view",
15 | dialogImport: () => import("./dialog-mount-view"),
16 | dialogParams,
17 | });
18 | };
19 |
--------------------------------------------------------------------------------
/src/panels/config/users/show-dialog-add-user.ts:
--------------------------------------------------------------------------------
1 | import { fireEvent } from "../../../common/dom/fire_event";
2 | import type { User } from "../../../data/user";
3 |
4 | export interface AddUserDialogParams {
5 | userAddedCallback: (user: User) => void;
6 | name?: string;
7 | }
8 |
9 | export const loadAddUserDialog = () => import("./dialog-add-user");
10 |
11 | export const showAddUserDialog = (
12 | element: HTMLElement,
13 | dialogParams: AddUserDialogParams
14 | ): void => {
15 | fireEvent(element, "show-dialog", {
16 | dialogTag: "dialog-add-user",
17 | dialogImport: loadAddUserDialog,
18 | dialogParams,
19 | });
20 | };
21 |
--------------------------------------------------------------------------------
/src/panels/config/users/show-dialog-admin-change-password.ts:
--------------------------------------------------------------------------------
1 | import { fireEvent } from "../../../common/dom/fire_event";
2 |
3 | export interface AdminChangePasswordDialogParams {
4 | userId: string;
5 | }
6 |
7 | export const loadAdminChangePasswordDialog = () =>
8 | import("./dialog-admin-change-password");
9 |
10 | export const showAdminChangePasswordDialog = (
11 | element: HTMLElement,
12 | dialogParams: AdminChangePasswordDialogParams
13 | ): void => {
14 | fireEvent(element, "show-dialog", {
15 | dialogTag: "dialog-admin-change-password",
16 | dialogImport: loadAdminChangePasswordDialog,
17 | dialogParams,
18 | });
19 | };
20 |
--------------------------------------------------------------------------------
/src/panels/lovelace/card-features/common/filter-modes.ts:
--------------------------------------------------------------------------------
1 | export const filterModes = (
2 | supportedModes: T[] | undefined,
3 | selectedModes: T[] | undefined
4 | ): T[] =>
5 | selectedModes
6 | ? selectedModes.filter((mode) => (supportedModes || []).includes(mode))
7 | : supportedModes || [];
8 |
--------------------------------------------------------------------------------
/src/panels/lovelace/cards/hui-entity-button-card.ts:
--------------------------------------------------------------------------------
1 | import { customElement } from "lit/decorators";
2 | import { HuiButtonCard } from "./hui-button-card";
3 |
4 | @customElement("hui-entity-button-card")
5 | class HuiEntityButtonCard extends HuiButtonCard {
6 | public setConfig(config): void {
7 | if (!config.entity) {
8 | throw new Error("Entity must be specified");
9 | }
10 | super.setConfig(config);
11 | }
12 | }
13 |
14 | declare global {
15 | interface HTMLElementTagNameMap {
16 | "hui-entity-button-card": HuiEntityButtonCard;
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/src/panels/lovelace/common/entity/toggle-entity.ts:
--------------------------------------------------------------------------------
1 | import { STATES_OFF } from "../../../../common/const";
2 | import type { HomeAssistant, ServiceCallResponse } from "../../../../types";
3 | import { turnOnOffEntity } from "./turn-on-off-entity";
4 |
5 | export const toggleEntity = (
6 | hass: HomeAssistant,
7 | entityId: string
8 | ): Promise => {
9 | const turnOn = STATES_OFF.includes(hass.states[entityId].state);
10 | return turnOnOffEntity(hass, entityId, turnOn);
11 | };
12 |
--------------------------------------------------------------------------------
/src/panels/lovelace/common/has-action.ts:
--------------------------------------------------------------------------------
1 | import type { ActionConfig } from "../../../data/lovelace/config/action";
2 | import type { ConfigEntity } from "../cards/types";
3 |
4 | export function hasAction(config?: ActionConfig): boolean {
5 | return config !== undefined && config.action !== "none";
6 | }
7 |
8 | export function hasAnyAction(config: ConfigEntity): boolean {
9 | return (
10 | !config.tap_action ||
11 | hasAction(config.tap_action) ||
12 | hasAction(config.hold_action) ||
13 | hasAction(config.double_tap_action)
14 | );
15 | }
16 |
--------------------------------------------------------------------------------
/src/panels/lovelace/common/icon-condition.ts:
--------------------------------------------------------------------------------
1 | import {
2 | mdiAccount,
3 | mdiAmpersand,
4 | mdiGateOr,
5 | mdiNumeric,
6 | mdiResponsive,
7 | mdiStateMachine,
8 | } from "@mdi/js";
9 | import type { Condition } from "./validate-condition";
10 |
11 | export const ICON_CONDITION: Record = {
12 | numeric_state: mdiNumeric,
13 | state: mdiStateMachine,
14 | screen: mdiResponsive,
15 | user: mdiAccount,
16 | and: mdiAmpersand,
17 | or: mdiGateOr,
18 | };
19 |
--------------------------------------------------------------------------------
/src/panels/lovelace/common/is-valid-object.ts:
--------------------------------------------------------------------------------
1 | // Check if given obj is a JS object and optionally contains all required keys
2 | export default function isValidObject(obj, requiredKeys = []) {
3 | return (
4 | obj &&
5 | typeof obj === "object" &&
6 | !Array.isArray(obj) &&
7 | requiredKeys.every((k) => k in obj)
8 | );
9 | }
10 |
--------------------------------------------------------------------------------
/src/panels/lovelace/editor/conditions/types.ts:
--------------------------------------------------------------------------------
1 | import type { HomeAssistant } from "../../../../types";
2 | import type { Condition } from "../../common/validate-condition";
3 |
4 | export interface LovelaceConditionEditorConstructor {
5 | defaultConfig?: Condition;
6 | validateUIConfig?: (condition: Condition, hass: HomeAssistant) => void;
7 | }
8 |
--------------------------------------------------------------------------------
/src/panels/lovelace/editor/gui-support-error.ts:
--------------------------------------------------------------------------------
1 | export class GUISupportError extends Error {
2 | public warnings?: string[];
3 |
4 | public errors?: string[];
5 |
6 | constructor(message: string, warnings?: string[], errors?: string[]) {
7 | super(message);
8 | this.name = "GUISupportError";
9 | this.warnings = warnings;
10 | this.errors = errors;
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/src/panels/lovelace/editor/lovelace-badges.ts:
--------------------------------------------------------------------------------
1 | import type { Badge } from "./types";
2 |
3 | export const coreBadges: Badge[] = [
4 | {
5 | type: "entity",
6 | showElement: true,
7 | },
8 | ];
9 |
--------------------------------------------------------------------------------
/src/panels/lovelace/editor/lovelace-headerfooters.ts:
--------------------------------------------------------------------------------
1 | import {
2 | mdiChartBellCurveCumulative,
3 | mdiGestureTapButton,
4 | mdiImageArea,
5 | } from "@mdi/js";
6 | import type { HeaderFooter } from "./types";
7 |
8 | export const headerFooterElements: HeaderFooter[] = [
9 | { type: "graph", icon: mdiChartBellCurveCumulative },
10 | { type: "buttons", icon: mdiGestureTapButton },
11 | { type: "picture", icon: mdiImageArea },
12 | ];
13 |
--------------------------------------------------------------------------------
/src/panels/lovelace/editor/process-editor-entities.ts:
--------------------------------------------------------------------------------
1 | import type { EntityConfig } from "../entity-rows/types";
2 |
3 | export function processEditorEntities(
4 | entities: (any | string)[]
5 | ): EntityConfig[] {
6 | return entities.map((entityConf) => {
7 | if (typeof entityConf === "string") {
8 | return { entity: entityConf };
9 | }
10 | return entityConf;
11 | });
12 | }
13 |
--------------------------------------------------------------------------------
/src/panels/lovelace/editor/structs/base-badge-struct.ts:
--------------------------------------------------------------------------------
1 | import { object, string, any } from "superstruct";
2 |
3 | export const baseLovelaceBadgeConfig = object({
4 | type: string(),
5 | visibility: any(),
6 | });
7 |
--------------------------------------------------------------------------------
/src/panels/lovelace/editor/structs/base-card-struct.ts:
--------------------------------------------------------------------------------
1 | import { object, string, any } from "superstruct";
2 |
3 | export const baseLovelaceCardConfig = object({
4 | type: string(),
5 | view_layout: any(),
6 | layout_options: any(),
7 | grid_options: any(),
8 | visibility: any(),
9 | });
10 |
--------------------------------------------------------------------------------
/src/panels/lovelace/editor/structs/button-entity-struct.ts:
--------------------------------------------------------------------------------
1 | import { boolean, object, optional, string } from "superstruct";
2 | import { actionConfigStruct } from "./action-struct";
3 |
4 | export const buttonEntityConfigStruct = object({
5 | entity: string(),
6 | name: optional(string()),
7 | icon: optional(string()),
8 | image: optional(string()),
9 | show_name: optional(boolean()),
10 | show_icon: optional(boolean()),
11 | tap_action: optional(actionConfigStruct),
12 | hold_action: optional(actionConfigStruct),
13 | double_tap_action: optional(actionConfigStruct),
14 | });
15 |
--------------------------------------------------------------------------------
/src/panels/lovelace/sections/const.ts:
--------------------------------------------------------------------------------
1 | export const GRID_SECTION_LAYOUT = "grid";
2 | export const DEFAULT_SECTION_LAYOUT = GRID_SECTION_LAYOUT;
3 |
--------------------------------------------------------------------------------
/src/panels/lovelace/views/const.ts:
--------------------------------------------------------------------------------
1 | export const MASONRY_VIEW_LAYOUT = "masonry";
2 | export const PANEL_VIEW_LAYOUT = "panel";
3 | export const SIDEBAR_VIEW_LAYOUT = "sidebar";
4 | export const SECTIONS_VIEW_LAYOUT = "sections";
5 |
6 | export const CARD_LAYOUTS = [
7 | MASONRY_VIEW_LAYOUT,
8 | PANEL_VIEW_LAYOUT,
9 | SIDEBAR_VIEW_LAYOUT,
10 | ];
11 | export const SECTION_VIEW_LAYOUTS = [SECTIONS_VIEW_LAYOUT];
12 |
--------------------------------------------------------------------------------
/src/panels/lovelace/views/default-section.ts:
--------------------------------------------------------------------------------
1 | import type { LocalizeFunc } from "../../../common/translations/localize";
2 |
3 | export const generateDefaultSection = (localize: LocalizeFunc) => ({
4 | type: "grid",
5 | cards: [
6 | {
7 | type: "heading",
8 | heading: localize(
9 | "ui.panel.lovelace.editor.section.default_section_title"
10 | ),
11 | },
12 | ],
13 | });
14 |
--------------------------------------------------------------------------------
/src/panels/lovelace/views/default-view-editable.ts:
--------------------------------------------------------------------------------
1 | // hui-view dependencies for when in edit mode.
2 | import "../../../components/ha-fab";
3 | import "../components/hui-card-options";
4 | import { importCreateCardDialog } from "../editor/card-editor/show-create-card-dialog";
5 | import { importDeleteCardDialog } from "../editor/card-editor/show-delete-card-dialog";
6 | import { importEditCardDialog } from "../editor/card-editor/show-edit-card-dialog";
7 |
8 | importCreateCardDialog();
9 | importDeleteCardDialog();
10 | importEditCardDialog();
11 |
--------------------------------------------------------------------------------
/src/panels/lovelace/views/get-view-type.ts:
--------------------------------------------------------------------------------
1 | import type { LovelaceViewConfig } from "../../../data/lovelace/config/view";
2 | import {
3 | MASONRY_VIEW_LAYOUT,
4 | PANEL_VIEW_LAYOUT,
5 | SECTIONS_VIEW_LAYOUT,
6 | } from "./const";
7 |
8 | export const getViewType = (config?: LovelaceViewConfig): string => {
9 | if (config?.type) {
10 | return config.type;
11 | }
12 | if (config?.panel) {
13 | return PANEL_VIEW_LAYOUT;
14 | }
15 | if (config?.sections) {
16 | return SECTIONS_VIEW_LAYOUT;
17 | }
18 | if (config?.cards) {
19 | return MASONRY_VIEW_LAYOUT;
20 | }
21 | return SECTIONS_VIEW_LAYOUT;
22 | };
23 |
--------------------------------------------------------------------------------
/src/panels/profile/show-long-lived-access-token-dialog.ts:
--------------------------------------------------------------------------------
1 | import { fireEvent } from "../../common/dom/fire_event";
2 |
3 | export interface LongLivedAccessTokenDialogParams {
4 | token: string;
5 | name: string;
6 | }
7 |
8 | export const showLongLivedAccessTokenDialog = (
9 | element: HTMLElement,
10 | longLivedAccessTokenDialogParams: LongLivedAccessTokenDialogParams
11 | ): void => {
12 | fireEvent(element, "show-dialog", {
13 | dialogTag: "ha-long-lived-access-token-dialog",
14 | dialogImport: () => import("./ha-long-lived-access-token-dialog"),
15 | dialogParams: longLivedAccessTokenDialogParams,
16 | });
17 | };
18 |
--------------------------------------------------------------------------------
/src/resources/append-ha-style.ts:
--------------------------------------------------------------------------------
1 | import { themeStyles } from "./theme/theme";
2 |
3 | const styleElement = document.createElement("style");
4 | styleElement.textContent = themeStyles;
5 | document.head.append(styleElement);
6 |
--------------------------------------------------------------------------------
/src/resources/custom-card-support.ts:
--------------------------------------------------------------------------------
1 | import { css, html, LitElement } from "lit";
2 |
3 | (LitElement.prototype as any).html = html;
4 | (LitElement.prototype as any).css = css;
5 |
--------------------------------------------------------------------------------
/src/resources/hammer.ts:
--------------------------------------------------------------------------------
1 | export {
2 | DIRECTION_LEFT,
3 | DIRECTION_RIGHT,
4 | Manager,
5 | Swipe,
6 | } from "@egjs/hammerjs";
7 |
--------------------------------------------------------------------------------
/src/resources/icon-metadata.ts:
--------------------------------------------------------------------------------
1 | import * as iconMetadata_ from "../../build/mdi/iconMetadata.json";
2 | import type { IconMetaFile } from "../types.js";
3 |
4 | export const iconMetadata = (iconMetadata_ as any).default as IconMetaFile;
5 |
--------------------------------------------------------------------------------
/src/resources/polyfills/element-getattributenames.ts:
--------------------------------------------------------------------------------
1 | // Source: https://developer.mozilla.org/en-US/docs/Web/API/Element/getAttributeNames
2 | if (Element.prototype.getAttributeNames === undefined) {
3 | Element.prototype.getAttributeNames = function () {
4 | const attributes = this.attributes;
5 | const length = attributes.length;
6 | const result = new Array(length);
7 | for (let i = 0; i < length; i++) {
8 | result[i] = attributes[i].name;
9 | }
10 | return result;
11 | };
12 | }
13 |
--------------------------------------------------------------------------------
/src/resources/polyfills/element-toggleattribute.ts:
--------------------------------------------------------------------------------
1 | // Source: https://gist.github.com/rebelchris/365f26f95d7e9f432f64f21886d9b9ef
2 | if (!Element.prototype.toggleAttribute) {
3 | Element.prototype.toggleAttribute = function (name, force) {
4 | if (force !== undefined) {
5 | force = !!force;
6 | }
7 |
8 | if (this.hasAttribute(name)) {
9 | if (force) {
10 | return true;
11 | }
12 |
13 | this.removeAttribute(name);
14 | return false;
15 | }
16 | if (force === false) {
17 | return false;
18 | }
19 |
20 | this.setAttribute(name, "");
21 | return true;
22 | };
23 | }
24 |
--------------------------------------------------------------------------------
/src/resources/polyfills/resize-observer.ts:
--------------------------------------------------------------------------------
1 | if (typeof window.ResizeObserver !== "function") {
2 | window.ResizeObserver = (
3 | await import(
4 | "@lit-labs/virtualizer/polyfills/resize-observer-polyfill/ResizeObserver"
5 | )
6 | ).default;
7 | }
8 |
9 | export {};
10 |
--------------------------------------------------------------------------------
/src/resources/sortable.ts:
--------------------------------------------------------------------------------
1 | import type Sortable from "sortablejs";
2 | import SortableCore, {
3 | AutoScroll,
4 | OnSpill,
5 | } from "sortablejs/modular/sortable.core.esm";
6 |
7 | SortableCore.mount(OnSpill);
8 | SortableCore.mount(new AutoScroll());
9 |
10 | export default SortableCore as typeof Sortable;
11 |
12 | export type { Sortable as SortableInstance };
13 |
--------------------------------------------------------------------------------
/src/resources/theme/theme.ts:
--------------------------------------------------------------------------------
1 | import { fontStyles } from "../roboto";
2 | import { colorDerivedVariables, colorStyles } from "./color.globals";
3 | import { mainDerivedVariables, mainStyles } from "./main.globals";
4 | import {
5 | typographyDerivedVariables,
6 | typographyStyles,
7 | } from "./typography.globals";
8 |
9 | export const themeStyles = [
10 | mainStyles.toString(),
11 | typographyStyles.toString(),
12 | colorStyles.toString(),
13 | fontStyles.toString(),
14 | ].join("");
15 |
16 | export const derivedStyles = {
17 | ...mainDerivedVariables,
18 | ...typographyDerivedVariables,
19 | ...colorDerivedVariables,
20 | };
21 |
--------------------------------------------------------------------------------
/src/resources/translations-metadata.ts:
--------------------------------------------------------------------------------
1 | import * as translationMetadata_ from "../../build/translations/translationMetadata.json";
2 | import type { TranslationMetadata } from "../types.js";
3 |
4 | export const translationMetadata = (translationMetadata_ as any)
5 | .default as TranslationMetadata;
6 |
--------------------------------------------------------------------------------
/src/resources/virtualizer.ts:
--------------------------------------------------------------------------------
1 | export const loadVirtualizer = async () => {
2 | await import("@lit-labs/virtualizer");
3 | };
4 |
--------------------------------------------------------------------------------
/src/state/notification-mixin.ts:
--------------------------------------------------------------------------------
1 | import type { Constructor } from "../types";
2 | import type { HassBaseEl } from "./hass-base-mixin";
3 |
4 | export default >(superClass: T) =>
5 | class extends superClass {
6 | protected firstUpdated(changedProps) {
7 | super.firstUpdated(changedProps);
8 | // @ts-ignore
9 | this.registerDialog({
10 | dialogShowEvent: "hass-notification",
11 | dialogTag: "notification-manager",
12 | dialogImport: () => import("../managers/notification-manager"),
13 | addHistory: false,
14 | });
15 | }
16 | };
17 |
--------------------------------------------------------------------------------
/src/types/echarts.d.ts:
--------------------------------------------------------------------------------
1 | declare module "echarts/lib/chart/graph/install" {
2 | export const install: EChartsExtensionInstaller;
3 | }
4 |
--------------------------------------------------------------------------------
/src/types/node-vibrant.d.ts:
--------------------------------------------------------------------------------
1 | // eslint-disable-next-line no-var
2 | declare var Vibrant: Any;
3 | declare module "node-vibrant" {
4 | export default Vibrant;
5 | }
6 |
--------------------------------------------------------------------------------
/src/util/bytes-to-string.ts:
--------------------------------------------------------------------------------
1 | export const bytesToString = (value = 0, decimals = 2): string => {
2 | if (value === 0) {
3 | return "0 Bytes";
4 | }
5 | const k = 1024;
6 | decimals = decimals < 0 ? 0 : decimals;
7 | const sizes = ["Bytes", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"];
8 | const i = Math.floor(Math.log(value) / Math.log(k));
9 | return `${parseFloat((value / k ** i).toFixed(decimals))} ${sizes[i]}`;
10 | };
11 |
--------------------------------------------------------------------------------
/src/util/custom-panel/create-custom-panel-element.ts:
--------------------------------------------------------------------------------
1 | export const createCustomPanelElement = (panelConfig) => {
2 | // Legacy support. Custom panels used to have to define element ha-panel-{name}
3 | const tagName =
4 | "html_url" in panelConfig
5 | ? `ha-panel-${panelConfig.name}`
6 | : panelConfig.name;
7 | return document.createElement(tagName);
8 | };
9 |
--------------------------------------------------------------------------------
/src/util/custom-panel/set-custom-panel-properties.ts:
--------------------------------------------------------------------------------
1 | export const setCustomPanelProperties = (root, properties) => {
2 | if ("setProperties" in root) {
3 | root.setProperties(properties);
4 | } else {
5 | Object.keys(properties).forEach((key) => {
6 | root[key] = properties[key];
7 | });
8 | }
9 | };
10 |
--------------------------------------------------------------------------------
/src/util/documentation-url.ts:
--------------------------------------------------------------------------------
1 | import type { HomeAssistant } from "../types";
2 |
3 | export const documentationUrl = (hass: HomeAssistant, path: string) =>
4 | `https://${
5 | hass.config.version.includes("b")
6 | ? "rc"
7 | : hass.config.version.includes("dev")
8 | ? "next"
9 | : "www"
10 | }.home-assistant.io${path}`;
11 |
--------------------------------------------------------------------------------
/src/util/empty.js:
--------------------------------------------------------------------------------
1 | /* empty file that we alias some files to that we don't want to include */
2 |
3 | export {}; // for Babel to treat as a module
4 |
--------------------------------------------------------------------------------
/src/util/fetch-with-auth.ts:
--------------------------------------------------------------------------------
1 | import type { Auth } from "home-assistant-js-websocket";
2 |
3 | export const fetchWithAuth = async (
4 | auth: Auth,
5 | input: RequestInfo,
6 | init: RequestInit = {}
7 | ) => {
8 | if (auth.expired) {
9 | await auth.refreshAccessToken();
10 | }
11 | init.credentials = "same-origin";
12 | if (!init.headers) {
13 | init.headers = {};
14 | }
15 | if (!init.headers) {
16 | init.headers = {};
17 | }
18 | // @ts-ignore
19 | init.headers.authorization = `Bearer ${auth.accessToken}`;
20 | return fetch(input, init);
21 | };
22 |
--------------------------------------------------------------------------------
/src/util/iframe.ts:
--------------------------------------------------------------------------------
1 | export const IFRAME_SANDBOX =
2 | "allow-forms allow-popups allow-pointer-lock allow-same-origin allow-scripts allow-modals allow-downloads";
3 |
--------------------------------------------------------------------------------
/src/util/is_ios.ts:
--------------------------------------------------------------------------------
1 | import type { HomeAssistant } from "../types";
2 | import { isSafari } from "./is_safari";
3 |
4 | export const isIosApp = (hass: HomeAssistant): boolean =>
5 | !!hass.auth.external && isSafari;
6 |
--------------------------------------------------------------------------------
/src/util/is_mac.ts:
--------------------------------------------------------------------------------
1 | export const isMac = /Mac/i.test(navigator.userAgent);
2 |
--------------------------------------------------------------------------------
/src/util/is_mobile.ts:
--------------------------------------------------------------------------------
1 | export const isMobileClient = /(?:iphone|android|ipad)/i.test(
2 | navigator.userAgent
3 | );
4 |
--------------------------------------------------------------------------------
/src/util/is_safari.ts:
--------------------------------------------------------------------------------
1 | export const isSafari = /^((?!chrome|android).)*safari/i.test(
2 | navigator.userAgent
3 | );
4 |
--------------------------------------------------------------------------------
/src/util/is_touch.ts:
--------------------------------------------------------------------------------
1 | export const isTouch =
2 | "ontouchstart" in window ||
3 | navigator.maxTouchPoints > 0 ||
4 | // @ts-ignore
5 | navigator.msMaxTouchPoints > 0;
6 |
--------------------------------------------------------------------------------
/src/util/launch-screen.ts:
--------------------------------------------------------------------------------
1 | import type { TemplateResult } from "lit";
2 | import { render } from "lit";
3 |
4 | export const removeLaunchScreen = () => {
5 | const launchScreenElement = document.getElementById("ha-launch-screen");
6 | if (launchScreenElement) {
7 | launchScreenElement.parentElement!.removeChild(launchScreenElement);
8 | }
9 | };
10 |
11 | export const renderLaunchScreenInfoBox = (content: TemplateResult) => {
12 | const infoBoxElement = document.getElementById("ha-launch-screen-info-box");
13 | if (infoBoxElement) {
14 | render(content, infoBoxElement);
15 | }
16 | };
17 |
--------------------------------------------------------------------------------
/src/util/toast-saved-success.ts:
--------------------------------------------------------------------------------
1 | import type { HomeAssistant } from "../types";
2 | import { showToast } from "./toast";
3 |
4 | export const showSaveSuccessToast = (el: HTMLElement, hass: HomeAssistant) =>
5 | showToast(el, {
6 | message: hass!.localize("ui.common.successfully_saved"),
7 | });
8 |
--------------------------------------------------------------------------------
/src/util/toast.ts:
--------------------------------------------------------------------------------
1 | import { fireEvent } from "../common/dom/fire_event";
2 | import type { ShowToastParams } from "../managers/notification-manager";
3 |
4 | export const showToast = (el: HTMLElement, params: ShowToastParams) =>
5 | fireEvent(el, "hass-notification", params);
6 |
--------------------------------------------------------------------------------
/src/util/url.ts:
--------------------------------------------------------------------------------
1 | export function obfuscateUrl(url: string) {
2 | if (url.endsWith(".ui.nabu.casa")) {
3 | return "https://•••••••••••••••••.ui.nabu.casa";
4 | }
5 | // hide any words that look like they might be a hostname or IP address
6 | return url.replace(/(?<=:\/\/)[\w-]+|(?<=\.)[\w-]+/g, (match) =>
7 | "•".repeat(match.length)
8 | );
9 | }
10 |
--------------------------------------------------------------------------------
/test/common/config/is_component_loaded.test.ts:
--------------------------------------------------------------------------------
1 | import { describe, it, expect } from "vitest";
2 | import { isComponentLoaded } from "../../../src/common/config/is_component_loaded";
3 | import type { HomeAssistant } from "../../../src/types";
4 |
5 | describe("isComponentLoaded", () => {
6 | it("should return if the component is loaded", () => {
7 | const hass = {
8 | config: { components: ["test_component"] },
9 | } as unknown as HomeAssistant;
10 | expect(isComponentLoaded(hass, "test_component")).toBe(true);
11 | expect(isComponentLoaded(hass, "other_component")).toBe(false);
12 | });
13 | });
14 |
--------------------------------------------------------------------------------
/test/common/datetime/duration_to_seconds.test.ts:
--------------------------------------------------------------------------------
1 | import { assert, describe, it } from "vitest";
2 |
3 | import durationToSeconds from "../../../src/common/datetime/duration_to_seconds";
4 |
5 | describe("durationToSeconds", () => {
6 | it("works", () => {
7 | assert.strictEqual(durationToSeconds("0:01:05"), 65);
8 | assert.strictEqual(durationToSeconds("11:01:05"), 39665);
9 | });
10 | });
11 |
--------------------------------------------------------------------------------
/test/common/datetime/resolve-time-zone.test.ts:
--------------------------------------------------------------------------------
1 | import { expect, test } from "vitest";
2 | import {
3 | LOCAL_TIME_ZONE,
4 | resolveTimeZone,
5 | } from "../../../src/common/datetime/resolve-time-zone";
6 | import { TimeZone } from "../../../src/data/translation";
7 |
8 | test("resolveTimeZone", () => {
9 | const serverTimeZone = "Vienna/Austria";
10 | expect(resolveTimeZone(TimeZone.local, serverTimeZone)).toBe(LOCAL_TIME_ZONE);
11 | expect(resolveTimeZone(TimeZone.server, serverTimeZone)).toBe(serverTimeZone);
12 | });
13 |
--------------------------------------------------------------------------------
/test/common/entity/compute_domain.test.ts:
--------------------------------------------------------------------------------
1 | import { assert, describe, it } from "vitest";
2 |
3 | import { computeDomain } from "../../../src/common/entity/compute_domain";
4 |
5 | describe("computeDomain", () => {
6 | it("Returns domains", () => {
7 | assert.equal(computeDomain("sensor.bla"), "sensor");
8 | assert.equal(computeDomain("switch.bla"), "switch");
9 | assert.equal(computeDomain("light.bla"), "light");
10 | assert.equal(
11 | computeDomain("persistent_notification.bla"),
12 | "persistent_notification"
13 | );
14 | });
15 | });
16 |
--------------------------------------------------------------------------------
/test/common/entity/compute_state_domain.test.ts:
--------------------------------------------------------------------------------
1 | import { assert, describe, it } from "vitest";
2 |
3 | import { computeStateDomain } from "../../../src/common/entity/compute_state_domain";
4 |
5 | describe("computeStateDomain", () => {
6 | it("Detects sensor domain", () => {
7 | const stateObj: any = {
8 | entity_id: "sensor.test",
9 | };
10 | assert.strictEqual(computeStateDomain(stateObj), "sensor");
11 | });
12 | });
13 |
--------------------------------------------------------------------------------
/test/common/entity/state_color.ts:
--------------------------------------------------------------------------------
1 | export {}; // for Babel to treat as a module
2 |
--------------------------------------------------------------------------------
/test/common/string/is_date.test.ts:
--------------------------------------------------------------------------------
1 | import { expect, test } from "vitest";
2 | import { isDate } from "../../../src/common/string/is_date";
3 |
4 | test("isDate", () => {
5 | expect(isDate("ABC")).toBe(false);
6 |
7 | expect(isDate("2021-02-03", false)).toBe(true);
8 | expect(isDate("2021-02-03", true)).toBe(true);
9 |
10 | expect(isDate("2021-05-25T19:23:52+00:00", true)).toBe(true);
11 | expect(isDate("2021-05-25T19:23:52+00:00", false)).toBe(false);
12 | });
13 |
--------------------------------------------------------------------------------
/test/setup.ts:
--------------------------------------------------------------------------------
1 | import { beforeAll } from "vitest";
2 |
3 | beforeAll(() => {
4 | global.window = {} as any;
5 | global.navigator = {} as any;
6 |
7 | global.__DEMO__ = false;
8 | });
9 |
--------------------------------------------------------------------------------