diff --git a/dimmer-button.js b/dimmer-button.js index 8f69066..e49b1e2 100644 --- a/dimmer-button.js +++ b/dimmer-button.js @@ -1,15 +1,15 @@ //TODO //Add automatic area on

when supported //value template support -//Scale text when card is smaller than ~200px //Select mode color -//Keep displaying newValue until the old value is updated import { LitElement, html, css } from "https://unpkg.com/lit-element@2.0.1/lit-element.js?module"; +console.info('%c DIMMER-BUTTON %c 0.3 ','color: antiquewhite; background: #B565C6;','color: salmon; background: gray;'); + class DimmerButton extends LitElement { static get properties() { @@ -20,14 +20,15 @@ class DimmerButton extends LitElement { } static getStubConfig() { - return { entity: '#Required',name: '#friendly_name',mode: '#supports "brightness" or "color_temp" for light and "volume" for media_player', bottom: "#optional text under name", height: "",background: "",foreground: "",icon: "",on_icon: "",off_icon: "",on_color: "",off_color: "" } + return { entity: '#Required',name: '#friendly_name',mode: '#supports "brightness" or "color_temp" for light and "volume" for media_player', direction: "horizontal", bottom: "#optional text under name", height: "",background: "",foreground: "",icon: "",on_icon: "",off_icon: "",on_color: "",off_color: "" } } constructor() { super(); this.hold = false; this.dim = false; - this.disabled = false; + this.move = false; + this.start = false; this.delta = 3; this.startY; this.startX; @@ -41,6 +42,9 @@ class DimmerButton extends LitElement { this.maxVol; this.newValue = 0; this.longPress = null; + this.active = ''; + this.cardWidth; + this.vertical = false; } entityConfig(entity) { @@ -68,7 +72,6 @@ class DimmerButton extends LitElement { this.iconOff = this.config.icon ? this.config.icon : this.config.off_icon ? this.config.off_icon : entity.attributes.icon ? entity.attributes.icon : "mdi:eye"; this.mode = "static"; this.displayState = entity.attributes.unit_of_measurement ? entity.attributes.unit_of_measurement: ''; - this.disabled = true; this.rangeMax = 0; }else if(entity.entity_id.includes("media_player.")){ this.iconOn = this.config.icon ? this.config.icon : this.config.on_icon ? this.config.on_icon : entity.attributes.icon ? entity.attributes.icon : "mdi:cast"; @@ -76,6 +79,7 @@ class DimmerButton extends LitElement { if(entity.attributes.supported_features & 4 && this.config.mode == "volume") { this.mode = "volume"; this.displayState = (entity.state === "playing" ? '• '+(this.newValue != 0 ? this.newValue : Math.round((entity.attributes.volume_level*100)))+'%' : ''); + this.maxVol = this.config.max_volume ? this.config.max_volume : 100; this.rangeMax = this.maxVol; this.rangeValue = (entity.attributes.volume_level*100); }else{ @@ -92,21 +96,36 @@ class DimmerButton extends LitElement { render() { const entity = this.config.entity; const entityStates = this.hass.states[entity] - let background = this.config.background ? this.config.background : "var(--ha-card-background)"; - let foreground = this.config.foreground ? this.config.foreground : "var(--primary-color)"; const name = this.config.name ? this.config.name : entityStates.attributes.friendly_name; const onColor = this.config.on_color ? this.config.on_color : "#fdd835"; const offColor = this.config.off_color ? this.config.off_color : "gray"; const cardHeight = this.config.height ? this.config.height : "150px"; - const bottomText = this.config.bottom; + let bottomText = parseInt(cardHeight) >= 150 ? this.config.bottom : ''; + let background = this.config.background ? this.config.background : "var(--ha-card-background)"; + let foreground = this.config.foreground ? this.config.foreground : "var(--primary-color)"; + let fontSizeH = parseInt(cardHeight) >= 150 ? "20px" : (20-((150-parseInt(cardHeight))/25))+"px"; + let fontSizeW = this.cardWidth >= 200 ? "20px" : (20-((200-this.cardWidth)/12.5))+"px"; + let fontSize = fontSizeH < fontSizeW ? fontSizeH : fontSizeW; + this.vertical = this.config.direction == 'vertical' ? true : false; this.entityConfig(entityStates); return html` -

