├── .editorconfig ├── .eslintrc.json ├── .gitattributes ├── .github ├── FUNDING.yml ├── ISSUE_TEMPLATE │ ├── bug_report.yml │ ├── config.yml │ └── feature_request.yml ├── PULL_REQUEST_TEMPLATE.md ├── PULL_REQUEST_TEMPLATE │ ├── bugfix.md │ ├── feature.md │ └── translation.md ├── dependabot.yml └── workflows │ ├── deploy-docs.yml │ ├── validate.yml │ └── webpack.yml ├── .gitignore ├── .markdownlint.jsonc ├── .prettierrc ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── dist └── mushroom-strategy.js ├── docs ├── contributing │ ├── code.md │ ├── documentation.md │ ├── getting-started.md │ ├── index.md │ ├── translations.md │ └── workflow.md ├── faq.md ├── full-example.md ├── getting-started │ ├── basic-setup.md │ └── installation.md ├── images │ ├── Hidden.png │ ├── additonal_cards.png │ ├── auto.png │ ├── chips.png │ ├── customizable.png │ ├── light_view.png │ ├── preview.gif │ └── views.png ├── index.md ├── options │ ├── area-options.md │ ├── card-options.md │ ├── domain-options.md │ ├── home-view-options.md │ ├── index.md │ └── view-options.md └── stylesheets │ └── extra.css ├── hacs.json ├── mkdocs.yml ├── package-lock.json ├── package.json ├── src ├── Registry.ts ├── cards │ ├── AbstractCard.ts │ ├── AreaCard.ts │ ├── BinarySensorCard.ts │ ├── CameraCard.ts │ ├── ClimateCard.ts │ ├── CoverCard.ts │ ├── FanCard.ts │ ├── HaAreaCard.ts │ ├── HeaderCard.ts │ ├── InputSelectCard.ts │ ├── LightCard.ts │ ├── LockCard.ts │ ├── MediaPlayerCard.ts │ ├── MiscellaneousCard.ts │ ├── NumberCard.ts │ ├── PersonCard.ts │ ├── SceneCard.ts │ ├── SelectCard.ts │ ├── SensorCard.ts │ ├── SwitchCard.ts │ ├── VacuumCard.ts │ └── ValveCard.ts ├── chips │ ├── AbstractChip.ts │ ├── ClimateChip.ts │ ├── CoverChip.ts │ ├── FanChip.ts │ ├── LightChip.ts │ ├── SwitchChip.ts │ └── WeatherChip.ts ├── configurationDefaults.ts ├── mushroom-strategy.ts ├── translations │ ├── de.json │ ├── en.json │ ├── es.json │ ├── nl.json │ └── pt-BR.json ├── types │ ├── homeassistant │ │ ├── README.md │ │ ├── common │ │ │ └── translations │ │ │ │ └── localize.ts │ │ ├── data │ │ │ ├── area_registry.ts │ │ │ ├── climate.ts │ │ │ ├── device_registry.ts │ │ │ ├── entity_registry.ts │ │ │ ├── floor_registry.ts │ │ │ ├── frontend.ts │ │ │ ├── light.ts │ │ │ ├── lovelace │ │ │ │ └── config │ │ │ │ │ ├── action.ts │ │ │ │ │ ├── badge.ts │ │ │ │ │ ├── card.ts │ │ │ │ │ ├── section.ts │ │ │ │ │ ├── strategy.ts │ │ │ │ │ ├── types.ts │ │ │ │ │ └── view.ts │ │ │ ├── registry.ts │ │ │ ├── translations.ts │ │ │ └── ws-themes.ts │ │ ├── panels │ │ │ ├── common │ │ │ │ └── validate-condition.ts │ │ │ └── lovelace │ │ │ │ ├── cards │ │ │ │ └── types.ts │ │ │ │ └── types.ts │ │ └── types.ts │ ├── lovelace-mushroom │ │ ├── README.md │ │ ├── cards │ │ │ ├── chips-card.ts │ │ │ ├── climate-card-config.ts │ │ │ ├── cover-card-config.ts │ │ │ ├── entity-card-config.ts │ │ │ ├── fan-card-config.ts │ │ │ ├── light-card-config.ts │ │ │ ├── lock-card-config.ts │ │ │ ├── media-player-card-config.ts │ │ │ ├── number-card-config.ts │ │ │ ├── person-card-config.ts │ │ │ ├── select-card-config.ts │ │ │ ├── template-card-config.ts │ │ │ ├── title-card-config.ts │ │ │ └── vacuum-card-config.ts │ │ ├── shared │ │ │ └── config │ │ │ │ ├── actions-config.ts │ │ │ │ ├── appearance-config.ts │ │ │ │ ├── entity-config.ts │ │ │ │ └── utils │ │ │ │ ├── info.ts │ │ │ │ └── layout.ts │ │ └── utils │ │ │ ├── info.ts │ │ │ └── lovelace │ │ │ └── chip │ │ │ └── types.ts │ └── strategy │ │ ├── strategy-cards.ts │ │ ├── strategy-generics.ts │ │ └── strategy-views.ts ├── utilities │ ├── RegistryFilter.ts │ ├── auxiliaries.ts │ ├── cardStacking.ts │ ├── debug.ts │ └── localize.ts └── views │ ├── AbstractView.ts │ ├── CameraView.ts │ ├── ClimateView.ts │ ├── CoverView.ts │ ├── FanView.ts │ ├── HomeView.ts │ ├── LightView.ts │ ├── LockView.ts │ ├── SceneView.ts │ ├── SwitchView.ts │ ├── VacuumView.ts │ └── ValveView.ts ├── tsconfig.json ├── webpack.config.ts └── webpack.dev.config.ts /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | end_of_line = lf 6 | indent_size = 2 7 | indent_style = space 8 | insert_final_newline = true 9 | max_line_length = 120 10 | tab_width = 2 11 | trim_trailing_whitespace = true 12 | 13 | [{*.markdown,*.md}] 14 | trim_trailing_whitespace = false 15 | 16 | [docs/**/*.md] 17 | ij_formatter_enabled = false -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "root": true, 3 | "env": { 4 | "es2020": true, 5 | "node": true 6 | }, 7 | "parser": "@typescript-eslint/parser", 8 | "parserOptions": { 9 | "ecmaVersion": 2020, 10 | "project": "./tsconfig.json", 11 | "sourceType": "module" 12 | }, 13 | "plugins": ["@typescript-eslint"], 14 | "extends": ["eslint:recommended", "plugin:@typescript-eslint/recommended", "plugin:prettier/recommended"], 15 | "ignorePatterns": ["dist/", "node_modules/", "src/types/homeassistant/", "src/types/lovelace-mushroom/"], 16 | "overrides": [ 17 | { 18 | "files": ["webpack.config.ts", "webpack.dev.config.ts"], 19 | "parserOptions": { 20 | "project": null 21 | } 22 | } 23 | ], 24 | "rules": { 25 | "@typescript-eslint/no-empty-function": "warn", 26 | "@typescript-eslint/no-unused-vars": [ 27 | "warn", 28 | { 29 | "argsIgnorePattern": "^_" 30 | } 31 | ], 32 | "no-console": "off", 33 | "no-empty-function": "off", 34 | "no-unused-vars": "off" 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto eol=lf -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: DigiLive 2 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.yml: -------------------------------------------------------------------------------- 1 | name: Bug Report 2 | description: File a bug report to help us improve the project. 3 | labels: ['bug'] 4 | body: 5 | - type: markdown 6 | attributes: 7 | value: | 8 | Thank you for taking the time to report a bug! 9 | Please fill out the requested information to help us understand and reproduce the issue. 10 | 11 | - type: input 12 | id: what-happened 13 | attributes: 14 | label: What happened? 15 | description: Briefly describe the bug you encountered. 16 | validations: 17 | required: true 18 | 19 | - type: textarea 20 | id: reproduce 21 | attributes: 22 | label: Steps to reproduce 23 | description: Please provide clear and concise steps to reproduce the issue. Be as detailed as possible. 24 | placeholder: | 25 | 1. ... 26 | 2. ... 27 | validations: 28 | required: true 29 | 30 | - type: textarea 31 | id: versions 32 | attributes: 33 | label: Versions 34 | description: Please provide the versions you use of the items below 35 | placeholder: | 36 | - Mushroom Dashboard: 37 | - Lovelace Mushroom: 38 | - Home Assistant: 39 | value: | 40 | - Mushroom Dashboard: 41 | - Lovelace Mushroom: 42 | - Home Assistant: 43 | validations: 44 | required: true 45 | 46 | - type: dropdown 47 | id: environment 48 | attributes: 49 | label: Environment 50 | description: What environment were you using when you encountered the bug? 51 | options: 52 | - 'Web Browser (specify name and version)' 53 | - 'Mobile Application (specify OS and version)' 54 | - 'Other (please specify, including version)' 55 | validations: 56 | required: true 57 | 58 | - type: input 59 | id: environment-version 60 | attributes: 61 | label: Environment and Version 62 | validations: 63 | required: false 64 | 65 | - type: textarea 66 | id: expected-behavior 67 | attributes: 68 | label: Expected Behavior 69 | description: What did you expect to happen? 70 | validations: 71 | required: true 72 | 73 | - type: textarea 74 | id: actual-behavior 75 | attributes: 76 | label: Actual Behavior 77 | description: What actually happened? 78 | validations: 79 | required: true 80 | 81 | - type: textarea 82 | id: error-logs 83 | attributes: 84 | label: Error Logs (if applicable) 85 | description: If you encountered any error messages or logs, please include them here. 86 | render: plain text 87 | 88 | - type: textarea 89 | id: additional-information 90 | attributes: 91 | label: Additional Information 92 | description: Please provide any other relevant information or attachments that might help in understanding the issue. 93 | placeholder: | 94 | Add additional information or drop files here. 95 | 96 | - type: checkboxes 97 | id: terms 98 | attributes: 99 | label: Guidelines 100 | description: By submitting this issue, you agree to abide by our [contribution guidelines](blob/main/CONTRIBUTING.md). 101 | options: 102 | - label: I have read and agree to the guidelines. 103 | required: true 104 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: false 2 | contact_links: 3 | - name: Wiki 4 | url: https://github.com/DigiLive/mushroom-strategy/wiki 5 | about: Please consult to Wiki for more information about the strategy and how to configure it. 6 | - name: Discussions 7 | url: https://github.com/DigiLive/mushroom-strategy/discussions 8 | about: Discuss any other topic about the strategy over here. 9 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.yml: -------------------------------------------------------------------------------- 1 | name: Feature Request 2 | description: Suggest a new feature or improvement for the project. 3 | labels: ['enhancement'] 4 | body: 5 | - type: markdown 6 | attributes: 7 | value: | 8 | Thank you for taking the time to suggest a new feature! 9 | Please provide as much detail as possible so we can understand your idea and its potential impact. 10 | 11 | - type: input 12 | id: feature-title 13 | attributes: 14 | label: Feature Title 15 | description: Briefly and clearly describe your proposed feature. 16 | placeholder: e.g., Add support for... 17 | validations: 18 | required: true 19 | 20 | - type: textarea 21 | id: what-is-it 22 | attributes: 23 | label: What is the feature? 24 | description: Describe the feature in detail. What would it do? How would it work? 25 | validations: 26 | required: true 27 | 28 | - type: textarea 29 | id: problem-it-solves 30 | attributes: 31 | label: What problem does this feature solve? 32 | description: Explain the user need or pain point that this feature addresses. Why is it important? 33 | validations: 34 | required: true 35 | 36 | - type: textarea 37 | id: proposed-solution 38 | attributes: 39 | label: Proposed Solution (Optional) 40 | description: | 41 | If you have specific ideas on how this feature could be implemented, please share them here. 42 | Include any technical details or UI/UX suggestions. 43 | 44 | - type: dropdown 45 | id: affected-area 46 | attributes: 47 | label: Affected Area (Optional) 48 | description: If this feature primarily relates to a specific part of the project, please indicate it. 49 | options: 50 | - User Interface (UI) 51 | - User Experience (UX) 52 | - Performance 53 | - Security 54 | - Documentation 55 | - Other (please specify below) 56 | default: 0 57 | 58 | - type: input 59 | id: affected-area-other 60 | attributes: 61 | label: Other Affected Area (if selected above) 62 | validations: 63 | required: false 64 | 65 | - type: textarea 66 | id: alternatives-considered 67 | attributes: 68 | label: Alternatives Considered (Optional) 69 | description: | 70 | Have you considered any alternative solutions or workarounds? 71 | If so, please describe them and why you think this proposed feature is better. 72 | 73 | - type: textarea 74 | id: mockups-designs 75 | attributes: 76 | label: Mockups or Designs (Optional) 77 | description: | 78 | If you have any mockups, wireframes, or design ideas to illustrate your feature, 79 | you can describe them here or attach them to the issue. 80 | 81 | - type: checkboxes 82 | id: terms 83 | attributes: 84 | label: Guidelines 85 | description: By submitting this issue, you agree to abide by our [contribution guidelines](blob/main/CONTRIBUTING.md). 86 | options: 87 | - label: I have read and agree to the guidelines. 88 | required: true 89 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | # Click the `Preview` tab and select the type of Pull Request you are submitting 2 | 3 | - [Bug Fix](?expand=1&template=bugfix.md) 4 | - [Feature](?expand=1&template=feature.md) 5 | 6 | > [!NOTE] 7 | > The above types do not apply to any translation itself. 8 | > To add or fix a translation, select a type below. 9 | > 10 | > - [Translation Contribution](?expand=1&template=translation.md) 11 | 12 | --- 13 | 14 | > [!CAUTION] 15 | > Any Pull Request that does not follow the above types will be rejected. 16 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE/bugfix.md: -------------------------------------------------------------------------------- 1 | # Bug Fix Pull Request 2 | 3 | Thank you for contributing to the project by fixing this bug! 4 | Please fill out the following information to help us review your pull request. 5 | 6 | --- 7 | 8 | ## Bug Summary 9 | 10 | Explain why this fix is needed and what problem it solves. 11 | If it relates to an existing issue, please link it. 12 | See [Linking a pull request to an issue](https://docs.github.com/en/issues/tracking-your-work-with-issues/using-issues/linking-a-pull-request-to-an-issue). 13 | 14 | [Briefly describe the bug you are fixing] 15 | 16 | --- 17 | 18 | ## Motivation and Context 19 | 20 | Explain why this bug needs to be fixed and the impact it has on the project or users. 21 | 22 | [Your explanation here] 23 | 24 | --- 25 | 26 | ## List of Changes 27 | 28 | [Provide a concise list of the main changes introduced by this pull request to fix the bug.] 29 | 30 | - ... 31 | 32 | ## Steps to Reproduce (if not covered in the linked issue) 33 | 34 | If the steps to reproduce the bug are not clearly outlined in the linked issue, please provide them here: 35 | 36 | 1. ... 37 | 2. ... 38 | 39 | ## Expected Behavior (if not covered in the linked issue) 40 | 41 | Describe what the expected behavior should have been before the bug occurred. 42 | 43 | [Your description of the expected behavior] 44 | 45 | ### Actual Behavior (if not covered in the linked issue) 46 | 47 | Describe the actual behavior that occurred due to the bug. 48 | 49 | [Your description of the actual behavior] 50 | 51 | --- 52 | 53 | ## Wiki Updates 54 | 55 | [If this bug fix requires any updates to the Wiki, please provide details here.] 56 | 57 | --- 58 | 59 | ## Agreements 60 | 61 | Please confirm the following by inserting an `x` between the brackets: 62 | 63 | - [ ] My code adheres to the [contribution guidelines](blob/main/CONTRIBUTING.md) of the project. 64 | - [ ] My changes generate no new warnings. 65 | - [ ] I have performed a self-review of my own code. 66 | - [ ] I have commented my code, particularly in hard-to-understand areas. 67 | - [ ] I have made corresponding changes to the documentation. 68 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE/feature.md: -------------------------------------------------------------------------------- 1 | # Feature Pull Request 2 | 3 | Thank you for contributing to the project! 4 | Please fill out the following information to help us review your pull request. 5 | 6 | --- 7 | 8 | ## Feature Summary 9 | 10 | [Briefly describe the feature you are proposing] 11 | 12 | --- 13 | 14 | ## Motivation and Context 15 | 16 | Explain why this feature is needed and what problem it solves. 17 | If it relates to an existing issue, please link it. 18 | See [Linking a pull request to an issue](https://docs.github.com/en/issues/tracking-your-work-with-issues/using-issues/linking-a-pull-request-to-an-issue). 19 | 20 | [Your explanation here] 21 | 22 | --- 23 | 24 | ## List of Changes 25 | 26 | [Provide a concise list of the main changes introduced by this pull request.] 27 | 28 | - ... 29 | 30 | ## Wiki Updates 31 | 32 | [If this bug feature requires any updates to the Wiki, please provide details here.] 33 | 34 | --- 35 | 36 | ## Agreements 37 | 38 | Please confirm the following by inserting an `x` between the brackets: 39 | 40 | - [ ] My code adheres to the [contribution guidelines](blob/main/CONTRIBUTING.md) of the project. 41 | - [ ] My changes generate no new warnings. 42 | - [ ] I have performed a self-review of my own code. 43 | - [ ] I have commented my code, particularly in hard-to-understand areas. 44 | - [ ] I have made corresponding changes to the documentation. 45 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE/translation.md: -------------------------------------------------------------------------------- 1 | # Translation Contribution Pull Request 2 | 3 | Thank you for contributing to the project's internationalization efforts! 4 | Please fill out the following information to help us review your translation changes. 5 | 6 | --- 7 | 8 | ## Type of Translation Contribution 9 | 10 | Please select the type of contribution: 11 | 12 | - [ ] Adding a new language translation 13 | - [ ] Fixing errors or improving an existing translation 14 | - [ ] Updating an existing translation with new strings 15 | 16 | --- 17 | 18 | ## Target Language 19 | 20 | Please specify the language you are adding or modifying: 21 | 22 | [List the target language here] 23 | 24 | --- 25 | 26 | ## Motivation and Context 27 | 28 | Explain why this translation (addition, fix, or update) is needed. 29 | 30 | - For fixes, please describe the original error. 31 | - For updates, briefly explain the context of the new strings. 32 | 33 | [Your explanation here] 34 | 35 | --- 36 | 37 | ## Scope of Changes 38 | 39 | Please describe the scope of your translation changes. 40 | Which parts of the project are affected by these translations? 41 | 42 | [Describe the affected areas] 43 | 44 | --- 45 | 46 | ## List of Changes 47 | 48 | Provide a concise list of the main changes you've made in this pull request. 49 | If it's a large update, you can highlight key areas. 50 | 51 | - ... 52 | 53 | --- 54 | 55 | ## Considerations for Reviewers 56 | 57 | Are there any specific areas you would like reviewers to pay extra attention to? 58 | For example, specific terminology, cultural nuances, or consistency with existing translations. 59 | 60 | [Any specific instructions for reviewers] 61 | 62 | --- 63 | 64 | ## Agreements 65 | 66 | Please confirm the following: 67 | 68 | - [ ] My code adheres to the [contribution guidelines](blob/main/CONTRIBUTING.md) of the project. 69 | - [ ] I have reviewed the existing translations for consistency. 70 | - [ ] I have used appropriate terminology and followed any project-specific translation guidelines. 71 | - [ ] I have tested the translations to the best of my ability. 72 | - [ ] My changes generate no new warnings or errors related to internationalization. 73 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | # https://docs.github.com/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file 2 | 3 | version: 2 4 | updates: 5 | - package-ecosystem: 'npm' 6 | directory: '/' 7 | schedule: 8 | interval: 'weekly' 9 | groups: 10 | dependencies: 11 | patterns: ['*'] 12 | labels: 13 | - 'dependencies' 14 | pull-request-branch-name: 15 | separator: '-' 16 | - package-ecosystem: 'github-actions' 17 | directory: '/' 18 | schedule: 19 | interval: 'weekly' 20 | groups: 21 | actions: 22 | patterns: ['*'] 23 | labels: 24 | - 'actions' 25 | pull-request-branch-name: 26 | separator: '-' 27 | -------------------------------------------------------------------------------- /.github/workflows/deploy-docs.yml: -------------------------------------------------------------------------------- 1 | name: Deploy Documentation 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | pull_request: 8 | branches: 9 | - main 10 | 11 | permissions: 12 | contents: write 13 | 14 | jobs: 15 | check-for-changes: 16 | name: Check for changes 17 | runs-on: ubuntu-latest 18 | outputs: 19 | changed: ${{ steps.check_files.outputs.any_changed }} 20 | steps: 21 | - name: Checkout Code 22 | uses: actions/checkout@v4 23 | with: 24 | fetch-depth: 0 25 | 26 | - name: Check for changed documentation files 27 | id: check_files 28 | uses: tj-actions/changed-files@v46 29 | with: 30 | files: | 31 | docs/** 32 | mkdocs.yml 33 | 34 | deploy: 35 | name: Deploy MkDocs Site 36 | runs-on: ubuntu-latest 37 | timeout-minutes: 10 38 | needs: check-for-changes 39 | if: needs.check-for-changes.outputs.changed == 'true' 40 | env: 41 | CI_COMMIT_AUTHOR: 'CI Bot' 42 | CI_COMMIT_EMAIL: 'ci@noreply.github.com' 43 | CI_COMMIT_MESSAGE: 'Continuous Integration - Deploy Documentation' 44 | 45 | steps: 46 | - name: Generate GitHub App Token 47 | id: generate_token 48 | uses: tibdex/github-app-token@v2 49 | with: 50 | app_id: ${{ secrets.APP_ID }} 51 | private_key: ${{ secrets.APP_PRIVATE_KEY }} 52 | 53 | - name: Checkout Code 54 | uses: actions/checkout@v4 55 | with: 56 | token: ${{ steps.generate_token.outputs.token }} 57 | fetch-depth: 0 58 | 59 | - name: Set up Python 60 | uses: actions/setup-python@v5 61 | with: 62 | python-version: '3.x' 63 | 64 | - name: Install MkDocs and dependencies 65 | run: pip install mkdocs mkdocs-material pymdown-extensions 66 | 67 | - name: Deploy Docs to GitHub Pages 68 | run: | 69 | git config --global user.name "${{ env.CI_COMMIT_AUTHOR }}" 70 | git config --global user.email "${{ env.CI_COMMIT_EMAIL }}" 71 | git remote set-url origin https://x-access-token:${{ steps.generate_token.outputs.token }}@github.com/DigiLive/mushroom-strategy.git 72 | mkdocs gh-deploy --force --clean --message "${{ env.CI_COMMIT_MESSAGE }}" 73 | -------------------------------------------------------------------------------- /.github/workflows/validate.yml: -------------------------------------------------------------------------------- 1 | name: HACS validation 2 | on: 3 | push: 4 | branches: 5 | - main 6 | jobs: 7 | hacs: 8 | name: HACS Action 9 | runs-on: 'ubuntu-latest' 10 | steps: 11 | - name: HACS Action 12 | uses: 'hacs/action@22.5.0' 13 | with: 14 | category: 'plugin' 15 | -------------------------------------------------------------------------------- /.github/workflows/webpack.yml: -------------------------------------------------------------------------------- 1 | name: Build distribution with Webpack 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | 8 | jobs: 9 | check-for-changes: 10 | name: Check for changes 11 | runs-on: ubuntu-latest 12 | outputs: 13 | changed: ${{ steps.check_files.outputs.any_changed }} 14 | steps: 15 | - name: Checkout Repository 16 | uses: actions/checkout@v4 17 | with: 18 | fetch-depth: 0 19 | 20 | - name: Check for changed source files 21 | id: check_files 22 | uses: tj-actions/changed-files@v46 23 | with: 24 | files: | 25 | src/** 26 | webpack.config.js 27 | 28 | build: 29 | name: Build Distribution 30 | runs-on: ubuntu-latest 31 | timeout-minutes: 10 32 | needs: check-for-changes 33 | if: needs.check-for-changes.outputs.changed == 'true' 34 | env: 35 | CI_COMMIT_AUTHOR: 'CI Bot' 36 | CI_COMMIT_EMAIL: 'ci@noreply.github.com' 37 | CI_COMMIT_MESSAGE: | 38 | Continuous Integration - Build Distribution 39 | 40 | [skip codacy] 41 | strategy: 42 | matrix: 43 | node-version: [22.x] 44 | 45 | steps: 46 | - name: Generate GitHub App Token 47 | id: generate_token 48 | uses: tibdex/github-app-token@v2 49 | with: 50 | app_id: ${{ secrets.APP_ID }} 51 | private_key: ${{ secrets.APP_PRIVATE_KEY }} 52 | 53 | - name: Checkout Repository 54 | uses: actions/checkout@v4 55 | with: 56 | token: ${{ steps.generate_token.outputs.token }} 57 | fetch-depth: 0 58 | 59 | - name: Setup Node.js ${{ matrix.node-version }} 60 | uses: actions/setup-node@v4 61 | with: 62 | node-version: ${{ matrix.node-version }} 63 | cache: 'npm' 64 | 65 | - name: Install Dependencies 66 | run: npm ci 67 | 68 | - name: Build Distribution 69 | run: npm run build 70 | 71 | - name: Commit Distribution Build 72 | run: | 73 | git config --global user.name "${{ env.CI_COMMIT_AUTHOR }}" 74 | git config --global user.email "${{ env.CI_COMMIT_EMAIL }}" 75 | git remote set-url origin https://x-access-token:${{ steps.generate_token.outputs.token }}@github.com/DigiLive/mushroom-strategy.git 76 | git add dist 77 | git diff --quiet && git diff --staged --quiet || (git commit -m "${{ env.CI_COMMIT_MESSAGE }}" && git push) 78 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /node_modules/ 2 | # Don't add directory /dist/ to .gitignore, as it is used by the build script 3 | -------------------------------------------------------------------------------- /.markdownlint.jsonc: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://raw.githubusercontent.com/DavidAnson/markdownlint/main/schema/markdownlint-config-schema-strict.json", 3 | "default": true, 4 | "MD013": { 5 | "line_length": 120, 6 | "code_block_line_length": 120, 7 | "heading_line_length": 80, 8 | "tables": false, 9 | }, 10 | "MD024": { 11 | "siblings_only": true, 12 | }, 13 | "MD033": { 14 | "allowed_elements": ["br", "summary", "details"], 15 | }, 16 | "MD040": false, 17 | "MD046": false, 18 | } 19 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "arrowParens": "always", 3 | "bracketSpacing": true, 4 | "endOfLine": "lf", 5 | "jsxSingleQuote": true, 6 | "printWidth": 120, 7 | "proseWrap": "preserve", 8 | "quoteProps": "as-needed", 9 | "semi": true, 10 | "singleQuote": true, 11 | "tabWidth": 2, 12 | "useTabs": false 13 | } 14 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | Copyright (c) 2025, Ferry Cools 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | 1. Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | 2. Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | 3. Neither the name of the copyright holder nor the names of its 17 | contributors may be used to endorse or promote products derived from 18 | this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Mushroom Dashboard Strategy 🍄✨ 2 | 3 | [![Release][releaseBadge]][releaseUrl] 4 | [![HACS][hacsBadge]][hacsUrl] 5 | [![Codacy][codacyBadge]][codacyUrl] 6 | 7 | --- 8 | 9 | **Effortlessly create stunning Home Assistant Dashboards with the Mushroom Dashboard Strategy!** 10 | 11 | * Are you tired of manually configuring your Home Assistant dashboards? 12 | Do you love the elegant design of Mushroom cards but wish for a simpler way to organize your entities, 13 | devices, and areas? 14 | 15 | The **Mushroom Dashboard Strategy** is your solution. 16 | It automatically generates beautiful, organized dashboards for Home Assistant, 17 | leveraging the power and aesthetics of Mushroom cards with minimal configuration. 18 | 19 | --- 20 | 21 | ## ⭐ **Why Choose Mushroom Dashboard Strategy?** 22 | 23 | * **⚡️ Automatic Dashboard Generation:** Go from zero to a beautiful dashboard with just a few lines of YAML. 24 | * **🏡 Intelligent Organization:** Automatically creates intuitive views for your devices, areas, and entities. 25 | * **🎨 Highly Customizable:** Tailor your dashboard to your unique smart home setup with extensive options. 26 | * **📈 Integrated Insights:** Seamlessly displays mini graph cards for your sensor data. 27 | 28 | --- 29 | 30 | ## 🚀 **Get Started in Minutes!** 31 | 32 | Ready to transform your Home Assistant experience? 33 | 34 | The **Mushroom Dashboard Strategy** is available through HACS (Home Assistant Community Store). 35 | 36 | ➡️ **[Explore the detailed documentation for Installation & Usage Guides!](https://digilive.github.io/mushroom-strategy/)** 37 | 38 | --- 39 | 40 | ## 📸 **Sneak Peek** 41 | 42 | ![Preview GIF](docs/images/preview.gif) 43 | 44 | --- 45 | 46 | ## 🤝 **Contributing & Support** 47 | 48 | We welcome contributions and feedback! 49 | 50 | * Have questions or need help? 51 | Check out our [Discussions](https://github.com/DigiLive/mushroom-strategy/discussions) page. 52 | 53 | * Found a bug or have an idea? 54 | Open an [Issue](https://github.com/DigiLive/mushroom-strategy/issues). 55 | 56 | * Enjoying the Mushroom Strategy? 57 | Consider giving our project a ⭐ [star on GitHub](https://github.com/DigiLive/mushroom-strategy) and exploring ways 58 | to ❤️ [sponsor the project](https://github.com/sponsors/DigiLive) to support its continued development! 59 | Your support helps us grow and improve. 60 | 61 | --- 62 | 63 | 64 | 65 | [codacyBadge]: https://app.codacy.com/project/badge/Grade/24de1e79aea445499917d9acd5ce9e04 66 | 67 | [hacsBadge]: https://img.shields.io/badge/HACS-Default-blue 68 | 69 | [releaseBadge]: https://img.shields.io/github/v/tag/digilive/mushroom-strategy?filter=v2.3.4&label=Release 70 | 71 | 72 | 73 | [releaseUrl]: https://github.com/DigiLive/mushroom-strategy/releases/tag/v2.3.4 74 | 75 | 76 | 77 | [codacyUrl]: https://app.codacy.com/gh/DigiLive/mushroom-strategy/dashboard?utm_source=gh&utm_medium=referral&utm_content=&utm_campaign=Badge_grade 78 | 79 | [hacsUrl]: https://hacs.xyz 80 | -------------------------------------------------------------------------------- /docs/contributing/code.md: -------------------------------------------------------------------------------- 1 | # 💻 Contributing Code 2 | 3 | Want to get your hands dirty with the code? Awesome! We appreciate all code contributions. 4 | 5 | 1. **Follow the [Workflow](workflow.md):** 6 | 7 | 2. **Make Your Changes:** Implement your bug fix or new feature. 8 | 9 | 3. **Test Your Changes:** Thoroughly test your changes to ensure they work as expected and don't introduce new issues. 10 | 11 | * You can build the strategy with `npm run build` (for production) or `npm run build-dev` (for development/testing). 12 | * Copy the built files to your Home Assistant's `www/community/mushroom-strategy` directory for testing. 13 | **Remember to clear the cache of your Home Assistant client** to see the changes. 14 | 15 | !!! info 16 | 17 | If your `www/community/mushroom-strategy` directory contains a file called `mushroom-strategy.js.gz`, rename or 18 | delete it. 19 | 20 | 4. **Format and Lint Your Changes:** 21 | 22 | * Run the formatter with `npm run ts:format`. 23 | * Build the strategy with `npm run build`. 24 | 25 | Both of these tasks should result without errors. 26 | 27 | 5. **Commit Your Changes.** 28 | 29 | 6. **Push to Your Fork.** 30 | 31 | 7. **Open a Pull Request (PR).** 32 | 33 | --- 34 | 35 | Thank you for taking the time to help us improve our project! Your contributions make a real difference. 🎉 36 | -------------------------------------------------------------------------------- /docs/contributing/documentation.md: -------------------------------------------------------------------------------- 1 | # 📄 Contributing to the Documentation 2 | 3 | Good documentation is crucial for our project's success! 4 | We truly appreciate any contributions, whether it's fixing a typo, clarifying a section, adding more examples, or even 5 | extending existing topics. This guide will walk you through the process of contributing. 6 | 7 | The entire documentation lives in the `docs/` folder of this repository. 8 | 9 | --- 10 | 11 | 1. **Follow the [Workflow](workflow.md):** 12 | 13 | 2. **Serve the Documentation Locally**: 14 | Start the local development server. This task needs to be run from the **project root** (where the `mkdocs.yml` file is): 15 | 16 | ```bash 17 | mkdocs serve 18 | ``` 19 | 20 | This will usually launch a local server, at `http://127.0.0.1:8000`. 21 | The server will automatically reload in your browser as you make and save changes to the documentation files. 22 | To stop the server, press **Ctrl + C** in the terminal. 23 | 24 | 3. **Edit Markdown Files**: All documentation content is written in **Markdown** (`.md` files). 25 | You can find them within the `docs/` folder. 26 | 27 | - For advanced formatting options, refer to the [Material for MkDocs reference](https://squidfunk.github.io/mkdocs-material/reference/). 28 | 29 | 4. **Add New Pages**: 30 | 31 | - Create a new `.md` file in the most appropriate directory within `docs/`. 32 | 33 | !!! important 34 | 35 | You'll need to add the new page to the navigation (`nav`) section of the `mkdocs.yml` file for it to appear in 36 | the sidebar. Follow the existing structure. 37 | 38 | 5. **Add Images**: 39 | 40 | - Place any image files into the `docs/images/` directory. 41 | - Reference them in your Markdown using the syntax: `![Alt text for accessibility](images/your-image-name.png)` 42 | 43 | 6. **Preview Changes**: As you save your `.md` files, the local server running at `http://127.0.0.1:8000` will 44 | automatically refresh, allowing you to see your changes instantly. 45 | 46 | 7. **Format and Lint Your Changes:** 47 | 48 | - Build the linter with `npm run md:lint-fix`. 49 | 50 | This task should result without errors. 51 | 52 | 8. **Commit Your Changes.** 53 | 54 | 9. **Push to Your Fork.** 55 | 56 | 10. **Open a Pull Request (PR).** 57 | 58 | --- 59 | 60 | ## Documentation Style and Quality 61 | 62 | To maintain consistency and quality: 63 | 64 | - **Clarity and Conciseness**: Use straightforward, clear, and concise language. 65 | - **Examples**: Include images and code examples whenever they help clarify a point. 66 | 67 | --- 68 | 69 | Thank you for taking the time to help us improve our documentation! Your contributions make a real difference. 🎉 70 | -------------------------------------------------------------------------------- /docs/contributing/getting-started.md: -------------------------------------------------------------------------------- 1 | # 🚀 Getting Started 2 | 3 | ## ⚙️ Prerequisites 4 | 5 | Before you begin, make sure you have the following installed on your system: 6 | 7 | - **Git**: For version control and managing your changes. 8 | 9 | - **Node.js and npm**: Required for running scripts defined in `package.json` (e.g., linting). 10 | Download from [nodejs.org](https://nodejs.org/en/download/). 11 | 12 | For contributing to the documentation, the following prerequisites are also required: 13 | 14 | - **Python 3.7 or higher**: Download from [python.org/downloads](https://www.python.org/downloads/). 15 | 16 | - **pip** (Python package installer): Usually comes with Python, but you can find installation instructions at 17 | [pip.pypa.io/en/stable/installation/](https://pip.pypa.io/en/stable/installation/). 18 | 19 | ## 🛠️ Local Environment 20 | 21 | To make and preview your changes, you'll need to set up a development environment locally: 22 | 23 | 1. **Fork the Repository**: Go to our main repository on GitHub and click the "Fork" button. 24 | This creates a copy of the repository under your GitHub account. 25 | 26 | 2. **Clone Your Fork**: On your local machine, clone your forked repository using Git. 27 | 28 | 3. **Install Node.js Dependencies**: 29 | Navigate to the root of the cloned project (where `package.json` is located) and install its dependencies: 30 | 31 | ```bash 32 | npm install 33 | ``` 34 | 35 | 4. **Install Python Documentation Tools**: 36 | Navigate to the root of the cloned project (where `mkdocs.yml` is located) and install MkDocs along with the 37 | necessary themes and plugins: 38 | 39 | ```bash 40 | pip install mkdocs mkdocs-material mkdocs-material-extensions 41 | ``` 42 | -------------------------------------------------------------------------------- /docs/contributing/index.md: -------------------------------------------------------------------------------- 1 | # 🤝 Contributing to Mushroom Strategy 2 | 3 | We love contributions from the community! Whether you're reporting a bug, suggesting a new feature, or submitting code 4 | changes, your help makes the Mushroom Strategy better for everyone. 5 | 6 | Please take a moment to review this guide before making a contribution. 7 | 8 | ## 📜 Code of Conduct 9 | 10 | To ensure a welcoming and inclusive environment, all contributors are expected to adhere to 11 | our [Code of Conduct](https://github.com/DigiLive/mushroom-strategy/blob/main/CODE_OF_CONDUCT.md). Please read it 12 | carefully. 13 | 14 | --- 15 | 16 | ## 🐞 Reporting Bugs 17 | 18 | Found a bug? That's not ideal, but your report helps us squash it! 19 | 20 | 1. **Check existing issues:** Before opening a new issue, please search 21 | our GitHub [Issues](https://github.com/DigiLive/mushroom-strategy/issues) 22 | or [Discussions](https://github.com/DigiLive/mushroom-strategy/discussions) to see if the bug has already been 23 | reported. 24 | 2. **Open a new issue:** If it's a new bug, please open 25 | a [new issue](https://github.com/DigiLive/mushroom-strategy/issues/new?template=bug_report.yml). 26 | 3. **Provide details:** In your report, please follow the instructions and template to include: 27 | 28 | * A clear and concise description of the bug. 29 | * Steps to reproduce the behavior. 30 | * Expected behavior. 31 | * Screenshots or animated GIFs (if applicable). 32 | * Your Home Assistant version and Mushroom Strategy version. 33 | 34 | --- 35 | 36 | ## ✨ Suggesting Features 37 | 38 | Have a great idea for a new feature or enhancement? We'd love to hear it! 39 | 40 | 1. **Check existing suggestions:** Search our GitHub [Issues](https://github.com/DigiLive/mushroom-strategy/issues) 41 | or [Discussions](https://github.com/DigiLive/mushroom-strategy/discussions) to see if the feature has already been 42 | requested. 43 | 2. **Open a new issue:** If it's a new idea, open 44 | a [new issue](https://github.com/DigiLive/mushroom-strategy/issues/new?template=feature_request.yml). 45 | 3. **Describe your idea:** Clearly explain the feature, why you think it's useful, and any potential use cases by 46 | following the instructions and template. 47 | 48 | --- 49 | 50 | ## 🙏 Get Support 51 | 52 | If you have questions about contributing or need help with your setup, please open a 53 | [discussion](https://github.com/DigiLive/mushroom-strategy/discussions) on our GitHub repository. 54 | -------------------------------------------------------------------------------- /docs/contributing/translations.md: -------------------------------------------------------------------------------- 1 | # 🌐 Translations 2 | 3 | Help us make Mushroom Strategy accessible to more users around the world by contributing and improving translations! 4 | 5 | Language tags have to follow [BCP 47](https://tools.ietf.org/html/bcp47). 6 | A list of most language tags can be found here: 7 | [IANA subtag registry](http://www.iana.org/assignments/language-subtag-registry/language-subtag-registry). 8 | Examples: fr, fr-CA, zh-Hans. 9 | 10 | 1. **Check for Existing Translations:** See if your language is already being worked on or exists. 11 | 2. **Locate Translation Files:** Language files are found within the `src/translations` directory. 12 | Each language has its own `locale.json` file (e.g., `en.json`, `nl.json`, `pt-BR.json`). 13 | 3. **Create or Update:** 14 | 15 | * **To create a new language:** Copy an existing `.json` file (e.g., `en.json`), rename it to your language 16 | code (e.g., `de.json` for German), and translate the property values. 17 | * **To update an existing language:** Open the `.json` file for your language and update any missing or 18 | outdated translations. 19 | 20 | 4. **Test Your Changes:** Thoroughly test your changes to ensure they work as expected and don't introduce new issues. 21 | 22 | * You can build the strategy with `npm run build` (for production) or `npm run build-dev` (for development/testing). 23 | * Copy the built files to your Home Assistant's `www/community/mushroom-strategy` directory for testing. 24 | **Remember to clear the cache of your Home Assistant client** to see the changes. 25 | 26 | !!! info 27 | 28 | If your `www/community/mushroom-strategy` directory contains a file called `mushroom-strategy.js.gz`, rename or 29 | delete it. 30 | 31 | 5. **Format and Lint Your Changes:** 32 | 33 | * Run the formatter with `npm run json:format`. 34 | * Run the formatter with `npm run ts:format`. 35 | * Build the strategy with `npm run build`. 36 | 37 | All of these tasks should result without errors. 38 | 39 | 6. **Commit Your Changes.** 40 | 41 | 7. **Push to Your Fork.** 42 | 43 | 8. **Open a Pull Request (PR).** 44 | 45 | --- 46 | 47 | !!! info 48 | 49 | **Integrating a new Translation:** 50 | 51 | * For your new language file to be picked up, it needs to be imported and registered at file 52 | `src/utilities/localize.ts`. 53 | * You will need to add an `import` statement for your new `.json` file at the top, following the existing pattern. 54 | * Then, you'll need to add it to the `languages` map, associating the language code with the imported module. 55 | 56 | **Special Handling for `language-country` Locales:** 57 | If you are adding a country-specific locale (e.g., `es-ES` for Spanish (Spain) or `en-GB` for English 58 | (United Kingdom)), you should create a file like `en-GB.json` in the `translations` folder. In 59 | `src/utilities/localize.ts`, you'll import it similarly and add it to the `languages` map using the full locale 60 | code. 61 | Please ensure you follow existing patterns for `language-country` codes, which typically use a hyphen (`-`) + a 62 | UPPER-cased country code in the file name and an underscore (`_`) + a lower-cased country code in the import key. 63 | 64 | !!! example 65 | ```typescript 66 | import * as en from '../translations/en.json'; 67 | import * as pt_br from '../translations/pt-BR.json'; 68 | 69 | /** Registry of currently supported languages */ 70 | const languages: Record = { 71 | en, 72 | 'pt-BR': pt_br, 73 | }; 74 | ``` 75 | -------------------------------------------------------------------------------- /docs/contributing/workflow.md: -------------------------------------------------------------------------------- 1 | # 🚀 Contributing Workflow 2 | 3 | This guide outlines a common workflow for contributing to our project. 4 | 5 | --- 6 | 7 | 1. **Fork the Repository** 8 | Start by forking **our repository** (the upstream project) to your own GitHub account. 9 | This creates a personal copy where you can make your changes without affecting the original project directly. 10 | 11 | 2. **Clone Your Fork** 12 | Clone your forked repository from your GitHub account to your local machine. 13 | 14 | 3. **Set Up Your Local Development Environment** 15 | Before making changes, ensure your local environment is ready. 16 | See [Getting Started](getting-started.md). 17 | 18 | 4. **Make Your Changes** 19 | Work in a new branch for better organization and easier pull requests and Implement your bug fix, new feature, or 20 | documentation update. 21 | See chapters [Code](code.md), [Documentation](documentation.md), and [Translations](translations.md) for guidance and 22 | details. 23 | 24 | 5. **Test Your Changes** 25 | Thoroughly test your changes to ensure they work as expected, address the intended problem, and do not introduce any 26 | new issues or regressions. 27 | 28 | 6. **Format and Lint Your Changes** 29 | Your code should be well-formatted and linted to ensure consistency and readability. 30 | If you've set up the project correctly, the tools for this should already be available to this project. 31 | 32 | 7. **Commit Your Changes** 33 | Stage your changes and commit them with a clear, descriptive message. 34 | Aim for a concise subject line followed by a more detailed body if necessary. 35 | E.g.: 36 | 37 | ```text 38 | Fix: Resolve issue with feature X 39 | 40 | A clear and concise description of what has been changed, why it was necessary, and any relevant context. 41 | ``` 42 | -------------------------------------------------------------------------------- /docs/faq.md: -------------------------------------------------------------------------------- 1 | # Frequently Asked Questions 2 | 3 | ??? question "How do I add a device or entity to an area?" 4 | 5 | You can add devices to an area by going to `Settings` found at the bottom of the sidebar. 6 | 7 | 1. Select `Devices & services`. 8 | 2. Select `Devices` or `Entities`at the top. 9 | 3. Choose the device or entity you wish to add to an area. 10 | 4. Select :material-pencil: or :material-cog: in the top right corner. 11 | 5. Choose an area in the area field. 12 | 13 | !!! warning 14 | If you created an entity manually (in your `configuration.yaml`), you may need to create a `unique_id` before 15 | you can set an area to it. 16 | See Home Assistant's [documentation](https://www.home-assistant.io/faq/unique_id){: target="_blank"} for more 17 | info about unique ids. 18 | 19 | ??? question "How do I hide entities from the Strategy?" 20 | 21 | When creating this dashboard for the first time, you might be overwhelmed by the number of entities. 22 | To reduce the number of entities shown, you can hide these entities by following the steps below: 23 | 24 | 1. Click and hold the entity. 25 | 2. Click :material-cog: in the top right corner of the popup. 26 | 3. Set `Visible` to `off`. 27 | 28 | 29 | !!! note 30 | If you don't want to hide the entity from all dashboards, you can use [Card Options](options/card-options.md) 31 | to hide specific entities and devices. 32 | 33 | ??? question "How do I get the id of entities, devices and areas?" 34 | 35 | * Entity Id 36 | 1. Select `Settings` at the bottom of the sidebar. 37 | 2. Select `Devices & services`. 38 | 3. Select `Entities` at the top. 39 | 4. Choose the entity you want to get the id of. 40 | 5. Click :material-cog: in the top right corner of the popup. 41 | 42 | * Device Id 43 | 1. Select `Settings` at the bottom of the sidebar. 44 | 2. Select `Devices & services`. 45 | 3. Select `Devices` at the top. 46 | 4. Select the device you want to get the id of. 47 | 5. The device id is shown as the **last** part of the url in the address bar. 48 | E.g.: `https://.../config/devices/device/h55b6k54j76g56` 49 | 50 | * Area Id 51 | 1. Select `Settings` at the bottom of the sidebar. 52 | 2. Select `Areas`. 53 | 3. Select :material-pencil: of the area you want to get the id of. 54 | -------------------------------------------------------------------------------- /docs/full-example.md: -------------------------------------------------------------------------------- 1 | # 📝 Full example using all the options provided with the strategy 2 | 3 | ```yaml 4 | strategy: 5 | type: custom:mushroom-strategy 6 | options: 7 | views: 8 | light: 9 | order: 1 10 | title: illumination 11 | switches: 12 | hidden: true 13 | icon: mdi:toggle-switch 14 | home_view: 15 | hidden: 16 | - areasTitle 17 | - greeting 18 | stack_count: 19 | areas: [2, 1] 20 | persons: 3 21 | domains: 22 | _: 23 | hide_config_entities: true 24 | stack_count: 1 25 | light: 26 | order: 1 27 | stack_count: 2 28 | title: "My cool lights" 29 | chips: 30 | weather_entity: weather.forecast_home 31 | climate_count: false 32 | cover_count: false 33 | extra_chips: 34 | - type: conditional 35 | conditions: 36 | - entity: lock.front_door 37 | state: unlocked 38 | chip: 39 | type: entity 40 | entity: lock.front_door 41 | icon_color: red 42 | content_info: none 43 | icon: '' 44 | use_entity_picture: false 45 | tap_action: 46 | action: toggle 47 | - type: conditional 48 | conditions: 49 | - entity: cover.garage_door 50 | state_not: closed 51 | chip: 52 | type: entity 53 | entity: cover.garage_door 54 | icon_color: red 55 | content_info: none 56 | tap_action: 57 | action: toggle 58 | areas: 59 | _: 60 | type: default 61 | family_room_id: 62 | name: Family Room 63 | icon: mdi:television 64 | icon_color: green 65 | extra_cards: 66 | - type: custom:mushroom-chips-card 67 | chips: 68 | - type: entity 69 | entity: sensor.family_room_temperature 70 | icon: mdi:thermometer 71 | icon_color: pink 72 | alignment: center 73 | kitchen_id: 74 | name: Kitchen 75 | icon: mdi:silverware-fork-knife 76 | icon_color: red 77 | order: 1 78 | master_bedroom_id: 79 | name: Master Bedroom 80 | icon: mdi:bed-king 81 | icon_color: blue 82 | kids_bedroom_id: 83 | name: Kids Bedroom 84 | icon: mdi:flower-tulip 85 | icon_color: green 86 | card_options: 87 | fan.master_bedroom_fan: 88 | type: custom:mushroom-fan-card 89 | remote.harmony_hub_wk: 90 | hidden: true 91 | quick_access_cards: 92 | - type: custom:mushroom-cover-card 93 | entity: cover.garage_door 94 | show_buttons_control: true 95 | - type: horizontal-stack 96 | cards: 97 | - type: custom:mushroom-lock-card 98 | entity: lock.front_door 99 | - type: custom:mushroom-entity-card 100 | entity: sensor.front_door_lock_battery 101 | name: Battery 102 | extra_cards: 103 | - type: custom:xiaomi-vacuum-map-card 104 | map_source: 105 | camera: camera.xiaomi_cloud_map_extractor 106 | calibration_source: 107 | camera: true 108 | entity: vacuum.robot_vacuum 109 | vacuum_platform: default 110 | extra_views: 111 | - theme: Backend-selected 112 | title: Cool view 113 | path: cool-view 114 | icon: mdi:emoticon-cool 115 | badges: [] 116 | cards: 117 | - type: markdown 118 | content: I am cool 119 | ``` 120 | -------------------------------------------------------------------------------- /docs/getting-started/basic-setup.md: -------------------------------------------------------------------------------- 1 | # ⚙️ Basic Setup 2 | 3 | To apply the Mushroom Strategy to a dashboard: 4 | 5 | 1. In the UI of the dashboard, select :material-pencil: in the top right corner. 6 | 2. If not taken to a Raw Configuration editor, click the three-dot menu in the top right corner. 7 | 3. Select `Raw configuration editor`. 8 | 4. Empty the configuration and add the following lines: 9 | 10 | ```yaml 11 | strategy: 12 | type: custom:mushroom-strategy 13 | ``` 14 | 15 | !!!warning 16 | 17 | You may see the following error: 18 | 19 | ``` 20 | Error loading the dashboard strategy: 21 | Error: Timeout waiting for strategy 22 | element ||-strategy-mushroom-strategy to 23 | be registered 24 | ``` 25 | 26 | This is mainly because of cache issues or HACS didn't create a reference. 27 | Try clearing the cache of your client and/or re-downloading the strategy from HACS. 28 | 29 | If it still doesn't work, please consult guide 30 | [How to solve: Error loading the dashboard strategy](https://github.com/DigiLive/mushroom-strategy/discussions/90). 31 | -------------------------------------------------------------------------------- /docs/getting-started/installation.md: -------------------------------------------------------------------------------- 1 | # 🚀 Installation 2 | 3 | ## ⚙️ Prerequisites 4 | 5 | Mushroom dashboard strategy and dependencies are available in [HACS][hacsUrl]{: target="_blank"} (Home Assistant 6 | Community Store). 7 | Install HACS if you don't have it already. 8 | For assistance, you can follow the [installation guide][hacsInstallationGuideUrl]{: target="_blank"}. 9 | 10 | Once you have HACS installed, you can install custom integration and plug-ins. 11 | This guide offers you badges to open your Home Assistant on the correct page. 12 | If the badges don't work, try installing from HACS manually: 13 | 14 | 1. Open HACS in Home Assistant (Usually in the menu on the left side). 15 | 2. At the top, search for the component you want to install. 16 | 3. Select the `three-dot` menu on the right side of the component and select `Download`. 17 | 4. Choose the desired version and select `Download` again. 18 | 19 | You need to install the following HACS integrations before you can use this strategy. 20 | Click the badges below and follow the installation instructions. 21 | They will open the HACS repository at your Home Assistant instance directly. 22 | 23 | [![Open in HACS at your Home Assistant instance.][hacsBadge]][hacsMushroomUrl]{: target="_blank"} to install 24 | [Mushroom][mushroomUrl]{: target="_blank"}. 25 | [![Open in HACS at your Home Assistant instance.][hacsBadge]][hacsMiniGraphUrl]{: target="_blank"} to 26 | install [Mini graph card][miniGraphUrl]{: target="_blank"}. 27 | 28 | ## 🛠️ Dashboard Installation 29 | 30 | If you meet all the prerequisites, click the badge below to install the strategy. 31 | 32 | [![Open in HACS at your Home Assistant instance.][hacsBadge]][hacsStrategyUrl]{: target="_blank"} 33 | 34 | ## 🛠️ Local Installation 35 | 36 | Please install the strategy with HACS as described above. 37 | If you require testing a custom build for debug purposes, follow these steps: 38 | 39 | 1. Build the strategy with `npm build` or `npm build-dev`. 40 | 2. Copy the build file(s) to folder `/www/community/mushroom-strategy`. 41 | 3. If file `mushroom-strategy.js.gz` exists in that folder, rename or delete it. 42 | 43 | !!! note 44 | 45 | Refresh the cache of the client you use to access Home Assistant. 46 | 47 | ## 🔄 Updating 48 | 49 | By default, Home Assistant will notify you when an update of the strategy is available. 50 | You can update the strategy by going to `Settings` found at the bottom of the sidebar. 51 | 52 | !!! tip 53 | 54 | You can enable notifications of pre-releases. 55 | 56 | * Go to `Settings` > `Devices & services` > `Entities`. 57 | * Search for `Mushroom Dashboard` and switch on the `Pre-release` entity. 58 | 59 | 60 | 61 | [hacsUrl]: https://hacs.xyz 62 | 63 | [hacsInstallationGuideUrl]: https://hacs.xyz/docs/setup/prerequisites 64 | 65 | [hacsBadge]: https://img.shields.io/badge/Open%20my%20HACS%20Repository-%2318BCF2?logo=homeassistant&logoColor=%23FFFFFF&labelColor=%2318BCF2 66 | 67 | [mushroomUrl]: https://github.com/piitaya/lovelace-mushroom 68 | 69 | [hacsMushroomUrl]: https://my.home-assistant.io/redirect/hacs_repository/?owner=piitaya&repository=lovelace-mushroom&category=frontend 70 | 71 | [miniGraphUrl]: https://github.com/kalkih/mini-graph-card 72 | 73 | [hacsMiniGraphUrl]: https://my.home-assistant.io/redirect/hacs_repository/?owner=kalkih&repository=mini-graph-card&category=frontend 74 | 75 | [hacsStrategyUrl]: https://my.home-assistant.io/redirect/hacs_repository/?owner=DigiLive&repository=mushroom-strategy&category=frontend 76 | -------------------------------------------------------------------------------- /docs/images/Hidden.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DigiLive/mushroom-strategy/43d5996453fed1cfa145a955b2d18eeb23dae1e4/docs/images/Hidden.png -------------------------------------------------------------------------------- /docs/images/additonal_cards.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DigiLive/mushroom-strategy/43d5996453fed1cfa145a955b2d18eeb23dae1e4/docs/images/additonal_cards.png -------------------------------------------------------------------------------- /docs/images/auto.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DigiLive/mushroom-strategy/43d5996453fed1cfa145a955b2d18eeb23dae1e4/docs/images/auto.png -------------------------------------------------------------------------------- /docs/images/chips.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DigiLive/mushroom-strategy/43d5996453fed1cfa145a955b2d18eeb23dae1e4/docs/images/chips.png -------------------------------------------------------------------------------- /docs/images/customizable.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DigiLive/mushroom-strategy/43d5996453fed1cfa145a955b2d18eeb23dae1e4/docs/images/customizable.png -------------------------------------------------------------------------------- /docs/images/light_view.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DigiLive/mushroom-strategy/43d5996453fed1cfa145a955b2d18eeb23dae1e4/docs/images/light_view.png -------------------------------------------------------------------------------- /docs/images/preview.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DigiLive/mushroom-strategy/43d5996453fed1cfa145a955b2d18eeb23dae1e4/docs/images/preview.gif -------------------------------------------------------------------------------- /docs/images/views.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DigiLive/mushroom-strategy/43d5996453fed1cfa145a955b2d18eeb23dae1e4/docs/images/views.png -------------------------------------------------------------------------------- /docs/index.md: -------------------------------------------------------------------------------- 1 | # :brown_mushroom: Welcome to the Mushroom Strategy Documentation 2 | 3 | [![Release][releaseBadge]][releaseUrl] 4 | [![HACS][hacsBadge]][hacsUrl] 5 | [![Codacy][codacyBadge]][codacyUrl] 6 | 7 | The **Mushroom Strategy** is an innovative solution for Home Assistant that empowers you to effortlessly create 8 | beautiful, intuitive, and automatically generated dashboards using the 9 | popular [Mushroom cards](https://github.com/piitaya/lovelace-mushroom). 10 | 11 | Say goodbye to tedious manual YAML configuration for every card! With the Mushroom Strategy, you can define your 12 | entities, areas, and devices and let the strategy intelligently build a dynamic and responsive dashboard tailored to 13 | your smart home. 14 | 15 | ## ✨ Key Features & Benefits 16 | 17 | * **Automated Dashboard Generation:** Create a comprehensive dashboard with minimal YAML, saving you countless hours. 18 | * **Leverages Mushroom Cards:** Enjoy the stunning aesthetics and rich functionality of Mushroom cards, renowned for 19 | their clean design and user-friendliness. 20 | * **Entity, Device, and Area-Aware:** Automatically organizes your Home Assistant components into logical, navigable 21 | views. 22 | * **Built-in Views:** Access pre-built views for specific domains like lights, fans, climate, and more, ensuring quick 23 | control. 24 | * **Highly Customizable:** While automated, the strategy provides ample options to fine-tune the appearance and behavior 25 | to match your preferences. 26 | * **Responsive Design:** Your generated dashboard will look great and function seamlessly across all devices – mobile, 27 | tablet, and desktop. 28 | * **Mini Graph:** Utilize [Mini Graphs](https://github.com/kalkih/mini-graph-card) to visualize data of sensors. 29 | * **Stateful Scenes Support:** Support for stateful scenes 30 | from [Stateful Scenes](https://github.com/hugobloem/stateful_scenes). 31 | 32 | ## 🚀 Get Started in Minutes 33 | 34 | Ready to transform your Home Assistant interface? Follow these guides to get your Mushroom Strategy dashboard up and 35 | running: 36 | 37 | * [**Installation Guide**](getting-started/installation.md): Step-by-step instructions to install the strategy via HACS 38 | or manually. 39 | * [**Basic Setup**](getting-started/basic-setup.md): Learn the fundamental configuration to generate your first 40 | dashboard. 41 | * [**Configuration Options**](options/index.md): Dive deeper into all available settings to customize your dashboard to 42 | perfection. 43 | * [**Usage Example**](full-example.md): An example to show most of the configuration options. 44 | 45 | --- 46 | 47 | We're excited for you to experience the simplicity and power of the Mushroom Strategy. If you have questions, encounter 48 | issues, or want to contribute, please visit our [GitHub repository](https://github.com/DigiLive/mushroom-strategy) and 49 | engage with the community! 50 | 51 | **Enjoying the Mushroom Strategy?** Consider giving our project a 52 | :star: [star on GitHub](https://github.com/DigiLive/mushroom-strategy) and exploring ways 53 | to :heart: [sponsor the project](https://github.com/sponsors/DigiLive) to support its continued development! Your 54 | support helps us grow and improve. 55 | 56 | ## 👀 Sneak Peak 57 | 58 | ![Preview GIF](images/preview.gif) 59 | 60 | ??? note "Click here for more images..." 61 | ![Automatic](images/auto.png) 62 | ![Views](images/views.png) 63 | ![customizable](images/customizable.png) 64 | 65 | 66 | 67 | [codacyBadge]: https://app.codacy.com/project/badge/Grade/24de1e79aea445499917d9acd5ce9e04 68 | 69 | [hacsBadge]: https://img.shields.io/badge/HACS-Default-blue 70 | 71 | [releaseBadge]: https://img.shields.io/github/v/tag/digilive/mushroom-strategy?filter=v2.3.4&label=Release 72 | 73 | 74 | 75 | [releaseUrl]: https://github.com/DigiLive/mushroom-strategy/releases/tag/v2.3.4 76 | 77 | 78 | 79 | [codacyUrl]: https://app.codacy.com/gh/DigiLive/mushroom-strategy/dashboard?utm_source=gh&utm_medium=referral&utm_content=&utm_campaign=Badge_grade 80 | 81 | [hacsUrl]: https://hacs.xyz 82 | -------------------------------------------------------------------------------- /docs/options/area-options.md: -------------------------------------------------------------------------------- 1 | # 🛋️ Area Options 2 | 3 | The `areas` group enables you to specify the configuration of specific areas. 4 | Each configuration is identified by an area id and can have the following options: 5 | 6 | | Name | Type | Default | Description | 7 | |:--------------|:---------------|:----------------|:---------------------------------------------------------------------------| 8 | | `extra_cards` | array of cards | `[]` | A list of cards to show on the top of the area sub-view. | 9 | | `hidden` | boolean | `false` | Set to `true` to exclude the area from the dashboard and views. | 10 | | `name` | string | `Area specific` | The name of the area. | 11 | | `order` | number | `unset` | Ordering position of the area in the list of available areas. | 12 | | `type` | string | `default` | Set to a type of area card. (Currently supported: `default` & `HaAreaCard` | 13 | 14 | Also, all options from the Template mushroom card and/or Home Assistant Area card are supported. 15 | Please follow the links below to see the additional options per card type. 16 | 17 | * [Mushroom Template Card][templateDocUrl]{: target="_blank"}. 18 | * [Home Assistant Area Card][areaDocUrl]{: target="_blank"}. 19 | 20 | ## Extra Cards 21 | 22 | The `extra_cards` group enables you to specify the configuration of additional cards an Area view. 23 | These cards will be shown last in the view. 24 | 25 | See Home View Options → [Extra Cards](#extra-cards) for more information. 26 | 27 | ## Example 28 | 29 | ```yaml 30 | strategy: 31 | type: custom:mushroom-strategy 32 | options: 33 | areas: 34 | family_room_id: 35 | name: Family Room 36 | icon: mdi:television 37 | icon_color: green 38 | order: 1 39 | extra_cards: 40 | - type: custom:mushroom-chips-card 41 | chips: 42 | - type: entity 43 | entity: sensor.family_room_temperature 44 | icon: mdi:thermometer 45 | icon_color: pink 46 | alignment: center 47 | kitchen_id: 48 | name: Kitchen 49 | icon: mdi:silverware-fork-knife 50 | icon_color: red 51 | order: 2 52 | garage_id: 53 | hidden: true 54 | hallway_id: 55 | type: HaAreaCard 56 | extra_cards: 57 | - type: custom:xiaomi-vacuum-map-card 58 | map_source: 59 | camera: camera.xiaomi_cloud_map_extractor 60 | calibration_source: 61 | camera: true 62 | entity: vacuum.robot_vacuum 63 | vacuum_platform: default 64 | views: [] 65 | ``` 66 | 67 | ## Undisclosed Area 68 | 69 | The strategy has a special area, named `undisclosed`. 70 | This area is enabled by default and includes the entities that aren't linked to any Home Assistant area. 71 | 72 | The area can be configured like any other area as described above. 73 | To exclude this area from the dashboard and views, set its property `hidden` to `true`. 74 | 75 | ## Setting options for all areas 76 | 77 | Use `_` as an identifier to set the options for all areas. 78 | The following example sets the type of all area-cards to the one of Home Assistant: 79 | 80 | ### Example 81 | 82 | ```yaml 83 | strategy: 84 | type: custom:mushroom-strategy 85 | options: 86 | areas: 87 | _: 88 | type: HaAreaCard 89 | views: [] 90 | ``` 91 | 92 | !!! note 93 | 94 | Area specific options take precedence over options set for all areas! 95 | 96 | 97 | 98 | [templateDocUrl]: https://github.com/piitaya/lovelace-mushroom/blob/main/docs/cards/template.md 99 | 100 | [areaDocUrl]: https://www.home-assistant.io/dashboards/area/#configuration-variables 101 | -------------------------------------------------------------------------------- /docs/options/card-options.md: -------------------------------------------------------------------------------- 1 | # :material-cards-outline: Card Options 2 | 3 | The `card_options` group enables you to specify the configuration of entity cards. 4 | Each configuration is identified by an entity id and can have the following options: 5 | 6 | | name | type | default | description | 7 | |:-------|:--------|:------------------|:------------------------------------------------------| 8 | | hidden | boolean | `false` | Set to `true` to exclude the card from the dashboard. | 9 | | type | string | `domain specific` | The type for card to apply. | 10 | | ... | ... | `type specific` | An option belonging to the given card type. | 11 | 12 | Depending on the type of card, you can also specify options belonging to that type. 13 | 14 | Providing a device id will enable you to hide all the entities associated with that device. 15 | 16 | ## Example 17 | 18 | ```yaml 19 | strategy: 20 | type: custom:mushroom-strategy 21 | options: 22 | card_options: 23 | fan.master_bedroom_fan: 24 | type: custom:mushroom-fan-card 25 | icon: mdi:fan 26 | remote.harmony_hub_wk: 27 | hidden: true 28 | 077ba0492c9bb3b3134f1f3a626a: # this is a device id 29 | hidden: true 30 | ``` 31 | 32 | !!! tip 33 | 34 | You can build your card at another dashboard and copy the `cards` group from the YAML of that dashboard into group 35 | `card_options` of the strategy configuration. The YAML can be found in the Raw configuration editor. 36 | -------------------------------------------------------------------------------- /docs/options/domain-options.md: -------------------------------------------------------------------------------- 1 | # 💡 Domain Options 2 | 3 | The `domains` group enables you to specify the configuration of a domain in a view. 4 | Each configuration is identified by a domain name and can have the following options: 5 | 6 | | Option | type | Default | Description | 7 | |:-------------------------|:--------|:------------------|:--------------------------------------------------------------------------| 8 | | hidden | boolean | `false` | Set to `true` to exclude the domain from the dashboard. | 9 | | hide_config_entities | boolean | `true` | Set to `false` to include config-entities to the dashboard. | 10 | | hide_diagnostic_entities | boolean | `true` | Set to `false` to include diagnostic-entities to the dashboard. | 11 | | order | number | `unset` | Ordering position of the domain entities in a view. | 12 | | showControls | boolean | `true` | Weather to show controls in a view, to switch all entities of the domain. | 13 | | stack_count | object | `{_: 1}` | Cards per row.[^1] | 14 | | title | string | `domain specific` | Title of the domain in a view. | 15 | 16 | [^1]: 17 | In the different views, the cards belonging to a specific domain will be horizontally stacked into a row. 18 | The number of cards per row can be configured with this option. 19 | 20 | !!! note 21 | 22 | * Domain `default` represents any other domain than supported by this strategy. 23 | * The `showControls` option will default to false for domain which can't be controlled. 24 | * The `hide_config_entities` and `hide_diagnostic_entities` options are only available as an "All domains" option. 25 | 26 | --- 27 | 28 | ## Setting options for all domains 29 | 30 | Use `_` as the identifier to set options for all domains. 31 | 32 | ## Example 33 | 34 | ```yaml 35 | strategy: 36 | type: custom:mushroom-strategy 37 | options: 38 | domains: 39 | _: 40 | stack_count: 2 41 | hide_config_entities: false 42 | light: 43 | title: "My cool lights" 44 | order: 1 45 | switch: 46 | stack_count: 3 47 | showControls: false 48 | default: # All other domains 49 | hidden: true 50 | ``` 51 | 52 | ??? info "Click to expand the full list of supported domains" 53 | 54 | - _ (All domains) 55 | - area 56 | - binary_sensor 57 | - camera 58 | - climate 59 | - cover 60 | - default (Miscellaneous) 61 | - fan 62 | - input_select 63 | - light 64 | - lock 65 | - media_player 66 | - number 67 | - person 68 | - scene 69 | - select 70 | - sensor 71 | - switch 72 | - vacuum 73 | - valve 74 | -------------------------------------------------------------------------------- /docs/options/index.md: -------------------------------------------------------------------------------- 1 | # ⚙️ Overview 2 | 3 | The dashboard can be highly customized using the `options` parameter in the yaml configuration of your dashboard. 4 | 5 | ```yaml 6 | strategy: 7 | type: custom:mushroom-strategy 8 | options: 9 | # Custom Configuration 10 | ``` 11 | 12 | By default, 13 | 14 | - All views and domains are enabled. 15 | - All chips are enabled and count the number of "active" entities. 16 | - For the weather chip, the entity is selected automatically unless you specify one. 17 | - All entities without an area are added to the `undisclosed` area. 18 | - All configuration- and diagnostic entities are hidden. 19 | 20 | The options are divided into groups as described below. 21 | 22 | | Name | Type | Default | Description | 23 | |:-------------------|:---------------|:----------------------|:------------------------------------------------------------------------------------------------------------------------------------------| 24 | | areas | object | undisclosed | See [Area Options](area-options.md). | 25 | | card_options | object | empty | See [Card Options](card-options.md). | 26 | | domains | object | All supported domains | See [Domain Options](domain-options.md). | 27 | | home_view | object | unset | See [Home View Options](home-view-options.md). | 28 | | chips | object | All supported chips | See [Chip Options](home-view-options.md#chip-options). | 29 | | quick_access_cards | array of cards | empty | List of cards to show between the greeting card and the area cards.
See [Quick Access Cards](home-view-options.md#quick-access-cards). | 30 | | extra_cards | array of cards | empty | List of cards to show below the area cards.
See [extra Cards](home-view-options.md#extra-cards). | 31 | | views | object | All supported views | See [View Options](view-options.md). | 32 | | extra_views | array of views | empty | List of user defined views to add to the dashboard.
See [Extra Views](view-options.md#extra-views). | 33 | 34 | ## Example 35 | 36 | ```yaml 37 | strategy: 38 | type: custom:mushroom-strategy 39 | options: 40 | areas: 41 | family_room_id: 42 | name: Family Room 43 | icon: mdi:sofa 44 | icon_color: green 45 | ``` 46 | -------------------------------------------------------------------------------- /docs/options/view-options.md: -------------------------------------------------------------------------------- 1 | # 👀 View Options 2 | 3 | Mushroom strategy includes several views to control/view entities of a specific domain. 4 | Hidden/Disabled entities or linked to a hidden area are excluded from the view. 5 | 6 | The following views are supported and enabled by default: 7 | 8 | | View | Type | Description | 9 | |:--------|:-------|:-------------------------------------------| 10 | | camera | object | View to control cameras. | 11 | | climate | object | View to control climates. | 12 | | cover | object | View to control covers. | 13 | | fan | object | View to control fans. | 14 | | home | object | An overview of several entities and areas. | 15 | | light | object | View to control lights. | 16 | | lock | object | View to control locks. | 17 | | scene | object | View to control scenes. | 18 | | switch | object | View to control switches. | 19 | | vacuum | object | View to control vacuums. | 20 | | valve | object | View to control valves. | 21 | 22 | The `views` group enables you to specify the configuration of a view. 23 | Each configuration is identified by a view name and can have the following options: 24 | 25 | | name | type | Default | description | 26 | |:-------|:--------|:-----------------------------------------------------------------------------|:-----------------------------------------------------------------------------------------------| 27 | | hidden | boolean | `false` | Set to `true` to exclude the view from the dashboard | 28 | | icon | string | `domain specific` | Icon of the view in the navigation bar. | 29 | | order | string | home, light, fan, cover, switch, climate, camera, vacuum, scene, lock, valve | Ordering position of the view in the navigation bar. | 30 | | title | string | `domain specific` | Title of the view in the navigation bar. (Shown when no icon is defined or hovering above it.) | 31 | 32 | ## Example 33 | 34 | ```yaml 35 | strategy: 36 | type: custom:mushroom-strategy 37 | options: 38 | views: 39 | light: 40 | order: 0 41 | title: illumination 42 | switch: 43 | order: 1 44 | hidden: true 45 | icon: mdi:toggle-switch 46 | views: [] 47 | ``` 48 | 49 | --- 50 | 51 | ## Extra Views 52 | 53 | The `extra_views` group enables you to specify the configuration of additional views. 54 | Each view can have the options as described in the [Home Assistant documentation][viewDocUrl]{: target="_blank"}. 55 | 56 | Extra views are sorted by order first and then by title, together with the build-in views. 57 | 58 | !!! tip 59 | 60 | You can build your view in a temporary dashboard and copy the `views` group from the YAML of that dashboard into 61 | group `extra_views` of the strategy configuration. The YAML can be found in the Raw configuration editor. 62 | 63 | ### Example 64 | 65 | ```yaml 66 | strategy: 67 | type: custom:mushroom-strategy 68 | options: 69 | extra_views: 70 | - theme: Backend-selected 71 | title: cool view 72 | path: cool-view 73 | order: Infinity 74 | icon: mdi:emoticon-cool 75 | badges: [] 76 | cards: 77 | - type: markdown 78 | content: I am cool 79 | ``` 80 | 81 | 82 | 83 | [viewDocUrl]: https://www.home-assistant.io/dashboards/views/#views 84 | -------------------------------------------------------------------------------- /docs/stylesheets/extra.css: -------------------------------------------------------------------------------- 1 | a[target="_blank"]::after { 2 | background-image: url('data:image/svg+xml;utf8,'); 3 | background-repeat: no-repeat; 4 | background-size: cover; 5 | content: ""; 6 | display: inline-block; 7 | height: 0.8em; 8 | margin-left: 0.3em; 9 | opacity: 0.7; 10 | vertical-align: middle; 11 | width: 0.8em; 12 | } 13 | 14 | [data-md-color-scheme="slate"] a[target="_blank"]::after { 15 | filter: invert(100%); 16 | } 17 | -------------------------------------------------------------------------------- /hacs.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Mushroom Dashboard Strategy", 3 | "render_readme": true, 4 | "filename": "mushroom-strategy.js", 5 | "homeassistant": "2024.7.0" 6 | } 7 | -------------------------------------------------------------------------------- /mkdocs.yml: -------------------------------------------------------------------------------- 1 | site_name: Mushroom Strategy Documentation 2 | site_url: https://digilive.github.io/mushroom-strategy/ 3 | site_description: The official documentation for Home Assistant's Mushroom Dashboard Strategy. 4 | 5 | repo_url: https://github.com/DigiLive/mushroom-strategy/ 6 | edit_uri: edit/main/docs/ 7 | 8 | site_author: Ferry Cools 9 | copyright: Copyright © 2024 - DigiLive. All Rights Reserved. 10 | 11 | theme: 12 | name: material 13 | icon: 14 | logo: material/mushroom 15 | palette: 16 | - media: '(prefers-color-scheme: light)' 17 | scheme: default 18 | primary: blue 19 | accent: light blue 20 | toggle: 21 | icon: material/brightness-7 22 | name: Switch to dark mode 23 | - media: '(prefers-color-scheme: dark)' 24 | scheme: slate 25 | primary: blue 26 | accent: light blue 27 | toggle: 28 | icon: material/brightness-4 29 | name: Switch to light mode 30 | - media: '(prefers-color-scheme)' 31 | toggle: 32 | icon: material/brightness-auto 33 | name: Switch to light/dark mode (auto) 34 | features: 35 | - navigation.tabs 36 | - navigation.sections 37 | - toc.integrate 38 | - toc.follow 39 | - search.suggest 40 | - search.highlight 41 | - content.code.copy 42 | - content.tabs 43 | - content.action.edit 44 | - content.footnote.tooltips 45 | 46 | extra_css: 47 | - stylesheets/extra.css 48 | 49 | nav: 50 | - Home: index.md 51 | - Getting Started: 52 | - Installation: getting-started/installation.md 53 | - Basic Setup: getting-started/basic-setup.md 54 | - Strategy Options: 55 | - Overview: options/index.md 56 | - Area Options: options/area-options.md 57 | - Card Options: options/card-options.md 58 | - Domain Options: options/domain-options.md 59 | - Home View Options: options/home-view-options.md 60 | - View Options: options/view-options.md 61 | - Full Example: full-example.md 62 | - FAQ: faq.md 63 | - Contributing: 64 | - contributing/index.md 65 | - Getting Started: contributing/getting-started.md 66 | - Workflow: contributing/workflow.md 67 | - Code: contributing/code.md 68 | - Documentation: contributing/documentation.md 69 | - Translations: contributing/translations.md 70 | 71 | markdown_extensions: 72 | - toc: 73 | permalink: '#' 74 | - admonition 75 | - pymdownx.superfences 76 | - pymdownx.details 77 | - footnotes 78 | - attr_list 79 | - pymdownx.emoji: 80 | emoji_index: !!python/name:material.extensions.emoji.twemoji 81 | emoji_generator: !!python/name:material.extensions.emoji.to_svg 82 | 83 | validation: 84 | nav: 85 | not_found: warn 86 | links: 87 | not_found: warn 88 | anchors: warn 89 | unrecognized_links: warn 90 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "mushroom-strategy", 3 | "version": "2.3.4", 4 | "description": "Automatically generate a dashboard of Mushroom cards.", 5 | "keywords": [ 6 | "dashboard", 7 | "strategy", 8 | "mushroom" 9 | ], 10 | "homepage": "https://github.com/DigiLive/mushroom-strategy", 11 | "bugs": "https://github.com/DigiLive/mushroom-strategy/issues", 12 | "license": "MIT", 13 | "author": { 14 | "name": "Ferry Cools" 15 | }, 16 | "contributors": [ 17 | { 18 | "name": "Aalian Khan" 19 | } 20 | ], 21 | "funding": { 22 | "type": "github", 23 | "url": "https://github.com/sponsors/DigiLive" 24 | }, 25 | "repository": { 26 | "type": "git", 27 | "url": "https://github.com/DigiLive/mushroom-strategy" 28 | }, 29 | "dependencies": { 30 | "deepmerge": "^4" 31 | }, 32 | "devDependencies": { 33 | "@typescript-eslint/eslint-plugin": "^8.33.0", 34 | "@typescript-eslint/parser": "^8.32.1", 35 | "eslint": "^9.27.0", 36 | "eslint-config-prettier": "^10.1.5", 37 | "eslint-plugin-prettier": "^5.4.0", 38 | "home-assistant-js-websocket": "^9.5.0", 39 | "markdownlint-cli2": "^0.18.1", 40 | "prettier": "^3.5.3", 41 | "superstruct": "^2.0.2", 42 | "ts-loader": "^9.5.2", 43 | "ts-node": "^10.9.2", 44 | "typescript": "^5.8.3", 45 | "version-bump-prompt": "^6", 46 | "webpack": "^5.99.9", 47 | "webpack-cli": "^6.0.1" 48 | }, 49 | "scripts": { 50 | "ts:format": "prettier --write \"**/*.ts\"", 51 | "json:format": "prettier --write \"**/*.json\"", 52 | "mkdocs:serve": "mkdocs serve", 53 | "md:lint": "markdownlint-cli2 \"**/*.md\" \"#node_modules\" \"#dist\"", 54 | "md:lint:fix": "markdownlint-cli2 \"**/*.md\" \"#node_modules\" \"#dist\" --fix", 55 | "build-dev": "webpack --config webpack.dev.config.ts", 56 | "build": "webpack", 57 | "bump": "bump --preid alpha package.json package-lock.json README.md ./docs/index.md ./src/mushroom-strategy.ts" 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/cards/AbstractCard.ts: -------------------------------------------------------------------------------- 1 | import { Registry } from '../Registry'; 2 | import { LovelaceCardConfig } from '../types/homeassistant/data/lovelace/config/card'; 3 | import { AbstractCardConfig } from '../types/strategy/strategy-cards'; 4 | import { RegistryEntry } from '../types/strategy/strategy-generics'; 5 | import { logMessage, lvlFatal } from '../utilities/debug'; 6 | 7 | /** 8 | * Abstract Card Class 9 | * 10 | * To create a card configuration, this class should be extended by a child class. 11 | * Child classes should override the default configuration so the card correctly reflects the entity. 12 | * 13 | * @remarks 14 | * Before using this class, the Registry module must be initialized by calling {@link Registry.initialize}. 15 | */ 16 | abstract class AbstractCard { 17 | /** The registry entry this card represents. */ 18 | readonly entity: RegistryEntry; 19 | 20 | /** 21 | * The card configuration for this entity. 22 | * 23 | * Child classes should override this property to reflect their own card type and options. 24 | */ 25 | protected configuration: LovelaceCardConfig = { 26 | type: 'custom:mushroom-entity-card', 27 | icon: 'mdi:help-circle', 28 | }; 29 | 30 | /** 31 | * Class constructor. 32 | * 33 | * @param {RegistryEntry} entity The registry entry to create a card configuration for. 34 | * 35 | * @remarks 36 | * Before this class can be used, the Registry module must be initialized by calling {@link Registry.initialize}. 37 | */ 38 | protected constructor(entity: RegistryEntry) { 39 | if (!Registry.initialized) { 40 | logMessage(lvlFatal, 'Registry not initialized!'); 41 | } 42 | 43 | this.entity = entity; 44 | } 45 | 46 | /** 47 | * Get a card configuration. 48 | * 49 | * The configuration should be set by any of the child classes so the card correctly reflects an entity. 50 | */ 51 | getCard(): AbstractCardConfig { 52 | return { 53 | ...this.configuration, 54 | entity: 'entity_id' in this.entity ? this.entity.entity_id : undefined, 55 | }; 56 | } 57 | } 58 | 59 | export default AbstractCard; 60 | -------------------------------------------------------------------------------- /src/cards/AreaCard.ts: -------------------------------------------------------------------------------- 1 | import { AreaRegistryEntry } from '../types/homeassistant/data/area_registry'; 2 | import { TemplateCardConfig } from '../types/lovelace-mushroom/cards/template-card-config'; 3 | import AbstractCard from './AbstractCard'; 4 | 5 | /** 6 | * Area Card Class 7 | * 8 | * Used to create card configuration for an entry of the HASS area registry. 9 | */ 10 | class AreaCard extends AbstractCard { 11 | /** Returns the default configuration object for the card. */ 12 | static getDefaultConfig(): TemplateCardConfig { 13 | return { 14 | type: 'custom:mushroom-template-card', 15 | primary: undefined, 16 | icon: 'mdi:floor-plan', 17 | icon_color: 'blue', 18 | tap_action: { action: 'navigate', navigation_path: '' }, 19 | hold_action: { action: 'none' }, 20 | }; 21 | } 22 | 23 | /** 24 | * Class constructor. 25 | * 26 | * @param {AreaRegistryEntry} area The HASS area to create a card configuration for. 27 | * @param {TemplateCardConfig} [customConfiguration] Custom card configuration. 28 | */ 29 | constructor(area: AreaRegistryEntry, customConfiguration?: TemplateCardConfig) { 30 | super(area); 31 | 32 | const configuration = AreaCard.getDefaultConfig(); 33 | 34 | let customConfig = customConfiguration; 35 | 36 | configuration.primary = area.name; 37 | configuration.icon = area.icon || configuration.icon; 38 | 39 | if (configuration.tap_action && 'navigation_path' in configuration.tap_action) { 40 | configuration.tap_action.navigation_path = area.area_id; 41 | } 42 | 43 | // Don't override the card type if set differently in the strategy options. 44 | if (customConfig) { 45 | customConfig = { ...customConfig, type: configuration.type }; 46 | } 47 | 48 | this.configuration = { ...this.configuration, ...configuration, ...customConfig }; 49 | } 50 | } 51 | 52 | export default AreaCard; 53 | -------------------------------------------------------------------------------- /src/cards/BinarySensorCard.ts: -------------------------------------------------------------------------------- 1 | // noinspection JSUnusedGlobalSymbols Class is dynamically imported. 2 | 3 | import { EntityRegistryEntry } from '../types/homeassistant/data/entity_registry'; 4 | import { EntityCardConfig } from '../types/lovelace-mushroom/cards/entity-card-config'; 5 | import SensorCard from './SensorCard'; 6 | 7 | /** 8 | * Sensor Card Class 9 | * 10 | * Used to create a card configuration to control an entity of the binary_sensor domain. 11 | */ 12 | class BinarySensorCard extends SensorCard { 13 | /** Returns the default configuration object for the card. */ 14 | static getDefaultConfig(): EntityCardConfig { 15 | return { 16 | type: 'custom:mushroom-entity-card', 17 | icon: 'mdi:power-cycle', 18 | icon_color: 'green', 19 | }; 20 | } 21 | 22 | /** 23 | * Class constructor. 24 | * 25 | * @param {EntityRegistryEntry} entity The HASS entity to create a card configuration for. 26 | * @param {EntityCardConfig} [customConfiguration] Custom card configuration. 27 | */ 28 | constructor(entity: EntityRegistryEntry, customConfiguration?: EntityCardConfig) { 29 | super(entity); 30 | 31 | this.configuration = { ...this.configuration, ...BinarySensorCard.getDefaultConfig(), ...customConfiguration }; 32 | } 33 | } 34 | 35 | export default BinarySensorCard; 36 | -------------------------------------------------------------------------------- /src/cards/CameraCard.ts: -------------------------------------------------------------------------------- 1 | // noinspection JSUnusedGlobalSymbols Class is dynamically imported. 2 | 3 | import { EntityRegistryEntry } from '../types/homeassistant/data/entity_registry'; 4 | import { PictureEntityCardConfig } from '../types/homeassistant/panels/lovelace/cards/types'; 5 | import AbstractCard from './AbstractCard'; 6 | 7 | /** 8 | * Camera Card Class 9 | * 10 | * Used to create a card configuration to control an entity of the camera domain. 11 | */ 12 | class CameraCard extends AbstractCard { 13 | /** Returns the default configuration object for the card. */ 14 | static getDefaultConfig(): PictureEntityCardConfig { 15 | return { 16 | entity: '', 17 | type: 'picture-entity', 18 | show_name: false, 19 | show_state: false, 20 | camera_view: 'live', 21 | }; 22 | } 23 | 24 | /** 25 | * Class constructor. 26 | * 27 | * @param {EntityRegistryEntry} entity The HASS entity to create a card configuration for. 28 | * @param {PictureEntityCardConfig} [customConfiguration] Custom card configuration. 29 | */ 30 | constructor(entity: EntityRegistryEntry, customConfiguration?: PictureEntityCardConfig) { 31 | super(entity); 32 | 33 | this.configuration = { ...this.configuration, ...CameraCard.getDefaultConfig(), ...customConfiguration }; 34 | } 35 | } 36 | 37 | export default CameraCard; 38 | -------------------------------------------------------------------------------- /src/cards/ClimateCard.ts: -------------------------------------------------------------------------------- 1 | // noinspection JSUnusedGlobalSymbols Class is dynamically imported. 2 | 3 | import { EntityRegistryEntry } from '../types/homeassistant/data/entity_registry'; 4 | import { ClimateCardConfig } from '../types/lovelace-mushroom/cards/climate-card-config'; 5 | import AbstractCard from './AbstractCard'; 6 | 7 | /** 8 | * Climate Card Class 9 | * 10 | * Used to create a card configuration to control an entity of the climate domain. 11 | */ 12 | class ClimateCard extends AbstractCard { 13 | /** Returns the default configuration object for the card. */ 14 | static getDefaultConfig(): ClimateCardConfig { 15 | return { 16 | type: 'custom:mushroom-climate-card', 17 | icon: undefined, 18 | hvac_modes: ['off', 'cool', 'heat', 'fan_only'], 19 | show_temperature_control: true, 20 | }; 21 | } 22 | 23 | /** 24 | * Class constructor. 25 | * 26 | * @param {EntityRegistryEntry} entity The HASS entity to create a card configuration for. 27 | * @param {ClimateCardConfig} [customConfiguration] Custom card configuration. 28 | */ 29 | constructor(entity: EntityRegistryEntry, customConfiguration?: ClimateCardConfig) { 30 | super(entity); 31 | 32 | this.configuration = { ...this.configuration, ...ClimateCard.getDefaultConfig(), ...customConfiguration }; 33 | } 34 | } 35 | 36 | export default ClimateCard; 37 | -------------------------------------------------------------------------------- /src/cards/CoverCard.ts: -------------------------------------------------------------------------------- 1 | // noinspection JSUnusedGlobalSymbols Class is dynamically imported. 2 | 3 | import { EntityRegistryEntry } from '../types/homeassistant/data/entity_registry'; 4 | import { CoverCardConfig } from '../types/lovelace-mushroom/cards/cover-card-config'; 5 | import AbstractCard from './AbstractCard'; 6 | 7 | /** 8 | * Cover Card Class 9 | * 10 | * Used to create a card configuration to control an entity of the cover domain. 11 | */ 12 | class CoverCard extends AbstractCard { 13 | /** Returns the default configuration object for the card. */ 14 | static getDefaultConfig(): CoverCardConfig { 15 | return { 16 | type: 'custom:mushroom-cover-card', 17 | icon: undefined, 18 | show_buttons_control: true, 19 | show_position_control: true, 20 | show_tilt_position_control: true, 21 | }; 22 | } 23 | 24 | /** 25 | * Class constructor. 26 | * 27 | * @param {EntityRegistryEntry} entity The HASS entity to create a card configuration for. 28 | * @param {CoverCardConfig} [customConfiguration] Custom card configuration. 29 | */ 30 | constructor(entity: EntityRegistryEntry, customConfiguration?: CoverCardConfig) { 31 | super(entity); 32 | 33 | this.configuration = { ...this.configuration, ...CoverCard.getDefaultConfig(), ...customConfiguration }; 34 | } 35 | } 36 | 37 | export default CoverCard; 38 | -------------------------------------------------------------------------------- /src/cards/FanCard.ts: -------------------------------------------------------------------------------- 1 | // noinspection JSUnusedGlobalSymbols Class is dynamically imported. 2 | 3 | import { EntityRegistryEntry } from '../types/homeassistant/data/entity_registry'; 4 | import { FanCardConfig } from '../types/lovelace-mushroom/cards/fan-card-config'; 5 | import AbstractCard from './AbstractCard'; 6 | 7 | /** 8 | * Fan Card Class 9 | * 10 | * Used to create a card configuration to control an entity of the fan domain. 11 | */ 12 | class FanCard extends AbstractCard { 13 | /** Returns the default configuration object for the card. */ 14 | static getDefaultConfig(): FanCardConfig { 15 | return { 16 | type: 'custom:mushroom-fan-card', 17 | icon: undefined, 18 | show_percentage_control: true, 19 | show_oscillate_control: true, 20 | icon_animation: true, 21 | }; 22 | } 23 | 24 | /** 25 | * Class constructor. 26 | * 27 | * @param {EntityRegistryEntry} entity The HASS entity to create a card configuration for. 28 | * @param {FanCardConfig} [customConfiguration] Custom card configuration. 29 | */ 30 | constructor(entity: EntityRegistryEntry, customConfiguration?: FanCardConfig) { 31 | super(entity); 32 | 33 | this.configuration = { ...this.configuration, ...FanCard.getDefaultConfig(), ...customConfiguration }; 34 | } 35 | } 36 | 37 | export default FanCard; 38 | -------------------------------------------------------------------------------- /src/cards/HaAreaCard.ts: -------------------------------------------------------------------------------- 1 | // noinspection JSUnusedGlobalSymbols Class is dynamically imported. 2 | 3 | import { AreaRegistryEntry } from '../types/homeassistant/data/area_registry'; 4 | import { AreaCardConfig } from '../types/homeassistant/panels/lovelace/cards/types'; 5 | import AbstractCard from './AbstractCard'; 6 | 7 | /** 8 | * HA Area Card Class 9 | * 10 | * Used to create card configuration for an entry of the HASS area registry. 11 | */ 12 | class AreaCard extends AbstractCard { 13 | /** Returns the default configuration object for the card. */ 14 | static getDefaultConfig(): AreaCardConfig { 15 | return { 16 | type: 'area', 17 | area: '', 18 | }; 19 | } 20 | 21 | /** 22 | * Class constructor. 23 | * 24 | * @param {AreaRegistryEntry} area The HASS entity to create a card configuration for. 25 | * @param {AreaCardConfig} [customConfiguration] Custom card configuration. 26 | */ 27 | constructor(area: AreaRegistryEntry, customConfiguration?: AreaCardConfig) { 28 | super(area); 29 | 30 | // Initialize the default configuration. 31 | const configuration = AreaCard.getDefaultConfig(); 32 | 33 | configuration.area = area.area_id; 34 | configuration.navigation_path = configuration.area; 35 | 36 | this.configuration = { 37 | ...this.configuration, 38 | ...configuration, 39 | ...customConfiguration, 40 | type: configuration.type, // Enforce the card type. 41 | }; 42 | } 43 | } 44 | 45 | export default AreaCard; 46 | -------------------------------------------------------------------------------- /src/cards/HeaderCard.ts: -------------------------------------------------------------------------------- 1 | import { HassServiceTarget } from 'home-assistant-js-websocket'; 2 | import { LovelaceCardConfig } from '../types/homeassistant/data/lovelace/config/card'; 3 | import { StackCardConfig } from '../types/homeassistant/panels/lovelace/cards/types'; 4 | import { CustomHeaderCardConfig, StrategyHeaderCardConfig } from '../types/strategy/strategy-cards'; 5 | 6 | /** 7 | * Header Card class. 8 | * 9 | * Used to create a card configuration for a Header Card. 10 | * The card can be used to describe a group of cards and optionally to control multiple entities. 11 | */ 12 | class HeaderCard { 13 | /** The target to control the entities of. */ 14 | private readonly target: HassServiceTarget; 15 | /** The current configuration of the card after instantiating this class. */ 16 | private readonly configuration: StrategyHeaderCardConfig; 17 | 18 | /** Returns the default configuration object for the card. */ 19 | static getDefaultConfig(): StrategyHeaderCardConfig { 20 | return { 21 | type: 'custom:mushroom-title-card', 22 | iconOn: 'mdi:power-on', 23 | iconOff: 'mdi:power-off', 24 | onService: 'none', 25 | offService: 'none', 26 | }; 27 | } 28 | 29 | /** 30 | * Class constructor. 31 | * 32 | * @param {HassServiceTarget} target The target which is optionally controlled by the card. 33 | * @param {CustomHeaderCardConfig} [customConfiguration] Custom card configuration. 34 | * 35 | * @remarks 36 | * The target object can contain one or multiple ids of different entry types. 37 | */ 38 | constructor(target: HassServiceTarget, customConfiguration?: CustomHeaderCardConfig) { 39 | this.target = target; 40 | this.configuration = { ...HeaderCard.getDefaultConfig(), ...customConfiguration }; 41 | } 42 | 43 | /** 44 | * Create a Header card configuration. 45 | * 46 | * @remarks 47 | * The card is represented by a horizontal stack of cards. 48 | * One title card and optionally two template cards to control entities. 49 | */ 50 | createCard(): StackCardConfig { 51 | // Create a title card. 52 | const cards: LovelaceCardConfig[] = [ 53 | { 54 | type: 'custom:mushroom-title-card', 55 | title: this.configuration.title, 56 | subtitle: this.configuration.subtitle, 57 | }, 58 | ]; 59 | 60 | // Add controls to the card. 61 | if (this.configuration.showControls) { 62 | cards.push({ 63 | type: 'horizontal-stack', 64 | cards: [ 65 | { 66 | type: 'custom:mushroom-template-card', 67 | icon: this.configuration.iconOff, 68 | layout: 'vertical', 69 | icon_color: 'red', 70 | tap_action: { 71 | action: 'call-service', 72 | service: this.configuration.offService, 73 | target: this.target, 74 | data: {}, 75 | }, 76 | }, 77 | { 78 | type: 'custom:mushroom-template-card', 79 | icon: this.configuration.iconOn, 80 | layout: 'vertical', 81 | icon_color: 'amber', 82 | tap_action: { 83 | action: 'call-service', 84 | service: this.configuration.onService, 85 | target: this.target, 86 | data: {}, 87 | }, 88 | }, 89 | ], 90 | }); 91 | } 92 | 93 | return { 94 | type: 'horizontal-stack', 95 | cards: cards, 96 | }; 97 | } 98 | } 99 | 100 | export default HeaderCard; 101 | -------------------------------------------------------------------------------- /src/cards/InputSelectCard.ts: -------------------------------------------------------------------------------- 1 | // noinspection JSUnusedGlobalSymbols Class is dynamically imported. 2 | 3 | import { EntityRegistryEntry } from '../types/homeassistant/data/entity_registry'; 4 | import { SelectCardConfig } from '../types/lovelace-mushroom/cards/select-card-config'; 5 | import SelectCard from './SelectCard'; 6 | 7 | /** 8 | * InputSelect Card Class 9 | * 10 | * Used to create a card configuration to control an entity of the input_select domain. 11 | */ 12 | class InputSelectCard extends SelectCard { 13 | /** Returns the default configuration object for the card. */ 14 | static getDefaultConfig(): SelectCardConfig { 15 | return { 16 | type: 'custom:mushroom-select-card', 17 | icon: undefined, 18 | }; 19 | } 20 | 21 | /** 22 | * Class constructor. 23 | * 24 | * @param {EntityRegistryEntry} entity The HASS entity to create a card configuration for. 25 | * @param {SelectCardConfig} [customConfiguration] Custom card configuration. 26 | */ 27 | constructor(entity: EntityRegistryEntry, customConfiguration?: SelectCardConfig) { 28 | super(entity); 29 | 30 | this.configuration = { ...this.configuration, ...InputSelectCard.getDefaultConfig(), ...customConfiguration }; 31 | } 32 | } 33 | 34 | export default InputSelectCard; 35 | -------------------------------------------------------------------------------- /src/cards/LightCard.ts: -------------------------------------------------------------------------------- 1 | // noinspection JSUnusedGlobalSymbols Class is dynamically imported. 2 | 3 | import { EntityRegistryEntry } from '../types/homeassistant/data/entity_registry'; 4 | import { LightCardConfig } from '../types/lovelace-mushroom/cards/light-card-config'; 5 | import { isCallServiceActionConfig } from '../types/strategy/strategy-generics'; 6 | import AbstractCard from './AbstractCard'; 7 | 8 | /** 9 | * Light Card Class 10 | * 11 | * Used to create a card configuration to control an entity of the light domain. 12 | */ 13 | class LightCard extends AbstractCard { 14 | /** Returns the default configuration object for the card. */ 15 | static getDefaultConfig(): LightCardConfig { 16 | return { 17 | type: 'custom:mushroom-light-card', 18 | icon: undefined, 19 | show_brightness_control: true, 20 | show_color_control: true, 21 | show_color_temp_control: true, 22 | use_light_color: true, 23 | double_tap_action: { 24 | action: 'call-service', 25 | perform_action: 'light.turn_on', 26 | target: { 27 | entity_id: undefined, 28 | }, 29 | data: { 30 | rgb_color: [255, 255, 255], 31 | }, 32 | }, 33 | }; 34 | } 35 | 36 | /** 37 | * Class constructor. 38 | * 39 | * @param {EntityRegistryEntry} entity The HASS entity to create a card configuration for. 40 | * @param {LightCardConfig} [customConfiguration] Custom card configuration. 41 | */ 42 | constructor(entity: EntityRegistryEntry, customConfiguration?: LightCardConfig) { 43 | super(entity); 44 | 45 | const configuration = LightCard.getDefaultConfig(); 46 | 47 | if (isCallServiceActionConfig(configuration.double_tap_action)) { 48 | configuration.double_tap_action.target = { entity_id: entity.entity_id }; 49 | } 50 | 51 | this.configuration = { ...this.configuration, ...configuration, ...customConfiguration }; 52 | } 53 | } 54 | 55 | export default LightCard; 56 | -------------------------------------------------------------------------------- /src/cards/LockCard.ts: -------------------------------------------------------------------------------- 1 | // noinspection JSUnusedGlobalSymbols Class is dynamically imported. 2 | 3 | import { EntityRegistryEntry } from '../types/homeassistant/data/entity_registry'; 4 | import { LockCardConfig } from '../types/lovelace-mushroom/cards/lock-card-config'; 5 | import AbstractCard from './AbstractCard'; 6 | 7 | /** 8 | * Lock Card Class 9 | * 10 | * Used to create a card configuration to control an entity of the lock domain. 11 | */ 12 | class LockCard extends AbstractCard { 13 | /** Returns the default configuration object for the card. */ 14 | static getDefaultConfig(): LockCardConfig { 15 | return { 16 | type: 'custom:mushroom-lock-card', 17 | icon: undefined, 18 | }; 19 | } 20 | 21 | /** 22 | * Class constructor. 23 | * 24 | * @param {EntityRegistryEntry} entity The HASS entity to create a card configuration for. 25 | * @param {LockCardConfig} [customConfiguration] Custom card configuration. 26 | */ 27 | constructor(entity: EntityRegistryEntry, customConfiguration?: LockCardConfig) { 28 | super(entity); 29 | 30 | this.configuration = { ...this.configuration, ...LockCard.getDefaultConfig(), ...customConfiguration }; 31 | } 32 | } 33 | 34 | export default LockCard; 35 | -------------------------------------------------------------------------------- /src/cards/MediaPlayerCard.ts: -------------------------------------------------------------------------------- 1 | // noinspection JSUnusedGlobalSymbols Class is dynamically imported. 2 | 3 | import { EntityRegistryEntry } from '../types/homeassistant/data/entity_registry'; 4 | import { MediaPlayerCardConfig } from '../types/lovelace-mushroom/cards/media-player-card-config'; 5 | import AbstractCard from './AbstractCard'; 6 | 7 | /** 8 | * Mediaplayer Card Class 9 | * 10 | * Used to create a card configuration to control an entity of the media_player domain. 11 | */ 12 | class MediaPlayerCard extends AbstractCard { 13 | /** Returns the default configuration object for the card. */ 14 | static getDefaultConfig(): MediaPlayerCardConfig { 15 | return { 16 | type: 'custom:mushroom-media-player-card', 17 | use_media_info: true, 18 | media_controls: ['on_off', 'play_pause_stop'], 19 | show_volume_level: true, 20 | volume_controls: ['volume_mute', 'volume_set', 'volume_buttons'], 21 | }; 22 | } 23 | 24 | /** 25 | * Class constructor. 26 | * 27 | * @param {EntityRegistryEntry} entity The HASS entity to create a card configuration for. 28 | * @param {MediaPlayerCardConfig} [customConfiguration] Custom card configuration. 29 | */ 30 | constructor(entity: EntityRegistryEntry, customConfiguration?: MediaPlayerCardConfig) { 31 | super(entity); 32 | 33 | this.configuration = { ...this.configuration, ...MediaPlayerCard.getDefaultConfig(), ...customConfiguration }; 34 | } 35 | } 36 | 37 | export default MediaPlayerCard; 38 | -------------------------------------------------------------------------------- /src/cards/MiscellaneousCard.ts: -------------------------------------------------------------------------------- 1 | import { EntityRegistryEntry } from '../types/homeassistant/data/entity_registry'; 2 | import { EntityCardConfig } from '../types/lovelace-mushroom/cards/entity-card-config'; 3 | import AbstractCard from './AbstractCard'; 4 | 5 | /** 6 | * Miscellaneous Card Class 7 | * 8 | * Used to create a card configuration to control an entity of any domain. 9 | */ 10 | class MiscellaneousCard extends AbstractCard { 11 | /** Returns the default configuration object for the card. */ 12 | static getDefaultConfig(): EntityCardConfig { 13 | return { 14 | type: 'custom:mushroom-entity-card', 15 | icon_color: 'blue-grey', 16 | }; 17 | } 18 | 19 | /** 20 | * Class constructor. 21 | * 22 | * @param {EntityRegistryEntry} entity The HASS entity to create a card configuration for. 23 | * @param {EntityCardConfig} [customConfiguration] Custom card configuration. 24 | */ 25 | constructor(entity: EntityRegistryEntry, customConfiguration?: EntityCardConfig) { 26 | super(entity); 27 | 28 | this.configuration = { ...this.configuration, ...MiscellaneousCard.getDefaultConfig(), ...customConfiguration }; 29 | } 30 | } 31 | 32 | export default MiscellaneousCard; 33 | -------------------------------------------------------------------------------- /src/cards/NumberCard.ts: -------------------------------------------------------------------------------- 1 | // noinspection JSUnusedGlobalSymbols Class is dynamically imported. 2 | 3 | import { EntityRegistryEntry } from '../types/homeassistant/data/entity_registry'; 4 | import { NumberCardConfig } from '../types/lovelace-mushroom/cards/number-card-config'; 5 | import AbstractCard from './AbstractCard'; 6 | 7 | /** 8 | * Number Card Class 9 | * 10 | * Used to create a card configuration to control an entity of the number domain. 11 | */ 12 | class NumberCard extends AbstractCard { 13 | /** Returns the default configuration object for the card. */ 14 | static getDefaultConfig(): NumberCardConfig { 15 | return { 16 | type: 'custom:mushroom-number-card', 17 | icon: undefined, 18 | }; 19 | } 20 | 21 | /** 22 | * Class constructor. 23 | * 24 | * @param {EntityRegistryEntry} entity The HASS entity to create a card configuration for. 25 | * @param {NumberCardConfig} [customConfiguration] Custom card configuration. 26 | */ 27 | constructor(entity: EntityRegistryEntry, customConfiguration?: NumberCardConfig) { 28 | super(entity); 29 | 30 | this.configuration = { ...this.configuration, ...NumberCard.getDefaultConfig(), ...customConfiguration }; 31 | } 32 | } 33 | 34 | export default NumberCard; 35 | -------------------------------------------------------------------------------- /src/cards/PersonCard.ts: -------------------------------------------------------------------------------- 1 | import { EntityRegistryEntry } from '../types/homeassistant/data/entity_registry'; 2 | import { PersonCardConfig } from '../types/lovelace-mushroom/cards/person-card-config'; 3 | import AbstractCard from './AbstractCard'; 4 | 5 | /** 6 | * Person Card Class 7 | * 8 | * Used to create a card configuration to control an entity of the person domain. 9 | */ 10 | class PersonCard extends AbstractCard { 11 | /** Returns the default configuration object for the card. */ 12 | static getDefaultConfig(): PersonCardConfig { 13 | return { 14 | type: 'custom:mushroom-person-card', 15 | layout: 'vertical', 16 | primary_info: 'none', 17 | secondary_info: 'none', 18 | icon_type: 'entity-picture', 19 | }; 20 | } 21 | 22 | /** 23 | * Class constructor. 24 | * 25 | * @param {EntityRegistryEntry} entity The HASS entity to create a card configuration for. 26 | * @param {PersonCardConfig} [customConfiguration] Custom card configuration. 27 | */ 28 | constructor(entity: EntityRegistryEntry, customConfiguration?: PersonCardConfig) { 29 | super(entity); 30 | 31 | this.configuration = { ...this.configuration, ...PersonCard.getDefaultConfig(), ...customConfiguration }; 32 | } 33 | } 34 | 35 | export default PersonCard; 36 | -------------------------------------------------------------------------------- /src/cards/SceneCard.ts: -------------------------------------------------------------------------------- 1 | // noinspection JSUnusedGlobalSymbols Class is dynamically imported. 2 | 3 | import { Registry } from '../Registry'; 4 | import { EntityRegistryEntry } from '../types/homeassistant/data/entity_registry'; 5 | import { EntityCardConfig } from '../types/lovelace-mushroom/cards/entity-card-config'; 6 | import AbstractCard from './AbstractCard'; 7 | import SwitchCard from './SwitchCard'; 8 | import { isCallServiceActionConfig } from '../types/strategy/strategy-generics'; 9 | 10 | /** 11 | * Scene Card Class 12 | * 13 | * Used to create a card configuration to control an entity of the scene domain. 14 | * 15 | * Supports Stateful scenes from https://github.com/hugobloem/stateful_scenes. 16 | * If the stateful scene entity is available, it will be used instead of the original scene entity. 17 | */ 18 | class SceneCard extends AbstractCard { 19 | /** Returns the default configuration object for the card. */ 20 | static getDefaultConfig(): EntityCardConfig { 21 | return { 22 | type: 'custom:mushroom-entity-card', 23 | tap_action: { 24 | action: 'perform-action', 25 | perform_action: 'scene.turn_on', 26 | target: {}, 27 | }, 28 | }; 29 | } 30 | 31 | /** 32 | * Class constructor. 33 | * 34 | * @param {EntityRegistryEntry} entity The HASS entity to create a card configuration for. 35 | * @param {EntityCardConfig} [customConfiguration] Custom card configuration. 36 | */ 37 | constructor(entity: EntityRegistryEntry, customConfiguration?: EntityCardConfig) { 38 | const sceneName = entity.entity_id.split('.').pop(); 39 | const statefulScene = Registry.entities.find((entity) => entity.entity_id === `switch.${sceneName}_stateful_scene`); 40 | 41 | super(statefulScene ?? entity); 42 | 43 | // Stateful scene support. 44 | if (statefulScene) { 45 | this.configuration = new SwitchCard(statefulScene).getCard(); 46 | 47 | return; 48 | } 49 | 50 | // Initialize the default configuration. 51 | const configuration = SceneCard.getDefaultConfig(); 52 | 53 | if (isCallServiceActionConfig(configuration.tap_action)) { 54 | configuration.tap_action.target = { entity_id: entity.entity_id }; 55 | } 56 | 57 | configuration.icon = Registry.hassStates[entity.entity_id]?.attributes.icon ?? configuration.icon; 58 | 59 | this.configuration = { ...this.configuration, ...configuration, ...customConfiguration }; 60 | } 61 | } 62 | 63 | export default SceneCard; 64 | -------------------------------------------------------------------------------- /src/cards/SelectCard.ts: -------------------------------------------------------------------------------- 1 | // noinspection JSUnusedGlobalSymbols Class is dynamically imported. 2 | 3 | import { EntityRegistryEntry } from '../types/homeassistant/data/entity_registry'; 4 | import { SelectCardConfig } from '../types/lovelace-mushroom/cards/select-card-config'; 5 | import AbstractCard from './AbstractCard'; 6 | 7 | /** 8 | * Select Card Class 9 | * 10 | * Used to create a card configuration to control an entity of the select domain. 11 | */ 12 | class SelectCard extends AbstractCard { 13 | /** Returns the default configuration object for the card. */ 14 | static getDefaultConfig(): SelectCardConfig { 15 | return { 16 | type: 'custom:mushroom-select-card', 17 | icon: undefined, 18 | }; 19 | } 20 | 21 | /** 22 | * Class constructor. 23 | * 24 | * @param {EntityRegistryEntry} entity The HASS entity to create a card configuration for. 25 | * @param {SelectCardConfig} [customConfiguration] Custom card configuration. 26 | */ 27 | constructor(entity: EntityRegistryEntry, customConfiguration?: SelectCardConfig) { 28 | super(entity); 29 | 30 | this.configuration = { ...this.configuration, ...SelectCard.getDefaultConfig(), ...customConfiguration }; 31 | } 32 | } 33 | 34 | export default SelectCard; 35 | -------------------------------------------------------------------------------- /src/cards/SensorCard.ts: -------------------------------------------------------------------------------- 1 | import { EntityRegistryEntry } from '../types/homeassistant/data/entity_registry'; 2 | import { EntityCardConfig } from '../types/lovelace-mushroom/cards/entity-card-config'; 3 | import AbstractCard from './AbstractCard'; 4 | 5 | /** 6 | * Sensor Card Class 7 | * 8 | * Used to create a card for controlling an entity of the sensor domain. 9 | */ 10 | class SensorCard extends AbstractCard { 11 | /** Returns the default configuration object for the card. */ 12 | static getDefaultConfig(): EntityCardConfig { 13 | return { 14 | type: 'custom:mushroom-entity-card', 15 | icon: 'mdi:information', 16 | animate: true, 17 | line_color: 'green', 18 | }; 19 | } 20 | 21 | /** 22 | * Class constructor. 23 | * 24 | * @param {EntityRegistryEntry} entity The HASS entity to create a card configuration for. 25 | * @param {EntityCardConfig} [customConfiguration] Custom card configuration. 26 | */ 27 | constructor(entity: EntityRegistryEntry, customConfiguration?: EntityCardConfig) { 28 | super(entity); 29 | 30 | this.configuration = { ...this.configuration, ...SensorCard.getDefaultConfig(), ...customConfiguration }; 31 | } 32 | } 33 | 34 | export default SensorCard; 35 | -------------------------------------------------------------------------------- /src/cards/SwitchCard.ts: -------------------------------------------------------------------------------- 1 | // noinspection JSUnusedGlobalSymbols Class is dynamically imported. 2 | 3 | import { EntityRegistryEntry } from '../types/homeassistant/data/entity_registry'; 4 | import { EntityCardConfig } from '../types/lovelace-mushroom/cards/entity-card-config'; 5 | import AbstractCard from './AbstractCard'; 6 | 7 | /** 8 | * Switch Card Class 9 | * 10 | * Used to create a card configuration to control an entity of the switch domain. 11 | */ 12 | class SwitchCard extends AbstractCard { 13 | /** Returns the default configuration object for the card. */ 14 | static getDefaultConfig(): EntityCardConfig { 15 | return { 16 | type: 'custom:mushroom-entity-card', 17 | icon: undefined, 18 | tap_action: { 19 | action: 'toggle', 20 | }, 21 | }; 22 | } 23 | 24 | /** 25 | * Class constructor. 26 | * 27 | * @param {EntityRegistryEntry} entity The HASS entity to create a card configuration for. 28 | * @param {EntityCardConfig} [customConfiguration] Custom card configuration. 29 | */ 30 | constructor(entity: EntityRegistryEntry, customConfiguration?: EntityCardConfig) { 31 | super(entity); 32 | 33 | this.configuration = { ...this.configuration, ...SwitchCard.getDefaultConfig(), ...customConfiguration }; 34 | } 35 | } 36 | 37 | export default SwitchCard; 38 | -------------------------------------------------------------------------------- /src/cards/VacuumCard.ts: -------------------------------------------------------------------------------- 1 | // noinspection JSUnusedGlobalSymbols Class is dynamically imported. 2 | 3 | import { EntityRegistryEntry } from '../types/homeassistant/data/entity_registry'; 4 | import { VACUUM_COMMANDS, VacuumCardConfig } from '../types/lovelace-mushroom/cards/vacuum-card-config'; 5 | import AbstractCard from './AbstractCard'; 6 | 7 | /** 8 | * Vacuum Card Class 9 | * 10 | * Used to create a card configuration to control an entity of the vacuum domain. 11 | */ 12 | class VacuumCard extends AbstractCard { 13 | /** Returns the default configuration object for the card. */ 14 | static getDefaultConfig(): VacuumCardConfig { 15 | return { 16 | type: 'custom:mushroom-vacuum-card', 17 | icon: undefined, 18 | icon_animation: true, 19 | commands: [...VACUUM_COMMANDS], 20 | tap_action: { 21 | action: 'more-info', 22 | }, 23 | }; 24 | } 25 | 26 | /** 27 | * Class constructor. 28 | * 29 | * @param {EntityRegistryEntry} entity The HASS entity to create a card configuration for. 30 | * @param {VacuumCardConfig} [customConfiguration] Custom card configuration. 31 | */ 32 | constructor(entity: EntityRegistryEntry, customConfiguration?: VacuumCardConfig) { 33 | super(entity); 34 | 35 | this.configuration = { ...this.configuration, ...VacuumCard.getDefaultConfig(), ...customConfiguration }; 36 | } 37 | } 38 | 39 | export default VacuumCard; 40 | -------------------------------------------------------------------------------- /src/cards/ValveCard.ts: -------------------------------------------------------------------------------- 1 | // noinspection JSUnusedGlobalSymbols Class is dynamically imported. 2 | 3 | import { EntityRegistryEntry } from '../types/homeassistant/data/entity_registry'; 4 | import { TemplateCardConfig } from '../types/lovelace-mushroom/cards/template-card-config'; 5 | import { localize } from '../utilities/localize'; 6 | import AbstractCard from './AbstractCard'; 7 | 8 | /** 9 | * Valve Card Class 10 | * 11 | * Used to create a card configuration to control an entity of the valve domain. 12 | */ 13 | class ValveCard extends AbstractCard { 14 | /** Returns the default configuration object for the card. */ 15 | static getDefaultConfig(): TemplateCardConfig { 16 | return { 17 | type: 'custom:mushroom-template-card', 18 | icon: 'mdi:valve', 19 | icon_color: 'blue', 20 | double_tap_action: { 21 | action: 'toggle', 22 | }, 23 | }; 24 | } 25 | 26 | /** 27 | * Class constructor. 28 | * 29 | * @param {EntityRegistryEntry} entity The HASS entity to create a card configuration for. 30 | * @param {VacuumCardConfig} [customConfiguration] Custom card configuration. 31 | */ 32 | constructor(entity: EntityRegistryEntry, customConfiguration?: TemplateCardConfig) { 33 | super(entity); 34 | 35 | // Initialize the default configuration. 36 | const configuration = ValveCard.getDefaultConfig(); 37 | 38 | configuration.entity = entity.entity_id; 39 | configuration.icon = entity.icon ?? configuration.icon; 40 | configuration.primary = entity.name ?? entity.original_name ?? '?'; 41 | configuration.secondary = `{% 42 | set mapping = { 43 | 'open': '${localize('valve.open')}', 44 | 'opening': '${localize('valve.opening')}', 45 | 'closed': '${localize('valve.closed')}', 46 | 'closing': '${localize('valve.closing')}', 47 | 'stopped': '${localize('valve.stopped')}', 48 | 'unavailable': '${localize('generic.unavailable')}' 49 | } 50 | %} 51 | {{ mapping.get(states('${entity.entity_id}'), '${localize('generic.unknown')}') }}`; 52 | 53 | this.configuration = { ...this.configuration, ...configuration, ...customConfiguration }; 54 | } 55 | } 56 | 57 | export default ValveCard; 58 | -------------------------------------------------------------------------------- /src/chips/AbstractChip.ts: -------------------------------------------------------------------------------- 1 | import { Registry } from '../Registry'; 2 | import { LovelaceChipConfig } from '../types/lovelace-mushroom/utils/lovelace/chip/types'; 3 | import { logMessage, lvlFatal } from '../utilities/debug'; 4 | 5 | abstract class AbstractChip { 6 | /** 7 | * Abstract Chip class. 8 | * 9 | * To create a chip configuration, this class should be extended by a child class. 10 | * Child classes should override the default configuration so the chip correctly reflects the entity. 11 | * 12 | * @remarks 13 | * Before using this class, the Registry module must be initialized by calling {@link Registry.initialize}. 14 | */ 15 | 16 | /** 17 | * Configuration of the chip. 18 | * 19 | * Child classes should override this property to reflect their own card type and options. 20 | */ 21 | protected configuration: LovelaceChipConfig = { 22 | // TODO: Check if this is correct vs custom:mushroom-template-badge. Also in child classes. 23 | type: 'template', 24 | }; 25 | 26 | /** 27 | * Class Constructor. 28 | * 29 | * @remarks 30 | * Before using this class, the Registry module must be initialized by calling {@link Registry.initialize}. 31 | */ 32 | protected constructor() { 33 | if (!Registry.initialized) { 34 | logMessage(lvlFatal, 'Registry not initialized!'); 35 | } 36 | } 37 | 38 | /** 39 | * Get a chip configuration. 40 | * 41 | * The configuration should be set by any of the child classes so the chip correctly reflects an entity. 42 | */ 43 | getChipConfiguration(): LovelaceChipConfig { 44 | return this.configuration; 45 | } 46 | } 47 | 48 | export default AbstractChip; 49 | -------------------------------------------------------------------------------- /src/chips/ClimateChip.ts: -------------------------------------------------------------------------------- 1 | // noinspection JSUnusedGlobalSymbols Class is dynamically imported. 2 | 3 | import { Registry } from '../Registry'; 4 | import { TemplateChipConfig } from '../types/lovelace-mushroom/utils/lovelace/chip/types'; 5 | import AbstractChip from './AbstractChip'; 6 | 7 | /** 8 | * Climate Chip class. 9 | * 10 | * Used to create a chip configuration to indicate how many climates are operating. 11 | */ 12 | class ClimateChip extends AbstractChip { 13 | /** Returns the default configuration object for the chip. */ 14 | static getDefaultConfig(): TemplateChipConfig { 15 | return { 16 | type: 'template', 17 | icon: 'mdi:thermostat', 18 | icon_color: 'orange', 19 | content: Registry.getCountTemplate('climate', 'ne', 'off'), 20 | tap_action: { 21 | action: 'none', 22 | }, 23 | hold_action: { 24 | action: 'navigate', 25 | navigation_path: 'climates', 26 | }, 27 | }; 28 | } 29 | 30 | /** 31 | * Class Constructor. 32 | * 33 | * @param {TemplateChipConfig} [customConfiguration] Custom chip configuration. 34 | */ 35 | constructor(customConfiguration?: TemplateChipConfig) { 36 | super(); 37 | 38 | this.configuration = { ...this.configuration, ...ClimateChip.getDefaultConfig(), ...customConfiguration }; 39 | } 40 | } 41 | 42 | export default ClimateChip; 43 | -------------------------------------------------------------------------------- /src/chips/CoverChip.ts: -------------------------------------------------------------------------------- 1 | // noinspection JSUnusedGlobalSymbols Class is dynamically imported. 2 | 3 | import { Registry } from '../Registry'; 4 | import { TemplateChipConfig } from '../types/lovelace-mushroom/utils/lovelace/chip/types'; 5 | import AbstractChip from './AbstractChip'; 6 | 7 | /** 8 | * Cover Chip class. 9 | * 10 | * Used to create a chip configuration to indicate how many covers aren't closed. 11 | */ 12 | class CoverChip extends AbstractChip { 13 | /** Returns the default configuration object for the chip. */ 14 | static getDefaultConfig(): TemplateChipConfig { 15 | return { 16 | type: 'template', 17 | icon: 'mdi:window-open', 18 | icon_color: 'cyan', 19 | content: Registry.getCountTemplate('cover', 'search', '(open|opening|closing)'), 20 | tap_action: { 21 | action: 'none', 22 | }, 23 | hold_action: { 24 | action: 'navigate', 25 | navigation_path: 'covers', 26 | }, 27 | }; 28 | } 29 | 30 | /** 31 | * Class Constructor. 32 | * 33 | * @param {TemplateChipConfig} [customConfiguration] Custom chip configuration. 34 | */ 35 | constructor(customConfiguration?: TemplateChipConfig) { 36 | super(); 37 | 38 | this.configuration = { ...this.configuration, ...CoverChip.getDefaultConfig(), ...customConfiguration }; 39 | } 40 | } 41 | 42 | export default CoverChip; 43 | -------------------------------------------------------------------------------- /src/chips/FanChip.ts: -------------------------------------------------------------------------------- 1 | // noinspection JSUnusedGlobalSymbols Class is dynamically imported. 2 | 3 | import { Registry } from '../Registry'; 4 | import { TemplateChipConfig } from '../types/lovelace-mushroom/utils/lovelace/chip/types'; 5 | import AbstractChip from './AbstractChip'; 6 | import RegistryFilter from '../utilities/RegistryFilter'; 7 | 8 | /** 9 | * Fan Chip class. 10 | * 11 | * Used to create a chip to indicate how many fans are on and to switch them all off. 12 | */ 13 | class FanChip extends AbstractChip { 14 | /** Returns the default configuration object for the chip. */ 15 | static getDefaultConfig(): TemplateChipConfig { 16 | return { 17 | type: 'template', 18 | icon: 'mdi:fan', 19 | icon_color: 'green', 20 | content: Registry.getCountTemplate('fan', 'eq', 'on'), 21 | tap_action: { 22 | action: 'perform-action', 23 | perform_action: 'fan.turn_off', 24 | target: { 25 | entity_id: new RegistryFilter(Registry.entities) 26 | .whereDomain('fan') 27 | .getValuesByProperty('entity_id') as string[], 28 | }, 29 | }, 30 | hold_action: { 31 | action: 'navigate', 32 | navigation_path: 'fans', 33 | }, 34 | }; 35 | } 36 | 37 | /** 38 | * Class Constructor. 39 | * 40 | * @param {TemplateChipConfig} [customConfiguration] Custom chip configuration. 41 | */ 42 | constructor(customConfiguration?: TemplateChipConfig) { 43 | super(); 44 | 45 | this.configuration = { ...this.configuration, ...FanChip.getDefaultConfig(), ...customConfiguration }; 46 | } 47 | } 48 | 49 | export default FanChip; 50 | -------------------------------------------------------------------------------- /src/chips/LightChip.ts: -------------------------------------------------------------------------------- 1 | // noinspection JSUnusedGlobalSymbols Class is dynamically imported. 2 | 3 | import { Registry } from '../Registry'; 4 | import { TemplateChipConfig } from '../types/lovelace-mushroom/utils/lovelace/chip/types'; 5 | import AbstractChip from './AbstractChip'; 6 | import RegistryFilter from '../utilities/RegistryFilter'; 7 | 8 | /** 9 | * Light Chip class. 10 | * 11 | * Used to create a chip configuration to indicate how many lights are on and to switch them all off. 12 | */ 13 | class LightChip extends AbstractChip { 14 | /** Returns the default configuration object for the chip. */ 15 | static getDefaultConfig(): TemplateChipConfig { 16 | return { 17 | type: 'template', 18 | icon: 'mdi:lightbulb-group', 19 | icon_color: 'amber', 20 | content: Registry.getCountTemplate('light', 'eq', 'on'), 21 | tap_action: { 22 | action: 'perform-action', 23 | perform_action: 'light.turn_off', 24 | target: { 25 | entity_id: new RegistryFilter(Registry.entities) 26 | .whereDomain('light') 27 | .getValuesByProperty('entity_id') as string[], 28 | }, 29 | }, 30 | hold_action: { 31 | action: 'navigate', 32 | navigation_path: 'lights', 33 | }, 34 | }; 35 | } 36 | 37 | /** 38 | * Class Constructor. 39 | * 40 | * @param {TemplateChipConfig} [customConfiguration] Custom chip configuration. 41 | */ 42 | constructor(customConfiguration?: TemplateChipConfig) { 43 | super(); 44 | 45 | this.configuration = { ...this.configuration, ...LightChip.getDefaultConfig(), ...customConfiguration }; 46 | } 47 | } 48 | 49 | export default LightChip; 50 | -------------------------------------------------------------------------------- /src/chips/SwitchChip.ts: -------------------------------------------------------------------------------- 1 | // noinspection JSUnusedGlobalSymbols Class is dynamically imported. 2 | 3 | import { Registry } from '../Registry'; 4 | import { TemplateChipConfig } from '../types/lovelace-mushroom/utils/lovelace/chip/types'; 5 | import AbstractChip from './AbstractChip'; 6 | import RegistryFilter from '../utilities/RegistryFilter'; 7 | 8 | /** 9 | * Switch Chip class. 10 | * 11 | * Used to create a chip configuration to indicate how many switches are on and to switch them all off. 12 | */ 13 | class SwitchChip extends AbstractChip { 14 | /** Returns the default configuration object for the chip. */ 15 | static getDefaultConfig(): TemplateChipConfig { 16 | return { 17 | type: 'template', 18 | icon: 'mdi:dip-switch', 19 | icon_color: 'blue', 20 | content: Registry.getCountTemplate('switch', 'eq', 'on'), 21 | tap_action: { 22 | action: 'perform-action', 23 | perform_action: 'switch.turn_off', 24 | target: { 25 | entity_id: new RegistryFilter(Registry.entities) 26 | .whereDomain('switch') 27 | .getValuesByProperty('entity_id') as string[], 28 | }, 29 | }, 30 | hold_action: { 31 | action: 'navigate', 32 | navigation_path: 'switches', 33 | }, 34 | }; 35 | } 36 | 37 | /** 38 | * Class Constructor. 39 | * 40 | * @param {TemplateChipConfig} [customConfiguration] Custom chip configuration. 41 | */ 42 | constructor(customConfiguration?: TemplateChipConfig) { 43 | super(); 44 | 45 | this.configuration = { ...this.configuration, ...SwitchChip.getDefaultConfig(), ...customConfiguration }; 46 | } 47 | } 48 | 49 | export default SwitchChip; 50 | -------------------------------------------------------------------------------- /src/chips/WeatherChip.ts: -------------------------------------------------------------------------------- 1 | // noinspection JSUnusedGlobalSymbols False positive. 2 | 3 | import { WeatherChipConfig } from '../types/lovelace-mushroom/utils/lovelace/chip/types'; 4 | import AbstractChip from './AbstractChip'; 5 | 6 | /** 7 | * Weather Chip class. 8 | * 9 | * Used to create a chip configuration to indicate the current weather. 10 | */ 11 | class WeatherChip extends AbstractChip { 12 | /** Returns the default configuration object for the chip. */ 13 | static getDefaultConfig(entityId: string): WeatherChipConfig { 14 | return { 15 | type: 'weather', 16 | entity: entityId, 17 | show_temperature: true, 18 | show_conditions: true, 19 | }; 20 | } 21 | 22 | /** 23 | * Class Constructor. 24 | * 25 | * @param {string} entityId Id of a weather entity. 26 | * @param {WeatherChipConfig} [customConfiguration] Custom chip configuration. 27 | */ 28 | constructor(entityId: string, customConfiguration?: WeatherChipConfig) { 29 | super(); 30 | 31 | this.configuration = { ...this.configuration, ...WeatherChip.getDefaultConfig(entityId), ...customConfiguration }; 32 | } 33 | } 34 | 35 | export default WeatherChip; 36 | -------------------------------------------------------------------------------- /src/translations/de.json: -------------------------------------------------------------------------------- 1 | { 2 | "camera": { 3 | "all_cameras": "Alle Kameras", 4 | "cameras": "Kameras" 5 | }, 6 | "climate": { 7 | "all_climates": "Alle Klimaanlagen", 8 | "climates": "Klimaanlagen" 9 | }, 10 | "cover": { 11 | "all_covers": "Alle Abdeckungen", 12 | "covers": "Abdeckungen" 13 | }, 14 | "fan": { 15 | "all_fans": "Alle Ventilatoren", 16 | "fans": "Ventilatoren" 17 | }, 18 | "generic": { 19 | "all": "Alle", 20 | "areas": "Bereiche", 21 | "busy": "Beschäftigt", 22 | "good_afternoon": "Guten Nachmittag", 23 | "good_evening": "Guten Abend", 24 | "good_morning": "Guten Morgen", 25 | "hello": "Hallo", 26 | "home": "Start", 27 | "miscellaneous": "Sonstiges", 28 | "numbers": "Zahlen", 29 | "off": "Aus", 30 | "on": "Ein", 31 | "open": "Offen", 32 | "unavailable": "Nicht verfügbar", 33 | "unclosed": "Nicht Geschlossen", 34 | "undisclosed": "Sonstiges", 35 | "unknown": "Unbekannt" 36 | }, 37 | "input_select": { 38 | "input_selects": "Auswahl-Eingaben" 39 | }, 40 | "light": { 41 | "all_lights": "Alle Leuchten", 42 | "lights": "Leuchten" 43 | }, 44 | "lock": { 45 | "locked": "Gesperrt", 46 | "all_locks": "Alle Schlösser", 47 | "locks": "Schlösser", 48 | "unlocked": "Entsperrt" 49 | }, 50 | "media_player": { 51 | "media_players": "Wiedergabegeräte" 52 | }, 53 | "scene": { 54 | "scenes": "Szenen" 55 | }, 56 | "select": { 57 | "selects": "Auswahlen" 58 | }, 59 | "sensor": { 60 | "binary": "Binäre", 61 | "sensors": "Sensoren" 62 | }, 63 | "switch": { 64 | "all_switches": "Alle Schalter", 65 | "switches": "Schalter" 66 | }, 67 | "vacuum": { 68 | "all_vacuums": "Alle Staubsauger", 69 | "vacuums": "Staubsauger" 70 | }, 71 | "valve": { 72 | "all_valves": "Alle Ventile", 73 | "valves": "Ventile", 74 | "open": "Offen", 75 | "opening": "Öffnet", 76 | "closed": "Geschlossen", 77 | "closing": "Schließt", 78 | "stopped": "Gestoppt", 79 | "unclosed": "Nicht geschlossen" 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /src/translations/en.json: -------------------------------------------------------------------------------- 1 | { 2 | "camera": { 3 | "all_cameras": "All Cameras", 4 | "cameras": "Cameras" 5 | }, 6 | "climate": { 7 | "all_climates": "All Climates", 8 | "climates": "Climates" 9 | }, 10 | "cover": { 11 | "all_covers": "All Covers", 12 | "covers": "Covers" 13 | }, 14 | "fan": { 15 | "all_fans": "All Fans", 16 | "fans": "Fans" 17 | }, 18 | "generic": { 19 | "all": "All", 20 | "areas": "Areas", 21 | "busy": "Busy", 22 | "good_afternoon": "Good afternoon", 23 | "good_evening": "Good evening", 24 | "good_morning": "Good morning", 25 | "hello": "Hello", 26 | "home": "Home", 27 | "miscellaneous": "Miscellaneous", 28 | "numbers": "Numbers", 29 | "off": "Off", 30 | "on": "On", 31 | "open": "Open", 32 | "unavailable": "Unavailable", 33 | "unclosed": "Unclosed", 34 | "undisclosed": "Other", 35 | "unknown": "Unknown" 36 | }, 37 | "input_select": { 38 | "input_selects": "Input Selects" 39 | }, 40 | "light": { 41 | "all_lights": "All Lights", 42 | "lights": "Lights" 43 | }, 44 | "lock": { 45 | "all_locks": "All Locks", 46 | "locked": "Locked", 47 | "locks": "Locks", 48 | "unlocked": "Unlocked" 49 | }, 50 | "media_player": { 51 | "media_players": "Media Players" 52 | }, 53 | "scene": { 54 | "scenes": "Scenes" 55 | }, 56 | "select": { 57 | "selects": "Selects" 58 | }, 59 | "sensor": { 60 | "binary": "Binary", 61 | "sensors": "Sensors" 62 | }, 63 | "switch": { 64 | "all_switches": "All Switches", 65 | "switches": "Switches" 66 | }, 67 | "vacuum": { 68 | "all_vacuums": "All Vacuums", 69 | "vacuums": "Vacuums" 70 | }, 71 | "valve": { 72 | "all_valves": "All Valves", 73 | "valves": "Valves", 74 | "open": "Open", 75 | "opening": "Opening", 76 | "closed": "Closed", 77 | "closing": "Closing", 78 | "stopped": "Stopped", 79 | "unclosed": "Unclosed" 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /src/translations/es.json: -------------------------------------------------------------------------------- 1 | { 2 | "camera": { 3 | "all_cameras": "Todas las Cámaras", 4 | "cameras": "Cámaras" 5 | }, 6 | "climate": { 7 | "all_climates": "Todos los Termostatos", 8 | "climates": "Termostatos" 9 | }, 10 | "cover": { 11 | "all_covers": "Todas las Cubiertas", 12 | "covers": "Cubiertas" 13 | }, 14 | "fan": { 15 | "all_fans": "Todos los Ventiladores", 16 | "fans": "Ventiladores" 17 | }, 18 | "generic": { 19 | "all": "Todo", 20 | "areas": "Áreas", 21 | "busy": "Ocupado", 22 | "good_afternoon": "Buenas tardes", 23 | "good_evening": "Buenas noches", 24 | "good_morning": "Buenos días", 25 | "hello": "Hola", 26 | "home": "Inicio", 27 | "miscellaneous": "Varios", 28 | "numbers": "Números", 29 | "off": "Apagado", 30 | "on": "Encendido", 31 | "open": "Abierto", 32 | "unavailable": "No Disponible", 33 | "unclosed": "Sin Cerrar", 34 | "undisclosed": "Varios", 35 | "unknown": "Desconocido" 36 | }, 37 | "input_select": { 38 | "input_selects": "Selecciones de Entrada" 39 | }, 40 | "light": { 41 | "all_lights": "Todas las Luces", 42 | "lights": "Luces" 43 | }, 44 | "lock": { 45 | "all_locks": "Todas las Candados", 46 | "locked": "Locked", 47 | "locks": "Candados", 48 | "unlocked": "Desbloqueado" 49 | }, 50 | "media_player": { 51 | "media_players": "Reproductores Multimedia" 52 | }, 53 | "scene": { 54 | "scenes": "Scenas" 55 | }, 56 | "select": { 57 | "selects": "Seleccionar" 58 | }, 59 | "sensor": { 60 | "binary": "Binario", 61 | "sensors": "Sensores" 62 | }, 63 | "switch": { 64 | "all_switches": "Todos los Apagadores", 65 | "switches": "Apagadores" 66 | }, 67 | "vacuum": { 68 | "all_vacuums": "Todas las Aspiradoras", 69 | "vacuums": "Aspiradoras" 70 | }, 71 | "valve": { 72 | "all_valves": "Todas las válvulas", 73 | "valves": "Válvulas", 74 | "open": "Abierta", 75 | "opening": "Abriendo", 76 | "closed": "Cerrada", 77 | "closing": "Cerrando", 78 | "stopped": "Detenida", 79 | "unclosed": "No Cerrada" 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /src/translations/nl.json: -------------------------------------------------------------------------------- 1 | { 2 | "camera": { 3 | "all_cameras": "Alle Cameras", 4 | "cameras": "Cameras" 5 | }, 6 | "climate": { 7 | "all_climates": "Alle Klimaatregelingen", 8 | "climates": "Klimaatregelingen" 9 | }, 10 | "cover": { 11 | "all_covers": "Alle Bedekkingen", 12 | "covers": "Bedekkingen" 13 | }, 14 | "fan": { 15 | "all_fans": "Alle Ventilatoren", 16 | "fans": "Ventilatoren" 17 | }, 18 | "generic": { 19 | "all": "Alle", 20 | "areas": "Ruimtes", 21 | "busy": "Bezig", 22 | "good_afternoon": "Goedemiddag", 23 | "good_evening": "Goedeavond", 24 | "good_morning": "Goedemorgen", 25 | "hello": "Hallo", 26 | "home": "Start", 27 | "miscellaneous": "Overige", 28 | "numbers": "Nummers", 29 | "off": "Uit", 30 | "on": "Aan", 31 | "open": "Open", 32 | "unavailable": "Onbeschikbaar", 33 | "unclosed": "Niet Gesloten", 34 | "undisclosed": "Overige", 35 | "unknown": "Onbekend" 36 | }, 37 | "input_select": { 38 | "input_selects": "Lijsten" 39 | }, 40 | "light": { 41 | "all_lights": "Alle Lampen", 42 | "lights": "Lampen" 43 | }, 44 | "lock": { 45 | "all_locks": "Alle Sloten", 46 | "locked": "Vergrendeld", 47 | "locks": "Sloten", 48 | "unlocked": "Ontgrendeld" 49 | }, 50 | "media_player": { 51 | "media_players": "Mediaspelers" 52 | }, 53 | "scene": { 54 | "scenes": "Scenes" 55 | }, 56 | "select": { 57 | "selects": "Statuslijsten" 58 | }, 59 | "sensor": { 60 | "binary": "Binaire", 61 | "sensors": "Sensoren" 62 | }, 63 | "switch": { 64 | "all_switches": "Alle Schakelaars", 65 | "switches": "Schakelaars" 66 | }, 67 | "vacuum": { 68 | "all_vacuums": "Alle Afzuiging", 69 | "vacuums": "Afzuiging" 70 | }, 71 | "valve": { 72 | "all_valves": "Alle kleppen", 73 | "valves": "Kleppen", 74 | "open": "Open", 75 | "opening": "Openen", 76 | "closed": "Gesloten", 77 | "closing": "Sluiten", 78 | "stopped": "Gestopt", 79 | "unclosed": "Niet gesloten" 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /src/translations/pt-BR.json: -------------------------------------------------------------------------------- 1 | { 2 | "camera": { 3 | "all_cameras": "Todas as câmeras", 4 | "cameras": "Câmeras" 5 | }, 6 | "climate": { 7 | "all_climates": "Todos os climatizadores", 8 | "climates": "Climatizadores" 9 | }, 10 | "cover": { 11 | "all_covers": "Todas as persianas", 12 | "covers": "Persianas" 13 | }, 14 | "fan": { 15 | "all_fans": "Todos os ventiladores", 16 | "fans": "Ventiladores" 17 | }, 18 | "generic": { 19 | "all": "Todos", 20 | "areas": "Áreas", 21 | "busy": "Ocupado", 22 | "good_afternoon": "Boa tarde", 23 | "good_evening": "Boa noite", 24 | "good_morning": "Bom dia", 25 | "hello": "Olá", 26 | "home": "Início", 27 | "miscellaneous": "Variados", 28 | "numbers": "Números", 29 | "off": "Desligado", 30 | "on": "Ligado", 31 | "open": "Aberto", 32 | "unavailable": "Indisponível", 33 | "unclosed": "Não fechado", 34 | "undisclosed": "Outro", 35 | "unknown": "Desconhecido" 36 | }, 37 | "input_select": { 38 | "input_selects": "Seleção de entrada" 39 | }, 40 | "light": { 41 | "all_lights": "Todas as luzes", 42 | "lights": "Luzes" 43 | }, 44 | "lock": { 45 | "all_locks": "Todas as fechaduras", 46 | "locked": "Travado", 47 | "locks": "Fechaduras", 48 | "unlocked": "Destravado" 49 | }, 50 | "media_player": { 51 | "media_players": "Reprodutores de mídia" 52 | }, 53 | "scene": { 54 | "scenes": "Cenas" 55 | }, 56 | "select": { 57 | "selects": "Seleção" 58 | }, 59 | "sensor": { 60 | "binary": "Binário", 61 | "sensors": "Sensores" 62 | }, 63 | "switch": { 64 | "all_switches": "Todos os interruptores", 65 | "switches": "Interruptores" 66 | }, 67 | "vacuum": { 68 | "all_vacuums": "Todos os aspiradores", 69 | "vacuums": "Aspiradores" 70 | }, 71 | "valve": { 72 | "all_valves": "Todas as válvulas", 73 | "valves": "Válvulas", 74 | "open": "Aberto", 75 | "opening": "Abrindo", 76 | "closed": "Fechado", 77 | "closing": "Fechando", 78 | "stopped": "Parado", 79 | "unclosed": "Nao fechado" 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /src/types/homeassistant/README.md: -------------------------------------------------------------------------------- 1 | # Notice 2 | 3 | This directory contains partial code from 4 | the [Home Assistant Frontend repository](https://github.com/home-assistant/frontend). 5 | 6 | The code mainly defines Home Assistant interfaces/types which are refactored to fit this repository. 7 | This means properties are added/removed from the originals and subtypes may have been changed. 8 | 9 | The [Apache 2.0 License](https://github.com/home-assistant/frontend/blob/dev/LICENSE.md) applies to all files in this 10 | directory. 11 | 12 | Copyright 2023 Ferry Cools 13 | 14 | Licensed under the Apache License, Version 2.0 (the "License"); 15 | you may not use this file except in compliance with the License. 16 | You may obtain a copy of the License at 17 | 18 | 19 | 20 | Unless required by applicable law or agreed to in writing, software 21 | distributed under the License is distributed on an "AS IS" BASIS, 22 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 23 | See the License for the specific language governing permissions and 24 | limitations under the License. 25 | -------------------------------------------------------------------------------- /src/types/homeassistant/common/translations/localize.ts: -------------------------------------------------------------------------------- 1 | import type { TranslationDict } from '../../types'; 2 | 3 | // Exclude some patterns from key type checking for now 4 | // These are intended to be removed as errors are fixed 5 | // Fixing component category will require tighter definition of types from backend and/or web socket 6 | export type LocalizeKeys = 7 | | FlattenObjectKeys> 8 | | `panel.${string}` 9 | | `ui.card.alarm_control_panel.${string}` 10 | | `ui.card.weather.attributes.${string}` 11 | | `ui.card.weather.cardinal_direction.${string}` 12 | | `ui.card.lawn_mower.actions.${string}` 13 | | `ui.components.calendar.event.rrule.${string}` 14 | | `ui.components.selectors.file.${string}` 15 | | `ui.components.logbook.messages.detected_device_classes.${string}` 16 | | `ui.components.logbook.messages.cleared_device_classes.${string}` 17 | | `ui.dialogs.entity_registry.editor.${string}` 18 | | `ui.dialogs.more_info_control.lawn_mower.${string}` 19 | | `ui.dialogs.more_info_control.vacuum.${string}` 20 | | `ui.dialogs.quick-bar.commands.${string}` 21 | | `ui.dialogs.unhealthy.reason.${string}` 22 | | `ui.dialogs.unsupported.reason.${string}` 23 | | `ui.panel.config.${string}.${'caption' | 'description'}` 24 | | `ui.panel.config.dashboard.${string}` 25 | | `ui.panel.config.zha.${string}` 26 | | `ui.panel.config.zwave_js.${string}` 27 | | `ui.panel.lovelace.card.${string}` 28 | | `ui.panel.lovelace.editor.${string}` 29 | | `ui.panel.page-authorize.form.${string}` 30 | | `component.${string}`; 31 | 32 | // Tweaked from https://www.raygesualdo.com/posts/flattening-object-keys-with-typescript-types 33 | export type FlattenObjectKeys, Key extends keyof T = keyof T> = Key extends string 34 | ? T[Key] extends Record 35 | ? `${Key}.${FlattenObjectKeys}` 36 | : `${Key}` 37 | : never; 38 | 39 | // Later, don't return string when HTML is passed, and don't allow undefined 40 | export type LocalizeFunc = ( 41 | key: Keys, 42 | values?: Record< 43 | string, 44 | string | number | { _$litType$: 1; strings: TemplateStringsArray; values: Array } | null | undefined 45 | >, 46 | ) => string; 47 | -------------------------------------------------------------------------------- /src/types/homeassistant/data/area_registry.ts: -------------------------------------------------------------------------------- 1 | import { RegistryEntry } from './registry'; 2 | 3 | /** 4 | * Represents an entry in the Area Registry in Home Assistant. 5 | * 6 | * @property {string[]} aliases - An array of aliases for the area. 7 | * @property {string} area_id - The unique identifier for the area. 8 | * @property {string|null} floor_id - The identifier for the area's floor, or null if not applicable. 9 | * @property {string|null} humidity_entity_id - The identifier for the area's humidity sensor, or null if not 10 | * applicable. 11 | * @property {string|null} icon - The icon to display for the area, or null if not specified. 12 | * @property {string[]} labels - Labels for grouping elements irrespective of their physical location or type. 13 | * @property {string} name - The name of the area. 14 | * @property {string|null} picture - The URL to a picture that should be used instead of the domain icon, or null if 15 | * not specified. 16 | * @property {string|null} temperature_entity_id - The identifier for the area's temperature sensor, or null if not 17 | * applicable. 18 | */ 19 | export interface AreaRegistryEntry extends RegistryEntry { 20 | aliases: string[]; 21 | area_id: string; 22 | floor_id: string | null; 23 | humidity_entity_id: string | null; 24 | icon: string | null; 25 | labels: string[]; 26 | name: string; 27 | picture: string | null; 28 | temperature_entity_id: string | null; 29 | } 30 | -------------------------------------------------------------------------------- /src/types/homeassistant/data/climate.ts: -------------------------------------------------------------------------------- 1 | /** Represents the available HVAC modes for climate control in Home Assistant. */ 2 | export const HVAC_MODES = ['auto', 'heat_cool', 'heat', 'cool', 'dry', 'fan_only', 'off'] as const; 3 | 4 | /** Represents a type for HVAC modes in Home Assistant. */ 5 | export type HvacMode = (typeof HVAC_MODES)[number]; 6 | -------------------------------------------------------------------------------- /src/types/homeassistant/data/device_registry.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Represents a device entity in the of Home Assistant's device registry . 3 | * 4 | * @property {string} id - Unique identifier of the device (generated by Home Assistant). 5 | * @property {string[]} config_entries - Config entries linked to this device. 6 | * @property {Record} config_entries_subentries - Subentries for the config entries. 7 | * @property {[string, string][]} connections - Tuples of (connection_type, connection identifier). 8 | * @property {[string, string][]} identifiers - Set of (DOMAIN, identifier) tuples identifying the device. 9 | * @property {string | null} manufacturer - The manufacturer of the device. 10 | * @property {string | null} model - The model name of the device. 11 | * @property {string | null} model_id - The model identifier of the device. 12 | * @property {string | null} name - The name of the device. 13 | * @property {string[]} labels - Labels for the device. 14 | * @property {string | null} sw_version - The firmware version of the device. 15 | * @property {string | null} hw_version - The hardware version of the device. 16 | * @property {string | null} serial_number - The serial number of the device. 17 | * @property {string | null} via_device_id - Identifier of a device that routes messages to this device. 18 | * @property {string | null} area_id - The area which the device is placed in. 19 | * @property {string | null} name_by_user - User configured name of the device. 20 | * @property {string[] | null} entry_type - The type of entry (e.g., service). 21 | * @property {string | null} disabled_by - Indicates what disabled this entity. 22 | * @property {string | null} configuration_url - URL for configuring the device. 23 | * @property {string | null} primary_config_entry - Identifier of the primary config entry for the device. 24 | */ 25 | export interface DeviceRegistryEntry { 26 | id: string; 27 | config_entries: string[]; 28 | config_entries_subentries: Record; 29 | connections: [string, string][]; 30 | identifiers: [string, string][]; 31 | manufacturer: string | null; 32 | model: string | null; 33 | model_id: string | null; 34 | name: string | null; 35 | labels: string[]; 36 | sw_version: string | null; 37 | hw_version: string | null; 38 | serial_number: string | null; 39 | via_device_id: string | null; 40 | area_id: string | null; 41 | name_by_user: string | null; 42 | entry_type: 'service' | null; 43 | disabled_by: 'user' | 'integration' | 'config_entry' | null; 44 | configuration_url: string | null; 45 | primary_config_entry: string | null; 46 | } 47 | -------------------------------------------------------------------------------- /src/types/homeassistant/data/floor_registry.ts: -------------------------------------------------------------------------------- 1 | import { RegistryEntry } from './registry'; 2 | 3 | /** 4 | * Represents a floor entry in the Floor Registry of Home Assistant. 5 | * 6 | * @property {string} floor_id - The unique identifier for the floor. 7 | * @property {string} name - The name of the floor. 8 | * @property {number | null} level - The level of the floor (optional). 9 | * @property {string | null} icon - The icon associated with the floor (optional). 10 | * @property {string[]} aliases - An array of aliases for the floor. 11 | */ 12 | export interface FloorRegistryEntry extends RegistryEntry { 13 | floor_id: string; 14 | name: string; 15 | level: number | null; 16 | icon: string | null; 17 | aliases: string[]; 18 | } 19 | -------------------------------------------------------------------------------- /src/types/homeassistant/data/frontend.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Represents user data for the frontend in Home Assistant. 3 | * 4 | * @property {boolean} [showAdvanced] - Indicates whether advanced options should be shown to the user. 5 | */ 6 | export interface CoreFrontendUserData { 7 | showAdvanced?: boolean; 8 | } 9 | -------------------------------------------------------------------------------- /src/types/homeassistant/data/light.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Represents the color options for a light entity in Home Assistant. 3 | * 4 | * @property {number} [color_temp_kelvin] - The color temperature in Kelvin. 5 | * @property {[number, number]} [hs_color] - The hue and saturation values. 6 | * @property {[number, number, number]} [rgb_color] - The red, green, and blue color values. 7 | * @property {[number, number, number, number]} [rgbw_color] - The red, green, blue, and white color values. 8 | * @property {[number, number, number, number, number]} [rgbww_color] - The red, green, blue, white, and warm white 9 | * color values. 10 | */ 11 | export type LightColor = 12 | | { color_temp_kelvin: number } 13 | | { hs_color: [number, number] } 14 | | { rgb_color: [number, number, number] } 15 | | { rgbw_color: [number, number, number, number] } 16 | | { rgbww_color: [number, number, number, number, number] }; 17 | -------------------------------------------------------------------------------- /src/types/homeassistant/data/lovelace/config/badge.ts: -------------------------------------------------------------------------------- 1 | import { Condition } from '../../../panels/common/validate-condition'; 2 | 3 | /** 4 | * Represents the configuration for a Lovelace badge in Home Assistant. 5 | * 6 | * @property {string} type - The type of the badge. 7 | * @property {Condition[]} [visibility] - An optional array of visibility conditions for the badge. 8 | * @property {any} [key] - Additional properties can be included in the configuration. 9 | */ 10 | export interface LovelaceBadgeConfig { 11 | type: string; 12 | visibility?: Condition[]; 13 | 14 | [key: string]: any; 15 | } 16 | -------------------------------------------------------------------------------- /src/types/homeassistant/data/lovelace/config/card.ts: -------------------------------------------------------------------------------- 1 | import { Condition } from '../../../panels/common/validate-condition'; 2 | import { LovelaceGridOptions, LovelaceLayoutOptions } from '../../../panels/lovelace/types'; 3 | 4 | /** 5 | * Represents the configuration for a Lovelace card in Home Assistant. 6 | * 7 | * @property {number} [index] - The index of the card in the view. 8 | * @property {number} [view_index] - The index of the view the card belongs to. 9 | * @property {any} [view_layout] - The layout options for the card view. 10 | * @property {LovelaceLayoutOptions} [layout_options] - Deprecated layout options; use `grid_options` instead. 11 | * @property {LovelaceGridOptions} [grid_options] - The grid options for the card layout. 12 | * @property {string} type - The type of the card. 13 | * @property {Condition[]} [visibility] - An optional array of visibility conditions for the card. 14 | * @property {any} [key] - Additional properties can be included in the configuration. 15 | */ 16 | export interface LovelaceCardConfig { 17 | index?: number; 18 | view_index?: number; 19 | view_layout?: any; 20 | /** @deprecated Use `grid_options` instead */ 21 | layout_options?: LovelaceLayoutOptions; 22 | grid_options?: LovelaceGridOptions; 23 | type: string; 24 | visibility?: Condition[]; 25 | 26 | [key: string]: any; 27 | } 28 | -------------------------------------------------------------------------------- /src/types/homeassistant/data/lovelace/config/section.ts: -------------------------------------------------------------------------------- 1 | import { Condition } from '../../../panels/common/validate-condition'; 2 | import { LovelaceCardConfig } from './card'; 3 | import { LovelaceStrategyConfig } from './strategy'; 4 | 5 | /** 6 | * Represents the base configuration for a Lovelace section in Home Assistant. 7 | * 8 | * @property {Condition[]} [visibility] - An optional array of visibility conditions for the section. 9 | * @property {number} [column_span] - The number of columns the section spans. 10 | * @property {number} [row_span] - The number of rows the section spans. 11 | * @property {string} [title] - The title of the section (deprecated; use heading card instead). 12 | */ 13 | export interface LovelaceBaseSectionConfig { 14 | visibility?: Condition[]; 15 | column_span?: number; 16 | row_span?: number; 17 | /** @deprecated Use heading card instead. */ 18 | title?: string; 19 | } 20 | 21 | export interface LovelaceSectionConfig /** 22 | * Represents the configuration for a Lovelace section in Home Assistant. 23 | * 24 | * @property {string} [type] - The type of the section. 25 | * @property {LovelaceCardConfig[]} [cards] - An optional array of cards contained within the section. 26 | */ 27 | extends LovelaceBaseSectionConfig { 28 | type?: string; 29 | cards?: LovelaceCardConfig[]; 30 | } 31 | 32 | /** 33 | * Represents the configuration for a Lovelace strategy section in Home Assistant. 34 | * 35 | * @property {LovelaceStrategyConfig} strategy - The strategy configuration for the section. 36 | */ 37 | export interface LovelaceStrategySectionConfig extends LovelaceBaseSectionConfig { 38 | strategy: LovelaceStrategyConfig; 39 | } 40 | 41 | /** Represents the raw configuration for a Lovelace section in Home Assistant. */ 42 | export type LovelaceSectionRawConfig = LovelaceSectionConfig | LovelaceStrategySectionConfig; 43 | -------------------------------------------------------------------------------- /src/types/homeassistant/data/lovelace/config/strategy.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Represents the configuration for a Lovelace strategy in Home Assistant. 3 | * 4 | * @property {string} type - The type of the strategy. 5 | * @property {any} [key] - Additional properties can be included in the configuration. 6 | */ 7 | export interface LovelaceStrategyConfig { 8 | type: string; 9 | 10 | [key: string]: any; 11 | } 12 | -------------------------------------------------------------------------------- /src/types/homeassistant/data/lovelace/config/types.ts: -------------------------------------------------------------------------------- 1 | import { LovelaceViewRawConfig } from './view'; 2 | 3 | /** Represents the base configuration for a Lovelace dashboard in Home Assistant. */ 4 | export interface LovelaceDashboardBaseConfig {} 5 | 6 | /** 7 | * Represents the configuration for a Lovelace dashboard in Home Assistant. 8 | * 9 | * @property {string} [background] - An optional background image or color for the dashboard. 10 | * @property {LovelaceViewRawConfig[]} views - An array of views contained within the dashboard. 11 | */ 12 | export interface LovelaceConfig extends LovelaceDashboardBaseConfig { 13 | background?: string; 14 | views: LovelaceViewRawConfig[]; 15 | } 16 | -------------------------------------------------------------------------------- /src/types/homeassistant/data/registry.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Represents a registry entry in Home Assistant. 3 | * 4 | * @property {number} created_at - The timestamp when the entry was created. 5 | * @property {number} modified_at - The timestamp when the entry was last modified. 6 | */ 7 | export interface RegistryEntry { 8 | created_at: number; 9 | modified_at: number; 10 | } 11 | -------------------------------------------------------------------------------- /src/types/homeassistant/data/translations.ts: -------------------------------------------------------------------------------- 1 | // noinspection JSUnusedGlobalSymbols 2 | 3 | import { HomeAssistant } from '../types'; 4 | 5 | /** Represents the different formats for numbers in Home Assistant. */ 6 | export enum NumberFormat { 7 | language = 'language', 8 | system = 'system', 9 | comma_decimal = 'comma_decimal', 10 | decimal_comma = 'decimal_comma', 11 | space_comma = 'space_comma', 12 | none = 'none', 13 | } 14 | 15 | /**Represents the different formats for time in Home Assistant. */ 16 | export enum TimeFormat { 17 | language = 'language', 18 | system = 'system', 19 | am_pm = '12', 20 | twenty_four = '24', 21 | } 22 | 23 | /** Represents the different time zones in Home Assistant. */ 24 | export enum TimeZone { 25 | local = 'local', 26 | server = 'server', 27 | } 28 | 29 | /** Represents the different formats for dates in Home Assistant. */ 30 | export enum DateFormat { 31 | language = 'language', 32 | system = 'system', 33 | DMY = 'DMY', 34 | MDY = 'MDY', 35 | YMD = 'YMD', 36 | } 37 | 38 | /**Represents the first weekday in Home Assistant. */ 39 | export enum FirstWeekday { 40 | language = 'language', 41 | monday = 'monday', 42 | tuesday = 'tuesday', 43 | wednesday = 'wednesday', 44 | thursday = 'thursday', 45 | friday = 'friday', 46 | saturday = 'saturday', 47 | sunday = 'sunday', 48 | } 49 | 50 | /** 51 | * Represents the locale data for the frontend in Home Assistant. 52 | * 53 | * @property {string} language - The language of the frontend. 54 | * @property {NumberFormat} number_format - The format for numbers. 55 | * @property {TimeFormat} time_format - The format for time. 56 | * @property {DateFormat} date_format - The format for dates. 57 | * @property {FirstWeekday} first_weekday - The first weekday. 58 | * @property {TimeZone} time_zone - The time zone. 59 | */ 60 | export interface FrontendLocaleData { 61 | language: string; 62 | number_format: NumberFormat; 63 | time_format: TimeFormat; 64 | date_format: DateFormat; 65 | first_weekday: FirstWeekday; 66 | time_zone: TimeZone; 67 | } 68 | 69 | /** Represents a category for translations in Home Assistant. */ 70 | export type TranslationCategory = 71 | | 'title' 72 | | 'state' 73 | | 'entity' 74 | | 'entity_component' 75 | | 'exceptions' 76 | | 'config' 77 | | 'config_subentries' 78 | | 'config_panel' 79 | | 'options' 80 | | 'device_automation' 81 | | 'mfa_setup' 82 | | 'system_health' 83 | | 'application_credentials' 84 | | 'issues' 85 | | 'selector' 86 | | 'services'; 87 | 88 | /** 89 | * Retrieves the translations for Home Assistant. 90 | * 91 | * @async 92 | * 93 | * @param {HomeAssistant} hass - The Home Assistant instance. 94 | * @param {string} language - The language for translations. 95 | * @param {TranslationCategory} category - The category of translations. 96 | * @param {string | string[]} [integration] - Optional integration name(s). 97 | * @param {boolean} [config_flow] - Optional flag for config flow. 98 | * 99 | * @returns {Promise>} A promise resolving to an object containing translation key-value pairs. 100 | */ 101 | export const getHassTranslations = async ( 102 | hass: HomeAssistant, 103 | language: string, 104 | category: TranslationCategory, 105 | integration?: string | string[], 106 | config_flow?: boolean, 107 | ): Promise> => { 108 | const result = await hass.callWS<{ resources: Record }>({ 109 | type: 'frontend/get_translations', 110 | language, 111 | category, 112 | integration, 113 | config_flow, 114 | }); 115 | return result.resources; 116 | }; 117 | -------------------------------------------------------------------------------- /src/types/homeassistant/data/ws-themes.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Represents the variables for a theme in Home Assistant. 3 | * 4 | * @property {string} primary-color - The primary color of the theme. 5 | * @property {string} text-primary-color - The primary text color of the theme. 6 | * @property {string} accent-color - The accent color of the theme. 7 | * @property {string} [key] - Additional theme variables as key-value pairs. 8 | */ 9 | export interface ThemeVars { 10 | // Incomplete 11 | 'primary-color': string; 12 | 'text-primary-color': string; 13 | 'accent-color': string; 14 | 15 | [key: string]: string; 16 | } 17 | 18 | /** 19 | * Represents a theme configuration in Home Assistant. 20 | * 21 | * @property {ThemeVars} modes.light - The light mode variables. 22 | * @property {ThemeVars} modes.dark - The dark mode variables. 23 | */ 24 | export type Theme = ThemeVars & { 25 | modes?: { 26 | light?: ThemeVars; 27 | dark?: ThemeVars; 28 | }; 29 | }; 30 | 31 | /** 32 | * Represents the overall themes configuration in Home Assistant. 33 | * 34 | * @property {string} default_theme - The default theme name. 35 | * @property {string | null} default_dark_theme - The default dark theme name or null. 36 | * @property {Record} themes - A record of available themes. 37 | * @property {boolean} darkMode - Currently effective dark mode. 38 | * It Will never be undefined. 39 | * If the user selected "auto" in the theme picker, this property will still contain 40 | * either true or false based on what has been determined via system preferences and 41 | * support for the selected theme. 42 | * @property {string} theme - Currently globally active theme name 43 | */ 44 | export interface Themes { 45 | default_theme: string; 46 | default_dark_theme: string | null; 47 | themes: Record; 48 | darkMode: boolean; 49 | theme: string; 50 | } 51 | -------------------------------------------------------------------------------- /src/types/homeassistant/panels/common/validate-condition.ts: -------------------------------------------------------------------------------- 1 | /** Represents a condition in Home Assistant. */ 2 | export type Condition = 3 | | NumericStateCondition 4 | | StateCondition 5 | | ScreenCondition 6 | | UserCondition 7 | | OrCondition 8 | | AndCondition; 9 | 10 | /** 11 | * Base interface for all conditions in Home Assistant. 12 | * 13 | * @property {string} condition - The type of condition. 14 | */ 15 | interface BaseCondition { 16 | condition: string; 17 | } 18 | 19 | /** 20 | * Represents a numeric state condition in Home Assistant. 21 | * 22 | * @property {'numeric_state'} condition - The condition type. 23 | * @property {string} [entity] - The entity to evaluate. 24 | * @property {string | number} [below] - The threshold value below which the condition is true. 25 | * @property {string | number} [above] - The threshold value above which the condition is true. 26 | */ 27 | export interface NumericStateCondition extends BaseCondition { 28 | condition: 'numeric_state'; 29 | entity?: string; 30 | below?: string | number; 31 | above?: string | number; 32 | } 33 | 34 | /** 35 | * Represents a state condition in Home Assistant. 36 | * 37 | * @property {'state'} condition - The condition type. 38 | * @property {string} [entity] - The entity to evaluate. 39 | * @property {string | string[]} [state] - The expected state of the entity. 40 | * @property {string | string[]} [state_not] - The state that the entity should not be in. 41 | */ 42 | export interface StateCondition extends BaseCondition { 43 | condition: 'state'; 44 | entity?: string; 45 | state?: string | string[]; 46 | state_not?: string | string[]; 47 | } 48 | 49 | /** 50 | * Represents a screen condition in Home Assistant. 51 | * 52 | * @property {'screen'} condition - The condition type. 53 | * @property {string} [media_query] - The media query for screen conditions. 54 | */ 55 | export interface ScreenCondition extends BaseCondition { 56 | condition: 'screen'; 57 | media_query?: string; 58 | } 59 | 60 | /** 61 | * Represents a user condition in Home Assistant. 62 | * 63 | * @property {'user'} condition - The condition type. 64 | * @property {string[]} [users] - The list of users for the condition. 65 | */ 66 | export interface UserCondition extends BaseCondition { 67 | condition: 'user'; 68 | users?: string[]; 69 | } 70 | 71 | /** 72 | * Represents an OR condition in Home Assistant. 73 | * 74 | * @property {'or'} condition - The condition type. 75 | * @property {Condition[]} [conditions] - The list of conditions to evaluate. 76 | */ 77 | export interface OrCondition extends BaseCondition { 78 | condition: 'or'; 79 | conditions?: Condition[]; 80 | } 81 | 82 | /** 83 | * Represents an AND condition in Home Assistant. 84 | * 85 | * @property {'and'} condition - The condition type. 86 | * @property {Condition[]} [conditions] - The list of conditions to evaluate. 87 | */ 88 | export interface AndCondition extends BaseCondition { 89 | condition: 'and'; 90 | conditions?: Condition[]; 91 | } 92 | -------------------------------------------------------------------------------- /src/types/homeassistant/panels/lovelace/cards/types.ts: -------------------------------------------------------------------------------- 1 | import { ActionConfig } from '../../../data/lovelace/config/action'; 2 | import { LovelaceCardConfig } from '../../../data/lovelace/config/card'; 3 | 4 | /** 5 | * Home Assistant Area Card Config. 6 | * 7 | * @property {string} area - The area associated with the card. 8 | * @property {string} [navigation_path] - Optional navigation path for the card. 9 | * @property {boolean} [show_camera] - Whether to show the camera view. 10 | * @property {"live" | "auto"} [camera_view] - The camera view mode. 11 | * @property {string} [aspect_ratio] - The aspect ratio of the card. 12 | * @see https://www.home-assistant.io/dashboards/area/ 13 | */ 14 | export interface AreaCardConfig extends LovelaceCardConfig { 15 | area: string; 16 | navigation_path?: string; 17 | show_camera?: boolean; 18 | camera_view?: 'live' | 'auto'; 19 | aspect_ratio?: string; 20 | } 21 | 22 | /** 23 | * Home Assistant Picture Entity Config. 24 | * 25 | * @property {string} entity - An entity_id used for the picture. 26 | * @property {string} [name] - Overwrite entity name. 27 | * @property {string} [image] - URL of an image. 28 | * @property {string} [camera_image] - Camera entity_id to use. 29 | * @property {"live" | "auto"} [camera_view] - The camera view mode. 30 | * @property {Record} [state_image] - Map entity states to images. 31 | * @property {string[]} [state_filter] - State-based CSS filters. 32 | * @property {string} [aspect_ratio] - Forces the height of the image to be a ratio of the width. 33 | * @property {ActionConfig} [tap_action] - Action taken on card tap. 34 | * @property {ActionConfig} [hold_action] - Action taken on card tap and hold. 35 | * @property {ActionConfig} [double_tap_action] - Action taken on card double tap. 36 | * @property {boolean} [show_name=true] - Shows name in footer. 37 | * @property {string} [theme=true] - Override the used theme for this card. 38 | * @property {boolean} [show_state] - Shows state in footer. 39 | * @see https://www.home-assistant.io/dashboards/picture-entity/ 40 | */ 41 | export interface PictureEntityCardConfig extends LovelaceCardConfig { 42 | entity: string; 43 | name?: string; 44 | image?: string; 45 | camera_image?: string; 46 | camera_view?: 'live' | 'auto'; 47 | state_image?: Record; 48 | state_filter?: string[]; 49 | aspect_ratio?: string; 50 | tap_action?: ActionConfig; 51 | hold_action?: ActionConfig; 52 | double_tap_action?: ActionConfig; 53 | show_name?: boolean; 54 | show_state?: boolean; 55 | theme?: string; 56 | } 57 | 58 | /** 59 | * Home Assistant Stack Card Config. 60 | * 61 | * @property {string} type - The stack type. 62 | * @property {Object[]} cards - The content of the stack. 63 | * @see https://www.home-assistant.io/dashboards/horizontal-stack/ 64 | * @see https://www.home-assistant.io/dashboards/vertical-stack/ 65 | */ 66 | export interface StackCardConfig extends LovelaceCardConfig { 67 | type: string; 68 | cards: LovelaceCardConfig[]; 69 | title?: string; 70 | } 71 | -------------------------------------------------------------------------------- /src/types/homeassistant/panels/lovelace/types.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Represents the layout options for Lovelace in Home Assistant. 3 | * 4 | * @property {number | "full"} [grid_columns] - The number of grid columns or "full". 5 | * @property {number | "auto"} [grid_rows] - The number of grid rows or "auto". 6 | * @property {number} [grid_max_columns] - The maximum number of grid columns. 7 | * @property {number} [grid_min_columns] - The minimum number of grid columns. 8 | * @property {number} [grid_min_rows] - The minimum number of grid rows. 9 | * @property {number} [grid_max_rows] - The maximum number of grid rows. 10 | */ 11 | export interface LovelaceLayoutOptions { 12 | grid_columns?: number | 'full'; 13 | grid_rows?: number | 'auto'; 14 | grid_max_columns?: number; 15 | grid_min_columns?: number; 16 | grid_min_rows?: number; 17 | grid_max_rows?: number; 18 | } 19 | 20 | /** 21 | * Represents the grid options for Lovelace in Home Assistant. 22 | * 23 | * @property {number | "full"} [columns] - The number of columns or "full". 24 | * @property {number | "auto"} [rows] - The number of rows or "auto". 25 | * @property {number} [max_columns] - The maximum number of columns. 26 | * @property {number} [min_columns] - The minimum number of columns. 27 | * @property {number} [min_rows] - The minimum number of rows. 28 | * @property {number} [max_rows] - The maximum number of rows. 29 | */ 30 | export interface LovelaceGridOptions { 31 | columns?: number | 'full'; 32 | rows?: number | 'auto'; 33 | max_columns?: number; 34 | min_columns?: number; 35 | min_rows?: number; 36 | max_rows?: number; 37 | } 38 | -------------------------------------------------------------------------------- /src/types/lovelace-mushroom/README.md: -------------------------------------------------------------------------------- 1 | # Notice 2 | 3 | This directory contains partial code from 4 | the [Lovelace Mushroom repository](https://github.com/piitaya/lovelace-mushroom). 5 | 6 | The code mainly defines Home Assistant interfaces/types which are refactored to fit this repository. 7 | This means properties are added/removed from the originals and subtypes may have been changed. 8 | 9 | The [Apache 2.0 License](https://github.com/home-assistant/frontend/blob/dev/LICENSE.md) applies to all files in this 10 | directory. 11 | 12 | Copyright 2023 Ferry Cools 13 | 14 | Licensed under the Apache License, Version 2.0 (the "License"); 15 | you may not use this file except in compliance with the License. 16 | You may obtain a copy of the License at 17 | 18 | 19 | 20 | Unless required by applicable law or agreed to in writing, software 21 | distributed under the License is distributed on an "AS IS" BASIS, 22 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 23 | See the License for the specific language governing permissions and 24 | limitations under the License. 25 | -------------------------------------------------------------------------------- /src/types/lovelace-mushroom/cards/chips-card.ts: -------------------------------------------------------------------------------- 1 | import { LovelaceCardConfig } from '../../homeassistant/data/lovelace/config/card'; 2 | import { LovelaceChipConfig } from '../utils/lovelace/chip/types'; 3 | 4 | /** 5 | * Chips Card Configuration 6 | * 7 | * @property {LovelaceChipConfig[]} chips - Array of chips to display. 8 | * @property {string} [alignment] - Chips alignment (start, end, center, justify). Defaults to 'start'. 9 | * 10 | * @see https://github.com/piitaya/lovelace-mushroom/blob/main/docs/cards/chips.md 11 | */ 12 | export interface ChipsCardConfig extends LovelaceCardConfig { 13 | chips: LovelaceChipConfig[]; 14 | alignment?: string; 15 | } 16 | -------------------------------------------------------------------------------- /src/types/lovelace-mushroom/cards/climate-card-config.ts: -------------------------------------------------------------------------------- 1 | import { HvacMode } from '../../homeassistant/data/climate'; 2 | import { LovelaceCardConfig } from '../../homeassistant/data/lovelace/config/card'; 3 | import { ActionsSharedConfig } from '../shared/config/actions-config'; 4 | import { AppearanceSharedConfig } from '../shared/config/appearance-config'; 5 | import { EntitySharedConfig } from '../shared/config/entity-config'; 6 | 7 | /** 8 | * Climate Card Configuration 9 | * 10 | * @property {boolean} [show_temperature_control] - Show buttons to control target temperature. Defaults to false. 11 | * @property {HvacMode[]} [hvac_modes] - List of HVAC modes to display. 12 | * (auto, heat_cool, heat, cool, dry, fan_only, off). 13 | * @property {boolean} [collapsible_controls] - Collapse controls when off. 14 | * 15 | * @see https://github.com/piitaya/lovelace-mushroom/blob/main/docs/cards/climate.md 16 | */ 17 | export type ClimateCardConfig = LovelaceCardConfig & 18 | EntitySharedConfig & 19 | AppearanceSharedConfig & 20 | ActionsSharedConfig & { 21 | show_temperature_control?: boolean; 22 | hvac_modes?: HvacMode[]; 23 | collapsible_controls?: boolean; 24 | }; 25 | -------------------------------------------------------------------------------- /src/types/lovelace-mushroom/cards/cover-card-config.ts: -------------------------------------------------------------------------------- 1 | import { LovelaceCardConfig } from '../../homeassistant/data/lovelace/config/card'; 2 | import { ActionsSharedConfig } from '../shared/config/actions-config'; 3 | import { AppearanceSharedConfig } from '../shared/config/appearance-config'; 4 | import { EntitySharedConfig } from '../shared/config/entity-config'; 5 | 6 | /** 7 | * Cover Card Configuration 8 | * 9 | * @property {boolean} [show_buttons_control] - Show buttons to open, close, and stop the cover. Defaults to false. 10 | * @property {boolean} [show_position_control] - Show a slider to control the position of the cover. Defaults to false. 11 | * @property {boolean} [show_tilt_position_control] - Show a slider to control the tilt position of the cover. Defaults 12 | * to false. 13 | * 14 | * @see https://github.com/piitaya/lovelace-mushroom/blob/main/docs/cards/cover.md 15 | */ 16 | export type CoverCardConfig = LovelaceCardConfig & 17 | EntitySharedConfig & 18 | AppearanceSharedConfig & 19 | ActionsSharedConfig & { 20 | show_buttons_control?: boolean; 21 | show_position_control?: boolean; 22 | show_tilt_position_control?: boolean; 23 | }; 24 | -------------------------------------------------------------------------------- /src/types/lovelace-mushroom/cards/entity-card-config.ts: -------------------------------------------------------------------------------- 1 | import { LovelaceCardConfig } from '../../homeassistant/data/lovelace/config/card'; 2 | import { ActionsSharedConfig } from '../shared/config/actions-config'; 3 | import { AppearanceSharedConfig } from '../shared/config/appearance-config'; 4 | import { EntitySharedConfig } from '../shared/config/entity-config'; 5 | 6 | /** 7 | * Entity Card Configuration 8 | * 9 | * @property {string} [icon_color] - Custom color for the icon when the entity's state is active. Defaults to 'blue'. 10 | * 11 | * @see https://github.com/piitaya/lovelace-mushroom/blob/main/docs/cards/entity.md 12 | */ 13 | export type EntityCardConfig = LovelaceCardConfig & 14 | EntitySharedConfig & 15 | AppearanceSharedConfig & 16 | ActionsSharedConfig & { 17 | icon_color?: string; 18 | }; 19 | -------------------------------------------------------------------------------- /src/types/lovelace-mushroom/cards/fan-card-config.ts: -------------------------------------------------------------------------------- 1 | import { LovelaceCardConfig } from '../../homeassistant/data/lovelace/config/card'; 2 | import { ActionsSharedConfig } from '../shared/config/actions-config'; 3 | import { AppearanceSharedConfig } from '../shared/config/appearance-config'; 4 | import { EntitySharedConfig } from '../shared/config/entity-config'; 5 | 6 | /** 7 | * Fan Card Configuration 8 | * 9 | * @property {boolean} [icon_animation] - Animate the icon when the fan is on. Defaults to false. 10 | * @property {boolean} [show_percentage_control] - Show a slider to control speed. Defaults to false. 11 | * @property {boolean} [show_oscillate_control] - Show a button to control oscillation. Defaults to false. 12 | * @property {boolean} [show_direction_control] - Show a button to control the direction. Defaults to false. 13 | * 14 | * @see https://github.com/piitaya/lovelace-mushroom/blob/main/docs/cards/fan.md 15 | */ 16 | export type FanCardConfig = LovelaceCardConfig & 17 | EntitySharedConfig & 18 | AppearanceSharedConfig & 19 | ActionsSharedConfig & { 20 | icon_animation?: boolean; 21 | show_percentage_control?: boolean; 22 | show_oscillate_control?: boolean; 23 | show_direction_control?: boolean; 24 | }; 25 | -------------------------------------------------------------------------------- /src/types/lovelace-mushroom/cards/light-card-config.ts: -------------------------------------------------------------------------------- 1 | import { LovelaceCardConfig } from '../../homeassistant/data/lovelace/config/card'; 2 | import { ActionsSharedConfig } from '../shared/config/actions-config'; 3 | import { AppearanceSharedConfig } from '../shared/config/appearance-config'; 4 | import { EntitySharedConfig } from '../shared/config/entity-config'; 5 | 6 | /** 7 | * Light Card Configuration 8 | * 9 | * @property {string} [icon_color] - Custom color for icon and brightness bar when the lights are on and 10 | * `use_light_color` is false; Defaults to 'blue'. 11 | * @property {boolean} [show_brightness_control] - Show a slider to control brightness. Defaults to false. 12 | * @property {boolean} [show_color_temp_control] - Show a slider to control temperature color; Defaults to false. 13 | * @property {boolean} [show_color_control] - Show a slider to control RGB color. Defaults to false. 14 | * @property {boolean} [collapsible_controls] - Collapse controls when off; Defaults to false. 15 | * @property {boolean} [use_light_color] - Colorize the icon and slider according to light temperature or color. 16 | * Defaults to false. 17 | * 18 | * @see https://github.com/piitaya/lovelace-mushroom/blob/main/docs/cards/light.md 19 | */ 20 | export type LightCardConfig = LovelaceCardConfig & 21 | EntitySharedConfig & 22 | AppearanceSharedConfig & 23 | ActionsSharedConfig & { 24 | icon_color?: string; 25 | show_brightness_control?: boolean; 26 | show_color_temp_control?: boolean; 27 | show_color_control?: boolean; 28 | collapsible_controls?: boolean; 29 | use_light_color?: boolean; 30 | }; 31 | -------------------------------------------------------------------------------- /src/types/lovelace-mushroom/cards/lock-card-config.ts: -------------------------------------------------------------------------------- 1 | import { LovelaceCardConfig } from '../../homeassistant/data/lovelace/config/card'; 2 | import { ActionsSharedConfig } from '../shared/config/actions-config'; 3 | import { AppearanceSharedConfig } from '../shared/config/appearance-config'; 4 | import { EntitySharedConfig } from '../shared/config/entity-config'; 5 | 6 | /** 7 | * Lock Card Configuration 8 | * 9 | * @see https://github.com/piitaya/lovelace-mushroom/blob/main/docs/cards/lock.md 10 | */ 11 | export type LockCardConfig = LovelaceCardConfig & EntitySharedConfig & AppearanceSharedConfig & ActionsSharedConfig; 12 | -------------------------------------------------------------------------------- /src/types/lovelace-mushroom/cards/media-player-card-config.ts: -------------------------------------------------------------------------------- 1 | import { LovelaceCardConfig } from '../../homeassistant/data/lovelace/config/card'; 2 | import { ActionsSharedConfig } from '../shared/config/actions-config'; 3 | import { AppearanceSharedConfig } from '../shared/config/appearance-config'; 4 | import { EntitySharedConfig } from '../shared/config/entity-config'; 5 | 6 | /** List of available media controls. */ 7 | export const MEDIA_LAYER_MEDIA_CONTROLS = [ 8 | 'on_off', 9 | 'shuffle', 10 | 'previous', 11 | 'play_pause_stop', 12 | 'next', 13 | 'repeat', 14 | ] as const; 15 | 16 | /** Represents a single media control option. */ 17 | export type MediaPlayerMediaControl = (typeof MEDIA_LAYER_MEDIA_CONTROLS)[number]; 18 | /** List of available volume controls. */ 19 | export const MEDIA_PLAYER_VOLUME_CONTROLS = ['volume_mute', 'volume_set', 'volume_buttons'] as const; 20 | /** Represents a single volume control option. */ 21 | export type MediaPlayerVolumeControl = (typeof MEDIA_PLAYER_VOLUME_CONTROLS)[number]; 22 | 23 | /** 24 | * Media Player Card Configuration. 25 | * 26 | * @property {boolean} [use_media_info] - Use media info instead of name, state, and icon when media is playing. 27 | * Defaults to false. 28 | * @property {boolean} [show_volume_level] - Show volume level next to media state when media is playing. 29 | * Defaults to false. 30 | * @property {MediaPlayerVolumeControl[]} [volume_controls] - List of controls to display. 31 | * (volume_mute, volume_set, volume_buttons) 32 | * @property {MediaPlayerMediaControl[]} [media_controls] - List of controls to display 33 | * (on_off, shuffle, previous, play_pause_stop, next, repeat) 34 | * @property {boolean} [collapsible_controls] - Collapse controls when off; Defaults to false. 35 | * 36 | * @see https://github.com/piitaya/lovelace-mushroom/blob/main/docs/cards/media-player.md 37 | */ 38 | export type MediaPlayerCardConfig = LovelaceCardConfig & 39 | EntitySharedConfig & 40 | AppearanceSharedConfig & 41 | ActionsSharedConfig & { 42 | use_media_info?: boolean; 43 | show_volume_level?: boolean; 44 | volume_controls?: MediaPlayerVolumeControl[]; 45 | media_controls?: MediaPlayerMediaControl[]; 46 | collapsible_controls?: boolean; 47 | }; 48 | -------------------------------------------------------------------------------- /src/types/lovelace-mushroom/cards/number-card-config.ts: -------------------------------------------------------------------------------- 1 | import { LovelaceCardConfig } from '../../homeassistant/data/lovelace/config/card'; 2 | import { ActionsSharedConfig } from '../shared/config/actions-config'; 3 | import { AppearanceSharedConfig } from '../shared/config/appearance-config'; 4 | import { EntitySharedConfig } from '../shared/config/entity-config'; 5 | 6 | export const DISPLAY_MODES = ['slider', 'buttons'] as const; 7 | 8 | type DisplayMode = (typeof DISPLAY_MODES)[number]; 9 | 10 | /** 11 | * Number Card Configuration 12 | * 13 | * @property {string} [icon_color] - Custom color for the icon when the entity state is active. Defaults to 'blue'. 14 | * @property {DisplayMode} [display_mode] - Slider or Button controls. Defaults to 'slider'. 15 | * 16 | * @see https://github.com/piitaya/lovelace-mushroom/blob/main/docs/cards/number.md 17 | */ 18 | export type NumberCardConfig = LovelaceCardConfig & 19 | EntitySharedConfig & 20 | AppearanceSharedConfig & 21 | ActionsSharedConfig & { 22 | icon_color?: string; 23 | display_mode?: DisplayMode; 24 | }; 25 | -------------------------------------------------------------------------------- /src/types/lovelace-mushroom/cards/person-card-config.ts: -------------------------------------------------------------------------------- 1 | import { LovelaceCardConfig } from '../../homeassistant/data/lovelace/config/card'; 2 | import { ActionsSharedConfig } from '../shared/config/actions-config'; 3 | import { AppearanceSharedConfig } from '../shared/config/appearance-config'; 4 | import { EntitySharedConfig } from '../shared/config/entity-config'; 5 | 6 | /** 7 | * Person Card Configuration 8 | * 9 | * @see https://github.com/piitaya/lovelace-mushroom/blob/main/docs/cards/person.md 10 | */ 11 | export type PersonCardConfig = LovelaceCardConfig & EntitySharedConfig & AppearanceSharedConfig & ActionsSharedConfig; 12 | -------------------------------------------------------------------------------- /src/types/lovelace-mushroom/cards/select-card-config.ts: -------------------------------------------------------------------------------- 1 | import { LovelaceCardConfig } from '../../homeassistant/data/lovelace/config/card'; 2 | import { ActionsSharedConfig } from '../shared/config/actions-config'; 3 | import { AppearanceSharedConfig } from '../shared/config/appearance-config'; 4 | import { EntitySharedConfig } from '../shared/config/entity-config'; 5 | 6 | /** 7 | * Select Card Configuration 8 | * 9 | * @see https://github.com/piitaya/lovelace-mushroom/blob/main/docs/cards/select.md 10 | */ 11 | export type SelectCardConfig = LovelaceCardConfig & 12 | EntitySharedConfig & 13 | AppearanceSharedConfig & 14 | ActionsSharedConfig & { 15 | icon_color?: string; 16 | }; 17 | -------------------------------------------------------------------------------- /src/types/lovelace-mushroom/cards/template-card-config.ts: -------------------------------------------------------------------------------- 1 | import { LovelaceCardConfig } from '../../homeassistant/data/lovelace/config/card'; 2 | import { ActionsSharedConfig } from '../shared/config/actions-config'; 3 | import { AppearanceSharedConfig } from '../shared/config/appearance-config'; 4 | 5 | /** 6 | * Template Card Configuration 7 | * 8 | * @property {string} [entity] - Entity associated with the card. 9 | * @property {string} [icon] - Icon to render. May contain templates. 10 | * @property {string} [icon_color] - Icon color to render. May contain templates. 11 | * @property {string} [primary] - Primary info to render. May contain templates. 12 | * @property {string} [secondary] - Secondary info to render. May contain templates. 13 | * @property {string} [badge_icon] - Badge icon to render. May contain templates. 14 | * @property {string} [badge_color] - Badge icon color to render. May contain templates. 15 | * @property {string} [picture] - The picture to render. May contain templates. 16 | * @property {boolean} [multiline_secondary] - Enables support for multiline text for the secondary info. 17 | * @property {string | string[]} [entity_id] - Only reacts to the state changes of these entities. This can be used if 18 | * the automatic analysis fails to find all relevant entities. 19 | * 20 | * @see https://github.com/piitaya/lovelace-mushroom/blob/main/docs/cards/template.md 21 | */ 22 | export type TemplateCardConfig = LovelaceCardConfig & 23 | AppearanceSharedConfig & 24 | ActionsSharedConfig & { 25 | entity?: string; 26 | icon?: string; 27 | icon_color?: string; 28 | primary?: string; 29 | secondary?: string; 30 | badge_icon?: string; 31 | badge_color?: string; 32 | picture?: string; 33 | multiline_secondary?: boolean; 34 | entity_id?: string | string[]; 35 | }; 36 | -------------------------------------------------------------------------------- /src/types/lovelace-mushroom/cards/title-card-config.ts: -------------------------------------------------------------------------------- 1 | import { ActionConfig } from '../../homeassistant/data/lovelace/config/action'; 2 | import { LovelaceCardConfig } from '../../homeassistant/data/lovelace/config/card'; 3 | 4 | /** 5 | * Title Card Configuration 6 | * 7 | * @property {string} [title] - Title to render. 8 | * This May contain templates. 9 | * @property {string} [subtitle] - Subtitle to render. 10 | * This May contain templates. 11 | * @property {ActionConfig} [title_tap_action] - Home assistant action to perform on title tap. 12 | * @property {ActionConfig} [subtitle_tap_action] - Home assistant action to perform on subtitle tap. 13 | * @property {string} [alignment] - Alignment of the title and subtitle. 14 | * 15 | * @see https://github.com/piitaya/lovelace-mushroom/blob/main/docs/cards/title.md 16 | */ 17 | export interface TitleCardConfig extends LovelaceCardConfig { 18 | title?: string; 19 | subtitle?: string; 20 | alignment?: string; 21 | title_tap_action?: ActionConfig; 22 | subtitle_tap_action?: ActionConfig; 23 | } 24 | -------------------------------------------------------------------------------- /src/types/lovelace-mushroom/cards/vacuum-card-config.ts: -------------------------------------------------------------------------------- 1 | import { LovelaceCardConfig } from '../../homeassistant/data/lovelace/config/card'; 2 | import { ActionsSharedConfig } from '../shared/config/actions-config'; 3 | import { AppearanceSharedConfig } from '../shared/config/appearance-config'; 4 | import { EntitySharedConfig } from '../shared/config/entity-config'; 5 | 6 | export const VACUUM_COMMANDS = ['on_off', 'start_pause', 'stop', 'locate', 'clean_spot', 'return_home'] as const; 7 | 8 | export type VacuumCommand = (typeof VACUUM_COMMANDS)[number]; 9 | 10 | /** 11 | * Vacuum Card Configuration 12 | * 13 | * @property {boolean} [icon_animation] - Animate the icon when vacuum is cleaning. 14 | * @property {VacuumCommand[]} [commands] - List of commands to display. 15 | * (on_off, start_pause, stop, locate, clean_spot, return_home). 16 | * 17 | * @see https://github.com/piitaya/lovelace-mushroom/blob/main/docs/cards/vacuum.md 18 | */ 19 | export interface VacuumCardConfig 20 | extends LovelaceCardConfig, 21 | EntitySharedConfig, 22 | AppearanceSharedConfig, 23 | ActionsSharedConfig { 24 | icon_animation?: boolean; 25 | commands?: VacuumCommand[]; 26 | } 27 | -------------------------------------------------------------------------------- /src/types/lovelace-mushroom/shared/config/actions-config.ts: -------------------------------------------------------------------------------- 1 | import { ActionConfig } from '../../../homeassistant/data/lovelace/config/action'; 2 | 3 | /** 4 | * Actions Shared Configuration 5 | * 6 | * @property {ActionConfig} [tap_action] - Action to perform on tap. 7 | * @property {ActionConfig} [hold_action] - Action to perform on hold. 8 | * @property {ActionConfig} [double_tap_action] - Action to perform on double tap. 9 | */ 10 | export type ActionsSharedConfig = { 11 | tap_action?: ActionConfig; 12 | hold_action?: ActionConfig; 13 | double_tap_action?: ActionConfig; 14 | }; 15 | -------------------------------------------------------------------------------- /src/types/lovelace-mushroom/shared/config/appearance-config.ts: -------------------------------------------------------------------------------- 1 | import { boolean, enums, Infer, object, optional } from 'superstruct'; 2 | import { ICON_TYPES, INFOS } from './utils/info'; 3 | import { layoutStruct } from './utils/layout'; 4 | 5 | /** 6 | * Schema for validating the shared appearance configuration of Mushroom cards. 7 | * 8 | * Properties: 9 | * - `layout`: Optional layout configuration (see `layoutStruct`). 10 | * - `fill_container`: Optional boolean indicating whether the card should fill its container. 11 | * - `primary_info`: Optional primary information to display (must be one of `INFOS`). 12 | * - `secondary_info`: Optional secondary information to display (must be one of `INFOS`). 13 | * - `icon_type`: Optional icon type to use (must be one of `ICON_TYPES`). 14 | */ 15 | export const appearanceSharedConfigStruct = object({ 16 | layout: optional(layoutStruct), 17 | fill_container: optional(boolean()), 18 | primary_info: optional(enums(INFOS)), 19 | secondary_info: optional(enums(INFOS)), 20 | icon_type: optional(enums(ICON_TYPES)), 21 | }); 22 | 23 | /** 24 | * Appearance Shared Configuration 25 | * 26 | * @property {string} [layout] - Layout type (horizontal, vertical, default). 27 | * @property {boolean} [fill_container] - Whether to fill the container. 28 | * @property {string} [primary_info] - Primary information to display. 29 | * @property {string} [secondary_info] - Secondary information to display. 30 | * @property {string} [icon_type] - Type of icon to display. 31 | */ 32 | export type AppearanceSharedConfig = Infer; 33 | -------------------------------------------------------------------------------- /src/types/lovelace-mushroom/shared/config/entity-config.ts: -------------------------------------------------------------------------------- 1 | import { Infer, object, optional, string } from 'superstruct'; 2 | 3 | /** 4 | * Schema for validating the shared entity configuration of Mushroom cards. 5 | * 6 | * Properties: 7 | * - `entity`: Optional entity ID to associate with the card. 8 | * - `name`: Optional custom name to display for the entity. 9 | * - `icon`: Optional custom icon to display for the entity. 10 | */ 11 | export const entitySharedConfigStruct = object({ 12 | entity: optional(string()), 13 | name: optional(string()), 14 | icon: optional(string()), 15 | }); 16 | 17 | /** 18 | * Entity Shared Configuration 19 | * 20 | * @type EntitySharedConfig 21 | * @property {string} [entity] - The entity ID associated with the configuration. 22 | * @property {string} [name] - The display name for the entity. 23 | * @property {string} [icon] - The icon to display for the entity. 24 | */ 25 | export type EntitySharedConfig = Infer; 26 | -------------------------------------------------------------------------------- /src/types/lovelace-mushroom/shared/config/utils/info.ts: -------------------------------------------------------------------------------- 1 | export const INFOS = ['name', 'state', 'last-changed', 'last-updated', 'none'] as const; 2 | export const ICON_TYPES = ['icon', 'entity-picture', 'none'] as const; 3 | -------------------------------------------------------------------------------- /src/types/lovelace-mushroom/shared/config/utils/layout.ts: -------------------------------------------------------------------------------- 1 | import { literal, union } from 'superstruct'; 2 | 3 | export const layoutStruct = union([literal('horizontal'), literal('vertical'), literal('default')]); 4 | -------------------------------------------------------------------------------- /src/types/lovelace-mushroom/utils/info.ts: -------------------------------------------------------------------------------- 1 | export const INFOS = ['name', 'state', 'last-changed', 'last-updated', 'none'] as const; 2 | export type Info = (typeof INFOS)[number]; 3 | -------------------------------------------------------------------------------- /src/types/strategy/strategy-cards.ts: -------------------------------------------------------------------------------- 1 | import { LovelaceCardConfig } from '../homeassistant/data/lovelace/config/card'; 2 | import { TitleCardConfig as MushroomTitleCardConfig } from '../lovelace-mushroom/cards/title-card-config'; 3 | import { ActionsSharedConfig } from '../lovelace-mushroom/shared/config/actions-config'; 4 | import { AppearanceSharedConfig } from '../lovelace-mushroom/shared/config/appearance-config'; 5 | import { EntitySharedConfig } from '../lovelace-mushroom/shared/config/entity-config'; 6 | 7 | /** 8 | * Abstract Card Config. 9 | */ 10 | export type AbstractCardConfig = LovelaceCardConfig & EntitySharedConfig & AppearanceSharedConfig & ActionsSharedConfig; 11 | 12 | /** 13 | * Header Card Config. 14 | * 15 | * @property {boolean} [showControls] - False to hide controls. 16 | * @property {string} [iconOn] - Icon to show for switching entities from the off state. 17 | * @property {string} [iconOff] - Icon to show for switching entities to the off state. 18 | * @property {string} [onService=none] - Service to call for switching entities from the off state. 19 | * @property {string} [offService=none] - Service to call for switching entities to the off state. 20 | */ 21 | export interface StrategyHeaderCardConfig extends MushroomTitleCardConfig { 22 | type: 'custom:mushroom-title-card'; 23 | showControls?: boolean; 24 | iconOn?: string; 25 | iconOff?: string; 26 | onService?: string; 27 | offService?: string; 28 | } 29 | 30 | /** Custom Configuration of a Strategy Header Card. */ 31 | export type CustomHeaderCardConfig = Omit; 32 | -------------------------------------------------------------------------------- /src/types/strategy/strategy-views.ts: -------------------------------------------------------------------------------- 1 | import { LovelaceViewConfig } from '../homeassistant/data/lovelace/config/view'; 2 | import { CustomHeaderCardConfig } from './strategy-cards'; 3 | import { SupportedDomains } from './strategy-generics'; 4 | 5 | /** 6 | * Options for the extended View class. 7 | * 8 | * @property {StrategyHeaderCardConfig} [headerCardConfiguration] - Options for the Header card. 9 | */ 10 | export interface ViewConfig extends LovelaceViewConfig { 11 | headerCardConfiguration?: CustomHeaderCardConfig; 12 | } 13 | 14 | /** 15 | * Interface for constructors of AbstractView subclasses that are expected to define a static domain property. 16 | * 17 | * @property {SupportedDomains | "home"} domain - The domain which the view is representing. 18 | */ 19 | export interface ViewConstructor { 20 | domain: SupportedDomains | 'home'; 21 | } 22 | -------------------------------------------------------------------------------- /src/utilities/auxiliaries.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Sanitize a classname. 3 | * 4 | * The name is sanitized by capitalizing the first character of the name or after an underscore. 5 | * The underscores are removed. 6 | * 7 | * @param {string} className Name of the class to sanitize. 8 | */ 9 | export function sanitizeClassName(className: string): string { 10 | return className.replace(/^([a-z])|([-_][a-z])/g, (match) => match.toUpperCase().replace(/[-_]/g, '')); 11 | } 12 | 13 | /** 14 | * Creates a deep clone of the provided value. 15 | * 16 | * - It uses the native `structuredClone` if available (supports most built-in types, circular references, etc.). 17 | * - Falls back to `JSON.parse(JSON.stringify(obj))` for plain objects and arrays if `structuredClone` is unavailable 18 | * or fails. 19 | * 20 | * @template T 21 | * @param {T} obj - The value to deep clone. 22 | * @returns {T} A deep clone of the input value, or the original value if cloning fails. 23 | */ 24 | export function deepClone(obj: T): T { 25 | if (typeof structuredClone === 'function') { 26 | try { 27 | return structuredClone(obj); 28 | } catch { 29 | // Ignore error: fallback to the next method 30 | } 31 | } 32 | 33 | try { 34 | return JSON.parse(JSON.stringify(obj)); 35 | } catch { 36 | return obj; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/utilities/cardStacking.ts: -------------------------------------------------------------------------------- 1 | import { LovelaceCardConfig } from '../types/homeassistant/data/lovelace/config/card'; 2 | import { StackCardConfig } from '../types/homeassistant/panels/lovelace/cards/types'; 3 | 4 | // noinspection GrazieInspection 5 | /** 6 | * Stacks an array of Lovelace card configurations into horizontal stacks based on their type. 7 | * 8 | * This method processes sequences of cards with the same type and applies a specified column count 9 | * for each type of card. 10 | * It returns a new array of stacked card configurations, preserving the original order of the cards. 11 | * 12 | * @param cardConfigurations - An array of Lovelace card configurations to be stacked. 13 | * @param defaultCount - The default number of cards to stack if the type or column count is not found in the mapping. 14 | * @param [columnCounts] - An object mapping card types to their respective column counts. 15 | * If a type is not found in the mapping, it defaults to 2. 16 | * @returns An array of stacked card configurations, where each configuration is a horizontal stack 17 | * containing a specified number of cards. 18 | * 19 | * @example 20 | * ```typescript 21 | * stackedCards = stackHorizontal(card, 2, {area: 1, 'custom:card': 2}); 22 | * ``` 23 | */ 24 | export function stackHorizontal( 25 | cardConfigurations: LovelaceCardConfig[], 26 | defaultCount: number = 2, 27 | columnCounts?: { 28 | [key: string]: number | undefined; 29 | }, 30 | ): LovelaceCardConfig[] { 31 | if (cardConfigurations.length <= 1) { 32 | return cardConfigurations; 33 | } 34 | 35 | // Function to process a sequence of cards 36 | const doStack = (cards: LovelaceCardConfig[], columnCount: number) => { 37 | if (cards.length <= 1) { 38 | return cards; 39 | } 40 | 41 | const stackedCardConfigurations: StackCardConfig[] = []; 42 | 43 | for (let i = 0; i < cards.length; i += columnCount) { 44 | stackedCardConfigurations.push({ 45 | type: 'horizontal-stack', 46 | cards: cards.slice(i, i + columnCount), 47 | } as StackCardConfig); 48 | } 49 | 50 | return stackedCardConfigurations; 51 | }; 52 | 53 | // Array to hold the processed cards 54 | const processedConfigurations: LovelaceCardConfig[] = []; 55 | 56 | for (let i = 0; i < cardConfigurations.length; ) { 57 | const currentCard = cardConfigurations[i]; 58 | const currentType = currentCard.type; 59 | 60 | // Start a new sequence 61 | const sequence: LovelaceCardConfig[] = []; 62 | 63 | // Collect all cards of the same type into the sequence 64 | while (i < cardConfigurations.length && cardConfigurations[i].type === currentType) { 65 | sequence.push(cardConfigurations[i]); 66 | i++; // Move to the next card 67 | } 68 | 69 | const columnCount = Math.max(columnCounts?.[currentType] || defaultCount, 1); 70 | 71 | // Process the sequence and add the result to the processedConfigurations array 72 | processedConfigurations.push(...doStack(sequence, columnCount)); 73 | } 74 | 75 | return processedConfigurations; 76 | } 77 | -------------------------------------------------------------------------------- /src/utilities/localize.ts: -------------------------------------------------------------------------------- 1 | import * as de from '../translations/de.json'; 2 | import * as en from '../translations/en.json'; 3 | import * as es from '../translations/es.json'; 4 | import * as nl from '../translations/nl.json'; 5 | import * as pt_br from '../translations/pt-BR.json'; 6 | import { HomeAssistant } from '../types/homeassistant/types'; 7 | import { logMessage, lvlWarn } from './debug'; 8 | 9 | /** Registry of currently supported languages */ 10 | const languages: Record = { 11 | de, 12 | en, 13 | es, 14 | nl, 15 | 'pt-BR': pt_br, 16 | }; 17 | 18 | /** The fallback language if the user-defined language isn't defined */ 19 | const DEFAULT_LANG = 'en'; 20 | 21 | /** 22 | * Get a string by keyword and language. 23 | * 24 | * @param {string} key The key to look for in the object notation of the language file (E.g., `generic.home`). 25 | * @param {string} lang The language to get the string from (E.g., `en`). 26 | * 27 | * @returns {string | undefined} The requested string or undefined if the keyword doesn't exist/on error. 28 | */ 29 | function getTranslatedString(key: string, lang: string): string | undefined { 30 | try { 31 | return key.split('.').reduce((o, i) => (o as Record)[i], languages[lang]) as string; 32 | } catch { 33 | return undefined; 34 | } 35 | } 36 | 37 | /** 38 | * Singleton instance of the localization function. 39 | * 40 | * This variable is set by {@link setupCustomLocalize} and used by {@link localize}. 41 | * 42 | * - Must be initialized before {@link localize} is called. 43 | * - Holds a closure that translates keys based on the language set during setup. 44 | * 45 | * @private 46 | */ 47 | let _localize: ((key: string) => string) | undefined = undefined; 48 | 49 | /** 50 | * Set up the localization. 51 | * 52 | * It reads the user-defined language with a fall-back to English and returns a function to get strings from 53 | * language-files by keyword. 54 | * 55 | * If the keyword is undefined, or on an error, the keyword itself is returned. 56 | * 57 | * @param {HomeAssistant} hass The Home Assistant object. 58 | */ 59 | export default function setupCustomLocalize(hass?: HomeAssistant): void { 60 | const lang = hass?.locale.language ?? DEFAULT_LANG; 61 | 62 | _localize = (key: string) => getTranslatedString(key, lang) ?? getTranslatedString(key, DEFAULT_LANG) ?? key; 63 | } 64 | 65 | /** 66 | * Translate a key using the globally configured localize function. 67 | */ 68 | export function localize(key: string): string { 69 | if (!_localize) { 70 | logMessage(lvlWarn, 'localize is not initialized! Call setupCustomLocalize first.'); 71 | 72 | return key; 73 | } 74 | return _localize(key); 75 | } 76 | -------------------------------------------------------------------------------- /src/views/CameraView.ts: -------------------------------------------------------------------------------- 1 | // noinspection JSUnusedGlobalSymbols Class is dynamically imported. 2 | 3 | import { Registry } from '../Registry'; 4 | import { CustomHeaderCardConfig } from '../types/strategy/strategy-cards'; 5 | import { SupportedDomains } from '../types/strategy/strategy-generics'; 6 | import { ViewConfig } from '../types/strategy/strategy-views'; 7 | import { localize } from '../utilities/localize'; 8 | import AbstractView from './AbstractView'; 9 | 10 | /** 11 | * Camera View Class. 12 | * 13 | * Used to create a view configuration for entities of the camera domain. 14 | */ 15 | class CameraView extends AbstractView { 16 | /** The domain of the entities that the view is representing. */ 17 | static readonly domain: SupportedDomains = 'camera' as const; 18 | 19 | /** Returns the default configuration object for the view. */ 20 | static getDefaultConfig(): ViewConfig { 21 | return { 22 | title: localize('camera.cameras'), 23 | path: 'cameras', 24 | icon: 'mdi:cctv', 25 | subview: false, 26 | headerCardConfiguration: { 27 | showControls: false, // FIXME: This should be named "show_controls". Also in other files and Wiki. 28 | }, 29 | }; 30 | } 31 | 32 | /** Returns the default configuration of the view's Header card. */ 33 | static getViewHeaderCardConfig(): CustomHeaderCardConfig { 34 | return { 35 | title: localize('camera.all_cameras'), 36 | subtitle: 37 | `${Registry.getCountTemplate(CameraView.domain, 'ne', 'off')} ${localize('camera.cameras')} ` + 38 | localize('generic.busy'), 39 | }; 40 | } 41 | 42 | /** 43 | * Class constructor. 44 | * 45 | * @param {ViewConfig} [customConfiguration] Custom view configuration. 46 | */ 47 | constructor(customConfiguration?: ViewConfig) { 48 | super(); 49 | 50 | this.initializeViewConfig(CameraView.getDefaultConfig(), customConfiguration, CameraView.getViewHeaderCardConfig()); 51 | } 52 | } 53 | 54 | export default CameraView; 55 | -------------------------------------------------------------------------------- /src/views/ClimateView.ts: -------------------------------------------------------------------------------- 1 | // noinspection JSUnusedGlobalSymbols Class is dynamically imported. 2 | 3 | import { Registry } from '../Registry'; 4 | import { CustomHeaderCardConfig } from '../types/strategy/strategy-cards'; 5 | import { SupportedDomains } from '../types/strategy/strategy-generics'; 6 | import { ViewConfig } from '../types/strategy/strategy-views'; 7 | import { localize } from '../utilities/localize'; 8 | import AbstractView from './AbstractView'; 9 | 10 | /** 11 | * Climate View Class. 12 | * 13 | * Used to create a view configuration for entities of the climate domain. 14 | */ 15 | class ClimateView extends AbstractView { 16 | /**The domain of the entities that the view is representing. */ 17 | static readonly domain: SupportedDomains = 'climate' as const; 18 | 19 | /** Returns the default configuration object for the view. */ 20 | static getDefaultConfig(): ViewConfig { 21 | return { 22 | title: localize('climate.climates'), 23 | path: 'climates', 24 | icon: 'mdi:thermostat', 25 | subview: false, 26 | headerCardConfiguration: { 27 | showControls: false, 28 | }, 29 | }; 30 | } 31 | 32 | /** Returns the default configuration of the view's Header card. */ 33 | static getViewHeaderCardConfig(): CustomHeaderCardConfig { 34 | return { 35 | title: localize('climate.all_climates'), 36 | subtitle: 37 | `${Registry.getCountTemplate(ClimateView.domain, 'ne', 'off')} ${localize('climate.climates')} ` + 38 | localize('generic.busy'), 39 | }; 40 | } 41 | 42 | /** 43 | * Class constructor. 44 | * 45 | * @param {ViewConfig} [customConfiguration] Custom view configuration. 46 | */ 47 | constructor(customConfiguration?: ViewConfig) { 48 | super(); 49 | 50 | this.initializeViewConfig( 51 | ClimateView.getDefaultConfig(), 52 | customConfiguration, 53 | ClimateView.getViewHeaderCardConfig(), 54 | ); 55 | } 56 | } 57 | 58 | export default ClimateView; 59 | -------------------------------------------------------------------------------- /src/views/CoverView.ts: -------------------------------------------------------------------------------- 1 | // noinspection JSUnusedGlobalSymbols Class is dynamically imported. 2 | 3 | import { Registry } from '../Registry'; 4 | import { CustomHeaderCardConfig } from '../types/strategy/strategy-cards'; 5 | import { SupportedDomains } from '../types/strategy/strategy-generics'; 6 | import { ViewConfig } from '../types/strategy/strategy-views'; 7 | import { localize } from '../utilities/localize'; 8 | import AbstractView from './AbstractView'; 9 | 10 | /** 11 | * Cover View Class. 12 | * 13 | * Used to create a view configuration for entities of the cover domain. 14 | */ 15 | class CoverView extends AbstractView { 16 | /** The domain of the entities that the view is representing. */ 17 | static readonly domain: SupportedDomains = 'cover' as const; 18 | 19 | /** Returns the default configuration object for the view. */ 20 | static getDefaultConfig(): ViewConfig { 21 | return { 22 | title: localize('cover.covers'), 23 | path: 'covers', 24 | icon: 'mdi:window-open', 25 | subview: false, 26 | headerCardConfiguration: { 27 | iconOn: 'mdi:arrow-up', 28 | iconOff: 'mdi:arrow-down', 29 | onService: 'cover.open_cover', 30 | offService: 'cover.close_cover', 31 | }, 32 | }; 33 | } 34 | 35 | /** Returns the default configuration of the view's Header card. */ 36 | static getViewHeaderCardConfig(): CustomHeaderCardConfig { 37 | return { 38 | title: localize('cover.all_covers'), 39 | subtitle: 40 | `${Registry.getCountTemplate(CoverView.domain, 'search', '(open|opening|closing)')} ` + 41 | `${localize('cover.covers')} ` + 42 | `${localize('generic.unclosed')}`, 43 | }; 44 | } 45 | 46 | /** 47 | * Class constructor. 48 | * 49 | * @param {ViewConfig} [customConfiguration] Custom view configuration. 50 | */ 51 | constructor(customConfiguration?: ViewConfig) { 52 | super(); 53 | 54 | this.initializeViewConfig(CoverView.getDefaultConfig(), customConfiguration, CoverView.getViewHeaderCardConfig()); 55 | } 56 | } 57 | 58 | export default CoverView; 59 | -------------------------------------------------------------------------------- /src/views/FanView.ts: -------------------------------------------------------------------------------- 1 | // noinspection JSUnusedGlobalSymbols Class is dynamically imported. 2 | 3 | import { Registry } from '../Registry'; 4 | import { CustomHeaderCardConfig } from '../types/strategy/strategy-cards'; 5 | import { SupportedDomains } from '../types/strategy/strategy-generics'; 6 | import { ViewConfig } from '../types/strategy/strategy-views'; 7 | import { localize } from '../utilities/localize'; 8 | import AbstractView from './AbstractView'; 9 | 10 | /** 11 | * Fan View Class. 12 | * 13 | * Used to create a view configuration for entities of the fan domain. 14 | */ 15 | class FanView extends AbstractView { 16 | /** The domain of the entities that the view is representing. */ 17 | static readonly domain: SupportedDomains = 'fan' as const; 18 | 19 | /** Returns the default configuration object for the view. */ 20 | static getDefaultConfig(): ViewConfig { 21 | return { 22 | title: localize('fan.fans'), 23 | path: 'fans', 24 | icon: 'mdi:fan', 25 | subview: false, 26 | headerCardConfiguration: { 27 | iconOn: 'mdi:fan', 28 | iconOff: 'mdi:fan-off', 29 | onService: 'fan.turn_on', 30 | offService: 'fan.turn_off', 31 | }, 32 | }; 33 | } 34 | 35 | /** Returns the default configuration of the view's Header card. */ 36 | static getViewHeaderCardConfig(): CustomHeaderCardConfig { 37 | return { 38 | title: localize('fan.all_fans'), 39 | subtitle: 40 | `${Registry.getCountTemplate(FanView.domain, 'eq', 'on')} ${localize('fan.fans')} ` + localize('generic.on'), 41 | }; 42 | } 43 | 44 | /** 45 | * Class constructor. 46 | * 47 | * @param {ViewConfig} [customConfiguration] Custom view configuration. 48 | */ 49 | constructor(customConfiguration?: ViewConfig) { 50 | super(); 51 | 52 | this.initializeViewConfig(FanView.getDefaultConfig(), customConfiguration, FanView.getViewHeaderCardConfig()); 53 | } 54 | } 55 | 56 | export default FanView; 57 | -------------------------------------------------------------------------------- /src/views/LightView.ts: -------------------------------------------------------------------------------- 1 | // noinspection JSUnusedGlobalSymbols Class is dynamically imported. 2 | 3 | import { Registry } from '../Registry'; 4 | import { CustomHeaderCardConfig } from '../types/strategy/strategy-cards'; 5 | import { ViewConfig } from '../types/strategy/strategy-views'; 6 | import { localize } from '../utilities/localize'; 7 | import AbstractView from './AbstractView'; 8 | 9 | /** 10 | * Light View Class. 11 | * 12 | * Used to create a view for entities of the light domain. 13 | * 14 | * @class LightView 15 | * @extends AbstractView 16 | */ 17 | class LightView extends AbstractView { 18 | /** The domain of the entities that the view is representing. */ 19 | static readonly domain = 'light' as const; 20 | 21 | /** Returns the default configuration object for the view. */ 22 | static getDefaultConfig(): ViewConfig { 23 | return { 24 | title: localize('light.lights'), 25 | path: 'lights', 26 | icon: 'mdi:lightbulb-group', 27 | subview: false, 28 | headerCardConfiguration: { 29 | iconOn: 'mdi:lightbulb', 30 | iconOff: 'mdi:lightbulb-off', 31 | onService: 'light.turn_on', 32 | offService: 'light.turn_off', 33 | }, 34 | }; 35 | } 36 | 37 | /** Returns the default configuration of the view's Header card. */ 38 | static getViewHeaderCardConfig(): CustomHeaderCardConfig { 39 | return { 40 | title: localize('light.all_lights'), 41 | subtitle: 42 | `${Registry.getCountTemplate(LightView.domain, 'eq', 'on')} ${localize('light.lights')} ` + 43 | localize('generic.on'), 44 | }; 45 | } 46 | 47 | constructor(customConfiguration?: ViewConfig) { 48 | super(); 49 | 50 | this.initializeViewConfig(LightView.getDefaultConfig(), customConfiguration, LightView.getViewHeaderCardConfig()); 51 | } 52 | } 53 | 54 | export default LightView; 55 | -------------------------------------------------------------------------------- /src/views/LockView.ts: -------------------------------------------------------------------------------- 1 | // noinspection JSUnusedGlobalSymbols Class is dynamically imported. 2 | 3 | import { Registry } from '../Registry'; 4 | import { CustomHeaderCardConfig } from '../types/strategy/strategy-cards'; 5 | import { ViewConfig } from '../types/strategy/strategy-views'; 6 | import { localize } from '../utilities/localize'; 7 | import AbstractView from './AbstractView'; 8 | 9 | /** 10 | * Lock View Class. 11 | * 12 | * Used to create a view configuration for entities of the lock domain. 13 | */ 14 | class LockView extends AbstractView { 15 | /** The domain of the entities that the view is representing. */ 16 | static readonly domain = 'lock' as const; 17 | 18 | /** Returns the default configuration object for the view. */ 19 | static getDefaultConfig(): ViewConfig { 20 | return { 21 | title: localize('locks.locks'), 22 | path: 'locks', 23 | icon: 'mdi:lock-open', 24 | subview: false, 25 | headerCardConfiguration: { 26 | iconOn: 'mdi:lock-open', 27 | iconOff: 'mdi:lock', 28 | onService: 'lock.lock', 29 | offService: 'lock.unlock', 30 | }, 31 | }; 32 | } 33 | 34 | /** Returns the default configuration of the view's Header card. */ 35 | static getViewHeaderCardConfig(): CustomHeaderCardConfig { 36 | return { 37 | title: localize('lock.all_locks'), 38 | subtitle: 39 | `${Registry.getCountTemplate(LockView.domain, 'ne', 'locked')} ${localize('lock.locks')} ` + 40 | localize('lock.unlocked'), 41 | }; 42 | } 43 | 44 | /** 45 | * Class constructor. 46 | * 47 | * @param {ViewConfig} [customConfiguration] Custom view configuration. 48 | */ 49 | constructor(customConfiguration?: ViewConfig) { 50 | super(); 51 | 52 | this.initializeViewConfig(LockView.getDefaultConfig(), customConfiguration, LockView.getViewHeaderCardConfig()); 53 | } 54 | } 55 | 56 | export default LockView; 57 | -------------------------------------------------------------------------------- /src/views/SceneView.ts: -------------------------------------------------------------------------------- 1 | // noinspection JSUnusedGlobalSymbols Class is dynamically imported. 2 | 3 | import { CustomHeaderCardConfig } from '../types/strategy/strategy-cards'; 4 | import { ViewConfig } from '../types/strategy/strategy-views'; 5 | import { localize } from '../utilities/localize'; 6 | import AbstractView from './AbstractView'; 7 | 8 | /** 9 | * Scene View Class. 10 | * 11 | * sed to create a view configuration for entities of the scene domain. 12 | */ 13 | class SceneView extends AbstractView { 14 | /** The domain of the entities that the view is representing. */ 15 | static readonly domain = 'scene' as const; 16 | 17 | /** Returns the default configuration object for the view. */ 18 | static getDefaultConfig(): ViewConfig { 19 | return { 20 | title: localize('scene.scenes'), 21 | path: 'scenes', 22 | icon: 'mdi:palette', 23 | subview: false, 24 | headerCardConfiguration: { 25 | showControls: false, 26 | }, 27 | }; 28 | } 29 | 30 | /** Returns the default configuration of the view's Header card. */ 31 | static getViewHeaderCardConfig(): CustomHeaderCardConfig { 32 | return {}; 33 | } 34 | 35 | /** 36 | * Class constructor. 37 | * 38 | * @param {ViewConfig} [customConfiguration] Custom view configuration. 39 | */ 40 | constructor(customConfiguration?: ViewConfig) { 41 | super(); 42 | 43 | this.initializeViewConfig(SceneView.getDefaultConfig(), customConfiguration, SceneView.getViewHeaderCardConfig()); 44 | } 45 | } 46 | 47 | export default SceneView; 48 | -------------------------------------------------------------------------------- /src/views/SwitchView.ts: -------------------------------------------------------------------------------- 1 | // noinspection JSUnusedGlobalSymbols Class is dynamically imported. 2 | 3 | import { Registry } from '../Registry'; 4 | import { CustomHeaderCardConfig } from '../types/strategy/strategy-cards'; 5 | import { ViewConfig } from '../types/strategy/strategy-views'; 6 | import { localize } from '../utilities/localize'; 7 | import AbstractView from './AbstractView'; 8 | 9 | /** 10 | * Switch View Class. 11 | * 12 | * Used to create a view configuration for entities of the switch domain. 13 | */ 14 | class SwitchView extends AbstractView { 15 | /** The domain of the entities that the view is representing. */ 16 | static readonly domain = 'switch' as const; 17 | 18 | /** Returns the default configuration object for the view. */ 19 | static getDefaultConfig(): ViewConfig { 20 | return { 21 | title: localize('switch.switches'), 22 | path: 'switches', 23 | icon: 'mdi:dip-switch', 24 | subview: false, 25 | headerCardConfiguration: { 26 | iconOn: 'mdi:power-plug', 27 | iconOff: 'mdi:power-plug-off', 28 | onService: 'switch.turn_on', 29 | offService: 'switch.turn_off', 30 | }, 31 | }; 32 | } 33 | 34 | /** Returns the default configuration of the view's Header card. */ 35 | static getViewHeaderCardConfig(): CustomHeaderCardConfig { 36 | return { 37 | title: localize('switch.all_switches'), 38 | subtitle: 39 | `${Registry.getCountTemplate(SwitchView.domain, 'eq', 'on')} ${localize('switch.switches')} ` + 40 | localize('generic.on'), 41 | }; 42 | } 43 | 44 | /** 45 | * Class constructor. 46 | * 47 | * @param {ViewConfig} [customConfiguration] Custom view configuration. 48 | */ 49 | constructor(customConfiguration?: ViewConfig) { 50 | super(); 51 | 52 | this.initializeViewConfig(SwitchView.getDefaultConfig(), customConfiguration, SwitchView.getViewHeaderCardConfig()); 53 | } 54 | } 55 | 56 | export default SwitchView; 57 | -------------------------------------------------------------------------------- /src/views/VacuumView.ts: -------------------------------------------------------------------------------- 1 | // noinspection JSUnusedGlobalSymbols Class is dynamically imported. 2 | 3 | import { Registry } from '../Registry'; 4 | import { CustomHeaderCardConfig } from '../types/strategy/strategy-cards'; 5 | import { ViewConfig } from '../types/strategy/strategy-views'; 6 | import { localize } from '../utilities/localize'; 7 | import AbstractView from './AbstractView'; 8 | 9 | /** 10 | * Vacuum View Class. 11 | * 12 | * Used to create a view configuration for entities of the vacuum domain. 13 | */ 14 | class VacuumView extends AbstractView { 15 | /** The domain of the entities that the view is representing. */ 16 | static readonly domain = 'vacuum' as const; 17 | 18 | /** Returns the default configuration object for the view. */ 19 | static getDefaultConfig(): ViewConfig { 20 | return { 21 | title: localize('vacuum.vacuums'), 22 | path: 'vacuums', 23 | icon: 'mdi:robot-vacuum', 24 | subview: false, 25 | headerCardConfiguration: { 26 | iconOn: 'mdi:robot-vacuum', 27 | iconOff: 'mdi:robot-vacuum-off', 28 | onService: 'vacuum.start', 29 | offService: 'vacuum.stop', 30 | }, 31 | }; 32 | } 33 | 34 | /** Returns the default configuration of the view's Header card. */ 35 | static getViewHeaderCardConfig(): CustomHeaderCardConfig { 36 | return { 37 | title: localize('vacuum.all_vacuums'), 38 | subtitle: 39 | Registry.getCountTemplate(VacuumView.domain, 'in', '[cleaning, returning]') + 40 | ` ${localize('vacuum.vacuums')} ${localize('generic.busy')}`, 41 | }; 42 | } 43 | 44 | /** 45 | * Class constructor. 46 | * 47 | * @param {ViewConfig} [customConfiguration] Custom view configuration. 48 | */ 49 | constructor(customConfiguration?: ViewConfig) { 50 | super(); 51 | 52 | this.initializeViewConfig(VacuumView.getDefaultConfig(), customConfiguration, VacuumView.getViewHeaderCardConfig()); 53 | } 54 | } 55 | 56 | export default VacuumView; 57 | -------------------------------------------------------------------------------- /src/views/ValveView.ts: -------------------------------------------------------------------------------- 1 | // noinspection JSUnusedGlobalSymbols Class is dynamically imported. 2 | 3 | import { Registry } from '../Registry'; 4 | import { CustomHeaderCardConfig } from '../types/strategy/strategy-cards'; 5 | import { ViewConfig } from '../types/strategy/strategy-views'; 6 | import { localize } from '../utilities/localize'; 7 | import AbstractView from './AbstractView'; 8 | 9 | /** 10 | * Valve View Class. 11 | * 12 | * Used to create a view configuration for entities of the valve domain. 13 | */ 14 | class ValveView extends AbstractView { 15 | /** The domain of the entities that the view is representing. */ 16 | static readonly domain = 'valve' as const; 17 | 18 | /** 19 | * Class constructor. 20 | * 21 | * @param {ViewConfig} [customConfiguration] Custom view configuration. 22 | */ 23 | constructor(customConfiguration?: ViewConfig) { 24 | super(); 25 | 26 | this.initializeViewConfig(ValveView.getDefaultConfig(), customConfiguration, ValveView.getViewHeaderCardConfig()); 27 | } 28 | 29 | /** Returns the default configuration object for the view. */ 30 | static getDefaultConfig(): ViewConfig { 31 | return { 32 | title: localize('valve.valves'), 33 | path: 'valves', 34 | icon: 'mdi:valve', 35 | subview: false, 36 | headerCardConfiguration: { 37 | iconOn: 'mdi:valve-open', 38 | iconOff: 'mdi:valve-closed', 39 | onService: 'valve.open_valve', 40 | offService: 'valve.close_valve', 41 | }, 42 | }; 43 | } 44 | 45 | /** Returns the default configuration of the view's Header card. */ 46 | static getViewHeaderCardConfig(): CustomHeaderCardConfig { 47 | return { 48 | title: localize('valve.all_valves'), 49 | subtitle: 50 | Registry.getCountTemplate(ValveView.domain, 'in', '[closed]') + 51 | ` ${localize('valve.valves')} ${localize('valve.unclosed')}`, 52 | }; 53 | } 54 | } 55 | 56 | export default ValveView; 57 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "include": ["src/**/*", "webpack.config.ts", "webpack.dev.config.ts"], 3 | "compilerOptions": { 4 | // 1. Language and Environment 5 | "target": "ES2020", 6 | "jsx": "react", 7 | // 2. Module System 8 | "module": "ES2020", 9 | "moduleResolution": "Node", 10 | "outDir": "./dist", 11 | "resolveJsonModule": true, 12 | // 3. JavaScript and Source Maps 13 | "allowJs": true, 14 | "sourceMap": true, 15 | // 4. Interop and Imports 16 | "allowSyntheticDefaultImports": true, 17 | "esModuleInterop": true, 18 | // 5. Type Checking and Strictness 19 | "strict": true, 20 | "noImplicitAny": true, 21 | "noImplicitThis": true, 22 | "noImplicitReturns": true, 23 | "strictNullChecks": true, 24 | // 6. Project Structure and Build Integrity 25 | "forceConsistentCasingInFileNames": true, 26 | "skipLibCheck": true 27 | }, 28 | "ts-node": { 29 | "compilerOptions": { 30 | "module": "CommonJS" 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /webpack.config.ts: -------------------------------------------------------------------------------- 1 | // noinspection JSUnusedGlobalSymbols 2 | 3 | import path from 'path'; 4 | import webpack from 'webpack'; 5 | 6 | const config: webpack.Configuration = { 7 | mode: 'production', 8 | entry: './src/mushroom-strategy.ts', 9 | output: { 10 | clean: true, 11 | filename: 'mushroom-strategy.js', 12 | path: path.resolve(__dirname, 'dist'), 13 | }, 14 | resolve: { 15 | extensions: ['.ts', '.js'], 16 | }, 17 | module: { 18 | rules: [ 19 | { 20 | test: /\.ts$/, 21 | use: 'ts-loader', 22 | exclude: /node_modules/, 23 | }, 24 | ], 25 | }, 26 | plugins: [ 27 | new webpack.optimize.LimitChunkCountPlugin({ 28 | maxChunks: 1, 29 | }), 30 | ], 31 | }; 32 | 33 | export default config; 34 | -------------------------------------------------------------------------------- /webpack.dev.config.ts: -------------------------------------------------------------------------------- 1 | // noinspection JSUnusedGlobalSymbols 2 | 3 | import path from 'path'; 4 | import webpack from 'webpack'; 5 | 6 | const config: webpack.Configuration = { 7 | mode: 'development', 8 | entry: './src/mushroom-strategy.ts', 9 | output: { 10 | filename: 'mushroom-strategy.js', 11 | path: path.resolve(__dirname, 'dist'), 12 | }, 13 | devtool: 'source-map', 14 | resolve: { 15 | extensions: ['.ts', '.js'], 16 | }, 17 | module: { 18 | rules: [ 19 | { 20 | test: /\.ts$/, 21 | use: 'ts-loader', 22 | exclude: /node_modules/, 23 | }, 24 | ], 25 | }, 26 | plugins: [ 27 | new webpack.optimize.LimitChunkCountPlugin({ 28 | maxChunks: 1, 29 | }), 30 | ], 31 | }; 32 | 33 | export default config; 34 | --------------------------------------------------------------------------------