diff --git a/layout-card.js b/layout-card.js index 2b200f8..1754cdb 100644 --- a/layout-card.js +++ b/layout-card.js @@ -10,7 +10,7 @@ function t(t,e,i,o){var s,n=arguments.length,a=n<3?e:null===o?o=Object.getOwnPro bottom: calc(16px + env(safe-area-inset-bottom)); z-index: 1; } - `}}t([tt()],St.prototype,"cards",void 0),t([tt()],St.prototype,"index",void 0),t([tt()],St.prototype,"narrow",void 0),t([tt()],St.prototype,"hass",void 0),t([tt()],St.prototype,"lovelace",void 0),t([tt()],St.prototype,"_editMode",void 0),t([tt()],St.prototype,"_config",void 0);class Mt extends St{constructor(){super(...arguments),this._mediaQueries=[]}async setConfig(t){var e,i,o,s;await super.setConfig(t);for(const t of this._config.cards)if("string"!=typeof(null===(e=t.view_layout)||void 0===e?void 0:e.show)&&(null===(o=null===(i=t.view_layout)||void 0===i?void 0:i.show)||void 0===o?void 0:o.mediaquery)){const e=window.matchMedia(`${t.view_layout.show.mediaquery}`);this._mediaQueries.push(e),e.addEventListener("change",(()=>this._makeLayout()))}else this._mediaQueries.push(null);this._observer&&this._observer.disconnect(),this._observer=new gt((()=>{this._updateSize()})),this._cardObserver&&this._cardObserver.disconnect(),(null===(s=t.layout)||void 0===s?void 0:s.reflow)&&(this._cardObserver=new MutationObserver((t=>{for(const e of t)"attributes"!==e.type||"style"!==e.attributeName&&"hidden"!==e.attributeName||this._makeLayout()})))}async updated(t){var e;await super.updated(t),(t.has("_columns")||t.has("cards"))&&this._makeLayout(),t.has("_editMode")&&this._makeLayout(),(t.has("narrow")||t.has("hass")&&(null===(e=t.get("hass"))||void 0===e?void 0:e.dockedSidebar)!=this.hass.dockedSidebar)&&(this._updateSize(),this._makeLayout())}async firstUpdated(){var t,e,i,o,s,n,a,r,l,d,c,h,u,p,v;this._updateSize();const g=(null===(t=this._config.layout)||void 0===t?void 0:t.width)||300,_=(null===(e=this._config.layout)||void 0===e?void 0:e.max_width)||((null===(i=this._config.layout)||void 0===i?void 0:i.width)?Math.ceil(1.5*(null===(o=this._config.layout)||void 0===o?void 0:o.width)):500),f=(null===(s=this._config.layout)||void 0===s?void 0:s.width)?2*this._config.layout.width:600,y=document.createElement("style");y.innerHTML=`\n :host {\n --column-max-width: ${_}px;\n --column-width: ${g}px;\n --column-widths: ${null!==(a=null===(n=this._config.layout)||void 0===n?void 0:n.column_widths)&&void 0!==a?a:"none"};\n --layout-margin: ${null!==(l=null===(r=this._config.layout)||void 0===r?void 0:r.margin)&&void 0!==l?l:"4px 4px 0px 4px"};\n --layout-padding: ${null!==(c=null===(d=this._config.layout)||void 0===d?void 0:d.padding)&&void 0!==c?c:"0px"};\n --card-margin: ${null!==(u=null===(h=this._config.layout)||void 0===h?void 0:h.card_margin)&&void 0!==u?u:"var(--masonry-view-card-margin, 4px 4px 8px)"};\n --layout-height: ${null!==(v=null===(p=this._config.layout)||void 0===p?void 0:p.height)&&void 0!==v?v:"auto"};\n }\n @media (max-width: ${_}px) {\n .column:first-child > * {\n margin-left: 0;\n }\n .column:last-child > * {\n margin-right: 0;\n }\n }\n @media (max-width: ${f-1}px) {\n .column {\n --column-max-width: ${f}px;\n }\n }\n `,this.shadowRoot.appendChild(y)}connectedCallback(){super.connectedCallback(),this._updateSize()}disconnectedCallback(){super.disconnectedCallback(),this._observer.disconnect()}async _updateSize(){var t,e,i;let o=this.getBoundingClientRect().width,s=0;s=Math.floor(o/((null===(t=this._config.layout)||void 0===t?void 0:t.width)||300)),s=Math.min(s,(null===(e=this._config.layout)||void 0===e?void 0:e.max_cols)||("docked"===(null===(i=this.hass)||void 0===i?void 0:i.dockedSidebar)?3:4)),s=Math.max(s,1),s!==this._columns&&(this._columns=s)}_shouldShow(t,e,i){var o;if(!super._shouldShow(t,e,i))return!1;if(null===(o=this._config.layout)||void 0===o?void 0:o.reflow){if("none"===getComputedStyle(t).display)return!1;if(!0===t.hidden)return!1}const s=this._mediaQueries[i];return!s||!!s.matches}isBreak(t){return"layout-break"===t.localName}async _makeLayout(){this._makeColumnLayout()}async _makeColumnLayout(){var t;if(this._observer.disconnect(),this._cardObserver&&this._cardObserver.disconnect(),!this._columns)return;let e=[];for(let t=0;t{const i=this._config.cards[e];return{card:t,config:i,index:e,show:this._shouldShow(t,i,e)}}));await this._placeColumnCards(e,i.filter((t=>{var e;return(null===(e=this.lovelace)||void 0===e?void 0:e.editMode)||t.show}))),e=e.filter((t=>t.childElementCount>0)),(null===(t=this._config.layout)||void 0===t?void 0:t.rtl)&&e.reverse();const o=this.shadowRoot.querySelector("#columns");for(;o.firstChild;)o.removeChild(o.firstChild);if(this._cardObserver)for(const t of this.cards)this._cardObserver.observe(t,{attributes:!0});for(const t of e)o.appendChild(t);this.requestUpdate(),await this.updateComplete,this._observer.observe(this)}async _placeColumnCards(t,e){}render(){return U` + `}}t([tt()],St.prototype,"cards",void 0),t([tt()],St.prototype,"index",void 0),t([tt()],St.prototype,"narrow",void 0),t([tt()],St.prototype,"hass",void 0),t([tt()],St.prototype,"lovelace",void 0),t([tt()],St.prototype,"_editMode",void 0),t([tt()],St.prototype,"_config",void 0);class Mt extends St{constructor(){super(...arguments),this._mediaQueries=[]}async setConfig(t){var e,i,o,s;await super.setConfig(t);for(const t of this._config.cards)if("string"!=typeof(null===(e=t.view_layout)||void 0===e?void 0:e.show)&&(null===(o=null===(i=t.view_layout)||void 0===i?void 0:i.show)||void 0===o?void 0:o.mediaquery)){const e=window.matchMedia(`${t.view_layout.show.mediaquery}`);this._mediaQueries.push(e),e.addEventListener("change",(()=>this._makeLayout()))}else this._mediaQueries.push(null);this._observer&&this._observer.disconnect(),this._observer=new gt((()=>{this._updateSize()})),this._cardObserver&&this._cardObserver.disconnect(),(null===(s=t.layout)||void 0===s?void 0:s.reflow)&&(this._cardObserver=new MutationObserver((t=>{for(const e of t)"attributes"!==e.type||"style"!==e.attributeName&&"hidden"!==e.attributeName||this._makeLayout()})))}async updated(t){var e;await super.updated(t),(t.has("_columns")||t.has("cards"))&&this._makeLayout(),t.has("_editMode")&&this._makeLayout(),(t.has("narrow")||t.has("hass")&&(null===(e=t.get("hass"))||void 0===e?void 0:e.dockedSidebar)!=this.hass.dockedSidebar)&&(this._updateSize(),this._makeLayout())}async firstUpdated(){var t,e,i,o,s,n,a,r,l,d,c,h,u,p,v,g;this._updateSize();const _=(null===(t=this._config.layout)||void 0===t?void 0:t.width)||300,f=(null===(e=this._config.layout)||void 0===e?void 0:e.max_width)||((null===(i=this._config.layout)||void 0===i?void 0:i.width)?Math.ceil(1.5*(null===(o=this._config.layout)||void 0===o?void 0:o.width)):500),y=(null===(s=this._config.layout)||void 0===s?void 0:s.width)?2*this._config.layout.width:600,m=document.createElement("style");m.innerHTML=`\n :host {\n --column-max-width: ${f}px;\n --column-width: ${_}px;\n --column-widths: ${null!==(a=null===(n=this._config.layout)||void 0===n?void 0:n.column_widths)&&void 0!==a?a:"none"};\n --layout-margin: ${null!==(l=null===(r=this._config.layout)||void 0===r?void 0:r.margin)&&void 0!==l?l:"4px 4px 0px 4px"};\n --layout-padding: ${null!==(c=null===(d=this._config.layout)||void 0===d?void 0:d.padding)&&void 0!==c?c:"0px"};\n --card-margin: ${null!==(u=null===(h=this._config.layout)||void 0===h?void 0:h.card_margin)&&void 0!==u?u:"var(--masonry-view-card-margin, 4px 4px 8px)"};\n --layout-height: ${null!==(v=null===(p=this._config.layout)||void 0===p?void 0:p.height)&&void 0!==v?v:"auto"};\n --layout-overflow: ${void 0!==(null===(g=this._config.layout)||void 0===g?void 0:g.height)?"auto":"visible"};\n }\n @media (max-width: ${f}px) {\n .column:first-child > * {\n margin-left: 0;\n }\n .column:last-child > * {\n margin-right: 0;\n }\n }\n @media (max-width: ${y-1}px) {\n .column {\n --column-max-width: ${y}px;\n }\n }\n `,this.shadowRoot.appendChild(m)}connectedCallback(){super.connectedCallback(),this._updateSize()}disconnectedCallback(){super.disconnectedCallback(),this._observer.disconnect()}async _updateSize(){var t,e,i;let o=this.getBoundingClientRect().width,s=0;s=Math.floor(o/((null===(t=this._config.layout)||void 0===t?void 0:t.width)||300)),s=Math.min(s,(null===(e=this._config.layout)||void 0===e?void 0:e.max_cols)||("docked"===(null===(i=this.hass)||void 0===i?void 0:i.dockedSidebar)?3:4)),s=Math.max(s,1),s!==this._columns&&(this._columns=s)}_shouldShow(t,e,i){var o;if(!super._shouldShow(t,e,i))return!1;if(null===(o=this._config.layout)||void 0===o?void 0:o.reflow){if("none"===getComputedStyle(t).display)return!1;if(!0===t.hidden)return!1}const s=this._mediaQueries[i];return!s||!!s.matches}isBreak(t){return"layout-break"===t.localName}async _makeLayout(){this._makeColumnLayout()}async _makeColumnLayout(){var t;if(this._observer.disconnect(),this._cardObserver&&this._cardObserver.disconnect(),!this._columns)return;let e=[];for(let t=0;t{const i=this._config.cards[e];return{card:t,config:i,index:e,show:this._shouldShow(t,i,e)}}));await this._placeColumnCards(e,i.filter((t=>{var e;return(null===(e=this.lovelace)||void 0===e?void 0:e.editMode)||t.show}))),e=e.filter((t=>t.childElementCount>0)),(null===(t=this._config.layout)||void 0===t?void 0:t.rtl)&&e.reverse();const o=this.shadowRoot.querySelector("#columns");for(;o.firstChild;)o.removeChild(o.firstChild);if(this._cardObserver)for(const t of this.cards)this._cardObserver.observe(t,{attributes:!0});for(const t of e)o.appendChild(t);this.requestUpdate(),await this.updateComplete,this._observer.observe(this)}async _placeColumnCards(t,e){}render(){return U`
${this._render_fab()} `}static get styles(){return[this._fab_styles,n` @@ -18,7 +18,7 @@ function t(t,e,i,o){var s,n=arguments.length,a=n<3?e:null===o?o=Object.getOwnPro display: block; height: 100%; box-sizing: border-box; - overflow-y: auto; + overflow-y: var(--layout-overflow); } #columns { @@ -33,7 +33,7 @@ function t(t,e,i,o){var s,n=arguments.length,a=n<3?e:null===o?o=Object.getOwnPro margin: var(--layout-margin); padding: var(--layout-padding); height: var(--layout-height); - overflow-y: auto; + overflow-y: var(--layout-overflow); } .column { grid-row: 1/2; @@ -44,7 +44,7 @@ function t(t,e,i,o){var s,n=arguments.length,a=n<3?e:null===o?o=Object.getOwnPro display: block; margin: var(--card-margin); } - `]}}t([tt()],Mt.prototype,"_columns",void 0),t([tt()],Mt.prototype,"_config",void 0);customElements.define("masonry-layout",class extends Mt{async _placeColumnCards(t,e){var i;const o=(null===(i=this._config.layout)||void 0===i?void 0:i.min_height)||5;function s(){let e=0;for(let i=0;ithis._placeCards()))}else this._mediaQueries.push(null);if(null===(s=this._config.layout)||void 0===s?void 0:s.mediaquery)for(const[t,e]of Object.entries(null===(n=this._config.layout)||void 0===n?void 0:n.mediaquery)){const e=window.matchMedia(t);this._layoutMQs.push(e),e.addEventListener("change",(()=>this._setGridStyles()))}this._setGridStyles()}async updated(t){await super.updated(t),(t.has("cards")||t.has("_editMode"))&&this._placeCards()}async firstUpdated(){var t,e,i,o,s,n;this._setGridStyles();const a=document.createElement("style");a.innerHTML=`\n :host {\n --layout-margin: ${null!==(e=null===(t=this._config.layout)||void 0===t?void 0:t.margin)&&void 0!==e?e:"4px 4px 0px 4px"};\n --layout-padding: ${null!==(o=null===(i=this._config.layout)||void 0===i?void 0:i.padding)&&void 0!==o?o:"0px"};\n --layout-height: ${null!==(n=null===(s=this._config.layout)||void 0===s?void 0:s.height)&&void 0!==n?n:"auto"};\n }`,this.shadowRoot.appendChild(a)}_setGridStyles(){const t=this.shadowRoot.querySelector("#root");if(!t)return;const e=e=>{for(const[i,o]of Object.entries(e))(i.startsWith("grid")||"grid"===i||"place-items"===i||"place-content"===i)&&t.style.setProperty(i,o)};t.style.cssText="",this._config.layout&&e(this._config.layout);for(const t of this._layoutMQs)if(t.matches){e(this._config.layout.mediaquery[t.media]);break}}_shouldShow(t,e,i){if(!super._shouldShow(t,e,i))return!1;const o=this._mediaQueries[i];return!o||!!o.matches}_placeCards(){var t,e;const i=this.shadowRoot.querySelector("#root");for(;i.firstChild;)i.removeChild(i.firstChild);let o=this.cards.map(((t,e)=>{const i=this._config.cards[e];return{card:t,config:i,index:e,show:this._shouldShow(t,i,e)}}));for(const s of o.filter((t=>{var e;return(null===(e=this.lovelace)||void 0===e?void 0:e.editMode)||t.show}))){const o=this.getCardElement(s);for(const[i,n]of Object.entries(null!==(e=null===(t=s.config)||void 0===t?void 0:t.view_layout)&&void 0!==e?e:{}))(i.startsWith("grid")||"place-self"===i)&&o.style.setProperty(i,n);i.appendChild(o)}}render(){return U`
+ `]}}t([tt()],Mt.prototype,"_columns",void 0),t([tt()],Mt.prototype,"_config",void 0);customElements.define("masonry-layout",class extends Mt{async _placeColumnCards(t,e){var i;const o=(null===(i=this._config.layout)||void 0===i?void 0:i.min_height)||5;function s(){let e=0;for(let i=0;isetTimeout((()=>t(1)),500)))]):1}}});customElements.define("horizontal-layout",class extends Mt{async _placeColumnCards(t,e){var i,o;let s=0;for(const n of e){s+=1,(null===(i=n.config.view_layout)||void 0===i?void 0:i.column)&&(s=n.config.view_layout.column);const e=t[(s-1)%t.length];e.appendChild(this.getCardElement(n)),this.isBreak(n.card)&&(s=0,(null===(o=this.lovelace)||void 0===o?void 0:o.editMode)||e.removeChild(n.card))}}});customElements.define("vertical-layout",class extends Mt{async _placeColumnCards(t,e){var i;let o=1;for(const s of e){(null===(i=s.config.view_layout)||void 0===i?void 0:i.column)&&(o=s.config.view_layout.column);t[(o-1)%t.length].appendChild(this.getCardElement(s)),this.isBreak(s.card)&&(o+=1)}}});class Tt extends HTMLElement{setConfig(){this.style.display="none";const t=document.createElement("ha-card");t.innerHTML="BREAK",t.style.cssText="\n background: red;\n text-align: center;\n font-size: large;\n color: white;\n padding: 16px;\n ",this.appendChild(t)}getCardSize(){return 0}set editMode(t){this.style.display=t?"block":"none"}static getConfigElement(){return document.createElement("layout-break-editor")}static getStubConfig(){return{}}}customElements.define("layout-break",Tt),window.customCards=window.customCards||[],window.customCards.push({type:"layout-break",name:"Layout Break",preview:!1,description:"Forces a break in the layout flow. For use with layout-card or special layouts."});class Ot extends HTMLElement{setConfig(t){const e=document.createElement("div");e.innerHTML="BREAK",this.appendChild(e)}}customElements.define("layout-break-editor",Ot);customElements.define("grid-layout",class extends St{constructor(){super(...arguments),this._mediaQueries=[],this._layoutMQs=[]}async setConfig(t){var e,i,o,s,n;await super.setConfig(t);for(const t of this._config.cards)if("string"!=typeof(null===(e=t.view_layout)||void 0===e?void 0:e.show)&&(null===(o=null===(i=t.view_layout)||void 0===i?void 0:i.show)||void 0===o?void 0:o.mediaquery)){const e=window.matchMedia(`${t.view_layout.show.mediaquery}`);this._mediaQueries.push(e),e.addEventListener("change",(()=>this._placeCards()))}else this._mediaQueries.push(null);if(null===(s=this._config.layout)||void 0===s?void 0:s.mediaquery)for(const[t,e]of Object.entries(null===(n=this._config.layout)||void 0===n?void 0:n.mediaquery)){const e=window.matchMedia(t);this._layoutMQs.push(e),e.addEventListener("change",(()=>this._setGridStyles()))}this._setGridStyles()}async updated(t){await super.updated(t),(t.has("cards")||t.has("_editMode"))&&this._placeCards()}async firstUpdated(){var t,e,i,o,s,n,a;this._setGridStyles();const r=document.createElement("style");r.innerHTML=`\n :host {\n --layout-margin: ${null!==(e=null===(t=this._config.layout)||void 0===t?void 0:t.margin)&&void 0!==e?e:"4px 4px 0px 4px"};\n --layout-padding: ${null!==(o=null===(i=this._config.layout)||void 0===i?void 0:i.padding)&&void 0!==o?o:"0px"};\n --layout-height: ${null!==(n=null===(s=this._config.layout)||void 0===s?void 0:s.height)&&void 0!==n?n:"auto"};\n --layout-overflow: ${void 0!==(null===(a=this._config.layout)||void 0===a?void 0:a.height)?"auto":"visible"};\n }`,this.shadowRoot.appendChild(r)}_setGridStyles(){const t=this.shadowRoot.querySelector("#root");if(!t)return;const e=e=>{for(const[i,o]of Object.entries(e))(i.startsWith("grid")||"grid"===i||"place-items"===i||"place-content"===i)&&t.style.setProperty(i,o)};t.style.cssText="",this._config.layout&&e(this._config.layout);for(const t of this._layoutMQs)if(t.matches){e(this._config.layout.mediaquery[t.media]);break}}_shouldShow(t,e,i){if(!super._shouldShow(t,e,i))return!1;const o=this._mediaQueries[i];return!o||!!o.matches}_placeCards(){var t,e;const i=this.shadowRoot.querySelector("#root");for(;i.firstChild;)i.removeChild(i.firstChild);let o=this.cards.map(((t,e)=>{const i=this._config.cards[e];return{card:t,config:i,index:e,show:this._shouldShow(t,i,e)}}));for(const s of o.filter((t=>{var e;return(null===(e=this.lovelace)||void 0===e?void 0:e.editMode)||t.show}))){const o=this.getCardElement(s);for(const[i,n]of Object.entries(null!==(e=null===(t=s.config)||void 0===t?void 0:t.view_layout)&&void 0!==e?e:{}))(i.startsWith("grid")||"place-self"===i)&&o.style.setProperty(i,n);i.appendChild(o)}}render(){return U`
${this._render_fab()}`}static get styles(){return[this._fab_styles,n` :host { height: 100%; @@ -56,7 +56,7 @@ function t(t,e,i,o){var s,n=arguments.length,a=n<3?e:null===o?o=Object.getOwnPro margin: var(--layout-margin); padding: var(--layout-padding); height: var(--layout-height); - overflow-y: auto; + overflow-y: var(--layout-overflow); } #root > * { margin: var(--masonry-view-card-margin, 4px 4px 8px); @@ -68,7 +68,7 @@ function t(t,e,i,o){var s,n=arguments.length,a=n<3?e:null===o?o=Object.getOwnPro :host(:not(:last-child)) { margin-bottom: 0 !important; } - `}static getConfigElement(){return document.createElement("layout-card-editor")}static getStubConfig(){return{layout_type:"masonry",layout:{},cards:[]}}}t([tt()],kt.prototype,"hass",void 0),t([tt()],kt.prototype,"editMode",void 0),t([tt()],kt.prototype,"isPanel",void 0),t([tt()],kt.prototype,"_config",void 0),t([tt()],kt.prototype,"_cards",void 0),t([tt()],kt.prototype,"_layoutElement",void 0),t([tt()],kt.prototype,"_layoutType",void 0),customElements.define("layout-card",kt),window.customCards=window.customCards||[],window.customCards.push({type:"layout-card",name:"Layout Card",preview:!1,description:"Like a stack card, but with way more control."});const Ut=["masonry","horizontal","vertical","grid"];class Pt extends Y{constructor(){super(...arguments),this._selectedTab=0,this._selectedCard=0,this._cardGUIMode=!0,this._cardGUIModeAvailable=!0}setConfig(t){this._config=t,console.log(this._config)}_handleSwitchTab(t){this._selectedTab=parseInt(t.detail.index,10)}_layoutChanged(t){t.stopPropagation();const e=t.target;this._config=Object.assign({},this._config),"layout_type"===e.id&&("default"===e.value?delete this._config.layout_type:this._config.layout_type=e.value),"layout"===e.id&&(this._config.layout=e.value),this.dispatchEvent(new CustomEvent("config-changed",{detail:{config:this._config}}))}_editCard(t){t.stopPropagation(),"add-card"!==t.target.id?(this._cardGUIMode=!0,this._cardEditorEl&&(this._cardEditorEl.GUImode=!0),this._cardGUIModeAvailable=!0,this._selectedCard=parseInt(t.detail.selected,10)):this._selectedCard=this._config.cards.length}_addCard(t){t.stopPropagation();const e=[...this._config.cards];e.push(t.detail.config),this._config=Object.assign(Object.assign({},this._config),{cards:e}),this._selectedCard=this._config.cards.length-1,this.dispatchEvent(new CustomEvent("config-changed",{detail:{config:this._config}}))}_updateCard(t){t.stopPropagation();const e=[...this._config.cards];e[this._selectedCard]=t.detail.config,this._config=Object.assign(Object.assign({},this._config),{cards:e}),this._cardGUIModeAvailable=t.detail.guiModeAvailable,this.dispatchEvent(new CustomEvent("config-changed",{detail:{config:this._config}}))}_GUIModeChange(t){t.stopPropagation(),this._cardGUIMode=t.detail.guiMode,this._cardGUIModeAvailable=t.detail.guiModeAvailable}_toggleMode(t){this._cardEditorEl.toggleMode()}_moveCard(t){const e=this._selectedCard,i=e+t.currentTarget.move,o=[...this._config.cards],s=o.splice(e,1)[0];o.splice(i,0,s),this._config=Object.assign(Object.assign({},this._config),{cards:o}),this._selectedCard=i,this.dispatchEvent(new CustomEvent("config-changed",{detail:{config:this._config}}))}_deleteCard(){const t=[...this._config.cards];t.splice(this._selectedCard,1),this._config=Object.assign(Object.assign({},this._config),{cards:t}),this._selectedCard=Math.max(0,this._selectedCard-1),this.dispatchEvent(new CustomEvent("config-changed",{detail:{config:this._config}}))}render(){return this.hass&&this._config?U` + `}static getConfigElement(){return document.createElement("layout-card-editor")}static getStubConfig(){return{layout_type:"masonry",layout:{},cards:[]}}}t([tt()],kt.prototype,"hass",void 0),t([tt()],kt.prototype,"editMode",void 0),t([tt()],kt.prototype,"isPanel",void 0),t([tt()],kt.prototype,"_config",void 0),t([tt()],kt.prototype,"_cards",void 0),t([tt()],kt.prototype,"_layoutElement",void 0),t([tt()],kt.prototype,"_layoutType",void 0),customElements.define("layout-card",kt),window.customCards=window.customCards||[],window.customCards.push({type:"layout-card",name:"Layout Card",preview:!1,description:"Like a stack card, but with way more control."});const Ut=async()=>{var t,e,i,o,s,n,a,r;if(customElements.get("ha-yaml-editor"))return;const l=document.createElement("partial-panel-resolver").getRoutes([{component_name:"developer-tools",url_path:"a"}]);await(null===(i=null===(e=null===(t=null==l?void 0:l.routes)||void 0===t?void 0:t.a)||void 0===e?void 0:e.load)||void 0===i?void 0:i.call(e));const d=document.createElement("developer-tools-router");await(null===(r=null===(a=null===(n=null===(s=null===(o=d)||void 0===o?void 0:o.routerOptions)||void 0===s?void 0:s.routes)||void 0===n?void 0:n.service)||void 0===a?void 0:a.load)||void 0===r?void 0:r.call(a))},Pt=["masonry","horizontal","vertical","grid"];class Lt extends Y{constructor(){super(...arguments),this._selectedTab=0,this._selectedCard=0,this._cardGUIMode=!0,this._cardGUIModeAvailable=!0}setConfig(t){this._config=t}firstUpdated(){Ut()}_handleSwitchTab(t){this._selectedTab=parseInt(t.detail.index,10)}_layoutChanged(t){t.stopPropagation();const e=t.target;this._config=Object.assign({},this._config),"layout_type"===e.id&&("default"===e.value?delete this._config.layout_type:this._config.layout_type=e.value),"layout"===e.id&&(this._config.layout=e.value),this.dispatchEvent(new CustomEvent("config-changed",{detail:{config:this._config}}))}_editCard(t){t.stopPropagation(),"add-card"!==t.target.id?(this._cardGUIMode=!0,this._cardEditorEl&&(this._cardEditorEl.GUImode=!0),this._cardGUIModeAvailable=!0,this._selectedCard=parseInt(t.detail.selected,10)):this._selectedCard=this._config.cards.length}_addCard(t){t.stopPropagation();const e=[...this._config.cards];e.push(t.detail.config),this._config=Object.assign(Object.assign({},this._config),{cards:e}),this._selectedCard=this._config.cards.length-1,this.dispatchEvent(new CustomEvent("config-changed",{detail:{config:this._config}}))}_updateCard(t){t.stopPropagation();const e=[...this._config.cards];e[this._selectedCard]=t.detail.config,this._config=Object.assign(Object.assign({},this._config),{cards:e}),this._cardGUIModeAvailable=t.detail.guiModeAvailable,this.dispatchEvent(new CustomEvent("config-changed",{detail:{config:this._config}}))}_GUIModeChange(t){t.stopPropagation(),this._cardGUIMode=t.detail.guiMode,this._cardGUIModeAvailable=t.detail.guiModeAvailable}_toggleMode(t){this._cardEditorEl.toggleMode()}_moveCard(t){const e=this._selectedCard,i=e+t.currentTarget.move,o=[...this._config.cards],s=o.splice(e,1)[0];o.splice(i,0,s),this._config=Object.assign(Object.assign({},this._config),{cards:o}),this._selectedCard=i,this.dispatchEvent(new CustomEvent("config-changed",{detail:{config:this._config}}))}_deleteCard(){const t=[...this._config.cards];t.splice(this._selectedCard,1),this._config=Object.assign(Object.assign({},this._config),{cards:t}),this._selectedCard=Math.max(0,this._selectedCard-1),this.dispatchEvent(new CustomEvent("config-changed",{detail:{config:this._config}}))}render(){return this.hass&&this._config?U`
${this.hass.localize("ui.panel.lovelace.editor.edit_view.types.masonry")} - ${Ut.map((t=>U` + ${Pt.map((t=>U` ${t} (layout-card) `))} @@ -213,7 +213,7 @@ function t(t,e,i,o){var s,n=arguments.length,a=n<3?e:null===o?o=Object.getOwnPro .gui-mode-button { margin-right: auto; } - `]}}t([tt()],Pt.prototype,"_config",void 0),t([tt()],Pt.prototype,"lovelace",void 0),t([tt()],Pt.prototype,"hass",void 0),t([et()],Pt.prototype,"_selectedTab",void 0),t([et()],Pt.prototype,"_selectedCard",void 0),t([et()],Pt.prototype,"_cardGUIMode",void 0),t([et()],Pt.prototype,"_cardGUIModeAvailable",void 0),t([function(t,e){return(({finisher:t,descriptor:e})=>(i,o)=>{var s;if(void 0===o){const o=null!==(s=i.originalKey)&&void 0!==s?s:i.key,n=null!=e?{kind:"method",placement:"prototype",key:o,descriptor:e(i.key)}:{...i,key:o};return null!=t&&(n.finisher=function(e){t(e,o)}),n}{const s=i.constructor;void 0!==e&&Object.defineProperty(i,o,e(o)),null==t||t(s,o)}})({descriptor:i=>{const o={get(){var e,i;return null!==(i=null===(e=this.renderRoot)||void 0===e?void 0:e.querySelector(t))&&void 0!==i?i:null},enumerable:!0,configurable:!0};if(e){const e="symbol"==typeof i?Symbol():"__"+i;o.get=function(){var i,o;return void 0===this[e]&&(this[e]=null!==(o=null===(i=this.renderRoot)||void 0===i?void 0:i.querySelector(t))&&void 0!==o?o:null),this[e]}}return o}})}("hui-card-element-editor")],Pt.prototype,"_cardEditorEl",void 0),customElements.define("layout-card-editor",Pt),customElements.whenDefined("hui-card-element-editor").then((()=>{const t=customElements.get("hui-card-element-editor"),e=t.prototype.getConfigElement;t.prototype.getConfigElement=async function(){const t=await e.bind(this)();if(t){const e=t.setConfig;t.setConfig=function(t){let i=JSON.parse(JSON.stringify(t));this._layoutData=i.view_layout,delete i.view_layout,e.bind(this)(i)}}return t};const i=t.prototype._handleUIConfigChanged;t.prototype._handleUIConfigChanged=function(t){this._configElement&&this._configElement._layoutData&&(t.detail.config.view_layout=this._configElement._layoutData),i.bind(this)(t)}}));const Lt=["masonry","horizontal","vertical","grid"];customElements.whenDefined("hui-view-editor").then((()=>{const t=customElements.get("hui-view-editor");(async()=>{var t,e,i,o,s,n,a,r;const l=document.createElement("partial-panel-resolver").getRoutes([{component_name:"developer-tools",url_path:"a"}]);await(null===(i=null===(e=null===(t=null==l?void 0:l.routes)||void 0===t?void 0:t.a)||void 0===e?void 0:e.load)||void 0===i?void 0:i.call(e));const d=document.createElement("developer-tools-router");await(null===(r=null===(a=null===(n=null===(s=null===(o=d)||void 0===o?void 0:o.routerOptions)||void 0===s?void 0:s.routes)||void 0===n?void 0:n.service)||void 0===a?void 0:a.load)||void 0===r?void 0:r.call(a))})();const e=t.prototype.firstUpdated;t.prototype.firstUpdated=function(){var t;null==e||e.bind(this)();const i=this.shadowRoot.querySelector("mwc-select");if(!i||i.layoutCardPatch)return;Lt.forEach((t=>{const e=document.createElement("mwc-list-item");e.value=`custom:${t}-layout`,e.innerHTML=`${t} (layout-card)`,i.appendChild(e)})),i.layoutCardPatched=!0;const o=document.createElement("ha-yaml-editor");o.label="Layout options",o.defaultValue=null!==(t=this._config.layout)&&void 0!==t?t:"",o.addEventListener("value-changed",(t=>{t.stopPropagation();const e=Object.assign({},this._config);e.layout=t.detail.value,this.dispatchEvent(new CustomEvent("view-config-changed",{detail:{config:e}}))})),this.shadowRoot.appendChild(o)};const i=t.prototype.updated;t.prototype.updated=function(t){if(null==i||i.bind(this)(t),t.has("_config")){const t=this.shadowRoot.querySelector("ha-yaml-editor");if(t)return;t.defaultValue=this._config.layout}}}));class Rt extends HTMLElement{setConfig(t){var e,i;this.height=null!==(e=t.height)&&void 0!==e?e:50,this.size=null!==(i=t.size)&&void 0!==i?i:Math.ceil(this.height/50),this.style.cssText=`\n display: block;\n height: ${this.height}px;\n `}getCardSize(){return this.size}static getConfigElement(){return document.createElement("gap-card-editor")}static getStubConfig(){return{}}}customElements.define("gap-card",Rt),window.customCards=window.customCards||[],window.customCards.push({type:"gap-card",name:"Gap Card",preview:!1,description:"Add a customizable gap in the layout."});class zt extends Y{setConfig(t){this._config=t}heightChanged(t){const e=Object.assign({},this._config);delete e.height,t.detail.value&&(e.height=parseInt(t.detail.value)),this._config=e,this.dispatchEvent(new CustomEvent("config-changed",{detail:{config:e}}))}sizeChanged(t){const e=Object.assign({},this._config);delete e.size,t.detail.value&&(e.size=parseInt(t.detail.value)),this._config=e,this.dispatchEvent(new CustomEvent("config-changed",{detail:{config:e}}))}render(){return U` + `]}}t([tt()],Lt.prototype,"_config",void 0),t([tt()],Lt.prototype,"lovelace",void 0),t([tt()],Lt.prototype,"hass",void 0),t([et()],Lt.prototype,"_selectedTab",void 0),t([et()],Lt.prototype,"_selectedCard",void 0),t([et()],Lt.prototype,"_cardGUIMode",void 0),t([et()],Lt.prototype,"_cardGUIModeAvailable",void 0),t([function(t,e){return(({finisher:t,descriptor:e})=>(i,o)=>{var s;if(void 0===o){const o=null!==(s=i.originalKey)&&void 0!==s?s:i.key,n=null!=e?{kind:"method",placement:"prototype",key:o,descriptor:e(i.key)}:{...i,key:o};return null!=t&&(n.finisher=function(e){t(e,o)}),n}{const s=i.constructor;void 0!==e&&Object.defineProperty(i,o,e(o)),null==t||t(s,o)}})({descriptor:i=>{const o={get(){var e,i;return null!==(i=null===(e=this.renderRoot)||void 0===e?void 0:e.querySelector(t))&&void 0!==i?i:null},enumerable:!0,configurable:!0};if(e){const e="symbol"==typeof i?Symbol():"__"+i;o.get=function(){var i,o;return void 0===this[e]&&(this[e]=null!==(o=null===(i=this.renderRoot)||void 0===i?void 0:i.querySelector(t))&&void 0!==o?o:null),this[e]}}return o}})}("hui-card-element-editor")],Lt.prototype,"_cardEditorEl",void 0),customElements.define("layout-card-editor",Lt),customElements.whenDefined("hui-card-element-editor").then((()=>{const t=customElements.get("hui-card-element-editor"),e=t.prototype.getConfigElement;t.prototype.getConfigElement=async function(){const t=await e.bind(this)();if(t){const e=t.setConfig;t.setConfig=function(t){let i=JSON.parse(JSON.stringify(t));this._layoutData=i.view_layout,delete i.view_layout,e.bind(this)(i)}}return t};const i=t.prototype._handleUIConfigChanged;t.prototype._handleUIConfigChanged=function(t){this._configElement&&this._configElement._layoutData&&(t.detail.config.view_layout=this._configElement._layoutData),i.bind(this)(t)}}));const Rt=["masonry","horizontal","vertical","grid"];customElements.whenDefined("hui-view-editor").then((()=>{const t=customElements.get("hui-view-editor");Ut();const e=t.prototype.firstUpdated;t.prototype.firstUpdated=function(){var t;null==e||e.bind(this)();const i=this.shadowRoot.querySelector("mwc-select");if(!i||i.layoutCardPatch)return;Rt.forEach((t=>{const e=document.createElement("mwc-list-item");e.value=`custom:${t}-layout`,e.innerHTML=`${t} (layout-card)`,i.appendChild(e)})),i.layoutCardPatched=!0;const o=document.createElement("ha-yaml-editor");o.label="Layout options",o.defaultValue=null!==(t=this._config.layout)&&void 0!==t?t:"",o.addEventListener("value-changed",(t=>{t.stopPropagation();const e=Object.assign({},this._config);e.layout=t.detail.value,this.dispatchEvent(new CustomEvent("view-config-changed",{detail:{config:e}}))})),this.shadowRoot.appendChild(o)};const i=t.prototype.updated;t.prototype.updated=function(t){if(null==i||i.bind(this)(t),t.has("_config")){const t=this.shadowRoot.querySelector("ha-yaml-editor");if(!t)return;t.defaultValue=this._config.layout}}}));class zt extends HTMLElement{setConfig(t){var e,i;this.height=null!==(e=t.height)&&void 0!==e?e:50,this.size=null!==(i=t.size)&&void 0!==i?i:Math.ceil(this.height/50),this.style.cssText=`\n display: block;\n height: ${this.height}px;\n `}getCardSize(){return this.size}static getConfigElement(){return document.createElement("gap-card-editor")}static getStubConfig(){return{}}}customElements.define("gap-card",zt),window.customCards=window.customCards||[],window.customCards.push({type:"gap-card",name:"Gap Card",preview:!1,description:"Add a customizable gap in the layout."});class Ht extends Y{setConfig(t){this._config=t}heightChanged(t){const e=Object.assign({},this._config);delete e.height,t.detail.value&&(e.height=parseInt(t.detail.value)),this._config=e,this.dispatchEvent(new CustomEvent("config-changed",{detail:{config:e}}))}sizeChanged(t){const e=Object.assign({},this._config);delete e.size,t.detail.value&&(e.size=parseInt(t.detail.value)),this._config=e,this.dispatchEvent(new CustomEvent("config-changed",{detail:{config:e}}))}render(){return U` - `}}t([tt()],zt.prototype,"_config",void 0),customElements.define("gap-card-editor",zt);var Ht="2.4.0";console.info(`%cLAYOUT-CARD ${Ht} IS INSTALLED`,"color: green; font-weight: bold",""); + `}}t([tt()],Ht.prototype,"_config",void 0),customElements.define("gap-card-editor",Ht);var Nt="2.4.1";console.info(`%cLAYOUT-CARD ${Nt} IS INSTALLED`,"color: green; font-weight: bold",""); diff --git a/package.json b/package.json index d13af83..8872273 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "layout-card", - "version": "2.4.0", + "version": "2.4.1", "description": "", "private": true, "scripts": { diff --git a/src/helpers.ts b/src/helpers.ts new file mode 100644 index 0000000..6980baa --- /dev/null +++ b/src/helpers.ts @@ -0,0 +1,15 @@ +export const loadHaYamlEditor = async () => { + if (customElements.get("ha-yaml-editor")) return; + + // Load in ha-yaml-editor from developer-tools-service + const ppResolver = document.createElement("partial-panel-resolver"); + const routes = (ppResolver as any).getRoutes([ + { + component_name: "developer-tools", + url_path: "a", + }, + ]); + await routes?.routes?.a?.load?.(); + const devToolsRouter = document.createElement("developer-tools-router"); + await (devToolsRouter as any)?.routerOptions?.routes?.service?.load?.(); +}; diff --git a/src/layout-card-editor.ts b/src/layout-card-editor.ts index dbbc551..4c52181 100644 --- a/src/layout-card-editor.ts +++ b/src/layout-card-editor.ts @@ -1,8 +1,8 @@ import { LitElement, html, CSSResultArray, css } from "lit"; import { property, state, query } from "lit/decorators.js"; import { LayoutCardConfig } from "./types"; +import { loadHaYamlEditor } from "./helpers"; -const LAYOUT_TYPES = ["masonry", "panel", "sidebar"]; const CUSTOM_LAYOUT_TYPES = ["masonry", "horizontal", "vertical", "grid"]; class LayoutCardEditor extends LitElement { @@ -19,7 +19,10 @@ class LayoutCardEditor extends LitElement { setConfig(config) { this._config = config; - console.log(this._config); + } + + firstUpdated() { + loadHaYamlEditor(); } _handleSwitchTab(ev: CustomEvent) { diff --git a/src/layouts/base-column-layout.ts b/src/layouts/base-column-layout.ts index 358d09c..19039ad 100644 --- a/src/layouts/base-column-layout.ts +++ b/src/layouts/base-column-layout.ts @@ -97,6 +97,9 @@ export class BaseColumnLayout extends BaseLayout { "var(--masonry-view-card-margin, 4px 4px 8px)" }; --layout-height: ${this._config.layout?.height ?? "auto"}; + --layout-overflow: ${ + this._config.layout?.height !== undefined ? "auto" : "visible" + }; } @media (max-width: ${column_max_width}px) { .column:first-child > * { @@ -226,7 +229,7 @@ export class BaseColumnLayout extends BaseLayout { display: block; height: 100%; box-sizing: border-box; - overflow-y: auto; + overflow-y: var(--layout-overflow); } #columns { @@ -241,7 +244,7 @@ export class BaseColumnLayout extends BaseLayout { margin: var(--layout-margin); padding: var(--layout-padding); height: var(--layout-height); - overflow-y: auto; + overflow-y: var(--layout-overflow); } .column { grid-row: 1/2; diff --git a/src/layouts/grid.ts b/src/layouts/grid.ts index 8bf0c00..3e27b9a 100644 --- a/src/layouts/grid.ts +++ b/src/layouts/grid.ts @@ -56,6 +56,9 @@ class GridLayout extends BaseLayout { --layout-margin: ${this._config.layout?.margin ?? "4px 4px 0px 4px"}; --layout-padding: ${this._config.layout?.padding ?? "0px"}; --layout-height: ${this._config.layout?.height ?? "auto"}; + --layout-overflow: ${ + this._config.layout?.height !== undefined ? "auto" : "visible" + }; }`; this.shadowRoot.appendChild(styleEl); } @@ -139,7 +142,7 @@ class GridLayout extends BaseLayout { margin: var(--layout-margin); padding: var(--layout-padding); height: var(--layout-height); - overflow-y: auto; + overflow-y: var(--layout-overflow); } #root > * { margin: var(--masonry-view-card-margin, 4px 4px 8px); diff --git a/src/layouts/masonry.ts b/src/layouts/masonry.ts index d125998..a0d1c8c 100644 --- a/src/layouts/masonry.ts +++ b/src/layouts/masonry.ts @@ -22,7 +22,12 @@ class MasonryLayout extends BaseColumnLayout { const col = shortestCol(); col.appendChild(this.getCardElement(c)); - col.length += c.card.getCardSize ? await c.card.getCardSize() : 1; + col.length += c.card.getCardSize + ? await (Promise.race([ + c.card.getCardSize(), + new Promise((resolve) => setTimeout(() => resolve(1), 500)), + ]) as Promise) + : 1; } } } diff --git a/src/patches/hui-view-editor.ts b/src/patches/hui-view-editor.ts index e6639de..baa8ede 100644 --- a/src/patches/hui-view-editor.ts +++ b/src/patches/hui-view-editor.ts @@ -1,21 +1,10 @@ +import { loadHaYamlEditor } from "../helpers"; const LAYOUT_TYPES = ["masonry", "horizontal", "vertical", "grid"]; customElements.whenDefined("hui-view-editor").then(() => { const HuiViewEditor = customElements.get("hui-view-editor"); - (async () => { - // Load in ha-yaml-editor from developer-tools-service - const ppResolver = document.createElement("partial-panel-resolver"); - const routes = (ppResolver as any).getRoutes([ - { - component_name: "developer-tools", - url_path: "a", - }, - ]); - await routes?.routes?.a?.load?.(); - const devToolsRouter = document.createElement("developer-tools-router"); - await (devToolsRouter as any)?.routerOptions?.routes?.service?.load?.(); - })(); + loadHaYamlEditor(); const firstUpdated = HuiViewEditor.prototype.firstUpdated; HuiViewEditor.prototype.firstUpdated = function () { @@ -55,7 +44,7 @@ customElements.whenDefined("hui-view-editor").then(() => { if (_changedProperties.has("_config")) { const layoutEditor = this.shadowRoot.querySelector("ha-yaml-editor"); - if (layoutEditor) return; + if (!layoutEditor) return; (layoutEditor as any).defaultValue = this._config.layout; } };