-

${entityStates.state} ${this.displayState}

-

${name}

- ${bottomText ? html`

${bottomText}

`: ''} - +
+ ${entityStates.state} ${this.displayState} + ${name} + ${bottomText ? html`${bottomText}`: ''} +
+ this._startCords(entity, e)} @pointerup=${e => this._endCords(entityStates, e)} @pointermove=${e => this._moveHandler(e)} @@ -123,40 +142,49 @@ class DimmerButton extends LitElement { let diffY = Math.abs(this.startY-e.pageY); let posDelta = 6; if(diffX > posDelta || diffY > posDelta){ - clearTimeout(this.longPress); + if(this.start) { + this.move = true; + } + clearTimeout(this.longPress); }; } _displayValue(e) { - this.newValue = parseInt(e); - this.requestUpdate(); + if(this.move){ + this.newValue = parseInt(e); + this.requestUpdate(); + } } _startCords(entity, e) { this.startX = e.pageX; this.startY = e.pageY; this.clientY = e.clientY; + this.start = true; + this.active = "active"; let target = e.target.parentElement; this.longPress = setTimeout(() => this._moreInfo('hass-more-info', { entityId: this.config.entity }, target), 600); } _endCords(entity, e) { clearTimeout(this.longPress); - this.newValue = 0; let diffX = Math.abs(e.pageX - this.startX); let diffY = Math.abs(e.pageY - this.startY); let scrollY = Math.abs(e.clientY - this.clientY); + this.move = false; + this.start = false; + this.active = ''; if(this.hold){ - this.hold = false; - return false; + this.hold = false; + return false; }; if((diffX < this.delta && diffY < this.delta)&&(e.button == 0 || e.button == undefined)){ this.dim = false; this._toggle(entity); }else{ - this.dim = true; + this.dim = true; }; - if(scrollY > 50){ + if(scrollY > 50 && !this.vertical){ this.dim = false; } } @@ -204,113 +232,157 @@ class DimmerButton extends LitElement { let num = 0; if(this.dim){ switch(this.mode){ - case "brightness": - this.hass.callService("homeassistant", "turn_on", { - entity_id: entity.entity_id, - brightness: value * 2.55 - }); - break; - case "color_temp": - num = Math.round(((entity.attributes.max_mireds-entity.attributes.min_mireds)*(value/100))+entity.attributes.min_mireds); - this.hass.callService("light", "turn_on", { - entity_id: entity.entity_id, - color_temp: num - }); - break; - case "volume": - this.maxVol = this.config.max_volume ? this.config.max_volume : 100; - num = this.maxVol>value ? (value/100) : (this.maxVol/100); - this.hass.callService("media_player", "volume_set", { - entity_id: entity.entity_id, - volume_level: num - }); - break; - case "pause": - case "toggle": - this._toggle(entity); - break; + case "brightness": + this.hass.callService("homeassistant", "turn_on", { + entity_id: entity.entity_id, + brightness: value * 2.55 + }); + break; + case "color_temp": + num = Math.round(((entity.attributes.max_mireds-entity.attributes.min_mireds)*(value/100))+entity.attributes.min_mireds); + this.hass.callService("light", "turn_on", { + entity_id: entity.entity_id, + color_temp: num + }); + break; + case "volume": + num = this.maxVol>value ? (value/100) : (this.maxVol/100); + this.hass.callService("media_player", "volume_set", { + entity_id: entity.entity_id, + volume_level: num + }); + break; + case "pause": + case "toggle": + this._toggle(entity); + break; + default: } }else{ - e.target.value = this.rangeValue; - this.newValue = 0; - this.dim = false; - this.requestUpdate(); - return false; + e.target.value = this.rangeValue; + this.newValue = 0; + this.dim = false; + this.requestUpdate(); + return false; } this.dim = false; } + updated(changedProperties) { + this.cardWidth = this.getBoundingClientRect().width; + if(!this.move){ + this.newValue = 0; + } + } + setConfig(config) { if (!config.entity) { - throw new Error("You need to define entity"); + throw new Error("You need to define an entity"); } this.config = config; } getCardSize() { - return 3; + const cardSize = this.config.height ? Math.round(parseInt(this.config.height)/50) : 3; + return cardSize; } static get styles() { return css` - p{ - position: relative; + ha-card{ + background: none; + } + + .text{ + overflow: hidden; + display: flex; + flex-flow: column wrap; + padding-left: 6%; + height: 100%; + width: 94%; + } + + span{ z-index: 1; pointer-events: none; text-transform: capitalize; margin: 0; } - p.off, p.paused, p.unavailable { + span.off, span.paused, span.unavailable { color: var(--color-off); } - p.on, p.playing { + span.on, span.playing { color: var(--color-on); } .icon{ - margin: 10px; + margin-right: 10px; --mdc-icon-size: 30px; + top: -3px; + position: relative; } .top { - font-size: var(--paper-font-title_-_font-size); - padding: 30px 0 0 20px; + font-size: var(--font-size); + min-height: 35px; + max-height: 40px; + min-width: 40%; + flex-grow: 1; + padding-top: calc(var(--card-height) / 5); + padding-right: 5%; + margin-bottom: -20px; } .middle { - font-size: var(--paper-font-title_-_font-size); + font-size: var(--font-size); font-weight: var(--paper-font-title_-_font-weight); - padding: 20px 0 5px 35px; + min-height: 30px; + max-height: 35px; + min-width: 50%; + flex-grow: 1; + padding-left: 1%; + padding-top: calc(3px + calc(var(--card-height) / 5)); } .bottom { font-size: var(--paper-font-body1_-_font-size); font-weight: var(--paper-font-body1_-_font-weight); - padding: 5px 0 0 35px; + flex-grow: 10; + max-height: 40px; + padding-left: 1%; + padding-right: 10%; + white-space: nowrap; } .button { height: var(--card-height); + width: 100%; position: relative; background: var(--dimmer-background); background-size: cover; border-radius: var(--ha-card-border-radius); - touch-action: pan-y; + touch-action: var(--touch); + overflow: hidden; } .button input[type="range"] { border-radius: var(--ha-card-border-radius); - width: 100%; margin: 0; - transition: box-shadow 0.2s ease-in-out; overflow: hidden; - height: 100%; -webkit-appearance: none; background: none; position: absolute; + width: var(--range-width); + height: var(--range-height); top: 0; - right: 0; + right: var(--right); + -webkit-transform:rotate(var(--rotation)); + -moz-transform:rotate(var(--rotation)); + -o-transform:rotate(var(--rotation)); + -ms-transform:rotate(var(--rotation)); + transform:rotate(var(--rotation)); + transform-origin: top right; } .button input[type="range"]::-webkit-slider-runnable-track { @@ -345,11 +417,19 @@ class DimmerButton extends LitElement { .button input[type="range"]:hover { cursor: pointer; } + + .active{ + -webkit-transform: scaleX(0.97) scaleY(0.95); + -ms-transform: scaleX(0.97) scaleY(0.95); + transform: scaleX(0.97) scaleY(0.95); + transition:all 0.3s ease-in; + } + span.effect { position: absolute; opacity: 0; - animation: ripple 200ms ease-in-out; - background-color: rgba(255, 255, 255, 0.9); + animation: ripple 200ms ease-in; + background-color: rgba(255, 255, 255, 0.7); height: 100%; width: 100%; left: 0;