diff --git a/config/README.md b/config/README.md
index 2c0fd84..a3ca8e0 100644
--- a/config/README.md
+++ b/config/README.md
@@ -40,11 +40,11 @@ https://github.com/ngocjohn/hass-config/assets/96962827/acc1a4db-b92e-4ab1-ac9d-
36,202 |
34 |
178 |
- 38 |
+ 63 |
52 |
- 31 |
- 1071 |
- 174 |
+ 30 |
+ 1083 |
+ 202 |
38 |
@@ -149,7 +149,6 @@ https://github.com/ngocjohn/hass-config/assets/96962827/acc1a4db-b92e-4ab1-ac9d-
- [Restriction Card](https://github.com/iantrich/restriction-card)
- [Roku Card](https://github.com/iantrich/roku-card)
- [Rpi Monitor Card](https://github.com/ironsheep/lovelace-rpi-monitor-card)
-- [Search Card](https://github.com/postlund/search-card)
- [Simple Thermostat](https://github.com/nervetattoo/simple-thermostat)
- [Slider Button Card](https://github.com/custom-cards/slider-button-card)
- [Spotify Lovelace Card](https://github.com/custom-cards/spotify-card)
diff --git a/config/custom_components/nodered/manifest.json b/config/custom_components/nodered/manifest.json
index d86171e..d9fb344 100644
--- a/config/custom_components/nodered/manifest.json
+++ b/config/custom_components/nodered/manifest.json
@@ -13,5 +13,5 @@
"documentation": "https://zachowj.github.io/node-red-contrib-home-assistant-websocket/guide/custom_integration/",
"iot_class": "local_push",
"issue_tracker": "https://github.com/zachowj/hass-node-red/issues",
- "version": "4.1.1"
+ "version": "4.1.2"
}
diff --git a/config/custom_components/xiaomi_miot/manifest.json b/config/custom_components/xiaomi_miot/manifest.json
index 9f34599..c384a51 100644
--- a/config/custom_components/xiaomi_miot/manifest.json
+++ b/config/custom_components/xiaomi_miot/manifest.json
@@ -17,5 +17,5 @@
"python-miio>=0.5.12",
"micloud>=0.5"
],
- "version": "1.0.4"
+ "version": "1.0.5"
}
diff --git a/config/dashboards/views/main-grid/grid_media.yaml b/config/dashboards/views/main-grid/grid_media.yaml
index 3e9f7dd..154e080 100755
--- a/config/dashboards/views/main-grid/grid_media.yaml
+++ b/config/dashboards/views/main-grid/grid_media.yaml
@@ -32,13 +32,9 @@
# padding: 0px !important;
# }
- type: custom:button-card
- entity: media_player.spotifyplus_ngoc_nguyen
- template:
- - tpl_spotify
- variables:
- playlist_type: default
- country_code: vn
+ type: custom:ytube-playlist-card
+ entity: media_player.ytube_music_player
+ extra: sensor.ytube_music_player_extra
# type: media-control
# entity: media_player.spotify
diff --git a/config/www/dashboard-resources/ytube-playlist-card.js b/config/www/dashboard-resources/ytube-playlist-card.js
new file mode 100755
index 0000000..7ed500d
--- /dev/null
+++ b/config/www/dashboard-resources/ytube-playlist-card.js
@@ -0,0 +1,261 @@
+function t(t,e,i,s){var r,n=arguments.length,o=n<3?e:null===s?s=Object.getOwnPropertyDescriptor(e,i):s;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)o=Reflect.decorate(t,e,i,s);else for(var a=t.length-1;a>=0;a--)(r=t[a])&&(o=(n<3?r(o):n>3?r(e,i,o):r(e,i))||o);return n>3&&o&&Object.defineProperty(e,i,o),o}function e(t,e){if(!Number.isInteger(e)||e<=0)throw new Error("Size must be an integer greater than zero.");const i=Math.ceil(t.length/e),s=Array(i);for(let r=0;r{for(let n=0;nnew a("string"==typeof t?t:t+"",void 0,n),l=(t,...e)=>{const i=1===t.length?t[0]:e.reduce(((e,i,s)=>e+(t=>{if(!0===t._$cssResult$)return t.cssText;if("number"==typeof t)return t;throw Error("Value passed to 'css' function must be a 'css' function result: "+t+". Use 'unsafeCSS' to pass non-literal values, but take care to ensure page security.")})(i)+t[s+1]),t[0]);return new a(i,t,n)},c=(t,e)=>{if(r)t.adoptedStyleSheets=e.map((t=>t instanceof CSSStyleSheet?t:t.styleSheet));else for(const i of e){const e=document.createElement("style"),r=s.litNonce;void 0!==r&&e.setAttribute("nonce",r),e.textContent=i.cssText,t.appendChild(e)}},d=r?t=>t:t=>t instanceof CSSStyleSheet?(t=>{let e="";for(const i of t.cssRules)e+=i.cssText;return h(e)})(t):t
+/**
+ * @license
+ * Copyright 2017 Google LLC
+ * SPDX-License-Identifier: BSD-3-Clause
+ */,{is:u,defineProperty:p,getOwnPropertyDescriptor:_,getOwnPropertyNames:m,getOwnPropertySymbols:g,getPrototypeOf:f}=Object,y=globalThis,$=y.trustedTypes,b=$?$.emptyScript:"",v=y.reactiveElementPolyfillSupport,A=(t,e)=>t,w={toAttribute(t,e){switch(e){case Boolean:t=t?b:null;break;case Object:case Array:t=null==t?t:JSON.stringify(t)}return t},fromAttribute(t,e){let i=t;switch(e){case Boolean:i=null!==t;break;case Number:i=null===t?null:Number(t);break;case Object:case Array:try{i=JSON.parse(t)}catch(t){i=null}}return i}},E=(t,e)=>!u(t,e),S={attribute:!0,type:String,converter:w,reflect:!1,hasChanged:E};Symbol.metadata??=Symbol("metadata"),y.litPropertyMetadata??=new WeakMap;class x extends HTMLElement{static addInitializer(t){this._$Ei(),(this.l??=[]).push(t)}static get observedAttributes(){return this.finalize(),this._$Eh&&[...this._$Eh.keys()]}static createProperty(t,e=S){if(e.state&&(e.attribute=!1),this._$Ei(),this.elementProperties.set(t,e),!e.noAccessor){const i=Symbol(),s=this.getPropertyDescriptor(t,i,e);void 0!==s&&p(this.prototype,t,s)}}static getPropertyDescriptor(t,e,i){const{get:s,set:r}=_(this.prototype,t)??{get(){return this[e]},set(t){this[e]=t}};return{get(){return s?.call(this)},set(e){const n=s?.call(this);r.call(this,e),this.requestUpdate(t,n,i)},configurable:!0,enumerable:!0}}static getPropertyOptions(t){return this.elementProperties.get(t)??S}static _$Ei(){if(this.hasOwnProperty(A("elementProperties")))return;const t=f(this);t.finalize(),void 0!==t.l&&(this.l=[...t.l]),this.elementProperties=new Map(t.elementProperties)}static finalize(){if(this.hasOwnProperty(A("finalized")))return;if(this.finalized=!0,this._$Ei(),this.hasOwnProperty(A("properties"))){const t=this.properties,e=[...m(t),...g(t)];for(const i of e)this.createProperty(i,t[i])}const t=this[Symbol.metadata];if(null!==t){const e=litPropertyMetadata.get(t);if(void 0!==e)for(const[t,i]of e)this.elementProperties.set(t,i)}this._$Eh=new Map;for(const[t,e]of this.elementProperties){const i=this._$Eu(t,e);void 0!==i&&this._$Eh.set(i,t)}this.elementStyles=this.finalizeStyles(this.styles)}static finalizeStyles(t){const e=[];if(Array.isArray(t)){const i=new Set(t.flat(1/0).reverse());for(const t of i)e.unshift(d(t))}else void 0!==t&&e.push(d(t));return e}static _$Eu(t,e){const i=e.attribute;return!1===i?void 0:"string"==typeof i?i:"string"==typeof t?t.toLowerCase():void 0}constructor(){super(),this._$Ep=void 0,this.isUpdatePending=!1,this.hasUpdated=!1,this._$Em=null,this._$Ev()}_$Ev(){this._$ES=new Promise((t=>this.enableUpdating=t)),this._$AL=new Map,this._$E_(),this.requestUpdate(),this.constructor.l?.forEach((t=>t(this)))}addController(t){(this._$EO??=new Set).add(t),void 0!==this.renderRoot&&this.isConnected&&t.hostConnected?.()}removeController(t){this._$EO?.delete(t)}_$E_(){const t=new Map,e=this.constructor.elementProperties;for(const i of e.keys())this.hasOwnProperty(i)&&(t.set(i,this[i]),delete this[i]);t.size>0&&(this._$Ep=t)}createRenderRoot(){const t=this.shadowRoot??this.attachShadow(this.constructor.shadowRootOptions);return c(t,this.constructor.elementStyles),t}connectedCallback(){this.renderRoot??=this.createRenderRoot(),this.enableUpdating(!0),this._$EO?.forEach((t=>t.hostConnected?.()))}enableUpdating(t){}disconnectedCallback(){this._$EO?.forEach((t=>t.hostDisconnected?.()))}attributeChangedCallback(t,e,i){this._$AK(t,i)}_$EC(t,e){const i=this.constructor.elementProperties.get(t),s=this.constructor._$Eu(t,i);if(void 0!==s&&!0===i.reflect){const r=(void 0!==i.converter?.toAttribute?i.converter:w).toAttribute(e,i.type);this._$Em=t,null==r?this.removeAttribute(s):this.setAttribute(s,r),this._$Em=null}}_$AK(t,e){const i=this.constructor,s=i._$Eh.get(t);if(void 0!==s&&this._$Em!==s){const t=i.getPropertyOptions(s),r="function"==typeof t.converter?{fromAttribute:t.converter}:void 0!==t.converter?.fromAttribute?t.converter:w;this._$Em=s,this[s]=r.fromAttribute(e,t.type),this._$Em=null}}requestUpdate(t,e,i){if(void 0!==t){if(i??=this.constructor.getPropertyOptions(t),!(i.hasChanged??E)(this[t],e))return;this.P(t,e,i)}!1===this.isUpdatePending&&(this._$ES=this._$ET())}P(t,e,i){this._$AL.has(t)||this._$AL.set(t,e),!0===i.reflect&&this._$Em!==t&&(this._$Ej??=new Set).add(t)}async _$ET(){this.isUpdatePending=!0;try{await this._$ES}catch(t){Promise.reject(t)}const t=this.scheduleUpdate();return null!=t&&await t,!this.isUpdatePending}scheduleUpdate(){return this.performUpdate()}performUpdate(){if(!this.isUpdatePending)return;if(!this.hasUpdated){if(this.renderRoot??=this.createRenderRoot(),this._$Ep){for(const[t,e]of this._$Ep)this[t]=e;this._$Ep=void 0}const t=this.constructor.elementProperties;if(t.size>0)for(const[e,i]of t)!0!==i.wrapped||this._$AL.has(e)||void 0===this[e]||this.P(e,this[e],i)}let t=!1;const e=this._$AL;try{t=this.shouldUpdate(e),t?(this.willUpdate(e),this._$EO?.forEach((t=>t.hostUpdate?.())),this.update(e)):this._$EU()}catch(e){throw t=!1,this._$EU(),e}t&&this._$AE(e)}willUpdate(t){}_$AE(t){this._$EO?.forEach((t=>t.hostUpdated?.())),this.hasUpdated||(this.hasUpdated=!0,this.firstUpdated(t)),this.updated(t)}_$EU(){this._$AL=new Map,this.isUpdatePending=!1}get updateComplete(){return this.getUpdateComplete()}getUpdateComplete(){return this._$ES}shouldUpdate(t){return!0}update(t){this._$Ej&&=this._$Ej.forEach((t=>this._$EC(t,this[t]))),this._$EU()}updated(t){}firstUpdated(t){}}x.elementStyles=[],x.shadowRootOptions={mode:"open"},x[A("elementProperties")]=new Map,x[A("finalized")]=new Map,v?.({ReactiveElement:x}),(y.reactiveElementVersions??=[]).push("2.0.4");
+/**
+ * @license
+ * Copyright 2017 Google LLC
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+const C=globalThis,P=C.trustedTypes,k=P?P.createPolicy("lit-html",{createHTML:t=>t}):void 0,T="$lit$",U=`lit$${Math.random().toFixed(9).slice(2)}$`,O="?"+U,M=`<${O}>`,R=document,H=()=>R.createComment(""),I=t=>null===t||"object"!=typeof t&&"function"!=typeof t,N=Array.isArray,z=t=>N(t)||"function"==typeof t?.[Symbol.iterator],j="[ \t\n\f\r]",D=/<(?:(!--|\/[^a-zA-Z])|(\/?[a-zA-Z][^>\s]*)|(\/?$))/g,L=/-->/g,B=/>/g,W=RegExp(`>|${j}(?:([^\\s"'>=/]+)(${j}*=${j}*(?:[^ \t\n\f\r"'\`<>=]|("|')|))|$)`,"g"),q=/'/g,V=/"/g,Y=/^(?:script|style|textarea|title)$/i,G=t=>(e,...i)=>({_$litType$:t,strings:e,values:i}),Z=G(1),J=Symbol.for("lit-noChange"),K=Symbol.for("lit-nothing"),F=new WeakMap,Q=R.createTreeWalker(R,129);function X(t,e){if(!N(t)||!t.hasOwnProperty("raw"))throw Error("invalid template strings array");return void 0!==k?k.createHTML(e):e}const tt=(t,e)=>{const i=t.length-1,s=[];let r,n=2===e?"":3===e?"":"")),s]};class et{constructor({strings:t,_$litType$:e},i){let s;this.parts=[];let r=0,n=0;const o=t.length-1,a=this.parts,[h,l]=tt(t,e);if(this.el=et.createElement(h,i),Q.currentNode=this.el.content,2===e||3===e){const t=this.el.content.firstChild;t.replaceWith(...t.childNodes)}for(;null!==(s=Q.nextNode())&&a.length0){s.textContent=P?P.emptyScript:"";for(let i=0;i2||""!==i[0]||""!==i[1]?(this._$AH=Array(i.length-1).fill(new String),this.strings=i):this._$AH=K}_$AI(t,e=this,i,s){const r=this.strings;let n=!1;if(void 0===r)t=it(this,t,e,0),n=!I(t)||t!==this._$AH&&t!==J,n&&(this._$AH=t);else{const s=t;let o,a;for(t=r[0],o=0;o{const s=i?.renderBefore??e;let r=s._$litPart$;if(void 0===r){const t=i?.renderBefore??null;s._$litPart$=r=new rt(e.insertBefore(H(),t),t,void 0,i??{})}return r._$AI(t),r
+/**
+ * @license
+ * Copyright 2017 Google LLC
+ * SPDX-License-Identifier: BSD-3-Clause
+ */};class ut extends x{constructor(){super(...arguments),this.renderOptions={host:this},this._$Do=void 0}createRenderRoot(){const t=super.createRenderRoot();return this.renderOptions.renderBefore??=t.firstChild,t}update(t){const e=this.render();this.hasUpdated||(this.renderOptions.isConnected=this.isConnected),super.update(t),this._$Do=dt(e,this.renderRoot,this.renderOptions)}connectedCallback(){super.connectedCallback(),this._$Do?.setConnected(!0)}disconnectedCallback(){super.disconnectedCallback(),this._$Do?.setConnected(!1)}render(){return J}}ut._$litElement$=!0,ut.finalized=!0,globalThis.litElementHydrateSupport?.({LitElement:ut});const pt=globalThis.litElementPolyfillSupport;pt?.({LitElement:ut}),(globalThis.litElementVersions??=[]).push("4.1.1");
+/**
+ * @license
+ * Copyright 2017 Google LLC
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+const _t=t=>(e,i)=>{void 0!==i?i.addInitializer((()=>{customElements.define(t,e)})):customElements.define(t,e)}
+/**
+ * @license
+ * Copyright 2017 Google LLC
+ * SPDX-License-Identifier: BSD-3-Clause
+ */,mt={attribute:!0,type:String,converter:w,reflect:!1,hasChanged:E},gt=(t=mt,e,i)=>{const{kind:s,metadata:r}=i;let n=globalThis.litPropertyMetadata.get(r);if(void 0===n&&globalThis.litPropertyMetadata.set(r,n=new Map),n.set(i.name,t),"accessor"===s){const{name:s}=i;return{set(i){const r=e.get.call(this);e.set.call(this,i),this.requestUpdate(s,r,t)},init(e){return void 0!==e&&this.P(s,void 0,t),e}}}if("setter"===s){const{name:s}=i;return function(i){const r=this[s];e.call(this,i),this.requestUpdate(s,r,t)}}throw Error("Unsupported decorator location: "+s)};function ft(t){return(e,i)=>"object"==typeof i?gt(t,e,i):((t,e,i)=>{const s=e.hasOwnProperty(i);return e.constructor.createProperty(i,s?{...t,wrapped:!0}:t),s?Object.getOwnPropertyDescriptor(e,i):void 0})(t,e,i)
+/**
+ * @license
+ * Copyright 2017 Google LLC
+ * SPDX-License-Identifier: BSD-3-Clause
+ */}function yt(t){return ft({...t,state:!0,attribute:!1})}
+/**
+ * @license
+ * Copyright 2017 Google LLC
+ * SPDX-License-Identifier: BSD-3-Clause
+ */const $t={ATTRIBUTE:1,CHILD:2,PROPERTY:3,BOOLEAN_ATTRIBUTE:4,EVENT:5,ELEMENT:6},bt=t=>(...e)=>({_$litDirective$:t,values:e});class vt{constructor(t){}get _$AU(){return this._$AM._$AU}_$AT(t,e,i){this._$Ct=t,this._$AM=e,this._$Ci=i}_$AS(t,e){return this.update(t,e)}update(t,e){return this.render(...e)}}
+/**
+ * @license
+ * Copyright 2018 Google LLC
+ * SPDX-License-Identifier: BSD-3-Clause
+ */const At="important",wt=" !"+At,Et=bt(class extends vt{constructor(t){if(super(t),t.type!==$t.ATTRIBUTE||"style"!==t.name||t.strings?.length>2)throw Error("The `styleMap` directive must be used in the `style` attribute and must be the only part in the attribute.")}render(t){return Object.keys(t).reduce(((e,i)=>{const s=t[i];return null==s?e:e+`${i=i.includes("-")?i:i.replace(/(?:^(webkit|moz|ms|o)|)(?=[A-Z])/g,"-$&").toLowerCase()}:${s};`}),"")}update(t,[e]){const{style:i}=t.element;if(void 0===this.ft)return this.ft=new Set(Object.keys(e)),this.render(e);for(const t of this.ft)null==e[t]&&(this.ft.delete(t),t.includes("-")?i.removeProperty(t):i[t]=null);for(const t in e){const s=e[t];if(null!=s){this.ft.add(t);const e="string"==typeof s&&s.endsWith(wt);t.includes("-")||e?i.setProperty(t,e?s.slice(0,-11):s,e?At:""):i[t]=s}}return J}});class St{constructor(t,e){this.hass=t,this.playerId=e}async browseMedia(t,e){return await this.hass.callWS({type:"media_player/browse_media",entity_id:this.playerId,media_content_type:t,media_content_id:e})}}class xt{constructor(t){this._entity=t,this.id=t.entity_id,this._state=t.state,this._attr=t.attributes}get isPaused(){return"paused"===this._state}get isPlaying(){return"playing"===this._state}get isIdle(){return"idle"===this._state}get isStandby(){return"standby"===this._state}get isUnavailable(){return"unavailable"===this._state}get isOff(){return"off"===this._state}get isActive(){return!this.isOff&&!this.isUnavailable&&!this.isIdle||!1}get mediaType(){return this._attr._media_type||""}get mediaId(){return this._attr._media_id||""}get currentTrack(){return this._attr.current_track}get playlistTitle(){return this._attr.current_playlist_title||""}get remotePlayerId(){return this._attr.remote_player_id||""}get muted(){return this._attr.is_volume_muted||!1}get shuffle(){return this._attr.shuffle||!1}get repeat(){return this._attr.repeat||"off"}get picture(){return this._attr.entity_picture_local||this._attr.entity_picture}get updatedAt(){return this._attr.media_position_updated_at||0}get position(){return this._attr.media_position||0}get duration(){return this._attr.media_duration||0}get progress(){if(this.isPlaying){const t=(Date.now()-new Date(this.updatedAt).getTime())/1e3;return(this.position+t)/this.duration*100}return this.position/this.duration*100}}class Ct{constructor(t,e){this.hass=t,this.config=e,this.haService=new St(t,e.entity),this.player=this._createPlayer(e.entity),this._extra=this._createExtra()}_createPlayer(t){const e=this.hass.states[t];if(!e)throw new Error("Player entity not found");return new xt(e)}_createExtra(){if(this.config.extra){const t=this.hass.states[this.config.extra];if(!t)throw new Error("Extra entity not found");return t}}}const Pt=(t,e,i=!1)=>{let s;const r=(...r)=>{const n=i&&!s;clearTimeout(s),s=window.setTimeout((()=>{s=void 0,i||t(...r)}),e),n&&t(...r)};return r.cancel=()=>{clearTimeout(s)},r};class kt extends ut{render(){return Z`
+
+ `}}kt.styles=l`
+ .loader {
+ height: 100%;
+ width: 100%;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ }
+ .music {
+ display: inline-flex;
+ position: relative;
+ max-width: calc(80% - 8px);
+ width: 100%;
+ max-height: calc(33% - 8px);
+ height: 100%;
+ align-items: center;
+ justify-content: space-between;
+ }
+
+ .bar {
+ width: 12px;
+ border-radius: 8px;
+ animation: loader 1.5s ease-in-out infinite;
+ }
+
+ @keyframes loader {
+ 0%,
+ 100% {
+ height: 2px;
+ }
+
+ 50% {
+ height: 80%;
+ }
+ }
+
+ .music .bar:nth-child(1) {
+ background: rgba(255, 255, 255, 0.1);
+ animation-delay: 1s;
+ }
+
+ .music .bar:nth-child(2) {
+ background: rgba(255, 255, 255, 0.3);
+ animation-delay: 0.8s;
+ }
+
+ .music .bar:nth-child(3) {
+ background: rgba(255, 255, 255, 0.5);
+ animation-delay: 0.6s;
+ }
+
+ .music .bar:nth-child(4) {
+ background: rgba(255, 255, 255, 0.7);
+ animation-delay: 0.4s;
+ }
+
+ .music .bar:nth-child(5) {
+ background: rgba(255, 255, 255, 0.9);
+ animation-delay: 0.2s;
+ }
+
+ .music .bar:nth-child(6) {
+ background: rgba(255, 255, 255, 0.9);
+ animation-delay: 0.2s;
+ }
+
+ .music .bar:nth-child(7) {
+ background: rgba(255, 255, 255, 0.7);
+ animation-delay: 0.4s;
+ }
+
+ .music .bar:nth-child(8) {
+ background: rgba(255, 255, 255, 0.5);
+ animation-delay: 0.6s;
+ }
+
+ .music .bar:nth-child(9) {
+ background: rgba(255, 255, 255, 0.3);
+ animation-delay: 0.8s;
+ }
+
+ .music .bar:nth-child(10) {
+ background: rgba(255, 255, 255, 0.1);
+ animation-delay: 1s;
+ }
+ `,customElements.define("ytube-playlist-loader",kt);var Tt=l`*,
+*::before,
+*::after {
+ box-sizing: border-box;
+}
+
+ha-card {
+ position: relative;
+ overflow: hidden;
+ width: 100%;
+ height: auto;
+ border: none !important;
+ border-radius: 0 !important;
+ background: none !important;
+ margin: 0;
+ padding: 0;
+}
+
+.grid::-webkit-scrollbar {
+ display: none !important;
+ /* Safari and Chrome */
+}
+
+
+.grid {
+ display: grid;
+ grid-template-columns: repeat(auto-fit, minmax(30%, 1fr));
+ grid-gap: 0.5em;
+ width: 100%;
+ height: 100%;
+ overflow-y: auto;
+ scroll-snap-type: y mandatory;
+ -ms-overflow-style: none;
+ scrollbar-width: none;
+}
+
+.grid-item {
+ position: relative;
+ overflow: hidden;
+ height: 100%;
+ border-radius: 1em;
+ cursor: pointer;
+ transition: all 0.4s cubic-bezier(0.075, 0.82, 0.165, 1);
+ box-shadow: rgba(0, 0, 0, 0.5) 0px 0px 10px;
+ border: 2px solid transparent;
+ scroll-snap-align: end;
+ scroll-snap-stop: always;
+}
+
+.grid-item:hover {
+ border-color: var(--primary-color);
+}
+
+.grid-item-thumbnail {
+ position: relative;
+ overflow: hidden;
+ height: 100%;
+ width: 100%;
+ filter: brightness(0.8);
+}
+
+.grid-item-thumbnail:hover {
+ filter: brightness(1);
+}
+
+.grid-item-thumbnail>img {
+ width: 100%;
+ height: 100%;
+ -o-object-fit: cover;
+ object-fit: cover;
+}
+
+.grid-item-title {
+ position: absolute;
+ top: 0;
+ left: 0;
+ opacity: 0;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ height: 100%;
+ width: 100%;
+ padding: 0em 0.1em;
+ overflow: hidden;
+ white-space: pretty;
+ text-align: center;
+ color: var(--text-primary-color);
+ font-size: 1.2em;
+ background-color: rgba(0, 0, 0, 0.7);
+ -webkit-backdrop-filter: blur(1px);
+ backdrop-filter: blur(1px);
+ transition: all 0.4s cubic-bezier(0.075, 0.82, 0.165, 1);
+}
+
+.grid-item:hover .grid-item-title {
+ opacity: 1;
+}`;let Ut=class extends ut{constructor(){super(...arguments),this._cardWidth=0,this._currentChunkIndex=0,this._chunkSize=40,this._chunks=[],this._renderedItems=[]}static get styles(){return Tt}async setConfig(t){if(!t.entity||"media_player"!==t.entity.split(".")[0])throw new Error("Specify an entity from within the media_player domain");this.config=t}connectedCallback(){super.connectedCallback(),window.YtubeCard=this,this.updateComplete.then((()=>this._attachObserver()))}disconnectedCallback(){super.disconnectedCallback(),this._resizeObserver&&this._resizeObserver.disconnect()}async _attachObserver(){this._resizeObserver||(this._resizeObserver=new ResizeObserver(Pt((()=>this._measureCard()),250,!1)));const t=this.shadowRoot.querySelector("ha-card");t&&this._resizeObserver.observe(t)}_measureCard(){const t=this.shadowRoot.querySelector("ha-card");t&&(this._cardWidth=t.clientWidth)}async firstUpdated(t){super.firstUpdated(t),this._attachObserver(),this._measureCard(),await this._loadContent()}async _loadContent(){this._loadingData=!0;const t=await this.store.haService.browseMedia("home2","Mixed for you");this._initialItems=t,this._loadingData=!1}_createStore(){this.store=new Ct(this.hass,this.config)}render(){return this.hass?(this._createStore(),Z`
+ ${this._loadingData?Z``:this._renderItems()}
+ `):Z``}_renderItems(){var t;const s=(null===(t=this._initialItems)||void 0===t?void 0:t.children)||[];0===this._chunks.length&&(this._chunks=e(s,this._chunkSize)),this._renderedItems=i(this._chunks.slice(0,this._currentChunkIndex+1));return Z`
+
+ ${this._renderedItems.map((t=>(t=>{const{thumbnail:e,title:i}=t;return Z`
+
{}}>
+
+
+
+
+ ${i}
+
+
+ `})(t)))}
+
+ `}_computeGridStyles(){const t=this._cardWidth,e=t/3*.9;return Et({gridTemplateColumns:`repeat(auto-fill, minmax(${e}px, 1fr))`,gridAutoRows:`${e+8}px`,gridGap:"8px",maxHeight:`${t}px`,overflowY:"auto"})}_handleScroll(t){const e=t.target;e.scrollHeight-e.scrollTop<=e.clientHeight+1&&this._loadMoreItems()}_loadMoreItems(){this._currentChunkIndex36,202
34 |
178 |
- 38 |
+ 63 |
52 |
- 31 |
- 1071 |
- 174 |
+ 30 |
+ 1083 |
+ 202 |
38 |
@@ -149,7 +149,6 @@ https://github.com/ngocjohn/hass-config/assets/96962827/acc1a4db-b92e-4ab1-ac9d-
- [Restriction Card](https://github.com/iantrich/restriction-card)
- [Roku Card](https://github.com/iantrich/roku-card)
- [Rpi Monitor Card](https://github.com/ironsheep/lovelace-rpi-monitor-card)
-- [Search Card](https://github.com/postlund/search-card)
- [Simple Thermostat](https://github.com/nervetattoo/simple-thermostat)
- [Slider Button Card](https://github.com/custom-cards/slider-button-card)
- [Spotify Lovelace Card](https://github.com/custom-cards/spotify-card)