├── .commit-template
├── .devcontainer
├── configuration.yaml
├── ui-lovelace.yaml
└── devcontainer.json
├── .github
├── FUNDING.yml
├── workflows
│ ├── build.yml
│ ├── release.yml
│ └── eslint.yml
└── ISSUE_TEMPLATE
│ ├── feature_request.md
│ └── bug_report.md
├── .eslintignore
├── hacs.json
├── .prettierrc.js
├── .vscode
└── extensions.json
├── commitlint.config.js
├── src
├── types.ts
└── kb-steam-card.ts
├── tsconfig.json
├── .eslintrc.js
├── rollup.config.js
├── LICENSE
├── .gitignore
├── info.md
├── CODE_OF_CONDUCT.md
├── package.json
├── README.md
└── dist
└── kb-steam-card.js
/.commit-template:
--------------------------------------------------------------------------------
1 | type(scope): subject
2 |
3 | description
--------------------------------------------------------------------------------
/.devcontainer/configuration.yaml:
--------------------------------------------------------------------------------
1 | default_config:
2 | lovelace:
3 | mode: yaml
4 | demo:
--------------------------------------------------------------------------------
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | custom:
2 | - https://paypal.me/thatkookooguy?locale.x=en_US
3 |
--------------------------------------------------------------------------------
/.eslintignore:
--------------------------------------------------------------------------------
1 | coverage
2 | test-results
3 | node_modules
4 | *.config.js
5 | examples
6 | .eslintrc.js
7 | dist/*
--------------------------------------------------------------------------------
/hacs.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Steam Card",
3 | "render_readme": true,
4 | "filename": "kb-steam-card.js"
5 | }
6 |
--------------------------------------------------------------------------------
/.prettierrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | semi: true,
3 | trailingComma: 'all',
4 | singleQuote: true,
5 | printWidth: 120,
6 | tabWidth: 2,
7 | };
--------------------------------------------------------------------------------
/.devcontainer/ui-lovelace.yaml:
--------------------------------------------------------------------------------
1 | resources:
2 | - url: http://127.0.0.1:5000/boilerplate-card.js
3 | type: module
4 | views:
5 | - cards:
6 | - type: custom:boilerplate-card
7 | name: Boilerplate Card Development
8 | entity: sun.sun
9 | test_gui: true
10 |
--------------------------------------------------------------------------------
/.vscode/extensions.json:
--------------------------------------------------------------------------------
1 | {
2 | "recommendations": [
3 | "github.vscode-pull-request-github",
4 | "eamodio.gitlens",
5 | "dbaeumer.vscode-eslint",
6 | "esbenp.prettier-vscode",
7 | "bierner.lit-html",
8 | "runem.lit-plugin",
9 | "auchenberg.vscode-browser-preview",
10 | "davidanson.vscode-markdownlint",
11 | "redhat.vscode-yaml"
12 | ]
13 | }
14 |
--------------------------------------------------------------------------------
/.github/workflows/build.yml:
--------------------------------------------------------------------------------
1 | name: "Build"
2 |
3 | on:
4 | push:
5 | branches:
6 | - master
7 | - next
8 | pull_request:
9 | branches:
10 | - master
11 | - next
12 |
13 | jobs:
14 | build:
15 | name: Test build
16 | runs-on: ubuntu-latest
17 | steps:
18 | - uses: actions/checkout@v1
19 | - name: Build
20 | run: |
21 | npm install
22 | npm run build
--------------------------------------------------------------------------------
/commitlint.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | extends: [ '@commitlint/config-angular' ],
3 | rules: {
4 | 'type-enum': [
5 | 2,
6 | 'always', [
7 | 'build',
8 | 'chore',
9 | 'ci',
10 | 'docs',
11 | 'feat',
12 | 'fix',
13 | 'perf',
14 | 'refactor',
15 | 'revert',
16 | 'style',
17 | 'test'
18 | ]
19 | ]
20 | }
21 | };
--------------------------------------------------------------------------------
/src/types.ts:
--------------------------------------------------------------------------------
1 | import { ActionConfig, LovelaceCardConfig } from 'custom-card-helpers';
2 |
3 | // TODO Add your configuration elements here for type-checking
4 | export interface BoilerplateCardConfig extends LovelaceCardConfig {
5 | type: string;
6 | name?: string;
7 | show_warning?: boolean;
8 | show_error?: boolean;
9 | test_gui?: boolean;
10 | entity?: string;
11 | tap_action?: ActionConfig;
12 | hold_action?: ActionConfig;
13 | double_tap_action?: ActionConfig;
14 | }
15 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "es2017",
4 | "module": "esnext",
5 | "moduleResolution": "node",
6 | "lib": ["es2017", "dom", "dom.iterable"],
7 | "noEmit": true,
8 | "noUnusedParameters": true,
9 | "noImplicitReturns": true,
10 | "noFallthroughCasesInSwitch": true,
11 | "strict": true,
12 | "noImplicitAny": false,
13 | "skipLibCheck": true,
14 | "resolveJsonModule": true,
15 | "experimentalDecorators": true
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature_request.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Feature request
3 | about: Suggest an idea for this project
4 | title: ''
5 | labels: feature request
6 | assignees: ''
7 | ---
8 |
9 | **Is your feature request related to a problem? Please describe.**
10 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
11 |
12 | **Describe the solution you'd like**
13 | A clear and concise description of what you want to happen.
14 |
15 | **Describe alternatives you've considered**
16 | A clear and concise description of any alternative solutions or features you've considered.
17 |
18 | **Additional context**
19 | Add any other context or screenshots about the feature request here.
20 |
--------------------------------------------------------------------------------
/.github/workflows/release.yml:
--------------------------------------------------------------------------------
1 | name: Release
2 | on:
3 | push:
4 | branches:
5 | - master
6 | - next
7 | jobs:
8 | release:
9 | name: Release
10 | runs-on: ubuntu-18.04
11 | steps:
12 | - name: Checkout
13 | uses: actions/checkout@v2
14 | with:
15 | fetch-depth: 0
16 | - name: Setup Node.js
17 | uses: actions/setup-node@v1
18 | with:
19 | node-version: 12
20 | - name: Install dependencies
21 | run: |
22 | npm ci
23 | npm install
24 | npm run build
25 | - name: Release
26 | env:
27 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
28 | NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
29 | run: npm run semantic-release
--------------------------------------------------------------------------------
/.github/workflows/eslint.yml:
--------------------------------------------------------------------------------
1 | name: Lint
2 |
3 | on:
4 | push:
5 | branches:
6 | - master
7 | pull_request:
8 | branches:
9 | - master
10 |
11 | jobs:
12 | run-linters:
13 | name: Run linters
14 | runs-on: ubuntu-latest
15 |
16 | steps:
17 | - name: Check out Git repository
18 | uses: actions/checkout@v2
19 |
20 | - name: Set up Node.js
21 | uses: actions/setup-node@v1
22 | with:
23 | node-version: 12
24 |
25 | # ESLint and Prettier must be in `package.json`
26 | - name: Install Node.js dependencies
27 | run: npm install
28 |
29 | - name: Run linters
30 | uses: wearerequired/lint-action@v1
31 | with:
32 | github_token: ${{ secrets.github_token }}
33 | # Enable linters
34 | eslint: true
35 | eslint_dir: src/
--------------------------------------------------------------------------------
/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | parser: '@typescript-eslint/parser', // Specifies the ESLint parser
3 | extends: [
4 | 'plugin:@typescript-eslint/recommended', // Uses the recommended rules from the @typescript-eslint/eslint-plugin
5 | 'prettier/@typescript-eslint', // Uses eslint-config-prettier to disable ESLint rules from @typescript-eslint/eslint-plugin that would conflict with prettier
6 | 'plugin:prettier/recommended', // Enables eslint-plugin-prettier and displays prettier errors as ESLint errors. Make sure this is always the last configuration in the extends array.
7 | ],
8 | parserOptions: {
9 | ecmaVersion: 2018, // Allows for the parsing of modern ECMAScript features
10 | sourceType: 'module', // Allows for the use of imports
11 | experimentalDecorators: true
12 | },
13 | rules: {
14 | '@typescript-eslint/camelcase': 0,
15 | '@typescript-eslint/no-unused-vars': 0
16 | }
17 | };
18 |
--------------------------------------------------------------------------------
/rollup.config.js:
--------------------------------------------------------------------------------
1 | import typescript from 'rollup-plugin-typescript2';
2 | import commonjs from 'rollup-plugin-commonjs';
3 | import nodeResolve from 'rollup-plugin-node-resolve';
4 | import babel from 'rollup-plugin-babel';
5 | import { terser } from 'rollup-plugin-terser';
6 | import serve from 'rollup-plugin-serve';
7 | import json from '@rollup/plugin-json';
8 |
9 | const dev = process.env.ROLLUP_WATCH;
10 |
11 | const serveopts = {
12 | contentBase: ['./dist'],
13 | host: '0.0.0.0',
14 | port: 5000,
15 | allowCrossOrigin: true,
16 | headers: {
17 | 'Access-Control-Allow-Origin': '*',
18 | },
19 | };
20 |
21 | const plugins = [
22 | nodeResolve({}),
23 | commonjs(),
24 | typescript(),
25 | json(),
26 | babel({
27 | exclude: 'node_modules/**',
28 | }),
29 | dev && serve(serveopts),
30 | !dev && terser(),
31 | ];
32 |
33 | export default [
34 | {
35 | input: 'src/kb-steam-card.ts',
36 | output: {
37 | dir: 'dist',
38 | format: 'es',
39 | },
40 | plugins: [...plugins],
41 | },
42 | ];
43 |
--------------------------------------------------------------------------------
/.devcontainer/devcontainer.json:
--------------------------------------------------------------------------------
1 | // See https://aka.ms/vscode-remote/devcontainer.json for format details.
2 | {
3 | "name": "Boilerplate Card Development",
4 | "image": "ludeeus/container:monster",
5 | "context": "..",
6 | "appPort": ["5000:5000", "9123:8123"],
7 | "postCreateCommand": "npm install",
8 | "runArgs": [
9 | "-v",
10 | "${env:HOME}${env:USERPROFILE}/.ssh:/tmp/.ssh" // This is added so you can push from inside the container
11 | ],
12 | "extensions": [
13 | "github.vscode-pull-request-github",
14 | "eamodio.gitlens",
15 | "dbaeumer.vscode-eslint",
16 | "esbenp.prettier-vscode",
17 | "bierner.lit-html",
18 | "runem.lit-plugin",
19 | "auchenberg.vscode-browser-preview",
20 | "davidanson.vscode-markdownlint",
21 | "redhat.vscode-yaml"
22 | ],
23 | "settings": {
24 | "files.eol": "\n",
25 | "editor.tabSize": 4,
26 | "terminal.integrated.shell.linux": "/bin/bash",
27 | "editor.formatOnPaste": false,
28 | "editor.formatOnSave": true,
29 | "editor.formatOnType": true,
30 | "files.trimTrailingWhitespace": true
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2020 thatkookooguy
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug report
3 | about: Create a report to help us improve
4 | title: ''
5 | labels: bug
6 | assignees: ''
7 | ---
8 |
9 |
14 |
15 | **Checklist:**
16 |
17 | - [ ] I updated to the latest version available
18 | - [ ] I cleared the cache of my browser
19 |
20 | **Release with the issue:**
21 |
22 | **Last working release (if known):**
23 |
24 | **Browser and Operating System:**
25 |
26 |
29 |
30 | **Description of problem:**
31 |
32 |
35 |
36 | **Javascript errors shown in the web inspector (if applicable):**
37 |
38 | ```
39 |
40 | ```
41 |
42 | **Additional information:**
43 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # kibibit
2 | test-results
3 |
4 | # Logs
5 | logs
6 | *.log
7 | npm-debug.log*
8 | yarn-debug.log*
9 | yarn-error.log*
10 | lerna-debug.log*
11 |
12 | # Diagnostic reports (https://nodejs.org/api/report.html)
13 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
14 |
15 | # Runtime data
16 | pids
17 | *.pid
18 | *.seed
19 | *.pid.lock
20 |
21 | # Directory for instrumented libs generated by jscoverage/JSCover
22 | lib-cov
23 |
24 | # Coverage directory used by tools like istanbul
25 | coverage
26 | *.lcov
27 |
28 | # nyc test coverage
29 | .nyc_output
30 |
31 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
32 | .grunt
33 |
34 | # Bower dependency directory (https://bower.io/)
35 | bower_components
36 |
37 | # node-waf configuration
38 | .lock-wscript
39 |
40 | # Compiled binary addons (https://nodejs.org/api/addons.html)
41 | build/Release
42 |
43 | # Dependency directories
44 | node_modules/
45 | jspm_packages/
46 |
47 | # Snowpack dependency directory (https://snowpack.dev/)
48 | web_modules/
49 |
50 | # TypeScript cache
51 | *.tsbuildinfo
52 |
53 | # Optional npm cache directory
54 | .npm
55 |
56 | # Optional eslint cache
57 | .eslintcache
58 |
59 | # Microbundle cache
60 | .rpt2_cache/
61 | .rts2_cache_cjs/
62 | .rts2_cache_es/
63 | .rts2_cache_umd/
64 |
65 | # Optional REPL history
66 | .node_repl_history
67 |
68 | # Output of 'npm pack'
69 | *.tgz
70 |
71 | # Yarn Integrity file
72 | .yarn-integrity
73 |
74 | # dotenv environment variables file
75 | .env
76 | .env.test
77 |
78 | # parcel-bundler cache (https://parceljs.org/)
79 | .cache
80 | .parcel-cache
81 |
82 | # Next.js build output
83 | .next
84 | out
85 |
86 | # Nuxt.js build / generate output
87 | .nuxt
88 | # dist
89 |
90 | # Gatsby files
91 | .cache/
92 | # Comment in the public line in if your project uses Gatsby and not Next.js
93 | # https://nextjs.org/blog/next-9-1#public-directory-support
94 | # public
95 |
96 | # vuepress build output
97 | .vuepress/dist
98 |
99 | # Serverless directories
100 | .serverless/
101 |
102 | # FuseBox cache
103 | .fusebox/
104 |
105 | # DynamoDB Local files
106 | .dynamodb/
107 |
108 | # TernJS port file
109 | .tern-port
110 |
111 | # Stores VSCode versions used for testing VSCode extensions
112 | .vscode-test
113 |
114 | # yarn v2
115 | .yarn/cache
116 | .yarn/unplugged
117 | .yarn/build-state.yml
118 | .yarn/install-state.gz
119 | .pnp.*
--------------------------------------------------------------------------------
/info.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | @kibibit/hass-kibibit-theme
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 | A Home Assistant card for Steam integrations
14 |
15 |
16 |
17 | ([Theme](https://github.com/kibibit/hass-kibibit-theme) used in screenshots)
18 |
19 | ## Screenshots
20 |
21 | ### away \ offline state
22 |
23 | 
24 |
25 | ### online state
26 |
27 | 
28 |
29 | ### while playing a game
30 |
31 | 
32 |
33 | ## Installation
34 |
35 | ### Prerequisites
36 |
37 | You need at least one [steam integration]() to use with this card.
38 |
39 | ### HACS (recommended)
40 |
41 | 1. Go to the Community Store.
42 | 2. Search for `steam card`.
43 | 3. Press `Install`.
44 |
45 | ### Manual Installation
46 |
47 | ```yaml
48 | resources:
49 | url: ''
50 | type: module
51 | ```
52 |
53 | ## Usage
54 |
55 | for a single user card, use `entity`:
56 |
57 | ```yaml
58 | entity: sensor.steam_
59 | type: 'custom:kb-steam-card'
60 | ```
61 |
62 | you can change the username using the following:
63 |
64 | ```yaml
65 | entity: sensor.steam_
66 | friendly_name: Myself
67 | type: 'custom:kb-steam-card'
68 | ```
69 |
70 | for multiple users, use the `entities` attribute:
71 | 
72 |
73 | ```yaml
74 | entities:
75 | - sensor.steam_
76 | - sensor.steam_
77 | - sensor.steam_
78 | type: 'custom:kb-steam-card'
79 | ```
80 |
81 | you can also show the game header image as background with `game_background: true`:
82 | 
83 |
84 | ```yaml
85 | entities:
86 | - sensor.steam_
87 | - sensor.steam_
88 | - sensor.steam_
89 | friendly_name: hello
90 | game_background: true
91 | type: 'custom:kb-steam-card'
92 | ```
93 |
94 | ## Stay in touch
95 |
96 | - Author - [Neil Kalman](https://github.com/thatkookooguy)
97 | - Website - [https://github.com/kibibit](https://github.com/kibibit)
98 | - StackOverflow - [thatkookooguy](https://stackoverflow.com/users/1788884/thatkookooguy)
99 | - Twitter - [@thatkookooguy](https://twitter.com/thatkookooguy)
100 | - Twitter - [@kibibit_opensrc](https://twitter.com/kibibit_opensrc)
101 |
102 | ## Support
103 |
104 | Hey dude! Help me out for a couple of :beers: or a :coffee: by clicking on the sponsering link!
105 |
--------------------------------------------------------------------------------
/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 | # Contributor Covenant Code of Conduct
2 |
3 | ## Our Pledge
4 |
5 | In the interest of fostering an open and welcoming environment, we as
6 | contributors and maintainers pledge to making participation in our project and
7 | our community a harassment-free experience for everyone, regardless of age, body
8 | size, disability, ethnicity, sex characteristics, gender identity and expression,
9 | level of experience, education, socio-economic status, nationality, personal
10 | appearance, race, religion, or sexual identity and orientation.
11 |
12 | ## Our Standards
13 |
14 | Examples of behavior that contributes to creating a positive environment
15 | include:
16 |
17 | * Using welcoming and inclusive language
18 | * Being respectful of differing viewpoints and experiences
19 | * Gracefully accepting constructive criticism
20 | * Focusing on what is best for the community
21 | * Showing empathy towards other community members
22 |
23 | Examples of unacceptable behavior by participants include:
24 |
25 | * The use of sexualized language or imagery and unwelcome sexual attention or
26 | advances
27 | * Trolling, insulting/derogatory comments, and personal or political attacks
28 | * Public or private harassment
29 | * Publishing others' private information, such as a physical or electronic
30 | address, without explicit permission
31 | * Other conduct which could reasonably be considered inappropriate in a
32 | professional setting
33 |
34 | ## Our Responsibilities
35 |
36 | Project maintainers are responsible for clarifying the standards of acceptable
37 | behavior and are expected to take appropriate and fair corrective action in
38 | response to any instances of unacceptable behavior.
39 |
40 | Project maintainers have the right and responsibility to remove, edit, or
41 | reject comments, commits, code, wiki edits, issues, and other contributions
42 | that are not aligned to this Code of Conduct, or to ban temporarily or
43 | permanently any contributor for other behaviors that they deem inappropriate,
44 | threatening, offensive, or harmful.
45 |
46 | ## Scope
47 |
48 | This Code of Conduct applies both within project spaces and in public spaces
49 | when an individual is representing the project or its community. Examples of
50 | representing a project or community include using an official project e-mail
51 | address, posting via an official social media account, or acting as an appointed
52 | representative at an online or offline event. Representation of a project may be
53 | further defined and clarified by project maintainers.
54 |
55 | ## Enforcement
56 |
57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be
58 | reported by contacting the project team at neilkalman@gmail.com. All
59 | complaints will be reviewed and investigated and will result in a response that
60 | is deemed necessary and appropriate to the circumstances. The project team is
61 | obligated to maintain confidentiality with regard to the reporter of an incident.
62 | Further details of specific enforcement policies may be posted separately.
63 |
64 | Project maintainers who do not follow or enforce the Code of Conduct in good
65 | faith may face temporary or permanent repercussions as determined by other
66 | members of the project's leadership.
67 |
68 | ## Attribution
69 |
70 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
71 | available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
72 |
73 | [homepage]: https://www.contributor-covenant.org
74 |
75 | For answers to common questions about this code of conduct, see
76 | https://www.contributor-covenant.org/faq
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@kibibit/kb-steam-card",
3 | "version": "0.0.0-development",
4 | "description": "Lovelace Steam Card",
5 | "keywords": [
6 | "home-assistant",
7 | "homeassistant",
8 | "hass",
9 | "automation",
10 | "lovelace",
11 | "custom-cards",
12 | "hassio"
13 | ],
14 | "module": "dist/kb-steam-card.js",
15 | "files": [
16 | "/dist",
17 | "info.md",
18 | "/themes",
19 | "hacs.json"
20 | ],
21 | "author": "thatkookooguy ",
22 | "license": "MIT",
23 | "dependencies": {
24 | "custom-card-helpers": "^1.6.6",
25 | "home-assistant-js-websocket": "^5.7.0",
26 | "lit-element": "^2.4.0",
27 | "lit-html": "^1.3.0",
28 | "timeago": "^1.6.7",
29 | "timeago.js": "^4.0.2"
30 | },
31 | "devDependencies": {
32 | "@babel/core": "^7.12.3",
33 | "@babel/plugin-proposal-class-properties": "^7.12.1",
34 | "@babel/plugin-proposal-decorators": "^7.12.1",
35 | "@commitlint/cli": "^11.0.0",
36 | "@commitlint/config-angular": "^11.0.0",
37 | "@commitlint/config-conventional": "^11.0.0",
38 | "@rollup/plugin-json": "^4.1.0",
39 | "@semantic-release/commit-analyzer": "^8.0.1",
40 | "@semantic-release/exec": "^5.0.0",
41 | "@semantic-release/git": "^9.0.0",
42 | "@semantic-release/github": "^7.1.2",
43 | "@semantic-release/release-notes-generator": "^9.0.1",
44 | "@typescript-eslint/eslint-plugin": "^4.7.0",
45 | "@typescript-eslint/parser": "^4.7.0",
46 | "all-contributors-cli": "^6.19.0",
47 | "commitizen": "^4.2.2",
48 | "coveralls": "^3.1.0",
49 | "cz-conventional-changelog": "^3.3.0",
50 | "eslint": "^7.13.0",
51 | "eslint-config-airbnb-base": "^14.2.1",
52 | "eslint-config-prettier": "^6.15.0",
53 | "eslint-plugin-import": "^2.22.1",
54 | "eslint-plugin-prettier": "^3.1.4",
55 | "husky": "^4.3.0",
56 | "jest": "^26.6.3",
57 | "jest-stare": "^2.2.0",
58 | "prettier": "^2.1.2",
59 | "rollup": "^2.33.2",
60 | "rollup-plugin-babel": "^4.3.3",
61 | "rollup-plugin-commonjs": "^10.1.0",
62 | "rollup-plugin-node-resolve": "^5.2.0",
63 | "rollup-plugin-serve": "^1.1.0",
64 | "rollup-plugin-terser": "^7.0.2",
65 | "rollup-plugin-typescript2": "^0.29.0",
66 | "rollup-plugin-uglify": "^6.0.4",
67 | "semantic-release": "^17.2.2",
68 | "semantic-release-cli": "^5.4.0",
69 | "ts-jest": "^26.4.4",
70 | "ts-node": "^9.0.0",
71 | "typescript": "^4.0.5"
72 | },
73 | "scripts": {
74 | "contributors:add": "all-contributors add",
75 | "contributors:generate": "all-contributors generate",
76 | "start": "rollup -c --watch",
77 | "build": "npm run lint && npm run rollup",
78 | "lint": "eslint src/*.ts",
79 | "lint:fix": "eslint src/*.ts --fix",
80 | "rollup": "rollup -c",
81 | "commit": "cz",
82 | "semantic-release": "semantic-release",
83 | "semantic-release:init": "semantic-release-cli setup"
84 | },
85 | "config": {
86 | "commitizen": {
87 | "path": "./node_modules/cz-conventional-changelog"
88 | }
89 | },
90 | "husky": {
91 | "hooks": {
92 | "prepare-commit-msg": "exec < /dev/tty && git cz --hook || true",
93 | "commit-msg": "commitlint -E HUSKY_GIT_PARAMS"
94 | }
95 | },
96 | "publishConfig": {
97 | "access": "public"
98 | },
99 | "repository": {
100 | "type": "git",
101 | "url": "https://github.com/Kibibit/kb-steam-card.git"
102 | },
103 | "bugs": {
104 | "url": "https://github.com/Kibibit/kb-steam-card/issues"
105 | }
106 | }
107 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | @kibibit/hass-kibibit-theme
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 | A Home Assistant card for Steam integrations
17 |
18 |
19 |
20 | ([Theme](https://github.com/kibibit/hass-kibibit-theme) used in screenshots)
21 |
22 | ## Screenshots
23 |
24 | ### away \ offline state
25 |
26 | 
27 |
28 | ### online state
29 |
30 | 
31 |
32 | ### while playing a game
33 |
34 | 
35 |
36 | ## Installation
37 |
38 | ### Prerequisites
39 | You need at least one [steam integration](https://www.home-assistant.io/integrations/steam_online/) to use with this card.
40 |
41 | ### HACS (recommended)
42 |
43 | 1. Go to the Community Store.
44 | 2. Search for `steam card`.
45 | 3. Press `Install`.
46 |
47 | ### Manual Installation
48 |
49 | ```yaml
50 | resources:
51 | url: ''
52 | type: module
53 | ```
54 |
55 | ## Usage
56 |
57 | for a single user card, use `entity`:
58 |
59 | ```yaml
60 | entity: sensor.steam_
61 | type: 'custom:kb-steam-card'
62 | ```
63 |
64 | you can change the username using the following:
65 |
66 | ```yaml
67 | entity: sensor.steam_
68 | friendly_name: Myself
69 | type: 'custom:kb-steam-card'
70 | ```
71 |
72 | for multiple users, use the `entities` attribute:
73 | 
74 |
75 | ```yaml
76 | entities:
77 | - sensor.steam_
78 | - sensor.steam_
79 | - sensor.steam_
80 | type: 'custom:kb-steam-card'
81 | ```
82 |
83 | you can also use a prefix selector to select all steam sensors:
84 |
85 | ```yaml
86 | type: 'custom:kb-steam-card'
87 | entities: sensor.steam_
88 | ```
89 |
90 | to show only **online users**, add the `online_only` attribute:
91 |
92 | ```yaml
93 | type: 'custom:kb-steam-card'
94 | entities: sensor.steam_
95 | online_only: true
96 | ```
97 |
98 | you can also show the game header image as background with `game_background: true`:
99 | 
100 |
101 | ```yaml
102 | entities:
103 | - sensor.steam_
104 | - sensor.steam_
105 | - sensor.steam_
106 | friendly_name: hello
107 | game_background: true
108 | type: 'custom:kb-steam-card'
109 | ```
110 |
111 | ## Stay in touch
112 |
113 | - Author - [Neil Kalman](https://github.com/thatkookooguy)
114 | - Website - [https://github.com/kibibit](https://github.com/kibibit)
115 | - StackOverflow - [thatkookooguy](https://stackoverflow.com/users/1788884/thatkookooguy)
116 | - Twitter - [@thatkookooguy](https://twitter.com/thatkookooguy)
117 | - Twitter - [@kibibit_opensrc](https://twitter.com/kibibit_opensrc)
118 |
119 | ## Support
120 |
121 | Hey dude! Help me out for a couple of :beers: or a :coffee: by clicking on the sponsering link!
122 |
--------------------------------------------------------------------------------
/src/kb-steam-card.ts:
--------------------------------------------------------------------------------
1 | import { LitElement, html, customElement, CSSResult, TemplateResult, css, PropertyDeclarations } from 'lit-element';
2 |
3 | import * as packageDetails from '../package.json';
4 |
5 | declare global {
6 | interface Window {
7 | customCards: {
8 | type: string;
9 | name: string;
10 | description: string;
11 | }[];
12 | }
13 | }
14 |
15 | console.info(
16 | `%c KB-STEAM-CARD \n%c ${packageDetails.version} `,
17 | 'color: orange; font-weight: bold; background: black',
18 | 'color: white; font-weight: bold; background: dimgray',
19 | );
20 |
21 | window.customCards = window.customCards || [];
22 | window.customCards.push({
23 | type: 'kb-steam-card',
24 | name: 'kb Steam Card',
25 | description: 'A card to show Steam integrations',
26 | });
27 |
28 | import { format } from 'timeago.js';
29 |
30 | @customElement('kb-steam-card')
31 | class KbSteamCard extends LitElement {
32 | hass;
33 | config;
34 | static get properties(): PropertyDeclarations {
35 | return {
36 | hass: {},
37 | config: {},
38 | };
39 | }
40 |
41 | render(): TemplateResult {
42 | return html`
43 |
44 | ${this.config.entity
45 | ? this.createEntityCard(this.hass.states[this.config.entity])
46 | : this.createEntitiesCard(this.config.entities)}
47 |
48 | `;
49 | }
50 |
51 | setConfig(config): void {
52 | if (!config.entities && !config.entity) {
53 | throw new Error('You need to define either a single entity or an entities field');
54 | }
55 | this.config = config;
56 | }
57 |
58 | // The height of your card. Home Assistant uses this to automatically
59 | // distribute all cards over the available columns.
60 | getCardSize(): number {
61 | return this.config.entities ? this.config.entities.length + 1 : 2;
62 | }
63 |
64 | _toggle(state): void {
65 | this.hass.callService('homeassistant', 'toggle', {
66 | entity_id: state.entity_id,
67 | });
68 | }
69 |
70 | createEntitiesCard(entities): TemplateResult[] {
71 | if (typeof entities === 'string') {
72 | const newEntities = [] as string[];
73 |
74 | Object.values(this.hass.states).forEach((entity: any) => {
75 | if (entity.entity_id.startsWith(entities)) {
76 | newEntities.push(entity.entity_id);
77 | }
78 | });
79 |
80 | entities = newEntities;
81 | }
82 |
83 | if (this.config.online_only) {
84 | const newEntities = [] as string[];
85 |
86 | entities.forEach((entity: string) => {
87 | const entityObj = this.hass.states[entity];
88 | if (entityObj && entityObj.state && entityObj.state !== 'offline') {
89 | newEntities.push(entity);
90 | }
91 | });
92 |
93 | entities = newEntities;
94 | }
95 |
96 | return [
97 | html` `,
98 | ...entities.map((ent, index) => {
99 | const entity = this.hass.states[ent];
100 | return entity
101 | ? html`
102 | this.handlePopup(entity)}
105 | >
106 |
107 |

108 |
${entity.attributes.friendly_name}
109 |
110 |
${entity.attributes.game || '-'}
111 | ${entity.attributes.game && this.config.game_background
112 | ? html`

`
113 | : ''}
114 |
115 | `
116 | : html` Entity ${ent} not found.
`;
117 | }),
118 | ];
119 | }
120 |
121 | handlePopup(entity) {
122 | const entityId = entity.entity_id;
123 | const e = new Event('hass-more-info', { composed: true }) as any;
124 | e.detail = { entityId };
125 | this.dispatchEvent(e);
126 | }
127 |
128 | createEntityCard(entity): TemplateResult {
129 | return html`
130 | this.handlePopup(entity)}>
131 |
132 | ${this.config.friendly_name ? this.config.friendly_name : entity.attributes.friendly_name}
133 |
134 | ${this.renderUserAvatar(entity)}
135 |
${entity.state}
136 |
137 |
138 | ${entity.attributes.level}
139 |
140 |
141 |
142 |
143 |
144 |
145 | ${entity.state === 'online' ? 'Online Since' : 'Last Online'}
146 |
147 | ${this.formatLastOnline(entity.attributes.last_online)}
148 |
149 | ${this.renderCurrentlyPlayingGame(entity)}
150 |
151 | `;
152 | }
153 |
154 | formatLastOnline(lastOnline): string {
155 | return format(new Date(lastOnline));
156 | }
157 |
158 | renderUserAvatar(entity): TemplateResult {
159 | return entity.attributes.entity_picture
160 | ? html`
`
161 | : html` `;
162 | }
163 |
164 | renderCurrentlyPlayingGame(entity): TemplateResult {
165 | const currentlyPlayingGame = entity.attributes.game;
166 |
167 | return currentlyPlayingGame
168 | ? html`
169 |
170 |
Now Playing
171 |
${entity.attributes.game}
172 |

173 |
174 | `
175 | : html``;
176 | }
177 |
178 | static get styles(): CSSResult {
179 | return css`
180 | /* :host {
181 | } */
182 |
183 | .card-header {
184 | width: 100%;
185 | padding-top: 8px;
186 | padding-bottom: 8px;
187 | }
188 |
189 | .kb-clickable {
190 | cursor: pointer;
191 | }
192 |
193 | .kb-steam-value {
194 | padding: 0 0.3em;
195 | }
196 |
197 | .kb-steam-value,
198 | .kb-steam-user {
199 | z-index: 2;
200 | }
201 |
202 | .kb-steam-game-bg {
203 | z-index: 0;
204 | position: absolute;
205 | right: 0;
206 | height: 170%;
207 | width: auto;
208 | opacity: 0.5;
209 | mask-image: linear-gradient(to right, transparent 10%, black 90%);
210 | -webkit-mask-image: linear-gradient(to right, transparent 10%, black 90%);
211 | }
212 |
213 | .not-found {
214 | background-color: yellow;
215 | font-family: sans-serif;
216 | font-size: 14px;
217 | padding: 8px;
218 | }
219 |
220 | ha-card,
221 | ha-card > .kb-container {
222 | padding: 16px;
223 | display: flex;
224 | flex-direction: column;
225 | align-items: center;
226 | }
227 |
228 | .kb-container {
229 | width: 100%;
230 | }
231 |
232 | .kb-steam-avatar {
233 | border-radius: 50%;
234 | width: 40px;
235 | height: 40px;
236 | margin: 8px;
237 | }
238 |
239 | ha-icon.kb-steam-avatar {
240 | display: flex;
241 | align-items: center;
242 | justify-content: center;
243 | background: rgba(0, 0, 0, 0.8);
244 | }
245 |
246 | .kb-steam-level {
247 | position: relative;
248 | margin: 16px;
249 | }
250 |
251 | .kb-steam-level > .kb-steam-level-text-container {
252 | position: absolute;
253 | top: 0;
254 | bottom: 0;
255 | left: 0;
256 | right: 0;
257 | display: flex;
258 | justify-content: center;
259 | /* align-items: center; */
260 | margin-top: 2px;
261 | color: var(--secondary-background-color);
262 | z-index: 2;
263 | /* fix for font */
264 | transform: translateY(1px);
265 | }
266 |
267 | .kb-steam-last-online {
268 | width: 100%;
269 | display: flex;
270 | align-items: center;
271 | justify-content: space-between;
272 | }
273 |
274 | .kb-steam-now-playing {
275 | width: 100%;
276 | overflow: hidden;
277 | margin-top: 2em;
278 | }
279 |
280 | .kb-steam-now-playing > .game-title {
281 | font-size: 1.7em;
282 | margin: 0.2em 0 1.5em;
283 | }
284 |
285 | .kb-steam-now-playing > .game-img {
286 | width: 100%;
287 | height: auto;
288 | }
289 |
290 | .kb-steam-multi {
291 | width: 100%;
292 | display: flex;
293 | align-items: center;
294 | justify-content: space-between;
295 | margin: 0 0 8px;
296 | position: relative;
297 | overflow: hidden;
298 | }
299 |
300 | .kb-steam-multi .kb-steam-user {
301 | display: flex;
302 | align-items: center;
303 | }
304 |
305 | .kb-steam-multi .kb-steam-avatar {
306 | margin: 0 16px 0 0;
307 | }
308 |
309 | .kb-steam-multi::before {
310 | z-index: 1;
311 | position: absolute;
312 | bottom: 0;
313 | left: 2em;
314 | width: 1em;
315 | height: 1em;
316 | border-radius: 50%;
317 | background: #646464;
318 | background-image: radial-gradient(top, #616161 0%, #616161 20%, #535353 60%);
319 | content: '';
320 | z-index: 3;
321 | }
322 |
323 | .kb-steam-multi.online::before,
324 | .kb-steam-multi.snooze::before {
325 | box-shadow: 0 0 1em #1c1c17, 0 0 1em #ff4242;
326 | background: #ff4f4f;
327 | }
328 |
329 | .kb-last {
330 | margin-bottom: 0;
331 | }
332 | `;
333 | }
334 | }
335 |
--------------------------------------------------------------------------------
/dist/kb-steam-card.js:
--------------------------------------------------------------------------------
1 | /*! *****************************************************************************
2 | Copyright (c) Microsoft Corporation.
3 |
4 | Permission to use, copy, modify, and/or distribute this software for any
5 | purpose with or without fee is hereby granted.
6 |
7 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
8 | REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
9 | AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
10 | INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
11 | LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
12 | OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
13 | PERFORMANCE OF THIS SOFTWARE.
14 | ***************************************************************************** */
15 | /**
16 | * @license
17 | * Copyright (c) 2017 The Polymer Project Authors. All rights reserved.
18 | * This code may only be used under the BSD style license found at
19 | * http://polymer.github.io/LICENSE.txt
20 | * The complete set of authors may be found at
21 | * http://polymer.github.io/AUTHORS.txt
22 | * The complete set of contributors may be found at
23 | * http://polymer.github.io/CONTRIBUTORS.txt
24 | * Code distributed by Google as part of the polymer project is also
25 | * subject to an additional IP rights grant found at
26 | * http://polymer.github.io/PATENTS.txt
27 | */
28 | const t="undefined"!=typeof window&&null!=window.customElements&&void 0!==window.customElements.polyfillWrapFlushCallback,e=(t,e,s=null)=>{for(;e!==s;){const s=e.nextSibling;t.removeChild(e),e=s}},s=`{{lit-${String(Math.random()).slice(2)}}}`,i=`\x3c!--${s}--\x3e`,n=new RegExp(`${s}|${i}`);class r{constructor(t,e){this.parts=[],this.element=e;const i=[],r=[],o=document.createTreeWalker(e.content,133,null,!1);let d=0,h=-1,p=0;const{strings:u,values:{length:m}}=t;for(;p0;){const e=u[p],s=c.exec(e)[2],i=s.toLowerCase()+"$lit$",r=t.getAttribute(i);t.removeAttribute(i);const a=r.split(n);this.parts.push({type:"attribute",index:h,name:s,strings:a}),p+=a.length-1}}"TEMPLATE"===t.tagName&&(r.push(t),o.currentNode=t.content)}else if(3===t.nodeType){const e=t.data;if(e.indexOf(s)>=0){const s=t.parentNode,r=e.split(n),o=r.length-1;for(let e=0;e{const s=t.length-e.length;return s>=0&&t.slice(s)===e},o=t=>-1!==t.index,l=()=>document.createComment(""),c=/([ \x09\x0a\x0c\x0d])([^\0-\x1F\x7F-\x9F "'>=/]+)([ \x09\x0a\x0c\x0d]*=[ \x09\x0a\x0c\x0d]*(?:[^ \x09\x0a\x0c\x0d"'`<>=]*|"[^"]*|'[^']*))$/;function d(t,e){const{element:{content:s},parts:i}=t,n=document.createTreeWalker(s,133,null,!1);let r=p(i),a=i[r],o=-1,l=0;const c=[];let d=null;for(;n.nextNode();){o++;const t=n.currentNode;for(t.previousSibling===d&&(d=null),e.has(t)&&(c.push(t),null===d&&(d=t)),null!==d&&l++;void 0!==a&&a.index===o;)a.index=null!==d?-1:a.index-l,r=p(i,r),a=i[r]}c.forEach((t=>t.parentNode.removeChild(t)))}const h=t=>{let e=11===t.nodeType?0:1;const s=document.createTreeWalker(t,133,null,!1);for(;s.nextNode();)e++;return e},p=(t,e=-1)=>{for(let s=e+1;s"function"==typeof t&&u.has(t),f={},g={};
43 | /**
44 | * @license
45 | * Copyright (c) 2017 The Polymer Project Authors. All rights reserved.
46 | * This code may only be used under the BSD style license found at
47 | * http://polymer.github.io/LICENSE.txt
48 | * The complete set of authors may be found at
49 | * http://polymer.github.io/AUTHORS.txt
50 | * The complete set of contributors may be found at
51 | * http://polymer.github.io/CONTRIBUTORS.txt
52 | * Code distributed by Google as part of the polymer project is also
53 | * subject to an additional IP rights grant found at
54 | * http://polymer.github.io/PATENTS.txt
55 | */
56 | class y{constructor(t,e,s){this.__parts=[],this.template=t,this.processor=e,this.options=s}update(t){let e=0;for(const s of this.__parts)void 0!==s&&s.setValue(t[e]),e++;for(const t of this.__parts)void 0!==t&&t.commit()}_clone(){const e=t?this.template.element.content.cloneNode(!0):document.importNode(this.template.element.content,!0),s=[],i=this.template.parts,n=document.createTreeWalker(e,133,null,!1);let r,a=0,l=0,c=n.nextNode();for(;at}),v=` ${s} `;class b{constructor(t,e,s,i){this.strings=t,this.values=e,this.type=s,this.processor=i}getHTML(){const t=this.strings.length-1;let e="",n=!1;for(let r=0;r-1||n)&&-1===t.indexOf("--\x3e",a+1);const o=c.exec(t);e+=null===o?t+(n?v:i):t.substr(0,o.index)+o[1]+o[2]+"$lit$"+o[3]+s}return e+=this.strings[t],e}getTemplateElement(){const t=document.createElement("template");let e=this.getHTML();return void 0!==_&&(e=_.createHTML(e)),t.innerHTML=e,t}}
70 | /**
71 | * @license
72 | * Copyright (c) 2017 The Polymer Project Authors. All rights reserved.
73 | * This code may only be used under the BSD style license found at
74 | * http://polymer.github.io/LICENSE.txt
75 | * The complete set of authors may be found at
76 | * http://polymer.github.io/AUTHORS.txt
77 | * The complete set of contributors may be found at
78 | * http://polymer.github.io/CONTRIBUTORS.txt
79 | * Code distributed by Google as part of the polymer project is also
80 | * subject to an additional IP rights grant found at
81 | * http://polymer.github.io/PATENTS.txt
82 | */const S=t=>null===t||!("object"==typeof t||"function"==typeof t),w=t=>Array.isArray(t)||!(!t||!t[Symbol.iterator]);class x{constructor(t,e,s){this.dirty=!0,this.element=t,this.name=e,this.strings=s,this.parts=[];for(let t=0;t{try{const t={get capture(){return T=!0,!1}};window.addEventListener("test",t,t),window.removeEventListener("test",t,t)}catch(t){}})();class A{constructor(t,e,s){this.value=void 0,this.__pendingValue=void 0,this.element=t,this.eventName=e,this.eventContext=s,this.__boundHandleEvent=t=>this.handleEvent(t)}setValue(t){this.__pendingValue=t}commit(){for(;m(this.__pendingValue);){const t=this.__pendingValue;this.__pendingValue=f,t(this)}if(this.__pendingValue===f)return;const t=this.__pendingValue,e=this.value,s=null==t||null!=e&&(t.capture!==e.capture||t.once!==e.once||t.passive!==e.passive),i=null!=t&&(null==e||s);s&&this.element.removeEventListener(this.eventName,this.__boundHandleEvent,this.__options),i&&(this.__options=$(t),this.element.addEventListener(this.eventName,this.__boundHandleEvent,this.__options)),this.value=t,this.__pendingValue=f}handleEvent(t){"function"==typeof this.value?this.value.call(this.eventContext||this.element,t):this.value.handleEvent(t)}}const $=t=>t&&(T?{capture:t.capture,passive:t.passive,once:t.once}:t.capture)
83 | /**
84 | * @license
85 | * Copyright (c) 2017 The Polymer Project Authors. All rights reserved.
86 | * This code may only be used under the BSD style license found at
87 | * http://polymer.github.io/LICENSE.txt
88 | * The complete set of authors may be found at
89 | * http://polymer.github.io/AUTHORS.txt
90 | * The complete set of contributors may be found at
91 | * http://polymer.github.io/CONTRIBUTORS.txt
92 | * Code distributed by Google as part of the polymer project is also
93 | * subject to an additional IP rights grant found at
94 | * http://polymer.github.io/PATENTS.txt
95 | */;function V(t){let e=U.get(t.type);void 0===e&&(e={stringsArray:new WeakMap,keyString:new Map},U.set(t.type,e));let i=e.stringsArray.get(t.strings);if(void 0!==i)return i;const n=t.strings.join(s);return i=e.keyString.get(n),void 0===i&&(i=new r(t,t.getTemplateElement()),e.keyString.set(n,i)),e.stringsArray.set(t.strings,i),i}const U=new Map,O=new WeakMap;
96 | /**
97 | * @license
98 | * Copyright (c) 2017 The Polymer Project Authors. All rights reserved.
99 | * This code may only be used under the BSD style license found at
100 | * http://polymer.github.io/LICENSE.txt
101 | * The complete set of authors may be found at
102 | * http://polymer.github.io/AUTHORS.txt
103 | * The complete set of contributors may be found at
104 | * http://polymer.github.io/CONTRIBUTORS.txt
105 | * Code distributed by Google as part of the polymer project is also
106 | * subject to an additional IP rights grant found at
107 | * http://polymer.github.io/PATENTS.txt
108 | */const R=new
109 | /**
110 | * @license
111 | * Copyright (c) 2017 The Polymer Project Authors. All rights reserved.
112 | * This code may only be used under the BSD style license found at
113 | * http://polymer.github.io/LICENSE.txt
114 | * The complete set of authors may be found at
115 | * http://polymer.github.io/AUTHORS.txt
116 | * The complete set of contributors may be found at
117 | * http://polymer.github.io/CONTRIBUTORS.txt
118 | * Code distributed by Google as part of the polymer project is also
119 | * subject to an additional IP rights grant found at
120 | * http://polymer.github.io/PATENTS.txt
121 | */
122 | class{handleAttributeExpressions(t,e,s,i){const n=e[0];if("."===n){return new N(t,e.slice(1),s).parts}if("@"===n)return[new A(t,e.slice(1),i.eventContext)];if("?"===n)return[new C(t,e.slice(1),s)];return new x(t,e,s).parts}handleTextExpression(t){return new P(t)}};
123 | /**
124 | * @license
125 | * Copyright (c) 2017 The Polymer Project Authors. All rights reserved.
126 | * This code may only be used under the BSD style license found at
127 | * http://polymer.github.io/LICENSE.txt
128 | * The complete set of authors may be found at
129 | * http://polymer.github.io/AUTHORS.txt
130 | * The complete set of contributors may be found at
131 | * http://polymer.github.io/CONTRIBUTORS.txt
132 | * Code distributed by Google as part of the polymer project is also
133 | * subject to an additional IP rights grant found at
134 | * http://polymer.github.io/PATENTS.txt
135 | */"undefined"!=typeof window&&(window.litHtmlVersions||(window.litHtmlVersions=[])).push("1.3.0");const M=(t,...e)=>new b(t,e,"html",R)
136 | /**
137 | * @license
138 | * Copyright (c) 2017 The Polymer Project Authors. All rights reserved.
139 | * This code may only be used under the BSD style license found at
140 | * http://polymer.github.io/LICENSE.txt
141 | * The complete set of authors may be found at
142 | * http://polymer.github.io/AUTHORS.txt
143 | * The complete set of contributors may be found at
144 | * http://polymer.github.io/CONTRIBUTORS.txt
145 | * Code distributed by Google as part of the polymer project is also
146 | * subject to an additional IP rights grant found at
147 | * http://polymer.github.io/PATENTS.txt
148 | */,j=(t,e)=>`${t}--${e}`;let z=!0;void 0===window.ShadyCSS?z=!1:void 0===window.ShadyCSS.prepareTemplateDom&&(console.warn("Incompatible ShadyCSS version detected. Please update to at least @webcomponents/webcomponentsjs@2.0.2 and @webcomponents/shadycss@1.3.1."),z=!1);const I=t=>e=>{const i=j(e.type,t);let n=U.get(i);void 0===n&&(n={stringsArray:new WeakMap,keyString:new Map},U.set(i,n));let a=n.stringsArray.get(e.strings);if(void 0!==a)return a;const o=e.strings.join(s);if(a=n.keyString.get(o),void 0===a){const s=e.getTemplateElement();z&&window.ShadyCSS.prepareTemplateDom(s,t),a=new r(e,s),n.keyString.set(o,a)}return n.stringsArray.set(e.strings,a),a},q=["html","svg"],L=new Set,D=(t,e,s)=>{L.add(t);const i=s?s.element:document.createElement("template"),n=e.querySelectorAll("style"),{length:r}=n;if(0===r)return void window.ShadyCSS.prepareTemplateStyles(i,t);const a=document.createElement("style");for(let t=0;t{q.forEach((e=>{const s=U.get(j(e,t));void 0!==s&&s.keyString.forEach((t=>{const{element:{content:e}}=t,s=new Set;Array.from(e.querySelectorAll("style")).forEach((t=>{s.add(t)})),d(t,s)}))}))})(t);const o=i.content;s?function(t,e,s=null){const{element:{content:i},parts:n}=t;if(null==s)return void i.appendChild(e);const r=document.createTreeWalker(i,133,null,!1);let a=p(n),o=0,l=-1;for(;r.nextNode();)for(l++,r.currentNode===s&&(o=h(e),s.parentNode.insertBefore(e,s));-1!==a&&n[a].index===l;){if(o>0){for(;-1!==a;)n[a].index+=o,a=p(n,a);return}a=p(n,a)}}(s,a,o.firstChild):o.insertBefore(a,o.firstChild),window.ShadyCSS.prepareTemplateStyles(i,t);const l=o.querySelector("style");if(window.ShadyCSS.nativeShadow&&null!==l)e.insertBefore(l.cloneNode(!0),e.firstChild);else if(s){o.insertBefore(a,o.firstChild);const t=new Set;t.add(a),d(s,t)}};window.JSCompiler_renameProperty=(t,e)=>t;const F={toAttribute(t,e){switch(e){case Boolean:return t?"":null;case Object:case Array:return null==t?t:JSON.stringify(t)}return t},fromAttribute(t,e){switch(e){case Boolean:return null!==t;case Number:return null===t?null:Number(t);case Object:case Array:return JSON.parse(t)}return t}},H=(t,e)=>e!==t&&(e==e||t==t),B={attribute:!0,type:String,converter:F,reflect:!1,hasChanged:H};class W extends HTMLElement{constructor(){super(),this.initialize()}static get observedAttributes(){this.finalize();const t=[];return this._classProperties.forEach(((e,s)=>{const i=this._attributeNameForProperty(s,e);void 0!==i&&(this._attributeToPropertyMap.set(i,s),t.push(i))})),t}static _ensureClassProperties(){if(!this.hasOwnProperty(JSCompiler_renameProperty("_classProperties",this))){this._classProperties=new Map;const t=Object.getPrototypeOf(this)._classProperties;void 0!==t&&t.forEach(((t,e)=>this._classProperties.set(e,t)))}}static createProperty(t,e=B){if(this._ensureClassProperties(),this._classProperties.set(t,e),e.noAccessor||this.prototype.hasOwnProperty(t))return;const s="symbol"==typeof t?Symbol():"__"+t,i=this.getPropertyDescriptor(t,s,e);void 0!==i&&Object.defineProperty(this.prototype,t,i)}static getPropertyDescriptor(t,e,s){return{get(){return this[e]},set(i){const n=this[t];this[e]=i,this.requestUpdateInternal(t,n,s)},configurable:!0,enumerable:!0}}static getPropertyOptions(t){return this._classProperties&&this._classProperties.get(t)||B}static finalize(){const t=Object.getPrototypeOf(this);if(t.hasOwnProperty("finalized")||t.finalize(),this.finalized=!0,this._ensureClassProperties(),this._attributeToPropertyMap=new Map,this.hasOwnProperty(JSCompiler_renameProperty("properties",this))){const t=this.properties,e=[...Object.getOwnPropertyNames(t),..."function"==typeof Object.getOwnPropertySymbols?Object.getOwnPropertySymbols(t):[]];for(const s of e)this.createProperty(s,t[s])}}static _attributeNameForProperty(t,e){const s=e.attribute;return!1===s?void 0:"string"==typeof s?s:"string"==typeof t?t.toLowerCase():void 0}static _valueHasChanged(t,e,s=H){return s(t,e)}static _propertyValueFromAttribute(t,e){const s=e.type,i=e.converter||F,n="function"==typeof i?i:i.fromAttribute;return n?n(t,s):t}static _propertyValueToAttribute(t,e){if(void 0===e.reflect)return;const s=e.type,i=e.converter;return(i&&i.toAttribute||F.toAttribute)(t,s)}initialize(){this._updateState=0,this._updatePromise=new Promise((t=>this._enableUpdatingResolver=t)),this._changedProperties=new Map,this._saveInstanceProperties(),this.requestUpdateInternal()}_saveInstanceProperties(){this.constructor._classProperties.forEach(((t,e)=>{if(this.hasOwnProperty(e)){const t=this[e];delete this[e],this._instanceProperties||(this._instanceProperties=new Map),this._instanceProperties.set(e,t)}}))}_applyInstanceProperties(){this._instanceProperties.forEach(((t,e)=>this[e]=t)),this._instanceProperties=void 0}connectedCallback(){this.enableUpdating()}enableUpdating(){void 0!==this._enableUpdatingResolver&&(this._enableUpdatingResolver(),this._enableUpdatingResolver=void 0)}disconnectedCallback(){}attributeChangedCallback(t,e,s){e!==s&&this._attributeToProperty(t,s)}_propertyToAttribute(t,e,s=B){const i=this.constructor,n=i._attributeNameForProperty(t,s);if(void 0!==n){const t=i._propertyValueToAttribute(e,s);if(void 0===t)return;this._updateState=8|this._updateState,null==t?this.removeAttribute(n):this.setAttribute(n,t),this._updateState=-9&this._updateState}}_attributeToProperty(t,e){if(8&this._updateState)return;const s=this.constructor,i=s._attributeToPropertyMap.get(t);if(void 0!==i){const t=s.getPropertyOptions(i);this._updateState=16|this._updateState,this[i]=s._propertyValueFromAttribute(e,t),this._updateState=-17&this._updateState}}requestUpdateInternal(t,e,s){let i=!0;if(void 0!==t){const n=this.constructor;s=s||n.getPropertyOptions(t),n._valueHasChanged(this[t],e,s.hasChanged)?(this._changedProperties.has(t)||this._changedProperties.set(t,e),!0!==s.reflect||16&this._updateState||(void 0===this._reflectingProperties&&(this._reflectingProperties=new Map),this._reflectingProperties.set(t,s))):i=!1}!this._hasRequestedUpdate&&i&&(this._updatePromise=this._enqueueUpdate())}requestUpdate(t,e){return this.requestUpdateInternal(t,e),this.updateComplete}async _enqueueUpdate(){this._updateState=4|this._updateState;try{await this._updatePromise}catch(t){}const t=this.performUpdate();return null!=t&&await t,!this._hasRequestedUpdate}get _hasRequestedUpdate(){return 4&this._updateState}get hasUpdated(){return 1&this._updateState}performUpdate(){if(!this._hasRequestedUpdate)return;this._instanceProperties&&this._applyInstanceProperties();let t=!1;const e=this._changedProperties;try{t=this.shouldUpdate(e),t?this.update(e):this._markUpdated()}catch(e){throw t=!1,this._markUpdated(),e}t&&(1&this._updateState||(this._updateState=1|this._updateState,this.firstUpdated(e)),this.updated(e))}_markUpdated(){this._changedProperties=new Map,this._updateState=-5&this._updateState}get updateComplete(){return this._getUpdateComplete()}_getUpdateComplete(){return this._updatePromise}shouldUpdate(t){return!0}update(t){void 0!==this._reflectingProperties&&this._reflectingProperties.size>0&&(this._reflectingProperties.forEach(((t,e)=>this._propertyToAttribute(e,this[e],t))),this._reflectingProperties=void 0),this._markUpdated()}updated(t){}firstUpdated(t){}}W.finalized=!0;
149 | /**
150 | * @license
151 | * Copyright (c) 2017 The Polymer Project Authors. All rights reserved.
152 | * This code may only be used under the BSD style license found at
153 | * http://polymer.github.io/LICENSE.txt
154 | * The complete set of authors may be found at
155 | * http://polymer.github.io/AUTHORS.txt
156 | * The complete set of contributors may be found at
157 | * http://polymer.github.io/CONTRIBUTORS.txt
158 | * Code distributed by Google as part of the polymer project is also
159 | * subject to an additional IP rights grant found at
160 | * http://polymer.github.io/PATENTS.txt
161 | */
162 | const J=window.ShadowRoot&&(void 0===window.ShadyCSS||window.ShadyCSS.nativeShadow)&&"adoptedStyleSheets"in Document.prototype&&"replace"in CSSStyleSheet.prototype,G=Symbol();class Y{constructor(t,e){if(e!==G)throw new Error("CSSResult is not constructable. Use `unsafeCSS` or `css` instead.");this.cssText=t}get styleSheet(){return void 0===this._styleSheet&&(J?(this._styleSheet=new CSSStyleSheet,this._styleSheet.replaceSync(this.cssText)):this._styleSheet=null),this._styleSheet}toString(){return this.cssText}}const K=(t,...e)=>{const s=e.reduce(((e,s,i)=>e+(t=>{if(t instanceof Y)return t.cssText;if("number"==typeof t)return t;throw new Error(`Value passed to 'css' function must be a 'css' function result: ${t}. Use 'unsafeCSS' to pass non-literal values, but\n take care to ensure page security.`)})(s)+t[i+1]),t[0]);return new Y(s,G)};
163 | /**
164 | * @license
165 | * Copyright (c) 2017 The Polymer Project Authors. All rights reserved.
166 | * This code may only be used under the BSD style license found at
167 | * http://polymer.github.io/LICENSE.txt
168 | * The complete set of authors may be found at
169 | * http://polymer.github.io/AUTHORS.txt
170 | * The complete set of contributors may be found at
171 | * http://polymer.github.io/CONTRIBUTORS.txt
172 | * Code distributed by Google as part of the polymer project is also
173 | * subject to an additional IP rights grant found at
174 | * http://polymer.github.io/PATENTS.txt
175 | */
176 | (window.litElementVersions||(window.litElementVersions=[])).push("2.4.0");const Z={};class Q extends W{static getStyles(){return this.styles}static _getUniqueStyles(){if(this.hasOwnProperty(JSCompiler_renameProperty("_styles",this)))return;const t=this.getStyles();if(Array.isArray(t)){const e=(t,s)=>t.reduceRight(((t,s)=>Array.isArray(s)?e(s,t):(t.add(s),t)),s),s=e(t,new Set),i=[];s.forEach((t=>i.unshift(t))),this._styles=i}else this._styles=void 0===t?[]:[t];this._styles=this._styles.map((t=>{if(t instanceof CSSStyleSheet&&!J){const e=Array.prototype.slice.call(t.cssRules).reduce(((t,e)=>t+e.cssText),"");return new Y(String(e),G)}return t}))}initialize(){super.initialize(),this.constructor._getUniqueStyles(),this.renderRoot=this.createRenderRoot(),window.ShadowRoot&&this.renderRoot instanceof window.ShadowRoot&&this.adoptStyles()}createRenderRoot(){return this.attachShadow({mode:"open"})}adoptStyles(){const t=this.constructor._styles;0!==t.length&&(void 0===window.ShadyCSS||window.ShadyCSS.nativeShadow?J?this.renderRoot.adoptedStyleSheets=t.map((t=>t instanceof CSSStyleSheet?t:t.styleSheet)):this._needsShimAdoptedStyleSheets=!0:window.ShadyCSS.ScopingShim.prepareAdoptedCssText(t.map((t=>t.cssText)),this.localName))}connectedCallback(){super.connectedCallback(),this.hasUpdated&&void 0!==window.ShadyCSS&&window.ShadyCSS.styleElement(this)}update(t){const e=this.render();super.update(t),e!==Z&&this.constructor.render(e,this.renderRoot,{scopeName:this.localName,eventContext:this}),this._needsShimAdoptedStyleSheets&&(this._needsShimAdoptedStyleSheets=!1,this.constructor._styles.forEach((t=>{const e=document.createElement("style");e.textContent=t.cssText,this.renderRoot.appendChild(e)})))}render(){return Z}}Q.finalized=!0,Q.render=(t,s,i)=>{if(!i||"object"!=typeof i||!i.scopeName)throw new Error("The `scopeName` option is required.");const n=i.scopeName,r=O.has(s),a=z&&11===s.nodeType&&!!s.host,o=a&&!L.has(n),l=o?document.createDocumentFragment():s;if(((t,s,i)=>{let n=O.get(s);void 0===n&&(e(s,s.firstChild),O.set(s,n=new P(Object.assign({templateFactory:V},i))),n.appendInto(s)),n.setValue(t),n.commit()})(t,l,Object.assign({templateFactory:I(n)},i)),o){const t=O.get(l);O.delete(l);const i=t.value instanceof y?t.value.template:void 0;D(n,l,i),e(s,s.firstChild),s.appendChild(l),O.set(s,t)}!r&&a&&window.ShadyCSS.styleElement(s.host)};var X=["second","minute","hour","day","week","month","year"];var tt=["秒","分钟","小时","天","周","个月","年"];var et={},st=function(t,e){et[t]=e},it=[60,60,24,7,365/7/12,12];function nt(t){return t instanceof Date?t:!isNaN(t)||/^\d+$/.test(t)?new Date(parseInt(t)):(t=(t||"").trim().replace(/\.\d+/,"").replace(/-/,"/").replace(/-/,"/").replace(/(\d)T(\d)/,"$1 $2").replace(/Z/," UTC").replace(/([+-]\d\d):?(\d\d)/," $1$2"),new Date(t))}var rt=function(t,e,s){return function(t,e){for(var s=t<0?1:0,i=t=Math.abs(t),n=0;t>=it[n]&&n(0==(n*=2)?9:1)&&(n+=1),e(t,n,i)[s].replace("%s",t.toString())}(function(t,e){return(+(e?nt(e):new Date)-+nt(t))/1e3}(t,s&&s.relativeDate),function(t){return et[t]||et.en_US}(e))};st("en_US",(function(t,e){if(0===e)return["just now","right now"];var s=X[Math.floor(e/2)];return t>1&&(s+="s"),[t+" "+s+" ago","in "+t+" "+s]})),st("zh_CN",(function(t,e){if(0===e)return["刚刚","片刻后"];var s=tt[~~(e/2)];return[t+" "+s+"前",t+" "+s+"后"]})),console.info("%c KB-STEAM-CARD \n%c 0.0.0-development ","color: orange; font-weight: bold; background: black","color: white; font-weight: bold; background: dimgray"),window.customCards=window.customCards||[],window.customCards.push({type:"kb-steam-card",name:"kb Steam Card",description:"A card to show Steam integrations"});let at=class extends Q{static get properties(){return{hass:{},config:{}}}render(){return M`
177 |
178 | ${this.config.entity?this.createEntityCard(this.hass.states[this.config.entity]):this.createEntitiesCard(this.config.entities)}
179 |
180 | `}setConfig(t){if(!t.entities&&!t.entity)throw new Error("You need to define either a single entity or an entities field");this.config=t}getCardSize(){return this.config.entities?this.config.entities.length+1:2}_toggle(t){this.hass.callService("homeassistant","toggle",{entity_id:t.entity_id})}createEntitiesCard(t){if("string"==typeof t){const e=[];Object.values(this.hass.states).forEach((s=>{s.entity_id.startsWith(t)&&e.push(s.entity_id)})),t=e}if(this.config.online_only){const e=[];t.forEach((t=>{const s=this.hass.states[t];s&&s.state&&"offline"!==s.state&&e.push(t)})),t=e}return[M` `,...t.map(((e,s)=>{const i=this.hass.states[e];return i?M`
181 | this.handlePopup(i)}
184 | >
185 |
186 |

187 |
${i.attributes.friendly_name}
188 |
189 |
${i.attributes.game||"-"}
190 | ${i.attributes.game&&this.config.game_background?M`

`:""}
191 |
192 | `:M` Entity ${e} not found.
`}))]}handlePopup(t){const e=t.entity_id,s=new Event("hass-more-info",{composed:!0});s.detail={entityId:e},this.dispatchEvent(s)}createEntityCard(t){return M`
193 | this.handlePopup(t)}>
194 |
195 | ${this.config.friendly_name?this.config.friendly_name:t.attributes.friendly_name}
196 |
197 | ${this.renderUserAvatar(t)}
198 |
${t.state}
199 |
200 |
201 | ${t.attributes.level}
202 |
203 |
204 |
205 |
206 |
207 |
208 | ${"online"===t.state?"Online Since":"Last Online"}
209 |
210 | ${this.formatLastOnline(t.attributes.last_online)}
211 |
212 | ${this.renderCurrentlyPlayingGame(t)}
213 |
214 | `}formatLastOnline(t){return rt(new Date(t))}renderUserAvatar(t){return t.attributes.entity_picture?M`
`:M` `}renderCurrentlyPlayingGame(t){return t.attributes.game?M`
215 |
216 |
Now Playing
217 |
${t.attributes.game}
218 |

219 |
220 | `:M``}static get styles(){return K`
221 | /* :host {
222 | } */
223 |
224 | .card-header {
225 | width: 100%;
226 | padding-top: 8px;
227 | padding-bottom: 8px;
228 | }
229 |
230 | .kb-clickable {
231 | cursor: pointer;
232 | }
233 |
234 | .kb-steam-value {
235 | padding: 0 0.3em;
236 | }
237 |
238 | .kb-steam-value,
239 | .kb-steam-user {
240 | z-index: 2;
241 | }
242 |
243 | .kb-steam-game-bg {
244 | z-index: 0;
245 | position: absolute;
246 | right: 0;
247 | height: 170%;
248 | width: auto;
249 | opacity: 0.5;
250 | mask-image: linear-gradient(to right, transparent 10%, black 90%);
251 | -webkit-mask-image: linear-gradient(to right, transparent 10%, black 90%);
252 | }
253 |
254 | .not-found {
255 | background-color: yellow;
256 | font-family: sans-serif;
257 | font-size: 14px;
258 | padding: 8px;
259 | }
260 |
261 | ha-card,
262 | ha-card > .kb-container {
263 | padding: 16px;
264 | display: flex;
265 | flex-direction: column;
266 | align-items: center;
267 | }
268 |
269 | .kb-container {
270 | width: 100%;
271 | }
272 |
273 | .kb-steam-avatar {
274 | border-radius: 50%;
275 | width: 40px;
276 | height: 40px;
277 | margin: 8px;
278 | }
279 |
280 | ha-icon.kb-steam-avatar {
281 | display: flex;
282 | align-items: center;
283 | justify-content: center;
284 | background: rgba(0, 0, 0, 0.8);
285 | }
286 |
287 | .kb-steam-level {
288 | position: relative;
289 | margin: 16px;
290 | }
291 |
292 | .kb-steam-level > .kb-steam-level-text-container {
293 | position: absolute;
294 | top: 0;
295 | bottom: 0;
296 | left: 0;
297 | right: 0;
298 | display: flex;
299 | justify-content: center;
300 | /* align-items: center; */
301 | margin-top: 2px;
302 | color: var(--secondary-background-color);
303 | z-index: 2;
304 | /* fix for font */
305 | transform: translateY(1px);
306 | }
307 |
308 | .kb-steam-last-online {
309 | width: 100%;
310 | display: flex;
311 | align-items: center;
312 | justify-content: space-between;
313 | }
314 |
315 | .kb-steam-now-playing {
316 | width: 100%;
317 | overflow: hidden;
318 | margin-top: 2em;
319 | }
320 |
321 | .kb-steam-now-playing > .game-title {
322 | font-size: 1.7em;
323 | margin: 0.2em 0 1.5em;
324 | }
325 |
326 | .kb-steam-now-playing > .game-img {
327 | width: 100%;
328 | height: auto;
329 | }
330 |
331 | .kb-steam-multi {
332 | width: 100%;
333 | display: flex;
334 | align-items: center;
335 | justify-content: space-between;
336 | margin: 0 0 8px;
337 | position: relative;
338 | overflow: hidden;
339 | }
340 |
341 | .kb-steam-multi .kb-steam-user {
342 | display: flex;
343 | align-items: center;
344 | }
345 |
346 | .kb-steam-multi .kb-steam-avatar {
347 | margin: 0 16px 0 0;
348 | }
349 |
350 | .kb-steam-multi::before {
351 | z-index: 1;
352 | position: absolute;
353 | bottom: 0;
354 | left: 2em;
355 | width: 1em;
356 | height: 1em;
357 | border-radius: 50%;
358 | background: #646464;
359 | background-image: radial-gradient(top, #616161 0%, #616161 20%, #535353 60%);
360 | content: '';
361 | z-index: 3;
362 | }
363 |
364 | .kb-steam-multi.online::before,
365 | .kb-steam-multi.snooze::before {
366 | box-shadow: 0 0 1em #1c1c17, 0 0 1em #ff4242;
367 | background: #ff4f4f;
368 | }
369 |
370 | .kb-last {
371 | margin-bottom: 0;
372 | }
373 | `}};var ot;
374 | /**
375 | @license
376 | Copyright (c) 2019 The Polymer Project Authors. All rights reserved.
377 | This code may only be used under the BSD style license found at
378 | http://polymer.github.io/LICENSE.txt The complete set of authors may be found at
379 | http://polymer.github.io/AUTHORS.txt The complete set of contributors may be
380 | found at http://polymer.github.io/CONTRIBUTORS.txt Code distributed by Google as
381 | part of the polymer project is also subject to an additional IP rights grant
382 | found at http://polymer.github.io/PATENTS.txt
383 | */at=function(t,e,s,i){var n,r=arguments.length,a=r<3?e:null===i?i=Object.getOwnPropertyDescriptor(e,s):i;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)a=Reflect.decorate(t,e,s,i);else for(var o=t.length-1;o>=0;o--)(n=t[o])&&(a=(r<3?n(a):r>3?n(e,s,a):n(e,s))||a);return r>3&&a&&Object.defineProperty(e,s,a),a}([(ot="kb-steam-card",t=>"function"==typeof t?((t,e)=>(window.customElements.define(t,e),e))(ot,t):((t,e)=>{const{kind:s,elements:i}=e;return{kind:s,elements:i,finisher(e){window.customElements.define(t,e)}}})(ot,t))],at);
384 |
--------------------------------------------------------------------------------