diff --git a/dist/index.js b/dist/index.js index 10cf16a..4538828 100644 --- a/dist/index.js +++ b/dist/index.js @@ -1,2 +1,2 @@ -var e,t,r=require("@formatjs/intl-utils"),n=function(e,t){return i(t).format(e)},i=function(e){return new Intl.DateTimeFormat(e.language,{year:"numeric",month:"long",day:"numeric"})};exports.NumberFormat=void 0,(e=exports.NumberFormat||(exports.NumberFormat={})).language="language",e.system="system",e.comma_decimal="comma_decimal",e.decimal_comma="decimal_comma",e.space_comma="space_comma",e.none="none",exports.TimeFormat=void 0,(t=exports.TimeFormat||(exports.TimeFormat={})).language="language",t.system="system",t.am_pm="12",t.twenty_four="24";var a=function(e){if(e.time_format===exports.TimeFormat.language||e.time_format===exports.TimeFormat.system){var t=e.time_format===exports.TimeFormat.language?e.language:void 0,r=(new Date).toLocaleString(t);return r.includes("AM")||r.includes("PM")}return e.time_format===exports.TimeFormat.am_pm},o=function(e,t){return u(t).format(e)},u=function(e){return new Intl.DateTimeFormat(e.language,{year:"numeric",month:"long",day:"numeric",hour:a(e)?"numeric":"2-digit",minute:"2-digit",hour12:a(e)})},c=function(e,t){return m(t).format(e)},m=function(e){return new Intl.DateTimeFormat(e.language,{hour:"numeric",minute:"2-digit",hour12:a(e)})};function s(){return(s=Object.assign||function(e){for(var t=1;t-1?e.split(".")[1].length:0;r.minimumFractionDigits=n,r.maximumFractionDigits=n}return r},v=["closed","locked","off"],y=new Set(["fan","input_boolean","light","switch","group","automation"]),w=function(e,t,r,n){n=n||{},r=null==r?{}:r;var i=new Event(t,{bubbles:void 0===n.bubbles||n.bubbles,cancelable:Boolean(n.cancelable),composed:void 0===n.composed||n.composed});return i.detail=r,e.dispatchEvent(i),i},x=new Set(["call-service","divider","section","weblink","cast","select"]),k={alert:"toggle",automation:"toggle",climate:"climate",cover:"cover",fan:"toggle",group:"group",input_boolean:"toggle",input_number:"input-number",input_select:"input-select",input_text:"input-text",light:"toggle",lock:"lock",media_player:"media-player",remote:"toggle",scene:"scene",script:"script",sensor:"sensor",timer:"timer",switch:"toggle",vacuum:"toggle",water_heater:"climate",input_datetime:"input-datetime"},D={alert:"mdi:alert",automation:"mdi:playlist-play",calendar:"mdi:calendar",camera:"mdi:video",climate:"mdi:thermostat",configurator:"mdi:settings",conversation:"mdi:text-to-speech",device_tracker:"mdi:account",fan:"mdi:fan",group:"mdi:google-circles-communities",history_graph:"mdi:chart-line",homeassistant:"mdi:home-assistant",homekit:"mdi:home-automation",image_processing:"mdi:image-filter-frames",input_boolean:"mdi:drawing",input_datetime:"mdi:calendar-clock",input_number:"mdi:ray-vertex",input_select:"mdi:format-list-bulleted",input_text:"mdi:textbox",light:"mdi:lightbulb",mailbox:"mdi:mailbox",notify:"mdi:comment-alert",person:"mdi:account",plant:"mdi:flower",proximity:"mdi:apple-safari",remote:"mdi:remote",scene:"mdi:google-pages",script:"mdi:file-document",sensor:"mdi:eye",simple_alarm:"mdi:bell",sun:"mdi:white-balance-sunny",switch:"mdi:flash",timer:"mdi:timer",updater:"mdi:cloud-upload",vacuum:"mdi:robot-vacuum",water_heater:"mdi:thermometer",weblink:"mdi:open-in-new"};function T(e,t){if(e in D)return D[e];switch(e){case"alarm_control_panel":switch(t){case"armed_home":return"mdi:bell-plus";case"armed_night":return"mdi:bell-sleep";case"disarmed":return"mdi:bell-outline";case"triggered":return"mdi:bell-ring";default:return"mdi:bell"}case"binary_sensor":return t&&"off"===t?"mdi:radiobox-blank":"mdi:checkbox-marked-circle";case"cover":return"closed"===t?"mdi:window-closed":"mdi:window-open";case"lock":return t&&"unlocked"===t?"mdi:lock-open":"mdi:lock";case"media_player":return t&&"off"!==t&&"idle"!==t?"mdi:cast-connected":"mdi:cast";case"zwave":switch(t){case"dead":return"mdi:emoticon-dead";case"sleeping":return"mdi:sleep";case"initializing":return"mdi:timer-sand";default:return"mdi:z-wave"}default:return console.warn("Unable to find icon for domain "+e+" ("+t+")"),"mdi:bookmark"}}var F=function(e){w(window,"haptic",e)},N=function(e,t,r){void 0===r&&(r=!1),r?history.replaceState(null,"",t):history.pushState(null,"",t),w(window,"location-changed",{replace:r})},S=function(e,t,r){void 0===r&&(r=!0);var n,i=l(t),a="group"===i?"homeassistant":i;switch(i){case"lock":n=r?"unlock":"lock";break;case"cover":n=r?"open_cover":"close_cover";break;default:n=r?"turn_on":"turn_off"}return e.callService(a,n,{entity_id:t})},I=function(e,t){var r=v.includes(e.states[t].state);return S(e,t,r)},O=function(e,t,r,n){if(n||(n={action:"more-info"}),!n.confirmation||n.confirmation.exemptions&&n.confirmation.exemptions.some(function(e){return e.user===t.user.id})||(F("warning"),confirm(n.confirmation.text||"Are you sure you want to "+n.action+"?")))switch(n.action){case"more-info":(r.entity||r.camera_image)&&w(e,"hass-more-info",{entityId:r.entity?r.entity:r.camera_image});break;case"navigate":n.navigation_path&&N(0,n.navigation_path);break;case"url":n.url_path&&window.open(n.url_path);break;case"toggle":r.entity&&(I(t,r.entity),F("success"));break;case"call-service":if(!n.service)return void F("failure");var i=n.service.split(".",2);t.callService(i[0],i[1],n.service_data,n.target),F("success");break;case"fire-dom-event":w(e,"ll-custom",n)}},E={humidity:"mdi:water-percent",illuminance:"mdi:brightness-5",temperature:"mdi:thermometer",pressure:"mdi:gauge",power:"mdi:flash",signal_strength:"mdi:wifi"},A={binary_sensor:function(e,t){var r="off"===e;switch(null==t?void 0:t.attributes.device_class){case"battery":return r?"mdi:battery":"mdi:battery-outline";case"battery_charging":return r?"mdi:battery":"mdi:battery-charging";case"cold":return r?"mdi:thermometer":"mdi:snowflake";case"connectivity":return r?"mdi:server-network-off":"mdi:server-network";case"door":return r?"mdi:door-closed":"mdi:door-open";case"garage_door":return r?"mdi:garage":"mdi:garage-open";case"power":return r?"mdi:power-plug-off":"mdi:power-plug";case"gas":case"problem":case"safety":case"tamper":return r?"mdi:check-circle":"mdi:alert-circle";case"smoke":return r?"mdi:check-circle":"mdi:smoke";case"heat":return r?"mdi:thermometer":"mdi:fire";case"light":return r?"mdi:brightness-5":"mdi:brightness-7";case"lock":return r?"mdi:lock":"mdi:lock-open";case"moisture":return r?"mdi:water-off":"mdi:water";case"motion":return r?"mdi:walk":"mdi:run";case"occupancy":return r?"mdi:home-outline":"mdi:home";case"opening":return r?"mdi:square":"mdi:square-outline";case"plug":return r?"mdi:power-plug-off":"mdi:power-plug";case"presence":return r?"mdi:home-outline":"mdi:home";case"running":return r?"mdi:stop":"mdi:play";case"sound":return r?"mdi:music-note-off":"mdi:music-note";case"update":return r?"mdi:package":"mdi:package-up";case"vibration":return r?"mdi:crop-portrait":"mdi:vibrate";case"window":return r?"mdi:window-closed":"mdi:window-open";default:return r?"mdi:radiobox-blank":"mdi:checkbox-marked-circle"}},cover:function(e){var t="closed"!==e.state;switch(e.attributes.device_class){case"garage":return t?"mdi:garage-open":"mdi:garage";case"door":return t?"mdi:door-open":"mdi:door-closed";case"shutter":return t?"mdi:window-shutter-open":"mdi:window-shutter";case"blind":return t?"mdi:blinds-open":"mdi:blinds";case"window":return t?"mdi:window-open":"mdi:window-closed";default:return T("cover",e.state)}},sensor:function(e){var t=e.attributes.device_class;if(t&&t in E)return E[t];if("battery"===t){var r=Number(e.state);if(isNaN(r))return"mdi:battery-unknown";var n=10*Math.round(r/10);return n>=100?"mdi:battery":n<=0?"mdi:battery-alert":"hass:battery-"+n}var i=e.attributes.unit_of_measurement;return"°C"===i||"°F"===i?"mdi:thermometer":T("sensor")},input_datetime:function(e){return e.attributes.has_date?e.attributes.has_time?T("input_datetime"):"mdi:calendar":"mdi:clock"}};exports.DEFAULT_DOMAIN_ICON="mdi:bookmark",exports.DEFAULT_PANEL="lovelace",exports.DEFAULT_VIEW_ENTITY_ID="group.default_view",exports.DOMAINS_HIDE_MORE_INFO=["input_number","input_select","input_text","scene","weblink"],exports.DOMAINS_MORE_INFO_NO_HISTORY=["camera","configurator","history_graph","scene"],exports.DOMAINS_TOGGLE=y,exports.DOMAINS_WITH_CARD=["climate","cover","configurator","input_select","input_number","input_text","lock","media_player","scene","script","timer","vacuum","water_heater","weblink"],exports.DOMAINS_WITH_MORE_INFO=["alarm_control_panel","automation","camera","climate","configurator","cover","fan","group","history_graph","input_datetime","light","lock","media_player","script","sun","updater","vacuum","water_heater","weather"],exports.STATES_OFF=v,exports.UNIT_C="°C",exports.UNIT_F="°F",exports.applyThemesOnElement=function(e,t,r,n){void 0===n&&(n=!1),e._themes||(e._themes={});var i=t.default_theme;("default"===r||r&&t.themes[r])&&(i=r);var a=s({},e._themes);if("default"!==i){var o=t.themes[i];Object.keys(o).forEach(function(t){var r="--"+t;e._themes[r]="",a[r]=o[t]})}if(e.updateStyles?e.updateStyles(a):window.ShadyCSS&&window.ShadyCSS.styleSubtree(e,a),n){var u=document.querySelector("meta[name=theme-color]");if(u){u.hasAttribute("default-content")||u.setAttribute("default-content",u.getAttribute("content"));var c=a["--primary-color"]||u.getAttribute("default-content");u.setAttribute("content",c)}}},exports.computeCardSize=function(e){return"function"==typeof e.getCardSize?e.getCardSize():4},exports.computeDomain=l,exports.computeEntity=function(e){return e.substr(e.indexOf(".")+1)},exports.computeRTL=d,exports.computeRTLDirection=function(e){return d(e)?"rtl":"ltr"},exports.computeStateDisplay=function(e,t,r,i){var a=void 0!==i?i:t.state;if("unknown"===a||"unavailable"===a)return e("state.default."+a);if(f(t)){if("monetary"===t.attributes.device_class)try{return b(a,r,{style:"currency",currency:t.attributes.unit_of_measurement})}catch(e){}return b(a,r)+(t.attributes.unit_of_measurement?" "+t.attributes.unit_of_measurement:"")}var u=p(t);if("input_datetime"===u){var m;if(void 0===i)return t.attributes.has_date&&t.attributes.has_time?(m=new Date(t.attributes.year,t.attributes.month-1,t.attributes.day,t.attributes.hour,t.attributes.minute),o(m,r)):t.attributes.has_date?(m=new Date(t.attributes.year,t.attributes.month-1,t.attributes.day),n(m,r)):t.attributes.has_time?((m=new Date).setHours(t.attributes.hour,t.attributes.minute),c(m,r)):t.state;try{var s=i.split(" ");if(2===s.length)return o(new Date(s.join("T")),r);if(1===s.length){if(i.includes("-"))return n(new Date(i+"T00:00"),r);if(i.includes(":")){var l=new Date;return c(new Date(l.toISOString().split("T")[0]+"T"+i),r)}}return i}catch(e){return i}}return"humidifier"===u&&"on"===a&&t.attributes.humidity?t.attributes.humidity+" %":"counter"===u||"number"===u||"input_number"===u?b(a,r):t.attributes.device_class&&e("component."+u+".state."+t.attributes.device_class+"."+a)||e("component."+u+".state._."+a)||a},exports.computeStateDomain=p,exports.createThing=function(e,t){void 0===t&&(t=!1);var r=function(e,t){return n("hui-error-card",{type:"error",error:e,config:t})},n=function(e,t){var n=window.document.createElement(e);try{if(!n.setConfig)return;n.setConfig(t)}catch(n){return console.error(e,n),r(n.message,t)}return n};if(!e||"object"!=typeof e||!t&&!e.type)return r("No type defined",e);var i=e.type;if(i&&i.startsWith("custom:"))i=i.substr("custom:".length);else if(t)if(x.has(i))i="hui-"+i+"-row";else{if(!e.entity)return r("Invalid config given.",e);var a=e.entity.split(".",1)[0];i="hui-"+(k[a]||"text")+"-entity-row"}else i="hui-"+i+"-card";if(customElements.get(i))return n(i,e);var o=r("Custom element doesn't exist: "+e.type+".",e);o.style.display="None";var u=setTimeout(function(){o.style.display=""},2e3);return customElements.whenDefined(e.type).then(function(){clearTimeout(u),w(o,"ll-rebuild",{},o)}),o},exports.debounce=function(e,t,r){var n;return void 0===r&&(r=!1),function(){var i=[].slice.call(arguments),a=this,o=function(){n=null,r||e.apply(a,i)},u=r&&!n;clearTimeout(n),n=setTimeout(o,t),u&&e.apply(a,i)}},exports.domainIcon=T,exports.evaluateFilter=function(e,t){var r=t.value||t,n=t.attribute?e.attributes[t.attribute]:e.state;switch(t.operator||"=="){case"==":return n===r;case"<=":return n<=r;case"<":return n=":return n>=r;case">":return n>r;case"!=":return n!==r;case"regex":return n.match(r);default:return!1}},exports.fireEvent=w,exports.fixedIcons=D,exports.formatDate=n,exports.formatDateMonth=function(e,t){return function(e){return new Intl.DateTimeFormat(e.language,{month:"long"})}(t).format(e)},exports.formatDateMonthYear=function(e,t){return function(e){return new Intl.DateTimeFormat(e.language,{month:"long",year:"numeric"})}(t).format(e)},exports.formatDateNumeric=function(e,t){return function(e){return new Intl.DateTimeFormat(e.language,{year:"numeric",month:"numeric",day:"numeric"})}(t).format(e)},exports.formatDateShort=function(e,t){return function(e){return new Intl.DateTimeFormat(e.language,{day:"numeric",month:"short"})}(t).format(e)},exports.formatDateTime=o,exports.formatDateTimeNumeric=function(e,t){return function(e){return new Intl.DateTimeFormat(e.language,{year:"numeric",month:"numeric",day:"numeric",hour:"numeric",minute:"2-digit",hour12:a(e)})}(t).format(e)},exports.formatDateTimeWithSeconds=function(e,t){return function(e){return new Intl.DateTimeFormat(e.language,{year:"numeric",month:"long",day:"numeric",hour:a(e)?"numeric":"2-digit",minute:"2-digit",second:"2-digit",hour12:a(e)})}(t).format(e)},exports.formatDateWeekday=function(e,t){return function(e){return new Intl.DateTimeFormat(e.language,{weekday:"long",month:"long",day:"numeric"})}(t).format(e)},exports.formatDateYear=function(e,t){return function(e){return new Intl.DateTimeFormat(e.language,{year:"numeric"})}(t).format(e)},exports.formatNumber=b,exports.formatTime=c,exports.formatTimeWeekday=function(e,t){return function(e){return new Intl.DateTimeFormat(e.language,{hour:a(e)?"numeric":"2-digit",minute:"2-digit",second:"2-digit",hour12:a(e)})}(t).format(e)},exports.formatTimeWithSeconds=function(e,t){return function(e){return new Intl.DateTimeFormat(e.language,{hour:a(e)?"numeric":"2-digit",minute:"2-digit",second:"2-digit",hour12:a(e)})}(t).format(e)},exports.forwardHaptic=F,exports.getLovelace=function(){var e=document.querySelector("home-assistant");if(e=(e=(e=(e=(e=(e=(e=(e=e&&e.shadowRoot)&&e.querySelector("home-assistant-main"))&&e.shadowRoot)&&e.querySelector("app-drawer-layout partial-panel-resolver"))&&e.shadowRoot||e)&&e.querySelector("ha-panel-lovelace"))&&e.shadowRoot)&&e.querySelector("hui-root")){var t=e.lovelace;return t.current_view=e.___curView,t}return null},exports.handleAction=function(e,t,r,n){var i;"double_tap"===n&&r.double_tap_action?i=r.double_tap_action:"hold"===n&&r.hold_action?i=r.hold_action:"tap"===n&&r.tap_action&&(i=r.tap_action),O(e,t,r,i)},exports.handleActionConfig=O,exports.handleClick=function(e,t,r,n,i){var a;if(i&&r.double_tap_action?a=r.double_tap_action:n&&r.hold_action?a=r.hold_action:!n&&r.tap_action&&(a=r.tap_action),a||(a={action:"more-info"}),!a.confirmation||a.confirmation.exemptions&&a.confirmation.exemptions.some(function(e){return e.user===t.user.id})||confirm(a.confirmation.text||"Are you sure you want to "+a.action+"?"))switch(a.action){case"more-info":(a.entity||r.entity||r.camera_image)&&(w(e,"hass-more-info",{entityId:a.entity?a.entity:r.entity?r.entity:r.camera_image}),a.haptic&&F(a.haptic));break;case"navigate":a.navigation_path&&(N(0,a.navigation_path),a.haptic&&F(a.haptic));break;case"url":a.url_path&&window.open(a.url_path),a.haptic&&F(a.haptic);break;case"toggle":r.entity&&(I(t,r.entity),a.haptic&&F(a.haptic));break;case"call-service":if(!a.service)return;var o=a.service.split(".",2),u=o[0],c=o[1],m=s({},a.service_data);"entity"===m.entity_id&&(m.entity_id=r.entity),t.callService(u,c,m,a.target),a.haptic&&F(a.haptic);break;case"fire-dom-event":w(e,"ll-custom",a),a.haptic&&F(a.haptic)}},exports.hasAction=function(e){return void 0!==e&&"none"!==e.action},exports.hasConfigOrEntityChanged=function(e,t,r){if(t.has("config")||r)return!0;if(e.config.entity){var n=t.get("hass");return!n||n.states[e.config.entity]!==e.hass.states[e.config.entity]}return!1},exports.hasDoubleClick=function(e){return void 0!==e&&"none"!==e.action},exports.isNumericState=f,exports.navigate=N,exports.numberFormatToLocale=g,exports.relativeTime=function(e,t,n,i){void 0===i&&(i=!0);var a=r.selectUnit(e,n);return i?function(e){return new Intl.RelativeTimeFormat(e.language,{numeric:"auto"})}(t).format(a.value,a.unit):Intl.NumberFormat(t.language,{style:"unit",unit:a.unit,unitDisplay:"long"}).format(Math.abs(a.value))},exports.round=h,exports.stateIcon=function(e){if(!e)return"mdi:bookmark";if(e.attributes.icon)return e.attributes.icon;var t=l(e.entity_id);return t in A?A[t](e):T(t,e.state)},exports.timerTimeRemaining=function(e){var t,r=3600*(t=e.attributes.remaining.split(":").map(Number))[0]+60*t[1]+t[2];if("active"===e.state){var n=(new Date).getTime(),i=new Date(e.last_changed).getTime();r=Math.max(r-(n-i)/1e3,0)}return r},exports.toggleEntity=I,exports.turnOnOffEntities=function(e,t,r){void 0===r&&(r=!0);var n={};t.forEach(function(t){if(v.includes(e.states[t].state)===r){var i=l(t),a=["cover","lock"].includes(i)?i:"homeassistant";a in n||(n[a]=[]),n[a].push(t)}}),Object.keys(n).forEach(function(t){var i;switch(t){case"lock":i=r?"unlock":"lock";break;case"cover":i=r?"open_cover":"close_cover";break;default:i=r?"turn_on":"turn_off"}e.callService(t,i,{entity_id:n[t]})})},exports.turnOnOffEntity=S; +var e,t,r=require("@formatjs/intl-utils"),n=function(e,t){return i(t).format(e)},i=function(e){return new Intl.DateTimeFormat(e.language,{year:"numeric",month:"long",day:"numeric"})};exports.NumberFormat=void 0,(e=exports.NumberFormat||(exports.NumberFormat={})).language="language",e.system="system",e.comma_decimal="comma_decimal",e.decimal_comma="decimal_comma",e.space_comma="space_comma",e.none="none",exports.TimeFormat=void 0,(t=exports.TimeFormat||(exports.TimeFormat={})).language="language",t.system="system",t.am_pm="12",t.twenty_four="24";var a=function(e){if(e.time_format===exports.TimeFormat.language||e.time_format===exports.TimeFormat.system){var t=e.time_format===exports.TimeFormat.language?e.language:void 0,r=(new Date).toLocaleString(t);return r.includes("AM")||r.includes("PM")}return e.time_format===exports.TimeFormat.am_pm},o=function(e,t){return u(t).format(e)},u=function(e){return new Intl.DateTimeFormat(e.language,{year:"numeric",month:"long",day:"numeric",hour:a(e)?"numeric":"2-digit",minute:"2-digit",hour12:a(e)})},c=function(e,t){return m(t).format(e)},m=function(e){return new Intl.DateTimeFormat(e.language,{hour:"numeric",minute:"2-digit",hour12:a(e)})};function s(){return(s=Object.assign||function(e){for(var t=1;t-1?e.split(".")[1].length:0;r.minimumFractionDigits=n,r.maximumFractionDigits=n}return r},v=["closed","locked","off"],y=new Set(["fan","input_boolean","light","switch","group","automation"]),w=function(e,t,r,n){n=n||{},r=null==r?{}:r;var i=new Event(t,{bubbles:void 0===n.bubbles||n.bubbles,cancelable:Boolean(n.cancelable),composed:void 0===n.composed||n.composed});return i.detail=r,e.dispatchEvent(i),i},x=new Set(["call-service","divider","section","weblink","cast","select"]),k={alert:"toggle",automation:"toggle",climate:"climate",cover:"cover",fan:"toggle",group:"group",input_boolean:"toggle",input_number:"input-number",input_select:"input-select",input_text:"input-text",light:"toggle",lock:"lock",media_player:"media-player",remote:"toggle",scene:"scene",script:"script",sensor:"sensor",timer:"timer",switch:"toggle",vacuum:"toggle",water_heater:"climate",input_datetime:"input-datetime"},D={alert:"mdi:alert",automation:"mdi:playlist-play",calendar:"mdi:calendar",camera:"mdi:video",climate:"mdi:thermostat",configurator:"mdi:settings",conversation:"mdi:text-to-speech",device_tracker:"mdi:account",fan:"mdi:fan",group:"mdi:google-circles-communities",history_graph:"mdi:chart-line",homeassistant:"mdi:home-assistant",homekit:"mdi:home-automation",image_processing:"mdi:image-filter-frames",input_boolean:"mdi:drawing",input_datetime:"mdi:calendar-clock",input_number:"mdi:ray-vertex",input_select:"mdi:format-list-bulleted",input_text:"mdi:textbox",light:"mdi:lightbulb",mailbox:"mdi:mailbox",notify:"mdi:comment-alert",person:"mdi:account",plant:"mdi:flower",proximity:"mdi:apple-safari",remote:"mdi:remote",scene:"mdi:google-pages",script:"mdi:file-document",sensor:"mdi:eye",simple_alarm:"mdi:bell",sun:"mdi:white-balance-sunny",switch:"mdi:flash",timer:"mdi:timer",updater:"mdi:cloud-upload",vacuum:"mdi:robot-vacuum",water_heater:"mdi:thermometer",weblink:"mdi:open-in-new"};function T(e,t){if(e in D)return D[e];switch(e){case"alarm_control_panel":switch(t){case"armed_home":return"mdi:bell-plus";case"armed_night":return"mdi:bell-sleep";case"disarmed":return"mdi:bell-outline";case"triggered":return"mdi:bell-ring";default:return"mdi:bell"}case"binary_sensor":return t&&"off"===t?"mdi:radiobox-blank":"mdi:checkbox-marked-circle";case"cover":return"closed"===t?"mdi:window-closed":"mdi:window-open";case"lock":return t&&"unlocked"===t?"mdi:lock-open":"mdi:lock";case"media_player":return t&&"off"!==t&&"idle"!==t?"mdi:cast-connected":"mdi:cast";case"zwave":switch(t){case"dead":return"mdi:emoticon-dead";case"sleeping":return"mdi:sleep";case"initializing":return"mdi:timer-sand";default:return"mdi:z-wave"}default:return console.warn("Unable to find icon for domain "+e+" ("+t+")"),"mdi:bookmark"}}var F=function(e){w(window,"haptic",e)},N=function(e,t,r){void 0===r&&(r=!1),r?history.replaceState(null,"",t):history.pushState(null,"",t),w(window,"location-changed",{replace:r})},S=function(e,t,r){void 0===r&&(r=!0);var n,i=l(t),a="group"===i?"homeassistant":i;switch(i){case"lock":n=r?"unlock":"lock";break;case"cover":n=r?"open_cover":"close_cover";break;default:n=r?"turn_on":"turn_off"}return e.callService(a,n,{entity_id:t})},I=function(e,t){var r=v.includes(e.states[t].state);return S(e,t,r)},O=function(e,t,r,n){if(n||(n={action:"more-info"}),!n.confirmation||n.confirmation.exemptions&&n.confirmation.exemptions.some(function(e){return e.user===t.user.id})||(F("warning"),confirm(n.confirmation.text||"Are you sure you want to "+n.action+"?")))switch(n.action){case"more-info":(r.entity||r.camera_image)&&w(e,"hass-more-info",{entityId:r.entity?r.entity:r.camera_image});break;case"navigate":n.navigation_path&&N(0,n.navigation_path);break;case"url":n.url_path&&window.open(n.url_path);break;case"toggle":r.entity&&(I(t,r.entity),F("success"));break;case"call-service":if(!n.service)return void F("failure");var i=n.service.split(".",2);t.callService(i[0],i[1],n.data,n.target),F("success");break;case"fire-dom-event":w(e,"ll-custom",n)}},E={humidity:"mdi:water-percent",illuminance:"mdi:brightness-5",temperature:"mdi:thermometer",pressure:"mdi:gauge",power:"mdi:flash",signal_strength:"mdi:wifi"},A={binary_sensor:function(e,t){var r="off"===e;switch(null==t?void 0:t.attributes.device_class){case"battery":return r?"mdi:battery":"mdi:battery-outline";case"battery_charging":return r?"mdi:battery":"mdi:battery-charging";case"cold":return r?"mdi:thermometer":"mdi:snowflake";case"connectivity":return r?"mdi:server-network-off":"mdi:server-network";case"door":return r?"mdi:door-closed":"mdi:door-open";case"garage_door":return r?"mdi:garage":"mdi:garage-open";case"power":return r?"mdi:power-plug-off":"mdi:power-plug";case"gas":case"problem":case"safety":case"tamper":return r?"mdi:check-circle":"mdi:alert-circle";case"smoke":return r?"mdi:check-circle":"mdi:smoke";case"heat":return r?"mdi:thermometer":"mdi:fire";case"light":return r?"mdi:brightness-5":"mdi:brightness-7";case"lock":return r?"mdi:lock":"mdi:lock-open";case"moisture":return r?"mdi:water-off":"mdi:water";case"motion":return r?"mdi:walk":"mdi:run";case"occupancy":return r?"mdi:home-outline":"mdi:home";case"opening":return r?"mdi:square":"mdi:square-outline";case"plug":return r?"mdi:power-plug-off":"mdi:power-plug";case"presence":return r?"mdi:home-outline":"mdi:home";case"running":return r?"mdi:stop":"mdi:play";case"sound":return r?"mdi:music-note-off":"mdi:music-note";case"update":return r?"mdi:package":"mdi:package-up";case"vibration":return r?"mdi:crop-portrait":"mdi:vibrate";case"window":return r?"mdi:window-closed":"mdi:window-open";default:return r?"mdi:radiobox-blank":"mdi:checkbox-marked-circle"}},cover:function(e){var t="closed"!==e.state;switch(e.attributes.device_class){case"garage":return t?"mdi:garage-open":"mdi:garage";case"door":return t?"mdi:door-open":"mdi:door-closed";case"shutter":return t?"mdi:window-shutter-open":"mdi:window-shutter";case"blind":return t?"mdi:blinds-open":"mdi:blinds";case"window":return t?"mdi:window-open":"mdi:window-closed";default:return T("cover",e.state)}},sensor:function(e){var t=e.attributes.device_class;if(t&&t in E)return E[t];if("battery"===t){var r=Number(e.state);if(isNaN(r))return"mdi:battery-unknown";var n=10*Math.round(r/10);return n>=100?"mdi:battery":n<=0?"mdi:battery-alert":"hass:battery-"+n}var i=e.attributes.unit_of_measurement;return"°C"===i||"°F"===i?"mdi:thermometer":T("sensor")},input_datetime:function(e){return e.attributes.has_date?e.attributes.has_time?T("input_datetime"):"mdi:calendar":"mdi:clock"}};exports.DEFAULT_DOMAIN_ICON="mdi:bookmark",exports.DEFAULT_PANEL="lovelace",exports.DEFAULT_VIEW_ENTITY_ID="group.default_view",exports.DOMAINS_HIDE_MORE_INFO=["input_number","input_select","input_text","scene","weblink"],exports.DOMAINS_MORE_INFO_NO_HISTORY=["camera","configurator","history_graph","scene"],exports.DOMAINS_TOGGLE=y,exports.DOMAINS_WITH_CARD=["climate","cover","configurator","input_select","input_number","input_text","lock","media_player","scene","script","timer","vacuum","water_heater","weblink"],exports.DOMAINS_WITH_MORE_INFO=["alarm_control_panel","automation","camera","climate","configurator","cover","fan","group","history_graph","input_datetime","light","lock","media_player","script","sun","updater","vacuum","water_heater","weather"],exports.STATES_OFF=v,exports.UNIT_C="°C",exports.UNIT_F="°F",exports.applyThemesOnElement=function(e,t,r,n){void 0===n&&(n=!1),e._themes||(e._themes={});var i=t.default_theme;("default"===r||r&&t.themes[r])&&(i=r);var a=s({},e._themes);if("default"!==i){var o=t.themes[i];Object.keys(o).forEach(function(t){var r="--"+t;e._themes[r]="",a[r]=o[t]})}if(e.updateStyles?e.updateStyles(a):window.ShadyCSS&&window.ShadyCSS.styleSubtree(e,a),n){var u=document.querySelector("meta[name=theme-color]");if(u){u.hasAttribute("default-content")||u.setAttribute("default-content",u.getAttribute("content"));var c=a["--primary-color"]||u.getAttribute("default-content");u.setAttribute("content",c)}}},exports.computeCardSize=function(e){return"function"==typeof e.getCardSize?e.getCardSize():4},exports.computeDomain=l,exports.computeEntity=function(e){return e.substr(e.indexOf(".")+1)},exports.computeRTL=d,exports.computeRTLDirection=function(e){return d(e)?"rtl":"ltr"},exports.computeStateDisplay=function(e,t,r,i){var a=void 0!==i?i:t.state;if("unknown"===a||"unavailable"===a)return e("state.default."+a);if(f(t)){if("monetary"===t.attributes.device_class)try{return b(a,r,{style:"currency",currency:t.attributes.unit_of_measurement})}catch(e){}return b(a,r)+(t.attributes.unit_of_measurement?" "+t.attributes.unit_of_measurement:"")}var u=p(t);if("input_datetime"===u){var m;if(void 0===i)return t.attributes.has_date&&t.attributes.has_time?(m=new Date(t.attributes.year,t.attributes.month-1,t.attributes.day,t.attributes.hour,t.attributes.minute),o(m,r)):t.attributes.has_date?(m=new Date(t.attributes.year,t.attributes.month-1,t.attributes.day),n(m,r)):t.attributes.has_time?((m=new Date).setHours(t.attributes.hour,t.attributes.minute),c(m,r)):t.state;try{var s=i.split(" ");if(2===s.length)return o(new Date(s.join("T")),r);if(1===s.length){if(i.includes("-"))return n(new Date(i+"T00:00"),r);if(i.includes(":")){var l=new Date;return c(new Date(l.toISOString().split("T")[0]+"T"+i),r)}}return i}catch(e){return i}}return"humidifier"===u&&"on"===a&&t.attributes.humidity?t.attributes.humidity+" %":"counter"===u||"number"===u||"input_number"===u?b(a,r):t.attributes.device_class&&e("component."+u+".state."+t.attributes.device_class+"."+a)||e("component."+u+".state._."+a)||a},exports.computeStateDomain=p,exports.createThing=function(e,t){void 0===t&&(t=!1);var r=function(e,t){return n("hui-error-card",{type:"error",error:e,config:t})},n=function(e,t){var n=window.document.createElement(e);try{if(!n.setConfig)return;n.setConfig(t)}catch(n){return console.error(e,n),r(n.message,t)}return n};if(!e||"object"!=typeof e||!t&&!e.type)return r("No type defined",e);var i=e.type;if(i&&i.startsWith("custom:"))i=i.substr("custom:".length);else if(t)if(x.has(i))i="hui-"+i+"-row";else{if(!e.entity)return r("Invalid config given.",e);var a=e.entity.split(".",1)[0];i="hui-"+(k[a]||"text")+"-entity-row"}else i="hui-"+i+"-card";if(customElements.get(i))return n(i,e);var o=r("Custom element doesn't exist: "+e.type+".",e);o.style.display="None";var u=setTimeout(function(){o.style.display=""},2e3);return customElements.whenDefined(e.type).then(function(){clearTimeout(u),w(o,"ll-rebuild",{},o)}),o},exports.debounce=function(e,t,r){var n;return void 0===r&&(r=!1),function(){var i=[].slice.call(arguments),a=this,o=function(){n=null,r||e.apply(a,i)},u=r&&!n;clearTimeout(n),n=setTimeout(o,t),u&&e.apply(a,i)}},exports.domainIcon=T,exports.evaluateFilter=function(e,t){var r=t.value||t,n=t.attribute?e.attributes[t.attribute]:e.state;switch(t.operator||"=="){case"==":return n===r;case"<=":return n<=r;case"<":return n=":return n>=r;case">":return n>r;case"!=":return n!==r;case"regex":return n.match(r);default:return!1}},exports.fireEvent=w,exports.fixedIcons=D,exports.formatDate=n,exports.formatDateMonth=function(e,t){return function(e){return new Intl.DateTimeFormat(e.language,{month:"long"})}(t).format(e)},exports.formatDateMonthYear=function(e,t){return function(e){return new Intl.DateTimeFormat(e.language,{month:"long",year:"numeric"})}(t).format(e)},exports.formatDateNumeric=function(e,t){return function(e){return new Intl.DateTimeFormat(e.language,{year:"numeric",month:"numeric",day:"numeric"})}(t).format(e)},exports.formatDateShort=function(e,t){return function(e){return new Intl.DateTimeFormat(e.language,{day:"numeric",month:"short"})}(t).format(e)},exports.formatDateTime=o,exports.formatDateTimeNumeric=function(e,t){return function(e){return new Intl.DateTimeFormat(e.language,{year:"numeric",month:"numeric",day:"numeric",hour:"numeric",minute:"2-digit",hour12:a(e)})}(t).format(e)},exports.formatDateTimeWithSeconds=function(e,t){return function(e){return new Intl.DateTimeFormat(e.language,{year:"numeric",month:"long",day:"numeric",hour:a(e)?"numeric":"2-digit",minute:"2-digit",second:"2-digit",hour12:a(e)})}(t).format(e)},exports.formatDateWeekday=function(e,t){return function(e){return new Intl.DateTimeFormat(e.language,{weekday:"long",month:"long",day:"numeric"})}(t).format(e)},exports.formatDateYear=function(e,t){return function(e){return new Intl.DateTimeFormat(e.language,{year:"numeric"})}(t).format(e)},exports.formatNumber=b,exports.formatTime=c,exports.formatTimeWeekday=function(e,t){return function(e){return new Intl.DateTimeFormat(e.language,{hour:a(e)?"numeric":"2-digit",minute:"2-digit",second:"2-digit",hour12:a(e)})}(t).format(e)},exports.formatTimeWithSeconds=function(e,t){return function(e){return new Intl.DateTimeFormat(e.language,{hour:a(e)?"numeric":"2-digit",minute:"2-digit",second:"2-digit",hour12:a(e)})}(t).format(e)},exports.forwardHaptic=F,exports.getLovelace=function(){var e=document.querySelector("home-assistant");if(e=(e=(e=(e=(e=(e=(e=(e=e&&e.shadowRoot)&&e.querySelector("home-assistant-main"))&&e.shadowRoot)&&e.querySelector("app-drawer-layout partial-panel-resolver"))&&e.shadowRoot||e)&&e.querySelector("ha-panel-lovelace"))&&e.shadowRoot)&&e.querySelector("hui-root")){var t=e.lovelace;return t.current_view=e.___curView,t}return null},exports.handleAction=function(e,t,r,n){var i;"double_tap"===n&&r.double_tap_action?i=r.double_tap_action:"hold"===n&&r.hold_action?i=r.hold_action:"tap"===n&&r.tap_action&&(i=r.tap_action),O(e,t,r,i)},exports.handleActionConfig=O,exports.handleClick=function(e,t,r,n,i){var a;if(i&&r.double_tap_action?a=r.double_tap_action:n&&r.hold_action?a=r.hold_action:!n&&r.tap_action&&(a=r.tap_action),a||(a={action:"more-info"}),!a.confirmation||a.confirmation.exemptions&&a.confirmation.exemptions.some(function(e){return e.user===t.user.id})||confirm(a.confirmation.text||"Are you sure you want to "+a.action+"?"))switch(a.action){case"more-info":(a.entity||r.entity||r.camera_image)&&(w(e,"hass-more-info",{entityId:a.entity?a.entity:r.entity?r.entity:r.camera_image}),a.haptic&&F(a.haptic));break;case"navigate":a.navigation_path&&(N(0,a.navigation_path),a.haptic&&F(a.haptic));break;case"url":a.url_path&&window.open(a.url_path),a.haptic&&F(a.haptic);break;case"toggle":r.entity&&(I(t,r.entity),a.haptic&&F(a.haptic));break;case"call-service":if(!a.service)return;var o=a.service.split(".",2),u=o[0],c=o[1],m=s({},a.data);"entity"===m.entity_id&&(m.entity_id=r.entity),t.callService(u,c,m,a.target),a.haptic&&F(a.haptic);break;case"fire-dom-event":w(e,"ll-custom",a),a.haptic&&F(a.haptic)}},exports.hasAction=function(e){return void 0!==e&&"none"!==e.action},exports.hasConfigOrEntityChanged=function(e,t,r){if(t.has("config")||r)return!0;if(e.config.entity){var n=t.get("hass");return!n||n.states[e.config.entity]!==e.hass.states[e.config.entity]}return!1},exports.hasDoubleClick=function(e){return void 0!==e&&"none"!==e.action},exports.isNumericState=f,exports.navigate=N,exports.numberFormatToLocale=g,exports.relativeTime=function(e,t,n,i){void 0===i&&(i=!0);var a=r.selectUnit(e,n);return i?function(e){return new Intl.RelativeTimeFormat(e.language,{numeric:"auto"})}(t).format(a.value,a.unit):Intl.NumberFormat(t.language,{style:"unit",unit:a.unit,unitDisplay:"long"}).format(Math.abs(a.value))},exports.round=h,exports.stateIcon=function(e){if(!e)return"mdi:bookmark";if(e.attributes.icon)return e.attributes.icon;var t=l(e.entity_id);return t in A?A[t](e):T(t,e.state)},exports.timerTimeRemaining=function(e){var t,r=3600*(t=e.attributes.remaining.split(":").map(Number))[0]+60*t[1]+t[2];if("active"===e.state){var n=(new Date).getTime(),i=new Date(e.last_changed).getTime();r=Math.max(r-(n-i)/1e3,0)}return r},exports.toggleEntity=I,exports.turnOnOffEntities=function(e,t,r){void 0===r&&(r=!0);var n={};t.forEach(function(t){if(v.includes(e.states[t].state)===r){var i=l(t),a=["cover","lock"].includes(i)?i:"homeassistant";a in n||(n[a]=[]),n[a].push(t)}}),Object.keys(n).forEach(function(t){var i;switch(t){case"lock":i=r?"unlock":"lock";break;case"cover":i=r?"open_cover":"close_cover";break;default:i=r?"turn_on":"turn_off"}e.callService(t,i,{entity_id:n[t]})})},exports.turnOnOffEntity=S; //# sourceMappingURL=index.js.map diff --git a/dist/index.js.map b/dist/index.js.map index f6bd957..a2c7bc2 100644 --- a/dist/index.js.map +++ b/dist/index.js.map @@ -1 +1 @@ -{"version":3,"file":"index.js","sources":["../src/types.ts","../src/datetime/format_date.ts","../src/datetime/use_am_pm.ts","../src/datetime/format_date_time.ts","../src/datetime/format_time.ts","../src/compute-domain.ts","../src/compute-rtl.ts","../src/compute-state-domain.ts","../src/format-number.ts","../src/const.ts","../src/fire-event.ts","../src/create-thing.ts","../src/domain_icons.ts","../src/evaluate-filter.ts","../src/haptic.ts","../src/navigate.ts","../src/turn-on-off-entity.ts","../src/toggle-entity.ts","../src/handle-action.ts","../src/sensor_icon.ts","../src/state_icon.ts","../src/binary_sensor_icon.ts","../src/cover_icon.ts","../src/input_datetime_icon.ts","../src/apply_themes_on_element.ts","../src/compute-card-size.ts","../src/compute-entity.ts","../src/compute-state-display.ts","../src/debounce.ts","../src/get-lovelace.ts","../src/handle-click.ts","../src/has-action.ts","../src/has-changed.ts","../src/has-double-click.ts","../src/datetime/relative_time.ts","../src/datetime/timer_time_remaining.ts","../src/datetime/duration_to_seconds.ts","../src/turn-on-off-entities.ts"],"sourcesContent":["import {\n HassEntities,\n HassConfig,\n Auth,\n Connection,\n MessageBase,\n HassServices,\n HassServiceTarget,\n} from \"home-assistant-js-websocket\";\nimport { HapticType } from \"./haptic\";\nimport { HASSDomEvent } from \"./fire-event\";\n\nexport interface ToggleMenuActionConfig extends BaseActionConfig {\n action: \"toggle-menu\";\n}\n\nexport interface ToggleActionConfig extends BaseActionConfig {\n action: \"toggle\";\n}\n\nexport interface CallServiceActionConfig extends BaseActionConfig {\n action: \"call-service\";\n service: string;\n service_data?: {\n entity_id?: string | [string];\n [key: string]: any;\n };\n\n target?: HassServiceTarget;\n repeat?: number;\n haptic?: HapticType;\n}\n\nexport interface NavigateActionConfig extends BaseActionConfig {\n action: \"navigate\";\n navigation_path: string;\n}\n\nexport interface UrlActionConfig extends BaseActionConfig {\n action: \"url\";\n url_path: string;\n}\n\nexport interface MoreInfoActionConfig extends BaseActionConfig {\n action: \"more-info\";\n entity?: string;\n}\n\nexport interface NoActionConfig extends BaseActionConfig {\n action: \"none\";\n}\n\nexport interface CustomActionConfig extends BaseActionConfig {\n action: \"fire-dom-event\";\n}\n\n/**\n * `repeat` and `haptic` are specifically for use in custom cards like the Button-Card\n */\nexport interface BaseActionConfig {\n confirmation?: ConfirmationRestrictionConfig;\n repeat?: number;\n haptic?: HapticType;\n}\n\nexport interface ConfirmationRestrictionConfig {\n text?: string;\n exemptions?: RestrictionConfig[];\n}\n\nexport interface RestrictionConfig {\n user: string;\n}\n\nexport type ActionConfig =\n | ToggleActionConfig\n | CallServiceActionConfig\n | NavigateActionConfig\n | UrlActionConfig\n | MoreInfoActionConfig\n | NoActionConfig\n | CustomActionConfig\n | ToggleMenuActionConfig;\n\nexport interface Window {\n // Custom panel entry point url\n customPanelJS: string;\n ShadyCSS: {\n nativeCss: boolean;\n nativeShadow: boolean;\n prepareTemplate(templateElement, elementName, elementExtension);\n styleElement(element);\n styleSubtree(element, overrideProperties);\n styleDocument(overrideProperties);\n getComputedStyleValue(element, propertyName);\n };\n}\n\ndeclare global {\n // for fire event\n interface HASSDomEvents {\n \"value-changed\": {\n value: unknown;\n };\n \"config-changed\": {\n config: any;\n };\n \"hass-more-info\": {\n entityId: string | undefined;\n };\n \"ll-rebuild\": {};\n \"ll-custom\": {};\n \"location-changed\": {\n replace: boolean;\n };\n \"show-dialog\": {};\n undefined;\n action: {\n action: string;\n };\n }\n}\n\ntype ValidHassDomEvent = keyof HASSDomEvents;\n\nexport type LocalizeFunc = (key: string, ...args: any[]) => string;\n\nexport interface Credential {\n auth_provider_type: string;\n auth_provider_id: string;\n}\n\nexport interface MFAModule {\n id: string;\n name: string;\n enabled: boolean;\n}\n\nexport interface CurrentUser {\n id: string;\n is_owner: boolean;\n is_admin: boolean;\n name: string;\n credentials: Credential[];\n mfa_modules: MFAModule[];\n}\n\nexport interface Theme {\n // Incomplete\n \"primary-color\": string;\n \"text-primary-color\": string;\n \"accent-color\": string;\n}\n\nexport interface Themes {\n default_theme: string;\n themes: { [key: string]: Theme };\n}\n\nexport interface Panel {\n component_name: string;\n config: { [key: string]: any } | null;\n icon: string | null;\n title: string | null;\n url_path: string;\n}\n\nexport interface Panels {\n [name: string]: Panel;\n}\n\nexport interface Resources {\n [language: string]: { [key: string]: string };\n}\n\nexport interface Translation {\n nativeName: string;\n isRTL: boolean;\n fingerprints: { [fragment: string]: string };\n}\n\nexport interface ServiceCallRequest {\n domain: string;\n service: string;\n serviceData?: Record;\n target?: HassServiceTarget;\n}\n\nexport interface HomeAssistant {\n auth: Auth;\n connection: Connection;\n connected: boolean;\n states: HassEntities;\n services: HassServices;\n config: HassConfig;\n themes: Themes;\n selectedTheme?: string | null;\n panels: Panels;\n panelUrl: string;\n\n // i18n\n // current effective language, in that order:\n // - backend saved user selected lanugage\n // - language in local appstorage\n // - browser language\n // - english (en)\n language: string;\n locale: FrontendLocaleData;\n // local stored language, keep that name for backward compability\n selectedLanguage: string | null;\n resources: Resources;\n localize: LocalizeFunc;\n translationMetadata: {\n fragments: string[];\n translations: {\n [lang: string]: Translation;\n };\n };\n\n dockedSidebar: boolean;\n moreInfoEntityId: string;\n user: CurrentUser;\n callService: (\n domain: ServiceCallRequest[\"domain\"],\n service: ServiceCallRequest[\"service\"],\n serviceData?: ServiceCallRequest[\"serviceData\"],\n target?: ServiceCallRequest[\"target\"]\n ) => Promise;\n callApi: (\n method: \"GET\" | \"POST\" | \"PUT\" | \"DELETE\",\n path: string,\n parameters?: { [key: string]: any }\n ) => Promise;\n fetchWithAuth: (\n path: string,\n init?: { [key: string]: any }\n ) => Promise;\n sendWS: (msg: MessageBase) => Promise;\n callWS: (msg: MessageBase) => Promise;\n}\n\nexport enum NumberFormat {\n language = \"language\",\n system = \"system\",\n comma_decimal = \"comma_decimal\",\n decimal_comma = \"decimal_comma\",\n space_comma = \"space_comma\",\n none = \"none\",\n}\n\nexport enum TimeFormat {\n language = \"language\",\n system = \"system\",\n am_pm = \"12\",\n twenty_four = \"24\",\n}\n\nexport interface FrontendLocaleData {\n language: string;\n number_format: NumberFormat;\n time_format: TimeFormat;\n}\n\nexport interface LovelaceCardConfig {\n index?: number;\n view_index?: number;\n type: string;\n [key: string]: any;\n}\n\nexport interface LovelaceCard extends HTMLElement {\n hass?: HomeAssistant;\n isPanel?: boolean;\n editMode?: boolean;\n getCardSize(): number | Promise;\n setConfig(config: LovelaceCardConfig): void;\n}\n\nexport interface LovelaceCardEditor extends HTMLElement {\n hass?: HomeAssistant;\n lovelace?: LovelaceConfig;\n setConfig(config: LovelaceCardConfig): void;\n}\n\nexport interface LovelaceConfig {\n title?: string;\n views: LovelaceViewConfig[];\n background?: string;\n}\n\nexport interface LovelaceViewConfig {\n index?: number;\n title?: string;\n badges?: Array;\n cards?: LovelaceCardConfig[];\n path?: string;\n icon?: string;\n theme?: string;\n panel?: boolean;\n background?: string;\n visible?: boolean | ShowViewConfig[];\n}\n\nexport interface ShowViewConfig {\n user?: string;\n}\n\nexport interface LovelaceBadgeConfig {\n type?: string;\n [key: string]: any;\n}\n\nexport interface ActionHandlerDetail {\n action: string;\n}\n\nexport type ActionHandlerEvent = HASSDomEvent;\n\nexport interface ActionHandlerOptions {\n hasHold?: boolean;\n hasDoubleClick?: boolean;\n}\n\nexport interface EntitiesCardEntityConfig extends EntityConfig {\n type?: string;\n secondary_info?:\n | \"entity-id\"\n | \"last-changed\"\n | \"last-triggered\"\n | \"last-updated\"\n | \"position\"\n | \"tilt-position\"\n | \"brightness\";\n action_name?: string;\n service?: string;\n service_data?: Record;\n url?: string;\n tap_action?: ActionConfig;\n hold_action?: ActionConfig;\n double_tap_action?: ActionConfig;\n state_color?: boolean;\n show_name?: boolean;\n show_icon?: boolean;\n}\n\nexport interface EntityConfig {\n entity: string;\n type?: string;\n name?: string;\n icon?: string;\n image?: string;\n}\n\nexport interface LovelaceElementConfigBase {\n type: string;\n style: Record;\n}\n","//REF: https://github.com/home-assistant/frontend/blob/dev/src/common/datetime/format_date.ts\n\nimport { FrontendLocaleData } from \"../types\";\n\n/**\n * Formatting a Date to the dddd, mmmm yy format e.g. Tuesday, August 10\n * @param dateObj The date to convert\n * @param locale The users's locale settings\n * @returns date string like \"Tuesday, August 10\"\n */\nexport const formatDateWeekday = (dateObj: Date, locale: FrontendLocaleData) =>\n formatDateWeekdayMem(locale).format(dateObj);\n\nconst formatDateWeekdayMem =\n (locale: FrontendLocaleData) =>\n new Intl.DateTimeFormat(locale.language, {\n weekday: \"long\",\n month: \"long\",\n day: \"numeric\",\n });\n\n/**\n * Formatting a Date to the mmmm dd, yyyy format e.g. August 10, 2021\n * @param dateObj The date to convert\n * @param locale The users's locale settings\n * @returns date string like \"August 10, 2021\"\n */\nexport const formatDate = (dateObj: Date, locale: FrontendLocaleData) =>\n formatDateMem(locale).format(dateObj);\n\nconst formatDateMem =\n (locale: FrontendLocaleData) =>\n new Intl.DateTimeFormat(locale.language, {\n year: \"numeric\",\n month: \"long\",\n day: \"numeric\",\n });\n\n/**\n * Formatting a Date to the classic date format e.g. 10/08/2021\n * @param dateObj The date to convert\n * @param locale The users's locale settings\n * @returns classic date format \"10/08/2021\"\n */\nexport const formatDateNumeric = (dateObj: Date, locale: FrontendLocaleData) =>\n formatDateNumericMem(locale).format(dateObj);\n\nconst formatDateNumericMem =\n (locale: FrontendLocaleData) =>\n new Intl.DateTimeFormat(locale.language, {\n year: \"numeric\",\n month: \"numeric\",\n day: \"numeric\",\n });\n\n\n/**\n * Formatting a Date to just a month with days e.g. Aug 10\n * @param dateObj The date to convert\n * @param locale The users's locale settings\n * @returns month and day like \"Aug 10\"\n */\nexport const formatDateShort = (dateObj: Date, locale: FrontendLocaleData) =>\nformatDateShortMem(locale).format(dateObj);\n\nconst formatDateShortMem =\n(locale: FrontendLocaleData) =>\n new Intl.DateTimeFormat(locale.language, {\n day: \"numeric\",\n month: \"short\",\n });\n\n\n/**\n * Formatting a Date to just a month with year e.g. August 2021\n * @param dateObj The date to convert\n * @param locale The users's locale settings\n * @returns month and year like \"August 2021\"\n */\nexport const formatDateMonthYear = (\ndateObj: Date,\nlocale: FrontendLocaleData\n) => formatDateMonthYearMem(locale).format(dateObj);\n\nconst formatDateMonthYearMem = (locale: FrontendLocaleData) =>\n new Intl.DateTimeFormat(locale.language, {\n month: \"long\",\n year: \"numeric\",\n });\n\n\n/**\n * Formatting a Date to just a month e.g. August\n * @param dateObj The date to convert\n * @param locale The users's locale settings\n * @returns the written out months of the date\n */\nexport const formatDateMonth = (dateObj: Date, locale: FrontendLocaleData) =>\nformatDateMonthMem(locale).format(dateObj);\n\nconst formatDateMonthMem = (locale: FrontendLocaleData) =>\n new Intl.DateTimeFormat(locale.language, {\n month: \"long\",\n });\n\n\n/**\n * Formatting a Date to just a year e.g. 2021\n * @param dateObj The date to convert\n * @param locale The users's locale settings\n * @returns the year of the date in yyyy\n */\nexport const formatDateYear = (dateObj: Date, locale: FrontendLocaleData) =>\nformatDateYearMem(locale).format(dateObj);\n\nconst formatDateYearMem = (locale: FrontendLocaleData) =>\n new Intl.DateTimeFormat(locale.language, {\n year: \"numeric\",\n });\n","// REF: https://github.com/home-assistant/frontend/blob/dev/src/common/datetime/use_am_pm.ts\r\n\r\nimport { FrontendLocaleData, TimeFormat } from \"../types\"\r\n\r\n/**\r\n * Checking if AM/PM time format is used within the browser.\r\n * @param locale Homeassistant frontend locale data\r\n * @returns \r\n */\r\nexport const useAmPm = (locale: FrontendLocaleData): boolean => {\r\n if (\r\n locale.time_format === TimeFormat.language ||\r\n locale.time_format === TimeFormat.system\r\n ) {\r\n const testLanguage =\r\n locale.time_format === TimeFormat.language ? locale.language : undefined;\r\n const test = new Date().toLocaleString(testLanguage);\r\n return test.includes(\"AM\") || test.includes(\"PM\");\r\n }\r\n\r\n return locale.time_format === TimeFormat.am_pm;\r\n};\r\n","//REF: https://github.com/home-assistant/frontend/blob/dev/src/common/datetime/format_date_time.ts\n\nimport { FrontendLocaleData } from \"../types\";\nimport { useAmPm } from \"./use_am_pm\";\n\n// August 9, 2021, 8:23 AM\n/**\n * Formatting a dateObject to date with time e.g. August 9, 2021, 8:23 AM\n * @param dateObj The date to convert\n * @param locale The users's locale settings\n * @returns month and day like \"August 9, 2021, 8:23 AM\"\n */\nexport const formatDateTime = (dateObj: Date, locale: FrontendLocaleData) =>\n formatDateTimeMem(locale).format(dateObj);\n\nconst formatDateTimeMem = (locale: FrontendLocaleData) =>\n new Intl.DateTimeFormat(locale.language, {\n year: \"numeric\",\n month: \"long\",\n day: \"numeric\",\n hour: useAmPm(locale) ? \"numeric\" : \"2-digit\",\n minute: \"2-digit\",\n hour12: useAmPm(locale),\n });\n\n\n/**\n * Formatting a dateObject to date with time e.g. August 9, 2021, 8:23:15 AM\n * @param dateObj The date to convert\n * @param locale The users's locale settings\n * @returns month and day like \"August 9, 2021, 8:23:15 AM\"\n */\nexport const formatDateTimeWithSeconds = (\n dateObj: Date,\n locale: FrontendLocaleData\n) => formatDateTimeWithSecondsMem(locale).format(dateObj);\n\nconst formatDateTimeWithSecondsMem =\n (locale: FrontendLocaleData) =>\n new Intl.DateTimeFormat(locale.language, {\n year: \"numeric\",\n month: \"long\",\n day: \"numeric\",\n hour: useAmPm(locale) ? \"numeric\" : \"2-digit\",\n minute: \"2-digit\",\n second: \"2-digit\",\n hour12: useAmPm(locale),\n });\n\n/**\n * Formatting a Date to just date with AM/PM time e.g. 9/8/2021, 8:23 AM\n * @param dateObj The date to convert\n * @param locale The users's locale settings\n * @returns month and day like \"9/8/2021, 8:23 AM\"\n */\nexport const formatDateTimeNumeric = (\n dateObj: Date,\n locale: FrontendLocaleData\n) => formatDateTimeNumericMem(locale).format(dateObj);\n\nconst formatDateTimeNumericMem =\n (locale: FrontendLocaleData) =>\n new Intl.DateTimeFormat(locale.language, {\n year: \"numeric\",\n month: \"numeric\",\n day: \"numeric\",\n hour: \"numeric\",\n minute: \"2-digit\",\n hour12: useAmPm(locale),\n });","//REF: https://github.com/home-assistant/frontend/blob/dev/src/common/datetime/format_time.ts\n\nimport { FrontendLocaleData } from \"../types\";\nimport { useAmPm } from \"./use_am_pm\";\n\n/**\n * 9:15 PM or 21:15\n * @param dateObj The time to convert\n * @param locale The users's locale settings\n * @returns Reformated time in hh:mm\n */\n export const formatTime = (dateObj: Date, locale: FrontendLocaleData) =>\n formatTimeMem(locale).format(dateObj);\n\n const formatTimeMem =\n (locale: FrontendLocaleData) =>\n new Intl.DateTimeFormat(locale.language, {\n hour: \"numeric\",\n minute: \"2-digit\",\n hour12: useAmPm(locale),\n });\n\n/**\n* 9:15:24 PM or 21:15:24\n* @param dateObj The time to convert\n* @param locale The users's locale settings\n* @returns Reformated time in hh:mm:ss\n*/\nexport const formatTimeWithSeconds = (\n dateObj: Date,\n locale: FrontendLocaleData\n) => formatTimeWithSecondsMem(locale).format(dateObj);\n\nconst formatTimeWithSecondsMem =\n (locale: FrontendLocaleData) =>\n new Intl.DateTimeFormat(locale.language, {\n hour: useAmPm(locale) ? \"numeric\" : \"2-digit\",\n minute: \"2-digit\",\n second: \"2-digit\",\n hour12: useAmPm(locale),\n });\n\n/**\n* Tuesday 7:00 PM or Tuesday 19:00\n* @param dateObj The datetime to convert\n* @param locale The users's locale settings\n* @returns Reformated weekday/time in dddd hh:mm\n*/\nexport const formatTimeWeekday = (dateObj: Date, locale: FrontendLocaleData) =>\n formatTimeWeekdayMem(locale).format(dateObj);\n\nconst formatTimeWeekdayMem =\n (locale: FrontendLocaleData) =>\n new Intl.DateTimeFormat(locale.language, {\n hour: useAmPm(locale) ? \"numeric\" : \"2-digit\",\n minute: \"2-digit\",\n second: \"2-digit\",\n hour12: useAmPm(locale),\n }); \n","export function computeDomain(entityId: string): string {\n return entityId.substr(0, entityId.indexOf(\".\"));\n}\n","import { HomeAssistant } from \"./types\";\n\nexport function computeRTL(hass: HomeAssistant) {\n const lang = hass?.locale?.language || \"en\";\n if (hass.translationMetadata.translations[lang]) {\n return hass.translationMetadata.translations[lang].isRTL || false;\n }\n return false;\n}\n\nexport function computeRTLDirection(hass: HomeAssistant) {\n return computeRTL(hass) ? \"rtl\" : \"ltr\";\n}\n","import { HassEntity } from \"home-assistant-js-websocket\";\nimport { computeDomain } from \"./compute-domain\";\n\nexport function computeStateDomain(stateObj: HassEntity) {\n return computeDomain(stateObj.entity_id);\n}\n","//REF: https://github.com/home-assistant/frontend/blob/dev/src/common/number/format_number.ts\n\nimport { HassEntity } from \"home-assistant-js-websocket\";\nimport { FrontendLocaleData, NumberFormat } from \"./types\";\n\n/**\n * Returns true if the entity is considered numeric based on the attributes it has\n * @param stateObj The entity state object\n */\n export const isNumericState = (stateObj: HassEntity): boolean =>\n !!stateObj.attributes.unit_of_measurement ||\n !!stateObj.attributes.state_class;\n\nexport const numberFormatToLocale = (\n localeOptions: FrontendLocaleData\n): string | string[] | undefined => {\n switch (localeOptions.number_format) {\n case NumberFormat.comma_decimal:\n return [\"en-US\", \"en\"]; // Use United States with fallback to English formatting 1,234,567.89\n case NumberFormat.decimal_comma:\n return [\"de\", \"es\", \"it\"]; // Use German with fallback to Spanish then Italian formatting 1.234.567,89\n case NumberFormat.space_comma:\n return [\"fr\", \"sv\", \"cs\"]; // Use French with fallback to Swedish and Czech formatting 1 234 567,89\n case NumberFormat.system:\n return undefined;\n default:\n return localeOptions.language;\n }\n};\n\nexport const round = (value: number, precision = 2): number =>\n Math.round(value * 10 ** precision) / 10 ** precision;\n\n/**\n * Formats a number based on the specified language with thousands separator(s) and decimal character for better legibility.\n * @param num The number to format\n * @param locale The user-selected language and number format, from `hass.locale`\n * @param options Intl.NumberFormatOptions to use\n */\nexport const formatNumber = (\n num: string | number,\n localeOptions?: FrontendLocaleData,\n options?: Intl.NumberFormatOptions\n): string => {\n const locale = localeOptions\n ? numberFormatToLocale(localeOptions)\n : undefined;\n\n // Polyfill for Number.isNaN, which is more reliable than the global isNaN()\n Number.isNaN =\n Number.isNaN ||\n function isNaN(input) {\n return typeof input === \"number\" && isNaN(input);\n };\n\n if (\n localeOptions?.number_format !== NumberFormat.none &&\n !Number.isNaN(Number(num)) &&\n Intl\n ) {\n try {\n return new Intl.NumberFormat(\n locale,\n getDefaultFormatOptions(num, options)\n ).format(Number(num));\n } catch (err: any) {\n // Don't fail when using \"TEST\" language\n // eslint-disable-next-line no-console\n console.error(err);\n return new Intl.NumberFormat(\n undefined,\n getDefaultFormatOptions(num, options)\n ).format(Number(num));\n }\n }\n if (typeof num === \"string\") {\n return num;\n }\n return `${round(num, options?.maximumFractionDigits).toString()}${\n options?.style === \"currency\" ? ` ${options.currency}` : \"\"\n }`;\n};\n\n/**\n * Generates default options for Intl.NumberFormat\n * @param num The number to be formatted\n * @param options The Intl.NumberFormatOptions that should be included in the returned options\n */\nconst getDefaultFormatOptions = (\n num: string | number,\n options?: Intl.NumberFormatOptions\n): Intl.NumberFormatOptions => {\n const defaultOptions: Intl.NumberFormatOptions = {\n maximumFractionDigits: 2,\n ...options,\n };\n\n if (typeof num !== \"string\") {\n return defaultOptions;\n }\n\n // Keep decimal trailing zeros if they are present in a string numeric value\n if (\n !options ||\n (!options.minimumFractionDigits && !options.maximumFractionDigits)\n ) {\n const digits = num.indexOf(\".\") > -1 ? num.split(\".\")[1].length : 0;\n defaultOptions.minimumFractionDigits = digits;\n defaultOptions.maximumFractionDigits = digits;\n }\n\n return defaultOptions;\n};\n","/** Constants to be used in the frontend. */\n\n// Constants should be alphabetically sorted by name.\n// Arrays with values should be alphabetically sorted if order doesn't matter.\n// Each constant should have a description what it is supposed to be used for.\n\n/** Icon to use when no icon specified for domain. */\nexport const DEFAULT_DOMAIN_ICON = \"mdi:bookmark\";\n\n/** Panel to show when no panel is picked. */\nexport const DEFAULT_PANEL = \"lovelace\";\n\n/** Domains that have a state card. */\nexport const DOMAINS_WITH_CARD = [\n \"climate\",\n \"cover\",\n \"configurator\",\n \"input_select\",\n \"input_number\",\n \"input_text\",\n \"lock\",\n \"media_player\",\n \"scene\",\n \"script\",\n \"timer\",\n \"vacuum\",\n \"water_heater\",\n \"weblink\"\n];\n\n/** Domains with separate more info dialog. */\nexport const DOMAINS_WITH_MORE_INFO = [\n \"alarm_control_panel\",\n \"automation\",\n \"camera\",\n \"climate\",\n \"configurator\",\n \"cover\",\n \"fan\",\n \"group\",\n \"history_graph\",\n \"input_datetime\",\n \"light\",\n \"lock\",\n \"media_player\",\n \"script\",\n \"sun\",\n \"updater\",\n \"vacuum\",\n \"water_heater\",\n \"weather\"\n];\n\n/** Domains that show no more info dialog. */\nexport const DOMAINS_HIDE_MORE_INFO = [\n \"input_number\",\n \"input_select\",\n \"input_text\",\n \"scene\",\n \"weblink\"\n];\n\n/** Domains that should have the history hidden in the more info dialog. */\nexport const DOMAINS_MORE_INFO_NO_HISTORY = [\n \"camera\",\n \"configurator\",\n \"history_graph\",\n \"scene\"\n];\n\n/** States that we consider \"off\". */\nexport const STATES_OFF = [\"closed\", \"locked\", \"off\"];\n\n/** Domains where we allow toggle in Lovelace. */\nexport const DOMAINS_TOGGLE = new Set([\n \"fan\",\n \"input_boolean\",\n \"light\",\n \"switch\",\n \"group\",\n \"automation\"\n]);\n\n/** Temperature units. */\nexport const UNIT_C = \"°C\";\nexport const UNIT_F = \"°F\";\n\n/** Entity ID of the default view. */\nexport const DEFAULT_VIEW_ENTITY_ID = \"group.default_view\";\n","// Polymer legacy event helpers used courtesy of the Polymer project.\n//\n// Copyright (c) 2017 The Polymer Authors. All rights reserved.\n//\n// Redistribution and use in source and binary forms, with or without\n// modification, are permitted provided that the following conditions are\n// met:\n//\n// * Redistributions of source code must retain the above copyright\n// notice, this list of conditions and the following disclaimer.\n// * Redistributions in binary form must reproduce the above\n// copyright notice, this list of conditions and the following disclaimer\n// in the documentation and/or other materials provided with the\n// distribution.\n// * Neither the name of Google Inc. nor the names of its\n// contributors may be used to endorse or promote products derived from\n// this software without specific prior written permission.\n//\n// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n// \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\ndeclare global {\n // tslint:disable-next-line\n interface HASSDomEvents {}\n}\n\nexport type ValidHassDomEvent = keyof HASSDomEvents;\n\nexport interface HASSDomEvent extends Event {\n detail: T;\n}\n\n/**\n * Dispatches a custom event with an optional detail value.\n *\n * @param {string} type Name of event type.\n * @param {*=} detail Detail value containing event-specific\n * payload.\n * @param {{ bubbles: (boolean|undefined),\n * cancelable: (boolean|undefined),\n * composed: (boolean|undefined) }=}\n * options Object specifying options. These may include:\n * `bubbles` (boolean, defaults to `true`),\n * `cancelable` (boolean, defaults to false), and\n * `node` on which to fire the event (HTMLElement, defaults to `this`).\n * @return {Event} The new event that was fired.\n */\nexport const fireEvent = (\n node: HTMLElement | Window,\n type: HassEvent,\n detail?: HASSDomEvents[HassEvent],\n options?: {\n bubbles?: boolean;\n cancelable?: boolean;\n composed?: boolean;\n }\n) => {\n options = options || {};\n // @ts-ignore\n detail = detail === null || detail === undefined ? {} : detail;\n const event = new Event(type, {\n bubbles: options.bubbles === undefined ? true : options.bubbles,\n cancelable: Boolean(options.cancelable),\n composed: options.composed === undefined ? true : options.composed\n });\n (event as any).detail = detail;\n node.dispatchEvent(event);\n return event;\n};\n","import { fireEvent } from \"./fire-event\";\n\nconst SPECIAL_TYPES = new Set([\n \"call-service\",\n \"divider\",\n \"section\",\n \"weblink\",\n \"cast\",\n \"select\"\n]);\nconst DOMAIN_TO_ELEMENT_TYPE = {\n alert: \"toggle\",\n automation: \"toggle\",\n climate: \"climate\",\n cover: \"cover\",\n fan: \"toggle\",\n group: \"group\",\n input_boolean: \"toggle\",\n input_number: \"input-number\",\n input_select: \"input-select\",\n input_text: \"input-text\",\n light: \"toggle\",\n lock: \"lock\",\n media_player: \"media-player\",\n remote: \"toggle\",\n scene: \"scene\",\n script: \"script\",\n sensor: \"sensor\",\n timer: \"timer\",\n switch: \"toggle\",\n vacuum: \"toggle\",\n // Temporary. Once climate is rewritten,\n // water heater should get it's own row.\n water_heater: \"climate\",\n input_datetime: \"input-datetime\"\n};\n\nexport const createThing = (cardConfig, isRow = false) => {\n const _createError = (error, config) => {\n return _createThing(\n \"hui-error-card\",\n {\n type: \"error\",\n error,\n config\n }\n );\n };\n\n const _createThing = (tag, config) => {\n const element = window.document.createElement(tag);\n try {\n // Preventing an error-card infinity loop: https://github.com/custom-cards/custom-card-helpers/issues/54\n if (!element.setConfig) return;\n element.setConfig(config);\n } catch (err) {\n console.error(tag, err);\n return _createError((err as Error).message, config);\n }\n return element;\n };\n\n if (!cardConfig || typeof cardConfig !== \"object\" || (!isRow && !cardConfig.type))\n return _createError(\"No type defined\", cardConfig);\n let tag = cardConfig.type;\n if (tag && tag.startsWith(\"custom:\")) {\n tag = tag.substr(\"custom:\".length);\n } else if (isRow) {\n if (SPECIAL_TYPES.has(tag)) {\n tag = `hui-${tag}-row`;\n } else {\n if (!cardConfig.entity) {\n return _createError(\"Invalid config given.\", cardConfig);\n }\n \n const domain = cardConfig.entity.split(\".\", 1)[0];\n tag = `hui-${DOMAIN_TO_ELEMENT_TYPE[domain] || \"text\"}-entity-row`;\n }\n } else {\n tag = `hui-${tag}-card`;\n }\n\n if (customElements.get(tag)) return _createThing(tag, cardConfig);\n\n // If element doesn't exist (yet) create an error\n const element = _createError(\n `Custom element doesn't exist: ${cardConfig.type}.`,\n cardConfig\n );\n element.style.display = \"None\";\n const timer = setTimeout(() => {\n element.style.display = \"\";\n }, 2000);\n // Remove error if element is defined later\n customElements.whenDefined(cardConfig.type).then(() => {\n clearTimeout(timer);\n fireEvent(element, \"ll-rebuild\", {}, element);\n });\n\n return element;\n};\n","/**\n * Return the icon to be used for a domain.\n *\n * Optionally pass in a state to influence the domain icon.\n */\nimport { DEFAULT_DOMAIN_ICON } from \"./const\";\n\nexport const fixedIcons = {\n alert: \"mdi:alert\",\n automation: \"mdi:playlist-play\",\n calendar: \"mdi:calendar\",\n camera: \"mdi:video\",\n climate: \"mdi:thermostat\",\n configurator: \"mdi:settings\",\n conversation: \"mdi:text-to-speech\",\n device_tracker: \"mdi:account\",\n fan: \"mdi:fan\",\n group: \"mdi:google-circles-communities\",\n history_graph: \"mdi:chart-line\",\n homeassistant: \"mdi:home-assistant\",\n homekit: \"mdi:home-automation\",\n image_processing: \"mdi:image-filter-frames\",\n input_boolean: \"mdi:drawing\",\n input_datetime: \"mdi:calendar-clock\",\n input_number: \"mdi:ray-vertex\",\n input_select: \"mdi:format-list-bulleted\",\n input_text: \"mdi:textbox\",\n light: \"mdi:lightbulb\",\n mailbox: \"mdi:mailbox\",\n notify: \"mdi:comment-alert\",\n person: \"mdi:account\",\n plant: \"mdi:flower\",\n proximity: \"mdi:apple-safari\",\n remote: \"mdi:remote\",\n scene: \"mdi:google-pages\",\n script: \"mdi:file-document\",\n sensor: \"mdi:eye\",\n simple_alarm: \"mdi:bell\",\n sun: \"mdi:white-balance-sunny\",\n switch: \"mdi:flash\",\n timer: \"mdi:timer\",\n updater: \"mdi:cloud-upload\",\n vacuum: \"mdi:robot-vacuum\",\n water_heater: \"mdi:thermometer\",\n weblink: \"mdi:open-in-new\"\n};\n\nexport function domainIcon(domain: string, state?: string): string {\n if (domain in fixedIcons) {\n return fixedIcons[domain];\n }\n\n switch (domain) {\n case \"alarm_control_panel\":\n switch (state) {\n case \"armed_home\":\n return \"mdi:bell-plus\";\n case \"armed_night\":\n return \"mdi:bell-sleep\";\n case \"disarmed\":\n return \"mdi:bell-outline\";\n case \"triggered\":\n return \"mdi:bell-ring\";\n default:\n return \"mdi:bell\";\n }\n\n case \"binary_sensor\":\n return state && state === \"off\"\n ? \"mdi:radiobox-blank\"\n : \"mdi:checkbox-marked-circle\";\n\n case \"cover\":\n return state === \"closed\" ? \"mdi:window-closed\" : \"mdi:window-open\";\n\n case \"lock\":\n return state && state === \"unlocked\" ? \"mdi:lock-open\" : \"mdi:lock\";\n\n case \"media_player\":\n return state && state !== \"off\" && state !== \"idle\"\n ? \"mdi:cast-connected\"\n : \"mdi:cast\";\n\n case \"zwave\":\n switch (state) {\n case \"dead\":\n return \"mdi:emoticon-dead\";\n case \"sleeping\":\n return \"mdi:sleep\";\n case \"initializing\":\n return \"mdi:timer-sand\";\n default:\n return \"mdi:z-wave\";\n }\n\n default:\n // tslint:disable-next-line\n console.warn(\n \"Unable to find icon for domain \" + domain + \" (\" + state + \")\"\n );\n return DEFAULT_DOMAIN_ICON;\n }\n}\n","import { HassEntity } from \"home-assistant-js-websocket\";\n\nexport const evaluateFilter = (stateObj: HassEntity, filter: any): boolean => {\n const operator = filter.operator || \"==\";\n const value = filter.value || filter;\n const state = filter.attribute\n ? stateObj.attributes[filter.attribute]\n : stateObj.state;\n\n switch (operator) {\n case \"==\":\n return state === value;\n case \"<=\":\n return state <= value;\n case \"<\":\n return state < value;\n case \">=\":\n return state >= value;\n case \">\":\n return state > value;\n case \"!=\":\n return state !== value;\n case \"regex\": {\n return state.match(value);\n }\n default:\n return false;\n }\n};\n","import { HASSDomEvent, fireEvent } from \"./fire-event\";\n\n/**\n * Broadcast haptic feedback requests\n */\n\n\n// Allowed types are from iOS HIG.\n// https://developer.apple.com/design/human-interface-guidelines/ios/user-interaction/feedback/#haptics\n// Implementors on platforms other than iOS should attempt to match the patterns (shown in HIG) as closely as possible.\nexport type HapticType =\n | \"success\"\n | \"warning\"\n | \"failure\"\n | \"light\"\n | \"medium\"\n | \"heavy\"\n | \"selection\";\n\ndeclare global {\n // for fire event\n interface HASSDomEvents {\n haptic: HapticType;\n }\n\n interface GlobalEventHandlersEventMap {\n haptic: HASSDomEvent;\n }\n}\n\nexport const forwardHaptic = (hapticType: HapticType) => {\n fireEvent(window, \"haptic\", hapticType);\n};\n","import { fireEvent } from \"./fire-event\";\n\ndeclare global {\n // for fire event\n interface HASSDomEvents {\n \"location-changed\": {\n replace: boolean;\n };\n }\n}\n\nexport const navigate = (\n _node: any,\n path: string,\n replace: boolean = false\n) => {\n if (replace) {\n history.replaceState(null, \"\", path);\n } else {\n history.pushState(null, \"\", path);\n }\n fireEvent(window, \"location-changed\", {\n replace\n });\n};\n","import { HomeAssistant } from \"./types\";\nimport { computeDomain } from \"./compute-domain\";\n\nexport const turnOnOffEntity = (\n hass: HomeAssistant,\n entityId: string,\n turnOn = true\n): Promise => {\n const stateDomain = computeDomain(entityId);\n const serviceDomain = stateDomain === \"group\" ? \"homeassistant\" : stateDomain;\n\n let service;\n switch (stateDomain) {\n case \"lock\":\n service = turnOn ? \"unlock\" : \"lock\";\n break;\n case \"cover\":\n service = turnOn ? \"open_cover\" : \"close_cover\";\n break;\n default:\n service = turnOn ? \"turn_on\" : \"turn_off\";\n }\n\n return hass.callService(serviceDomain, service, { entity_id: entityId });\n};\n","import { STATES_OFF } from \"./const\";\nimport { turnOnOffEntity } from \"./turn-on-off-entity\";\nimport { HomeAssistant } from \"./types\";\n\nexport const toggleEntity = (\n hass: HomeAssistant,\n entityId: string\n): Promise => {\n const turnOn = STATES_OFF.includes(hass.states[entityId].state);\n return turnOnOffEntity(hass, entityId, turnOn);\n};\n","import { HomeAssistant, ActionConfig } from \"./types\";\nimport { forwardHaptic } from \"./haptic\";\nimport { fireEvent } from \"./fire-event\";\nimport { navigate } from \"./navigate\";\nimport { toggleEntity } from \"./toggle-entity\";\n\nexport const handleActionConfig = (\n node: HTMLElement,\n hass: HomeAssistant,\n config: {\n entity?: string;\n camera_image?: string;\n hold_action?: ActionConfig;\n tap_action?: ActionConfig;\n double_tap_action?: ActionConfig;\n },\n actionConfig: ActionConfig | undefined\n): void => {\n if (!actionConfig) {\n actionConfig = {\n action: \"more-info\",\n };\n }\n\n if (\n actionConfig.confirmation &&\n (!actionConfig.confirmation.exemptions ||\n !actionConfig.confirmation.exemptions.some(\n (e) => e.user === hass!.user!.id\n ))\n ) {\n forwardHaptic(\"warning\");\n\n if (\n !confirm(\n actionConfig.confirmation.text ||\n `Are you sure you want to ${actionConfig.action}?`\n )\n ) {\n return;\n }\n }\n\n switch (actionConfig.action) {\n case \"more-info\":\n if (config.entity || config.camera_image) {\n fireEvent(node, \"hass-more-info\", {\n entityId: config.entity ? config.entity : config.camera_image!,\n });\n }\n break;\n case \"navigate\":\n if (actionConfig.navigation_path) {\n navigate(node, actionConfig.navigation_path);\n }\n break;\n case \"url\":\n if (actionConfig.url_path) {\n window.open(actionConfig.url_path);\n }\n break;\n case \"toggle\":\n if (config.entity) {\n toggleEntity(hass, config.entity!);\n forwardHaptic(\"success\");\n }\n break;\n case \"call-service\": {\n if (!actionConfig.service) {\n forwardHaptic(\"failure\");\n return;\n }\n const [domain, service] = actionConfig.service.split(\".\", 2);\n hass.callService(domain, service, actionConfig.service_data, actionConfig.target);\n forwardHaptic(\"success\");\n break;\n }\n case \"fire-dom-event\": {\n fireEvent(node, \"ll-custom\", actionConfig);\n }\n }\n};\n\nexport const handleAction = (\n node: HTMLElement,\n hass: HomeAssistant,\n config: {\n entity?: string;\n camera_image?: string;\n hold_action?: ActionConfig;\n tap_action?: ActionConfig;\n double_tap_action?: ActionConfig;\n },\n action: string\n): void => {\n let actionConfig: ActionConfig | undefined;\n\n if (action === \"double_tap\" && config.double_tap_action) {\n actionConfig = config.double_tap_action;\n } else if (action === \"hold\" && config.hold_action) {\n actionConfig = config.hold_action;\n } else if (action === \"tap\" && config.tap_action) {\n actionConfig = config.tap_action;\n }\n\n handleActionConfig(node, hass, config, actionConfig);\n};\n","/** Return an icon representing a sensor state. */\nimport { HassEntity } from \"home-assistant-js-websocket\";\nimport { UNIT_C, UNIT_F } from \"./const\";\nimport { domainIcon } from \"./domain_icons\";\n\nconst fixedDeviceClassIcons = {\n humidity: \"mdi:water-percent\",\n illuminance: \"mdi:brightness-5\",\n temperature: \"mdi:thermometer\",\n pressure: \"mdi:gauge\",\n power: \"mdi:flash\",\n signal_strength: \"mdi:wifi\",\n};\n\nexport const sensorIcon = (state: HassEntity) => {\n const dclass = state.attributes.device_class;\n\n if (dclass && dclass in fixedDeviceClassIcons) {\n return fixedDeviceClassIcons[dclass];\n }\n if (dclass === \"battery\") {\n const battery = Number(state.state);\n if (isNaN(battery)) {\n return \"mdi:battery-unknown\";\n }\n const batteryRound = Math.round(battery / 10) * 10;\n if (batteryRound >= 100) {\n return \"mdi:battery\";\n }\n if (batteryRound <= 0) {\n return \"mdi:battery-alert\";\n }\n // Will return one of the following icons: (listed so extractor picks up)\n // mdi:battery-10\n // mdi:battery-20\n // mdi:battery-30\n // mdi:battery-40\n // mdi:battery-50\n // mdi:battery-60\n // mdi:battery-70\n // mdi:battery-80\n // mdi:battery-90\n // We obscure 'hass' in iconname so this name does not get picked up\n return `${\"hass\"}:battery-${batteryRound}`;\n }\n\n const unit = state.attributes.unit_of_measurement;\n if (unit === UNIT_C || unit === UNIT_F) {\n return \"mdi:thermometer\";\n }\n return domainIcon(\"sensor\");\n};\n","import { HassEntity } from \"home-assistant-js-websocket\";\nimport { computeDomain } from \"./compute-domain\";\nimport { DEFAULT_DOMAIN_ICON } from \"./const\";\nimport { binarySensorIcon } from \"./binary_sensor_icon\";\nimport { coverIcon } from \"./cover_icon\";\nimport { sensorIcon } from \"./sensor_icon\";\nimport { inputDateTimeIcon } from \"./input_datetime_icon\";\nimport { domainIcon } from \"./domain_icons\";\n\nconst domainIcons = {\n binary_sensor: binarySensorIcon,\n cover: coverIcon,\n sensor: sensorIcon,\n input_datetime: inputDateTimeIcon,\n};\n\nexport const stateIcon = (state: HassEntity) => {\n if (!state) {\n return DEFAULT_DOMAIN_ICON;\n }\n if (state.attributes.icon) {\n return state.attributes.icon;\n }\n\n const domain = computeDomain(state.entity_id);\n\n if (domain in domainIcons) {\n return domainIcons[domain](state);\n }\n return domainIcon(domain, state.state);\n};\n","import { HassEntity } from \"home-assistant-js-websocket\";\n\n/** Return an icon representing a binary sensor state. */\n\nexport const binarySensorIcon = (state?: string, stateObj?: HassEntity) => {\n const is_off = state === \"off\";\n switch (stateObj?.attributes.device_class) {\n case \"battery\":\n return is_off ? \"mdi:battery\" : \"mdi:battery-outline\";\n case \"battery_charging\":\n return is_off ? \"mdi:battery\" : \"mdi:battery-charging\";\n case \"cold\":\n return is_off ? \"mdi:thermometer\" : \"mdi:snowflake\";\n case \"connectivity\":\n return is_off ? \"mdi:server-network-off\" : \"mdi:server-network\";\n case \"door\":\n return is_off ? \"mdi:door-closed\" : \"mdi:door-open\";\n case \"garage_door\":\n return is_off ? \"mdi:garage\" : \"mdi:garage-open\";\n case \"power\":\n return is_off ? \"mdi:power-plug-off\" : \"mdi:power-plug\";\n case \"gas\":\n case \"problem\":\n case \"safety\":\n case \"tamper\":\n return is_off ? \"mdi:check-circle\" : \"mdi:alert-circle\";\n case \"smoke\":\n return is_off ? \"mdi:check-circle\" : \"mdi:smoke\";\n case \"heat\":\n return is_off ? \"mdi:thermometer\" : \"mdi:fire\";\n case \"light\":\n return is_off ? \"mdi:brightness-5\" : \"mdi:brightness-7\";\n case \"lock\":\n return is_off ? \"mdi:lock\" : \"mdi:lock-open\";\n case \"moisture\":\n return is_off ? \"mdi:water-off\" : \"mdi:water\";\n case \"motion\":\n return is_off ? \"mdi:walk\" : \"mdi:run\";\n case \"occupancy\":\n return is_off ? \"mdi:home-outline\" : \"mdi:home\";\n case \"opening\":\n return is_off ? \"mdi:square\" : \"mdi:square-outline\";\n case \"plug\":\n return is_off ? \"mdi:power-plug-off\" : \"mdi:power-plug\";\n case \"presence\":\n return is_off ? \"mdi:home-outline\" : \"mdi:home\";\n case \"running\":\n return is_off ? \"mdi:stop\" : \"mdi:play\";\n case \"sound\":\n return is_off ? \"mdi:music-note-off\" : \"mdi:music-note\";\n case \"update\":\n return is_off ? \"mdi:package\" : \"mdi:package-up\";\n case \"vibration\":\n return is_off ? \"mdi:crop-portrait\" : \"mdi:vibrate\";\n case \"window\":\n return is_off ? \"mdi:window-closed\" : \"mdi:window-open\";\n default:\n return is_off ? \"mdi:radiobox-blank\" : \"mdi:checkbox-marked-circle\";\n }\n};\n","/** Return an icon representing a cover state. */\nimport { HassEntity } from \"home-assistant-js-websocket\";\nimport { domainIcon } from \"./domain_icons\";\n\nexport const coverIcon = (state: HassEntity): string => {\n const open = state.state !== \"closed\";\n switch (state.attributes.device_class) {\n case \"garage\":\n return open ? \"mdi:garage-open\" : \"mdi:garage\";\n case \"door\":\n return open ? \"mdi:door-open\" : \"mdi:door-closed\";\n case \"shutter\":\n return open ? \"mdi:window-shutter-open\" : \"mdi:window-shutter\";\n case \"blind\":\n return open ? \"mdi:blinds-open\" : \"mdi:blinds\";\n case \"window\":\n return open ? \"mdi:window-open\" : \"mdi:window-closed\";\n default:\n return domainIcon(\"cover\", state.state);\n }\n};\n","/** Return an icon representing an input datetime state. */\nimport { domainIcon } from \"./domain_icons\";\nimport { HassEntity } from \"home-assistant-js-websocket\";\n\nexport const inputDateTimeIcon = (state: HassEntity): string => {\n if (!state.attributes.has_date) {\n return \"mdi:clock\";\n }\n if (!state.attributes.has_time) {\n return \"mdi:calendar\";\n }\n return domainIcon(\"input_datetime\");\n};\n","/**\n * Apply a theme to an element by setting the CSS variables on it.\n *\n * element: Element to apply theme on.\n * themes: HASS Theme information\n * localTheme: selected theme.\n * updateMeta: boolean if we should update the theme-color meta element.\n */\nexport const applyThemesOnElement = (\n element,\n themes,\n localTheme,\n updateMeta = false\n) => {\n if (!element._themes) {\n element._themes = {};\n }\n let themeName = themes.default_theme;\n if (localTheme === \"default\" || (localTheme && themes.themes[localTheme])) {\n themeName = localTheme;\n }\n const styles = { ...element._themes };\n if (themeName !== \"default\") {\n const theme = themes.themes[themeName];\n Object.keys(theme).forEach((key) => {\n const prefixedKey = \"--\" + key;\n element._themes[prefixedKey] = \"\";\n styles[prefixedKey] = theme[key];\n });\n }\n if (element.updateStyles) {\n element.updateStyles(styles);\n } else if ((window as any).ShadyCSS) {\n // implement updateStyles() method of Polemer elements\n (window as any).ShadyCSS.styleSubtree(/** @type {!HTMLElement} */ (element), styles);\n }\n\n if (!updateMeta) {\n return;\n }\n\n const meta = document.querySelector(\"meta[name=theme-color]\");\n if (meta) {\n if (!meta.hasAttribute(\"default-content\")) {\n meta.setAttribute(\"default-content\", meta.getAttribute(\"content\")!);\n }\n const themeColor =\n styles[\"--primary-color\"] || meta.getAttribute(\"default-content\");\n meta.setAttribute(\"content\", themeColor);\n }\n}\n","import { LovelaceCard } from \"./types\";\n\nexport const computeCardSize = (card: LovelaceCard): number | Promise => {\n return typeof card.getCardSize === \"function\" ? card.getCardSize() : 4;\n};","export function computeEntity(entityId: string): string {\n return entityId.substr(entityId.indexOf(\".\") + 1);\n}\n","import { HassEntity } from \"home-assistant-js-websocket\";\nimport { formatDateTime } from \"./datetime/format_date_time\";\nimport { formatDate } from \"./datetime/format_date\";\nimport { formatTime } from \"./datetime/format_time\";\nimport { LocalizeFunc } from \"./translations/localize\";\nimport { computeStateDomain } from \"./compute-state-domain\";\nimport { FrontendLocaleData } from \"./types\";\nimport { formatNumber, isNumericState } from \"./format-number\";\n\nexport const computeStateDisplay = (\n localize: LocalizeFunc,\n stateObj: HassEntity,\n locale: FrontendLocaleData,\n state?: string\n): string => {\n const compareState = state !== undefined ? state : stateObj.state;\n\n if (compareState === \"unknown\" || compareState === \"unavailable\") {\n return localize(`state.default.${compareState}`);\n }\n\n // Entities with a `unit_of_measurement` or `state_class` are numeric values and should use `formatNumber`\n if (isNumericState(stateObj)) {\n if (stateObj.attributes.device_class === \"monetary\") {\n try {\n return formatNumber(compareState, locale, {\n style: \"currency\",\n currency: stateObj.attributes.unit_of_measurement,\n });\n } catch (_err) {\n // fallback to default\n }\n }\n return `${formatNumber(compareState, locale)}${\n stateObj.attributes.unit_of_measurement\n ? \" \" + stateObj.attributes.unit_of_measurement\n : \"\"\n }`;\n }\n\n const domain = computeStateDomain(stateObj);\n\n if (domain === \"input_datetime\") {\n if (state !== undefined) {\n // If trying to display an explicit state, need to parse the explict state to `Date` then format.\n // Attributes aren't available, we have to use `state`.\n try {\n const components = state.split(\" \");\n if (components.length === 2) {\n // Date and time.\n return formatDateTime(new Date(components.join(\"T\")), locale);\n }\n if (components.length === 1) {\n if (state.includes(\"-\")) {\n // Date only.\n return formatDate(new Date(`${state}T00:00`), locale);\n }\n if (state.includes(\":\")) {\n // Time only.\n const now = new Date();\n return formatTime(\n new Date(`${now.toISOString().split(\"T\")[0]}T${state}`),\n locale\n );\n }\n }\n return state;\n } catch (_e) {\n // Formatting methods may throw error if date parsing doesn't go well,\n // just return the state string in that case.\n return state;\n }\n } else {\n // If not trying to display an explicit state, create `Date` object from `stateObj`'s attributes then format.\n let date: Date;\n if (stateObj.attributes.has_date && stateObj.attributes.has_time) {\n date = new Date(\n stateObj.attributes.year,\n stateObj.attributes.month - 1,\n stateObj.attributes.day,\n stateObj.attributes.hour,\n stateObj.attributes.minute\n );\n return formatDateTime(date, locale);\n }\n if (stateObj.attributes.has_date) {\n date = new Date(\n stateObj.attributes.year,\n stateObj.attributes.month - 1,\n stateObj.attributes.day\n );\n return formatDate(date, locale);\n }\n if (stateObj.attributes.has_time) {\n date = new Date();\n date.setHours(stateObj.attributes.hour, stateObj.attributes.minute);\n return formatTime(date, locale);\n }\n return stateObj.state;\n }\n }\n\n if (domain === \"humidifier\") {\n if (compareState === \"on\" && stateObj.attributes.humidity) {\n return `${stateObj.attributes.humidity} %`;\n }\n }\n\n // `counter` `number` and `input_number` domains do not have a unit of measurement but should still use `formatNumber`\n if (\n domain === \"counter\" ||\n domain === \"number\" ||\n domain === \"input_number\"\n ) {\n return formatNumber(compareState, locale);\n }\n\n return (\n // Return device class translation\n (stateObj.attributes.device_class &&\n localize(\n `component.${domain}.state.${stateObj.attributes.device_class}.${compareState}`\n )) ||\n // Return default translation\n localize(`component.${domain}.state._.${compareState}`) ||\n // We don't know! Return the raw state.\n compareState\n );\n};","/**\r\n * Returns a function, that, as long as it continues to be invoked, will not be triggered. It will be called after it stops being called for `wait` ms.\r\n * This can be usefull for ResizeObservers for example.\r\n * @param func The function you want to debounce\r\n * @param wait Period to wait in ms\r\n * @param immediate Triggering on the leading edge instead of the trailing\r\n * @returns Debounced Function\r\n */\r\n// eslint-disable-next-line: ban-types\r\nexport const debounce = unknown>(\r\n func: T,\r\n wait: number,\r\n immediate = false\r\n): T => {\r\n let timeout;\r\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\r\n // @ts-ignore\r\n return function (...args) {\r\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\r\n // @ts-ignore\r\n // eslint-disable-next-line @typescript-eslint/no-this-alias\r\n const context = this;\r\n const later = () => {\r\n timeout = null;\r\n if (!immediate) {\r\n func.apply(context, args);\r\n }\r\n };\r\n const callNow = immediate && !timeout;\r\n clearTimeout(timeout);\r\n timeout = setTimeout(later, wait);\r\n if (callNow) {\r\n func.apply(context, args);\r\n }\r\n };\r\n};\r\n","export const getLovelace = () => {\n let root: any = document.querySelector('home-assistant');\n root = root && root.shadowRoot;\n root = root && root.querySelector('home-assistant-main');\n root = root && root.shadowRoot;\n root = root && root.querySelector('app-drawer-layout partial-panel-resolver');\n root = root && root.shadowRoot || root;\n root = root && root.querySelector('ha-panel-lovelace');\n root = root && root.shadowRoot;\n root = root && root.querySelector('hui-root');\n if (root) {\n const ll = root.lovelace;\n ll.current_view = root.___curView;\n return ll;\n }\n return null;\n}\n","import { HomeAssistant, ActionConfig } from \"./types\";\nimport { fireEvent } from \"./fire-event\";\nimport { forwardHaptic } from \"./haptic\";\nimport { navigate } from \"./navigate\";\nimport { toggleEntity } from \"./toggle-entity\";\n\nexport const handleClick = (\n node: HTMLElement,\n hass: HomeAssistant,\n config: {\n entity?: string;\n camera_image?: string;\n hold_action?: ActionConfig;\n tap_action?: ActionConfig;\n double_tap_action?: ActionConfig;\n },\n hold: boolean,\n dblClick: boolean\n): void => {\n let actionConfig: ActionConfig | undefined;\n\n if (dblClick && config.double_tap_action) {\n actionConfig = config.double_tap_action;\n } else if (hold && config.hold_action) {\n actionConfig = config.hold_action;\n } else if (!hold && config.tap_action) {\n actionConfig = config.tap_action;\n }\n\n if (!actionConfig) {\n actionConfig = {\n action: \"more-info\"\n };\n }\n\n if (\n actionConfig.confirmation &&\n (!actionConfig.confirmation.exemptions ||\n !actionConfig.confirmation.exemptions.some(\n e => e.user === hass!.user!.id\n ))\n ) {\n if (\n !confirm(\n actionConfig.confirmation.text ||\n `Are you sure you want to ${actionConfig.action}?`\n )\n ) {\n return;\n }\n }\n\n switch (actionConfig.action) {\n case \"more-info\":\n if (actionConfig.entity || config.entity || config.camera_image) {\n fireEvent(node, \"hass-more-info\", {\n entityId: actionConfig.entity\n ? actionConfig.entity\n : config.entity\n ? config.entity\n : config.camera_image\n });\n if (actionConfig.haptic) forwardHaptic(actionConfig.haptic);\n }\n break;\n case \"navigate\":\n if (actionConfig.navigation_path) {\n navigate(node, actionConfig.navigation_path);\n if (actionConfig.haptic) forwardHaptic(actionConfig.haptic);\n }\n break;\n case \"url\":\n actionConfig.url_path && window.open(actionConfig.url_path);\n if (actionConfig.haptic) forwardHaptic(actionConfig.haptic);\n break;\n case \"toggle\":\n if (config.entity) {\n toggleEntity(hass, config.entity!);\n if (actionConfig.haptic) forwardHaptic(actionConfig.haptic);\n }\n break;\n case \"call-service\": {\n if (!actionConfig.service) {\n return;\n }\n const [domain, service] = actionConfig.service.split(\".\", 2);\n const serviceData = { ...actionConfig.service_data };\n if (serviceData.entity_id === \"entity\") {\n serviceData.entity_id = config.entity;\n }\n hass.callService(domain, service, serviceData, actionConfig.target);\n if (actionConfig.haptic) forwardHaptic(actionConfig.haptic);\n break;\n }\n case \"fire-dom-event\": {\n fireEvent(node, \"ll-custom\", actionConfig);\n if (actionConfig.haptic) forwardHaptic(actionConfig.haptic);\n break;\n }\n }\n};\n","import { ActionConfig } from \"./types\";\n\nexport function hasAction(config?: ActionConfig): boolean {\n return config !== undefined && config.action !== \"none\";\n}\n","import { PropertyValues } from \"lit\";\n\nimport { HomeAssistant } from \"./types\";\n\n// Check if config or Entity changed\nexport function hasConfigOrEntityChanged(\n element: any,\n changedProps: PropertyValues,\n forceUpdate: Boolean,\n): boolean {\n if (changedProps.has('config') || forceUpdate) {\n return true;\n }\n\n if (element.config!.entity) {\n const oldHass = changedProps.get('hass') as HomeAssistant | undefined;\n if (oldHass) {\n return (\n oldHass.states[element.config!.entity]\n !== element.hass!.states[element.config!.entity]\n );\n }\n return true;\n } else {\n return false;\n }\n}","import { ActionConfig } from \"./types\";\n\n// Check if config or Entity changed\nexport function hasDoubleClick(config?: ActionConfig): boolean {\n return config !== undefined && config.action !== \"none\";\n}","//REF: https://github.com/home-assistant/frontend/blob/dev/src/common/datetime/relative_time.ts\n\nimport { selectUnit } from \"@formatjs/intl-utils\";\nimport { FrontendLocaleData } from \"../types\";\n\n const formatRelTimeMem =\n (locale: FrontendLocaleData) =>\n new Intl.RelativeTimeFormat(locale.language, { numeric: \"auto\" });\n\n/**\n * Calculate a string representing a date object as relative time from now.\n *\n * Example output: 5 minutes ago, in 3 days.\n */\n export const relativeTime = (\n from: Date,\n locale: FrontendLocaleData,\n to?: Date,\n includeTense = true\n): string => {\n const diff = selectUnit(from, to);\n if (includeTense) {\n return formatRelTimeMem(locale).format(diff.value, diff.unit);\n }\n return Intl.NumberFormat(locale.language, {\n style: \"unit\",\n unit: diff.unit,\n unitDisplay: \"long\",\n }).format(Math.abs(diff.value));\n};\n","import { HassEntity } from \"home-assistant-js-websocket\";\nimport durationToSeconds from \"../datetime/duration_to_seconds\";\n\nexport function timerTimeRemaining(stateObj: HassEntity) {\n let timeRemaining = durationToSeconds(stateObj.attributes.remaining);\n\n if (stateObj.state === \"active\") {\n const now = new Date().getTime();\n const madeActive = new Date(stateObj.last_changed).getTime();\n timeRemaining = Math.max(timeRemaining - (now - madeActive) / 1000, 0);\n }\n\n return timeRemaining;\n}\n","/**\n * Convert a Duration hh:mm:ss format to seconds\n * @param duration hh:mm:ss formated duration\n * @returns duration in seconds\n */\n export default function durationToSeconds(duration: string): number {\n const parts = duration.split(\":\").map(Number);\n return parts[0] * 3600 + parts[1] * 60 + parts[2];\n}\n","import { HomeAssistant } from \"./types\";\nimport { STATES_OFF } from \"./const\";\nimport { computeDomain } from \"./compute-domain\";\n\nexport const turnOnOffEntities = (\n hass: HomeAssistant,\n entityIds: string[],\n turnOn = true\n): void => {\n const domainsToCall = {};\n entityIds.forEach((entityId) => {\n if (STATES_OFF.includes(hass.states[entityId].state) === turnOn) {\n const stateDomain = computeDomain(entityId);\n const serviceDomain = [\"cover\", \"lock\"].includes(stateDomain)\n ? stateDomain\n : \"homeassistant\";\n\n if (!(serviceDomain in domainsToCall)) {\n domainsToCall[serviceDomain] = [];\n }\n domainsToCall[serviceDomain].push(entityId);\n }\n });\n\n Object.keys(domainsToCall).forEach((domain) => {\n let service;\n switch (domain) {\n case \"lock\":\n service = turnOn ? \"unlock\" : \"lock\";\n break;\n case \"cover\":\n service = turnOn ? \"open_cover\" : \"close_cover\";\n break;\n default:\n service = turnOn ? \"turn_on\" : \"turn_off\";\n }\n\n const entities = domainsToCall[domain];\n hass.callService(domain, service, { entity_id: entities });\n });\n};\n"],"names":["NumberFormat","TimeFormat","formatDate","dateObj","locale","formatDateMem","format","Intl","DateTimeFormat","language","year","month","day","useAmPm","time_format","system","testLanguage","undefined","test","Date","toLocaleString","includes","am_pm","formatDateTime","formatDateTimeMem","hour","minute","hour12","formatTime","formatTimeMem","computeDomain","entityId","substr","indexOf","computeRTL","hass","lang","translationMetadata","translations","isRTL","computeStateDomain","stateObj","entity_id","isNumericState","attributes","unit_of_measurement","state_class","numberFormatToLocale","localeOptions","number_format","comma_decimal","decimal_comma","space_comma","round","value","precision","Math","formatNumber","num","options","Number","isNaN","input","none","getDefaultFormatOptions","err","console","error","maximumFractionDigits","toString","style","currency","defaultOptions","minimumFractionDigits","digits","split","length","STATES_OFF","DOMAINS_TOGGLE","Set","fireEvent","node","type","detail","event","Event","bubbles","cancelable","Boolean","composed","dispatchEvent","SPECIAL_TYPES","DOMAIN_TO_ELEMENT_TYPE","alert","automation","climate","cover","fan","group","input_boolean","input_number","input_select","input_text","light","lock","media_player","remote","scene","script","sensor","timer","switch","vacuum","water_heater","input_datetime","fixedIcons","calendar","camera","configurator","conversation","device_tracker","history_graph","homeassistant","homekit","image_processing","mailbox","notify","person","plant","proximity","simple_alarm","sun","updater","weblink","domainIcon","domain","state","warn","evaluateFilter","forwardHaptic","hapticType","window","navigate","_node","path","replace","history","replaceState","pushState","turnOnOffEntity","turnOn","service","stateDomain","serviceDomain","callService","toggleEntity","states","handleActionConfig","config","actionConfig","action","confirmation","exemptions","some","e","user","id","confirm","text","entity","camera_image","navigation_path","url_path","open","service_data","target","fixedDeviceClassIcons","humidity","illuminance","temperature","pressure","power","signal_strength","domainIcons","binary_sensor","is_off","device_class","dclass","battery","batteryRound","unit","has_date","has_time","element","themes","localTheme","updateMeta","_themes","themeName","default_theme","styles","theme","Object","keys","forEach","key","prefixedKey","updateStyles","ShadyCSS","styleSubtree","meta","document","querySelector","hasAttribute","setAttribute","getAttribute","themeColor","card","getCardSize","localize","compareState","_err","date","setHours","components","join","now","toISOString","_e","cardConfig","isRow","_createError","_createThing","tag","createElement","setConfig","message","startsWith","has","customElements","get","display","setTimeout","whenDefined","then","clearTimeout","func","wait","immediate","timeout","args","context","this","later","apply","callNow","filter","attribute","operator","match","formatDateMonthMem","formatDateMonthYearMem","formatDateNumericMem","formatDateShortMem","formatDateTimeNumericMem","second","formatDateTimeWithSecondsMem","weekday","formatDateWeekdayMem","formatDateYearMem","formatTimeWeekdayMem","formatTimeWithSecondsMem","root","shadowRoot","ll","lovelace","current_view","___curView","double_tap_action","hold_action","tap_action","hold","dblClick","haptic","serviceData","changedProps","forceUpdate","oldHass","from","to","includeTense","diff","selectUnit","RelativeTimeFormat","numeric","formatRelTimeMem","unitDisplay","abs","icon","parts","timeRemaining","remaining","map","getTime","madeActive","last_changed","max","entityIds","domainsToCall","push"],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"index.js","sources":["../src/types.ts","../src/datetime/format_date.ts","../src/datetime/use_am_pm.ts","../src/datetime/format_date_time.ts","../src/datetime/format_time.ts","../src/compute-domain.ts","../src/compute-rtl.ts","../src/compute-state-domain.ts","../src/format-number.ts","../src/const.ts","../src/fire-event.ts","../src/create-thing.ts","../src/domain_icons.ts","../src/evaluate-filter.ts","../src/haptic.ts","../src/navigate.ts","../src/turn-on-off-entity.ts","../src/toggle-entity.ts","../src/handle-action.ts","../src/sensor_icon.ts","../src/state_icon.ts","../src/binary_sensor_icon.ts","../src/cover_icon.ts","../src/input_datetime_icon.ts","../src/apply_themes_on_element.ts","../src/compute-card-size.ts","../src/compute-entity.ts","../src/compute-state-display.ts","../src/debounce.ts","../src/get-lovelace.ts","../src/handle-click.ts","../src/has-action.ts","../src/has-changed.ts","../src/has-double-click.ts","../src/datetime/relative_time.ts","../src/datetime/timer_time_remaining.ts","../src/datetime/duration_to_seconds.ts","../src/turn-on-off-entities.ts"],"sourcesContent":["import {\n HassEntities,\n HassConfig,\n Auth,\n Connection,\n MessageBase,\n HassServices,\n HassServiceTarget,\n} from \"home-assistant-js-websocket\";\nimport { HapticType } from \"./haptic\";\nimport { HASSDomEvent } from \"./fire-event\";\n\nexport interface ToggleMenuActionConfig extends BaseActionConfig {\n action: \"toggle-menu\";\n}\n\nexport interface ToggleActionConfig extends BaseActionConfig {\n action: \"toggle\";\n}\n\nexport interface CallServiceActionConfig extends BaseActionConfig {\n action: \"call-service\";\n service: string;\n data?: {\n entity_id?: string | [string];\n [key: string]: any;\n };\n\n target?: HassServiceTarget;\n repeat?: number;\n haptic?: HapticType;\n}\n\nexport interface NavigateActionConfig extends BaseActionConfig {\n action: \"navigate\";\n navigation_path: string;\n}\n\nexport interface UrlActionConfig extends BaseActionConfig {\n action: \"url\";\n url_path: string;\n}\n\nexport interface MoreInfoActionConfig extends BaseActionConfig {\n action: \"more-info\";\n entity?: string;\n}\n\nexport interface NoActionConfig extends BaseActionConfig {\n action: \"none\";\n}\n\nexport interface CustomActionConfig extends BaseActionConfig {\n action: \"fire-dom-event\";\n}\n\n/**\n * `repeat` and `haptic` are specifically for use in custom cards like the Button-Card\n */\nexport interface BaseActionConfig {\n confirmation?: ConfirmationRestrictionConfig;\n repeat?: number;\n haptic?: HapticType;\n}\n\nexport interface ConfirmationRestrictionConfig {\n text?: string;\n exemptions?: RestrictionConfig[];\n}\n\nexport interface RestrictionConfig {\n user: string;\n}\n\nexport type ActionConfig =\n | ToggleActionConfig\n | CallServiceActionConfig\n | NavigateActionConfig\n | UrlActionConfig\n | MoreInfoActionConfig\n | NoActionConfig\n | CustomActionConfig\n | ToggleMenuActionConfig;\n\nexport interface Window {\n // Custom panel entry point url\n customPanelJS: string;\n ShadyCSS: {\n nativeCss: boolean;\n nativeShadow: boolean;\n prepareTemplate(templateElement, elementName, elementExtension);\n styleElement(element);\n styleSubtree(element, overrideProperties);\n styleDocument(overrideProperties);\n getComputedStyleValue(element, propertyName);\n };\n}\n\ndeclare global {\n // for fire event\n interface HASSDomEvents {\n \"value-changed\": {\n value: unknown;\n };\n \"config-changed\": {\n config: any;\n };\n \"hass-more-info\": {\n entityId: string | undefined;\n };\n \"ll-rebuild\": {};\n \"ll-custom\": {};\n \"location-changed\": {\n replace: boolean;\n };\n \"show-dialog\": {};\n undefined;\n action: {\n action: string;\n };\n }\n}\n\ntype ValidHassDomEvent = keyof HASSDomEvents;\n\nexport type LocalizeFunc = (key: string, ...args: any[]) => string;\n\nexport interface Credential {\n auth_provider_type: string;\n auth_provider_id: string;\n}\n\nexport interface MFAModule {\n id: string;\n name: string;\n enabled: boolean;\n}\n\nexport interface CurrentUser {\n id: string;\n is_owner: boolean;\n is_admin: boolean;\n name: string;\n credentials: Credential[];\n mfa_modules: MFAModule[];\n}\n\nexport interface Theme {\n // Incomplete\n \"primary-color\": string;\n \"text-primary-color\": string;\n \"accent-color\": string;\n}\n\nexport interface Themes {\n default_theme: string;\n themes: { [key: string]: Theme };\n}\n\nexport interface Panel {\n component_name: string;\n config: { [key: string]: any } | null;\n icon: string | null;\n title: string | null;\n url_path: string;\n}\n\nexport interface Panels {\n [name: string]: Panel;\n}\n\nexport interface Resources {\n [language: string]: { [key: string]: string };\n}\n\nexport interface Translation {\n nativeName: string;\n isRTL: boolean;\n fingerprints: { [fragment: string]: string };\n}\n\nexport interface ServiceCallRequest {\n domain: string;\n service: string;\n serviceData?: Record;\n target?: HassServiceTarget;\n}\n\nexport interface HomeAssistant {\n auth: Auth;\n connection: Connection;\n connected: boolean;\n states: HassEntities;\n services: HassServices;\n config: HassConfig;\n themes: Themes;\n selectedTheme?: string | null;\n panels: Panels;\n panelUrl: string;\n\n // i18n\n // current effective language, in that order:\n // - backend saved user selected lanugage\n // - language in local appstorage\n // - browser language\n // - english (en)\n language: string;\n locale: FrontendLocaleData;\n // local stored language, keep that name for backward compability\n selectedLanguage: string | null;\n resources: Resources;\n localize: LocalizeFunc;\n translationMetadata: {\n fragments: string[];\n translations: {\n [lang: string]: Translation;\n };\n };\n\n dockedSidebar: boolean;\n moreInfoEntityId: string;\n user: CurrentUser;\n callService: (\n domain: ServiceCallRequest[\"domain\"],\n service: ServiceCallRequest[\"service\"],\n serviceData?: ServiceCallRequest[\"serviceData\"],\n target?: ServiceCallRequest[\"target\"]\n ) => Promise;\n callApi: (\n method: \"GET\" | \"POST\" | \"PUT\" | \"DELETE\",\n path: string,\n parameters?: { [key: string]: any }\n ) => Promise;\n fetchWithAuth: (\n path: string,\n init?: { [key: string]: any }\n ) => Promise;\n sendWS: (msg: MessageBase) => Promise;\n callWS: (msg: MessageBase) => Promise;\n}\n\nexport enum NumberFormat {\n language = \"language\",\n system = \"system\",\n comma_decimal = \"comma_decimal\",\n decimal_comma = \"decimal_comma\",\n space_comma = \"space_comma\",\n none = \"none\",\n}\n\nexport enum TimeFormat {\n language = \"language\",\n system = \"system\",\n am_pm = \"12\",\n twenty_four = \"24\",\n}\n\nexport interface FrontendLocaleData {\n language: string;\n number_format: NumberFormat;\n time_format: TimeFormat;\n}\n\nexport interface LovelaceCardConfig {\n index?: number;\n view_index?: number;\n type: string;\n [key: string]: any;\n}\n\nexport interface LovelaceCard extends HTMLElement {\n hass?: HomeAssistant;\n isPanel?: boolean;\n editMode?: boolean;\n getCardSize(): number | Promise;\n setConfig(config: LovelaceCardConfig): void;\n}\n\nexport interface LovelaceCardEditor extends HTMLElement {\n hass?: HomeAssistant;\n lovelace?: LovelaceConfig;\n setConfig(config: LovelaceCardConfig): void;\n}\n\nexport interface LovelaceConfig {\n title?: string;\n views: LovelaceViewConfig[];\n background?: string;\n}\n\nexport interface LovelaceViewConfig {\n index?: number;\n title?: string;\n badges?: Array;\n cards?: LovelaceCardConfig[];\n path?: string;\n icon?: string;\n theme?: string;\n panel?: boolean;\n background?: string;\n visible?: boolean | ShowViewConfig[];\n}\n\nexport interface ShowViewConfig {\n user?: string;\n}\n\nexport interface LovelaceBadgeConfig {\n type?: string;\n [key: string]: any;\n}\n\nexport interface ActionHandlerDetail {\n action: string;\n}\n\nexport type ActionHandlerEvent = HASSDomEvent;\n\nexport interface ActionHandlerOptions {\n hasHold?: boolean;\n hasDoubleClick?: boolean;\n}\n\nexport interface EntitiesCardEntityConfig extends EntityConfig {\n type?: string;\n secondary_info?:\n | \"entity-id\"\n | \"last-changed\"\n | \"last-triggered\"\n | \"last-updated\"\n | \"position\"\n | \"tilt-position\"\n | \"brightness\";\n action_name?: string;\n service?: string;\n data?: Record;\n url?: string;\n tap_action?: ActionConfig;\n hold_action?: ActionConfig;\n double_tap_action?: ActionConfig;\n state_color?: boolean;\n show_name?: boolean;\n show_icon?: boolean;\n}\n\nexport interface EntityConfig {\n entity: string;\n type?: string;\n name?: string;\n icon?: string;\n image?: string;\n}\n\nexport interface LovelaceElementConfigBase {\n type: string;\n style: Record;\n}\n","//REF: https://github.com/home-assistant/frontend/blob/dev/src/common/datetime/format_date.ts\n\nimport { FrontendLocaleData } from \"../types\";\n\n/**\n * Formatting a Date to the dddd, mmmm yy format e.g. Tuesday, August 10\n * @param dateObj The date to convert\n * @param locale The users's locale settings\n * @returns date string like \"Tuesday, August 10\"\n */\nexport const formatDateWeekday = (dateObj: Date, locale: FrontendLocaleData) =>\n formatDateWeekdayMem(locale).format(dateObj);\n\nconst formatDateWeekdayMem =\n (locale: FrontendLocaleData) =>\n new Intl.DateTimeFormat(locale.language, {\n weekday: \"long\",\n month: \"long\",\n day: \"numeric\",\n });\n\n/**\n * Formatting a Date to the mmmm dd, yyyy format e.g. August 10, 2021\n * @param dateObj The date to convert\n * @param locale The users's locale settings\n * @returns date string like \"August 10, 2021\"\n */\nexport const formatDate = (dateObj: Date, locale: FrontendLocaleData) =>\n formatDateMem(locale).format(dateObj);\n\nconst formatDateMem =\n (locale: FrontendLocaleData) =>\n new Intl.DateTimeFormat(locale.language, {\n year: \"numeric\",\n month: \"long\",\n day: \"numeric\",\n });\n\n/**\n * Formatting a Date to the classic date format e.g. 10/08/2021\n * @param dateObj The date to convert\n * @param locale The users's locale settings\n * @returns classic date format \"10/08/2021\"\n */\nexport const formatDateNumeric = (dateObj: Date, locale: FrontendLocaleData) =>\n formatDateNumericMem(locale).format(dateObj);\n\nconst formatDateNumericMem =\n (locale: FrontendLocaleData) =>\n new Intl.DateTimeFormat(locale.language, {\n year: \"numeric\",\n month: \"numeric\",\n day: \"numeric\",\n });\n\n\n/**\n * Formatting a Date to just a month with days e.g. Aug 10\n * @param dateObj The date to convert\n * @param locale The users's locale settings\n * @returns month and day like \"Aug 10\"\n */\nexport const formatDateShort = (dateObj: Date, locale: FrontendLocaleData) =>\nformatDateShortMem(locale).format(dateObj);\n\nconst formatDateShortMem =\n(locale: FrontendLocaleData) =>\n new Intl.DateTimeFormat(locale.language, {\n day: \"numeric\",\n month: \"short\",\n });\n\n\n/**\n * Formatting a Date to just a month with year e.g. August 2021\n * @param dateObj The date to convert\n * @param locale The users's locale settings\n * @returns month and year like \"August 2021\"\n */\nexport const formatDateMonthYear = (\ndateObj: Date,\nlocale: FrontendLocaleData\n) => formatDateMonthYearMem(locale).format(dateObj);\n\nconst formatDateMonthYearMem = (locale: FrontendLocaleData) =>\n new Intl.DateTimeFormat(locale.language, {\n month: \"long\",\n year: \"numeric\",\n });\n\n\n/**\n * Formatting a Date to just a month e.g. August\n * @param dateObj The date to convert\n * @param locale The users's locale settings\n * @returns the written out months of the date\n */\nexport const formatDateMonth = (dateObj: Date, locale: FrontendLocaleData) =>\nformatDateMonthMem(locale).format(dateObj);\n\nconst formatDateMonthMem = (locale: FrontendLocaleData) =>\n new Intl.DateTimeFormat(locale.language, {\n month: \"long\",\n });\n\n\n/**\n * Formatting a Date to just a year e.g. 2021\n * @param dateObj The date to convert\n * @param locale The users's locale settings\n * @returns the year of the date in yyyy\n */\nexport const formatDateYear = (dateObj: Date, locale: FrontendLocaleData) =>\nformatDateYearMem(locale).format(dateObj);\n\nconst formatDateYearMem = (locale: FrontendLocaleData) =>\n new Intl.DateTimeFormat(locale.language, {\n year: \"numeric\",\n });\n","// REF: https://github.com/home-assistant/frontend/blob/dev/src/common/datetime/use_am_pm.ts\r\n\r\nimport { FrontendLocaleData, TimeFormat } from \"../types\"\r\n\r\n/**\r\n * Checking if AM/PM time format is used within the browser.\r\n * @param locale Homeassistant frontend locale data\r\n * @returns \r\n */\r\nexport const useAmPm = (locale: FrontendLocaleData): boolean => {\r\n if (\r\n locale.time_format === TimeFormat.language ||\r\n locale.time_format === TimeFormat.system\r\n ) {\r\n const testLanguage =\r\n locale.time_format === TimeFormat.language ? locale.language : undefined;\r\n const test = new Date().toLocaleString(testLanguage);\r\n return test.includes(\"AM\") || test.includes(\"PM\");\r\n }\r\n\r\n return locale.time_format === TimeFormat.am_pm;\r\n};\r\n","//REF: https://github.com/home-assistant/frontend/blob/dev/src/common/datetime/format_date_time.ts\n\nimport { FrontendLocaleData } from \"../types\";\nimport { useAmPm } from \"./use_am_pm\";\n\n// August 9, 2021, 8:23 AM\n/**\n * Formatting a dateObject to date with time e.g. August 9, 2021, 8:23 AM\n * @param dateObj The date to convert\n * @param locale The users's locale settings\n * @returns month and day like \"August 9, 2021, 8:23 AM\"\n */\nexport const formatDateTime = (dateObj: Date, locale: FrontendLocaleData) =>\n formatDateTimeMem(locale).format(dateObj);\n\nconst formatDateTimeMem = (locale: FrontendLocaleData) =>\n new Intl.DateTimeFormat(locale.language, {\n year: \"numeric\",\n month: \"long\",\n day: \"numeric\",\n hour: useAmPm(locale) ? \"numeric\" : \"2-digit\",\n minute: \"2-digit\",\n hour12: useAmPm(locale),\n });\n\n\n/**\n * Formatting a dateObject to date with time e.g. August 9, 2021, 8:23:15 AM\n * @param dateObj The date to convert\n * @param locale The users's locale settings\n * @returns month and day like \"August 9, 2021, 8:23:15 AM\"\n */\nexport const formatDateTimeWithSeconds = (\n dateObj: Date,\n locale: FrontendLocaleData\n) => formatDateTimeWithSecondsMem(locale).format(dateObj);\n\nconst formatDateTimeWithSecondsMem =\n (locale: FrontendLocaleData) =>\n new Intl.DateTimeFormat(locale.language, {\n year: \"numeric\",\n month: \"long\",\n day: \"numeric\",\n hour: useAmPm(locale) ? \"numeric\" : \"2-digit\",\n minute: \"2-digit\",\n second: \"2-digit\",\n hour12: useAmPm(locale),\n });\n\n/**\n * Formatting a Date to just date with AM/PM time e.g. 9/8/2021, 8:23 AM\n * @param dateObj The date to convert\n * @param locale The users's locale settings\n * @returns month and day like \"9/8/2021, 8:23 AM\"\n */\nexport const formatDateTimeNumeric = (\n dateObj: Date,\n locale: FrontendLocaleData\n) => formatDateTimeNumericMem(locale).format(dateObj);\n\nconst formatDateTimeNumericMem =\n (locale: FrontendLocaleData) =>\n new Intl.DateTimeFormat(locale.language, {\n year: \"numeric\",\n month: \"numeric\",\n day: \"numeric\",\n hour: \"numeric\",\n minute: \"2-digit\",\n hour12: useAmPm(locale),\n });","//REF: https://github.com/home-assistant/frontend/blob/dev/src/common/datetime/format_time.ts\n\nimport { FrontendLocaleData } from \"../types\";\nimport { useAmPm } from \"./use_am_pm\";\n\n/**\n * 9:15 PM or 21:15\n * @param dateObj The time to convert\n * @param locale The users's locale settings\n * @returns Reformated time in hh:mm\n */\n export const formatTime = (dateObj: Date, locale: FrontendLocaleData) =>\n formatTimeMem(locale).format(dateObj);\n\n const formatTimeMem =\n (locale: FrontendLocaleData) =>\n new Intl.DateTimeFormat(locale.language, {\n hour: \"numeric\",\n minute: \"2-digit\",\n hour12: useAmPm(locale),\n });\n\n/**\n* 9:15:24 PM or 21:15:24\n* @param dateObj The time to convert\n* @param locale The users's locale settings\n* @returns Reformated time in hh:mm:ss\n*/\nexport const formatTimeWithSeconds = (\n dateObj: Date,\n locale: FrontendLocaleData\n) => formatTimeWithSecondsMem(locale).format(dateObj);\n\nconst formatTimeWithSecondsMem =\n (locale: FrontendLocaleData) =>\n new Intl.DateTimeFormat(locale.language, {\n hour: useAmPm(locale) ? \"numeric\" : \"2-digit\",\n minute: \"2-digit\",\n second: \"2-digit\",\n hour12: useAmPm(locale),\n });\n\n/**\n* Tuesday 7:00 PM or Tuesday 19:00\n* @param dateObj The datetime to convert\n* @param locale The users's locale settings\n* @returns Reformated weekday/time in dddd hh:mm\n*/\nexport const formatTimeWeekday = (dateObj: Date, locale: FrontendLocaleData) =>\n formatTimeWeekdayMem(locale).format(dateObj);\n\nconst formatTimeWeekdayMem =\n (locale: FrontendLocaleData) =>\n new Intl.DateTimeFormat(locale.language, {\n hour: useAmPm(locale) ? \"numeric\" : \"2-digit\",\n minute: \"2-digit\",\n second: \"2-digit\",\n hour12: useAmPm(locale),\n }); \n","export function computeDomain(entityId: string): string {\n return entityId.substr(0, entityId.indexOf(\".\"));\n}\n","import { HomeAssistant } from \"./types\";\n\nexport function computeRTL(hass: HomeAssistant) {\n const lang = hass?.locale?.language || \"en\";\n if (hass.translationMetadata.translations[lang]) {\n return hass.translationMetadata.translations[lang].isRTL || false;\n }\n return false;\n}\n\nexport function computeRTLDirection(hass: HomeAssistant) {\n return computeRTL(hass) ? \"rtl\" : \"ltr\";\n}\n","import { HassEntity } from \"home-assistant-js-websocket\";\nimport { computeDomain } from \"./compute-domain\";\n\nexport function computeStateDomain(stateObj: HassEntity) {\n return computeDomain(stateObj.entity_id);\n}\n","//REF: https://github.com/home-assistant/frontend/blob/dev/src/common/number/format_number.ts\n\nimport { HassEntity } from \"home-assistant-js-websocket\";\nimport { FrontendLocaleData, NumberFormat } from \"./types\";\n\n/**\n * Returns true if the entity is considered numeric based on the attributes it has\n * @param stateObj The entity state object\n */\n export const isNumericState = (stateObj: HassEntity): boolean =>\n !!stateObj.attributes.unit_of_measurement ||\n !!stateObj.attributes.state_class;\n\nexport const numberFormatToLocale = (\n localeOptions: FrontendLocaleData\n): string | string[] | undefined => {\n switch (localeOptions.number_format) {\n case NumberFormat.comma_decimal:\n return [\"en-US\", \"en\"]; // Use United States with fallback to English formatting 1,234,567.89\n case NumberFormat.decimal_comma:\n return [\"de\", \"es\", \"it\"]; // Use German with fallback to Spanish then Italian formatting 1.234.567,89\n case NumberFormat.space_comma:\n return [\"fr\", \"sv\", \"cs\"]; // Use French with fallback to Swedish and Czech formatting 1 234 567,89\n case NumberFormat.system:\n return undefined;\n default:\n return localeOptions.language;\n }\n};\n\nexport const round = (value: number, precision = 2): number =>\n Math.round(value * 10 ** precision) / 10 ** precision;\n\n/**\n * Formats a number based on the specified language with thousands separator(s) and decimal character for better legibility.\n * @param num The number to format\n * @param locale The user-selected language and number format, from `hass.locale`\n * @param options Intl.NumberFormatOptions to use\n */\nexport const formatNumber = (\n num: string | number,\n localeOptions?: FrontendLocaleData,\n options?: Intl.NumberFormatOptions\n): string => {\n const locale = localeOptions\n ? numberFormatToLocale(localeOptions)\n : undefined;\n\n // Polyfill for Number.isNaN, which is more reliable than the global isNaN()\n Number.isNaN =\n Number.isNaN ||\n function isNaN(input) {\n return typeof input === \"number\" && isNaN(input);\n };\n\n if (\n localeOptions?.number_format !== NumberFormat.none &&\n !Number.isNaN(Number(num)) &&\n Intl\n ) {\n try {\n return new Intl.NumberFormat(\n locale,\n getDefaultFormatOptions(num, options)\n ).format(Number(num));\n } catch (err: any) {\n // Don't fail when using \"TEST\" language\n // eslint-disable-next-line no-console\n console.error(err);\n return new Intl.NumberFormat(\n undefined,\n getDefaultFormatOptions(num, options)\n ).format(Number(num));\n }\n }\n if (typeof num === \"string\") {\n return num;\n }\n return `${round(num, options?.maximumFractionDigits).toString()}${\n options?.style === \"currency\" ? ` ${options.currency}` : \"\"\n }`;\n};\n\n/**\n * Generates default options for Intl.NumberFormat\n * @param num The number to be formatted\n * @param options The Intl.NumberFormatOptions that should be included in the returned options\n */\nconst getDefaultFormatOptions = (\n num: string | number,\n options?: Intl.NumberFormatOptions\n): Intl.NumberFormatOptions => {\n const defaultOptions: Intl.NumberFormatOptions = {\n maximumFractionDigits: 2,\n ...options,\n };\n\n if (typeof num !== \"string\") {\n return defaultOptions;\n }\n\n // Keep decimal trailing zeros if they are present in a string numeric value\n if (\n !options ||\n (!options.minimumFractionDigits && !options.maximumFractionDigits)\n ) {\n const digits = num.indexOf(\".\") > -1 ? num.split(\".\")[1].length : 0;\n defaultOptions.minimumFractionDigits = digits;\n defaultOptions.maximumFractionDigits = digits;\n }\n\n return defaultOptions;\n};\n","/** Constants to be used in the frontend. */\n\n// Constants should be alphabetically sorted by name.\n// Arrays with values should be alphabetically sorted if order doesn't matter.\n// Each constant should have a description what it is supposed to be used for.\n\n/** Icon to use when no icon specified for domain. */\nexport const DEFAULT_DOMAIN_ICON = \"mdi:bookmark\";\n\n/** Panel to show when no panel is picked. */\nexport const DEFAULT_PANEL = \"lovelace\";\n\n/** Domains that have a state card. */\nexport const DOMAINS_WITH_CARD = [\n \"climate\",\n \"cover\",\n \"configurator\",\n \"input_select\",\n \"input_number\",\n \"input_text\",\n \"lock\",\n \"media_player\",\n \"scene\",\n \"script\",\n \"timer\",\n \"vacuum\",\n \"water_heater\",\n \"weblink\"\n];\n\n/** Domains with separate more info dialog. */\nexport const DOMAINS_WITH_MORE_INFO = [\n \"alarm_control_panel\",\n \"automation\",\n \"camera\",\n \"climate\",\n \"configurator\",\n \"cover\",\n \"fan\",\n \"group\",\n \"history_graph\",\n \"input_datetime\",\n \"light\",\n \"lock\",\n \"media_player\",\n \"script\",\n \"sun\",\n \"updater\",\n \"vacuum\",\n \"water_heater\",\n \"weather\"\n];\n\n/** Domains that show no more info dialog. */\nexport const DOMAINS_HIDE_MORE_INFO = [\n \"input_number\",\n \"input_select\",\n \"input_text\",\n \"scene\",\n \"weblink\"\n];\n\n/** Domains that should have the history hidden in the more info dialog. */\nexport const DOMAINS_MORE_INFO_NO_HISTORY = [\n \"camera\",\n \"configurator\",\n \"history_graph\",\n \"scene\"\n];\n\n/** States that we consider \"off\". */\nexport const STATES_OFF = [\"closed\", \"locked\", \"off\"];\n\n/** Domains where we allow toggle in Lovelace. */\nexport const DOMAINS_TOGGLE = new Set([\n \"fan\",\n \"input_boolean\",\n \"light\",\n \"switch\",\n \"group\",\n \"automation\"\n]);\n\n/** Temperature units. */\nexport const UNIT_C = \"°C\";\nexport const UNIT_F = \"°F\";\n\n/** Entity ID of the default view. */\nexport const DEFAULT_VIEW_ENTITY_ID = \"group.default_view\";\n","// Polymer legacy event helpers used courtesy of the Polymer project.\n//\n// Copyright (c) 2017 The Polymer Authors. All rights reserved.\n//\n// Redistribution and use in source and binary forms, with or without\n// modification, are permitted provided that the following conditions are\n// met:\n//\n// * Redistributions of source code must retain the above copyright\n// notice, this list of conditions and the following disclaimer.\n// * Redistributions in binary form must reproduce the above\n// copyright notice, this list of conditions and the following disclaimer\n// in the documentation and/or other materials provided with the\n// distribution.\n// * Neither the name of Google Inc. nor the names of its\n// contributors may be used to endorse or promote products derived from\n// this software without specific prior written permission.\n//\n// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n// \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\ndeclare global {\n // tslint:disable-next-line\n interface HASSDomEvents {}\n}\n\nexport type ValidHassDomEvent = keyof HASSDomEvents;\n\nexport interface HASSDomEvent extends Event {\n detail: T;\n}\n\n/**\n * Dispatches a custom event with an optional detail value.\n *\n * @param {string} type Name of event type.\n * @param {*=} detail Detail value containing event-specific\n * payload.\n * @param {{ bubbles: (boolean|undefined),\n * cancelable: (boolean|undefined),\n * composed: (boolean|undefined) }=}\n * options Object specifying options. These may include:\n * `bubbles` (boolean, defaults to `true`),\n * `cancelable` (boolean, defaults to false), and\n * `node` on which to fire the event (HTMLElement, defaults to `this`).\n * @return {Event} The new event that was fired.\n */\nexport const fireEvent = (\n node: HTMLElement | Window,\n type: HassEvent,\n detail?: HASSDomEvents[HassEvent],\n options?: {\n bubbles?: boolean;\n cancelable?: boolean;\n composed?: boolean;\n }\n) => {\n options = options || {};\n // @ts-ignore\n detail = detail === null || detail === undefined ? {} : detail;\n const event = new Event(type, {\n bubbles: options.bubbles === undefined ? true : options.bubbles,\n cancelable: Boolean(options.cancelable),\n composed: options.composed === undefined ? true : options.composed\n });\n (event as any).detail = detail;\n node.dispatchEvent(event);\n return event;\n};\n","import { fireEvent } from \"./fire-event\";\n\nconst SPECIAL_TYPES = new Set([\n \"call-service\",\n \"divider\",\n \"section\",\n \"weblink\",\n \"cast\",\n \"select\"\n]);\nconst DOMAIN_TO_ELEMENT_TYPE = {\n alert: \"toggle\",\n automation: \"toggle\",\n climate: \"climate\",\n cover: \"cover\",\n fan: \"toggle\",\n group: \"group\",\n input_boolean: \"toggle\",\n input_number: \"input-number\",\n input_select: \"input-select\",\n input_text: \"input-text\",\n light: \"toggle\",\n lock: \"lock\",\n media_player: \"media-player\",\n remote: \"toggle\",\n scene: \"scene\",\n script: \"script\",\n sensor: \"sensor\",\n timer: \"timer\",\n switch: \"toggle\",\n vacuum: \"toggle\",\n // Temporary. Once climate is rewritten,\n // water heater should get it's own row.\n water_heater: \"climate\",\n input_datetime: \"input-datetime\"\n};\n\nexport const createThing = (cardConfig, isRow = false) => {\n const _createError = (error, config) => {\n return _createThing(\n \"hui-error-card\",\n {\n type: \"error\",\n error,\n config\n }\n );\n };\n\n const _createThing = (tag, config) => {\n const element = window.document.createElement(tag);\n try {\n // Preventing an error-card infinity loop: https://github.com/custom-cards/custom-card-helpers/issues/54\n if (!element.setConfig) return;\n element.setConfig(config);\n } catch (err) {\n console.error(tag, err);\n return _createError((err as Error).message, config);\n }\n return element;\n };\n\n if (!cardConfig || typeof cardConfig !== \"object\" || (!isRow && !cardConfig.type))\n return _createError(\"No type defined\", cardConfig);\n let tag = cardConfig.type;\n if (tag && tag.startsWith(\"custom:\")) {\n tag = tag.substr(\"custom:\".length);\n } else if (isRow) {\n if (SPECIAL_TYPES.has(tag)) {\n tag = `hui-${tag}-row`;\n } else {\n if (!cardConfig.entity) {\n return _createError(\"Invalid config given.\", cardConfig);\n }\n \n const domain = cardConfig.entity.split(\".\", 1)[0];\n tag = `hui-${DOMAIN_TO_ELEMENT_TYPE[domain] || \"text\"}-entity-row`;\n }\n } else {\n tag = `hui-${tag}-card`;\n }\n\n if (customElements.get(tag)) return _createThing(tag, cardConfig);\n\n // If element doesn't exist (yet) create an error\n const element = _createError(\n `Custom element doesn't exist: ${cardConfig.type}.`,\n cardConfig\n );\n element.style.display = \"None\";\n const timer = setTimeout(() => {\n element.style.display = \"\";\n }, 2000);\n // Remove error if element is defined later\n customElements.whenDefined(cardConfig.type).then(() => {\n clearTimeout(timer);\n fireEvent(element, \"ll-rebuild\", {}, element);\n });\n\n return element;\n};\n","/**\n * Return the icon to be used for a domain.\n *\n * Optionally pass in a state to influence the domain icon.\n */\nimport { DEFAULT_DOMAIN_ICON } from \"./const\";\n\nexport const fixedIcons = {\n alert: \"mdi:alert\",\n automation: \"mdi:playlist-play\",\n calendar: \"mdi:calendar\",\n camera: \"mdi:video\",\n climate: \"mdi:thermostat\",\n configurator: \"mdi:settings\",\n conversation: \"mdi:text-to-speech\",\n device_tracker: \"mdi:account\",\n fan: \"mdi:fan\",\n group: \"mdi:google-circles-communities\",\n history_graph: \"mdi:chart-line\",\n homeassistant: \"mdi:home-assistant\",\n homekit: \"mdi:home-automation\",\n image_processing: \"mdi:image-filter-frames\",\n input_boolean: \"mdi:drawing\",\n input_datetime: \"mdi:calendar-clock\",\n input_number: \"mdi:ray-vertex\",\n input_select: \"mdi:format-list-bulleted\",\n input_text: \"mdi:textbox\",\n light: \"mdi:lightbulb\",\n mailbox: \"mdi:mailbox\",\n notify: \"mdi:comment-alert\",\n person: \"mdi:account\",\n plant: \"mdi:flower\",\n proximity: \"mdi:apple-safari\",\n remote: \"mdi:remote\",\n scene: \"mdi:google-pages\",\n script: \"mdi:file-document\",\n sensor: \"mdi:eye\",\n simple_alarm: \"mdi:bell\",\n sun: \"mdi:white-balance-sunny\",\n switch: \"mdi:flash\",\n timer: \"mdi:timer\",\n updater: \"mdi:cloud-upload\",\n vacuum: \"mdi:robot-vacuum\",\n water_heater: \"mdi:thermometer\",\n weblink: \"mdi:open-in-new\"\n};\n\nexport function domainIcon(domain: string, state?: string): string {\n if (domain in fixedIcons) {\n return fixedIcons[domain];\n }\n\n switch (domain) {\n case \"alarm_control_panel\":\n switch (state) {\n case \"armed_home\":\n return \"mdi:bell-plus\";\n case \"armed_night\":\n return \"mdi:bell-sleep\";\n case \"disarmed\":\n return \"mdi:bell-outline\";\n case \"triggered\":\n return \"mdi:bell-ring\";\n default:\n return \"mdi:bell\";\n }\n\n case \"binary_sensor\":\n return state && state === \"off\"\n ? \"mdi:radiobox-blank\"\n : \"mdi:checkbox-marked-circle\";\n\n case \"cover\":\n return state === \"closed\" ? \"mdi:window-closed\" : \"mdi:window-open\";\n\n case \"lock\":\n return state && state === \"unlocked\" ? \"mdi:lock-open\" : \"mdi:lock\";\n\n case \"media_player\":\n return state && state !== \"off\" && state !== \"idle\"\n ? \"mdi:cast-connected\"\n : \"mdi:cast\";\n\n case \"zwave\":\n switch (state) {\n case \"dead\":\n return \"mdi:emoticon-dead\";\n case \"sleeping\":\n return \"mdi:sleep\";\n case \"initializing\":\n return \"mdi:timer-sand\";\n default:\n return \"mdi:z-wave\";\n }\n\n default:\n // tslint:disable-next-line\n console.warn(\n \"Unable to find icon for domain \" + domain + \" (\" + state + \")\"\n );\n return DEFAULT_DOMAIN_ICON;\n }\n}\n","import { HassEntity } from \"home-assistant-js-websocket\";\n\nexport const evaluateFilter = (stateObj: HassEntity, filter: any): boolean => {\n const operator = filter.operator || \"==\";\n const value = filter.value || filter;\n const state = filter.attribute\n ? stateObj.attributes[filter.attribute]\n : stateObj.state;\n\n switch (operator) {\n case \"==\":\n return state === value;\n case \"<=\":\n return state <= value;\n case \"<\":\n return state < value;\n case \">=\":\n return state >= value;\n case \">\":\n return state > value;\n case \"!=\":\n return state !== value;\n case \"regex\": {\n return state.match(value);\n }\n default:\n return false;\n }\n};\n","import { HASSDomEvent, fireEvent } from \"./fire-event\";\n\n/**\n * Broadcast haptic feedback requests\n */\n\n\n// Allowed types are from iOS HIG.\n// https://developer.apple.com/design/human-interface-guidelines/ios/user-interaction/feedback/#haptics\n// Implementors on platforms other than iOS should attempt to match the patterns (shown in HIG) as closely as possible.\nexport type HapticType =\n | \"success\"\n | \"warning\"\n | \"failure\"\n | \"light\"\n | \"medium\"\n | \"heavy\"\n | \"selection\";\n\ndeclare global {\n // for fire event\n interface HASSDomEvents {\n haptic: HapticType;\n }\n\n interface GlobalEventHandlersEventMap {\n haptic: HASSDomEvent;\n }\n}\n\nexport const forwardHaptic = (hapticType: HapticType) => {\n fireEvent(window, \"haptic\", hapticType);\n};\n","import { fireEvent } from \"./fire-event\";\n\ndeclare global {\n // for fire event\n interface HASSDomEvents {\n \"location-changed\": {\n replace: boolean;\n };\n }\n}\n\nexport const navigate = (\n _node: any,\n path: string,\n replace: boolean = false\n) => {\n if (replace) {\n history.replaceState(null, \"\", path);\n } else {\n history.pushState(null, \"\", path);\n }\n fireEvent(window, \"location-changed\", {\n replace\n });\n};\n","import { HomeAssistant } from \"./types\";\nimport { computeDomain } from \"./compute-domain\";\n\nexport const turnOnOffEntity = (\n hass: HomeAssistant,\n entityId: string,\n turnOn = true\n): Promise => {\n const stateDomain = computeDomain(entityId);\n const serviceDomain = stateDomain === \"group\" ? \"homeassistant\" : stateDomain;\n\n let service;\n switch (stateDomain) {\n case \"lock\":\n service = turnOn ? \"unlock\" : \"lock\";\n break;\n case \"cover\":\n service = turnOn ? \"open_cover\" : \"close_cover\";\n break;\n default:\n service = turnOn ? \"turn_on\" : \"turn_off\";\n }\n\n return hass.callService(serviceDomain, service, { entity_id: entityId });\n};\n","import { STATES_OFF } from \"./const\";\nimport { turnOnOffEntity } from \"./turn-on-off-entity\";\nimport { HomeAssistant } from \"./types\";\n\nexport const toggleEntity = (\n hass: HomeAssistant,\n entityId: string\n): Promise => {\n const turnOn = STATES_OFF.includes(hass.states[entityId].state);\n return turnOnOffEntity(hass, entityId, turnOn);\n};\n","import { HomeAssistant, ActionConfig } from \"./types\";\nimport { forwardHaptic } from \"./haptic\";\nimport { fireEvent } from \"./fire-event\";\nimport { navigate } from \"./navigate\";\nimport { toggleEntity } from \"./toggle-entity\";\n\nexport const handleActionConfig = (\n node: HTMLElement,\n hass: HomeAssistant,\n config: {\n entity?: string;\n camera_image?: string;\n hold_action?: ActionConfig;\n tap_action?: ActionConfig;\n double_tap_action?: ActionConfig;\n },\n actionConfig: ActionConfig | undefined\n): void => {\n if (!actionConfig) {\n actionConfig = {\n action: \"more-info\",\n };\n }\n\n if (\n actionConfig.confirmation &&\n (!actionConfig.confirmation.exemptions ||\n !actionConfig.confirmation.exemptions.some(\n (e) => e.user === hass!.user!.id\n ))\n ) {\n forwardHaptic(\"warning\");\n\n if (\n !confirm(\n actionConfig.confirmation.text ||\n `Are you sure you want to ${actionConfig.action}?`\n )\n ) {\n return;\n }\n }\n\n switch (actionConfig.action) {\n case \"more-info\":\n if (config.entity || config.camera_image) {\n fireEvent(node, \"hass-more-info\", {\n entityId: config.entity ? config.entity : config.camera_image!,\n });\n }\n break;\n case \"navigate\":\n if (actionConfig.navigation_path) {\n navigate(node, actionConfig.navigation_path);\n }\n break;\n case \"url\":\n if (actionConfig.url_path) {\n window.open(actionConfig.url_path);\n }\n break;\n case \"toggle\":\n if (config.entity) {\n toggleEntity(hass, config.entity!);\n forwardHaptic(\"success\");\n }\n break;\n case \"call-service\": {\n if (!actionConfig.service) {\n forwardHaptic(\"failure\");\n return;\n }\n const [domain, service] = actionConfig.service.split(\".\", 2);\n hass.callService(domain, service, actionConfig.data, actionConfig.target);\n forwardHaptic(\"success\");\n break;\n }\n case \"fire-dom-event\": {\n fireEvent(node, \"ll-custom\", actionConfig);\n }\n }\n};\n\nexport const handleAction = (\n node: HTMLElement,\n hass: HomeAssistant,\n config: {\n entity?: string;\n camera_image?: string;\n hold_action?: ActionConfig;\n tap_action?: ActionConfig;\n double_tap_action?: ActionConfig;\n },\n action: string\n): void => {\n let actionConfig: ActionConfig | undefined;\n\n if (action === \"double_tap\" && config.double_tap_action) {\n actionConfig = config.double_tap_action;\n } else if (action === \"hold\" && config.hold_action) {\n actionConfig = config.hold_action;\n } else if (action === \"tap\" && config.tap_action) {\n actionConfig = config.tap_action;\n }\n\n handleActionConfig(node, hass, config, actionConfig);\n};\n","/** Return an icon representing a sensor state. */\nimport { HassEntity } from \"home-assistant-js-websocket\";\nimport { UNIT_C, UNIT_F } from \"./const\";\nimport { domainIcon } from \"./domain_icons\";\n\nconst fixedDeviceClassIcons = {\n humidity: \"mdi:water-percent\",\n illuminance: \"mdi:brightness-5\",\n temperature: \"mdi:thermometer\",\n pressure: \"mdi:gauge\",\n power: \"mdi:flash\",\n signal_strength: \"mdi:wifi\",\n};\n\nexport const sensorIcon = (state: HassEntity) => {\n const dclass = state.attributes.device_class;\n\n if (dclass && dclass in fixedDeviceClassIcons) {\n return fixedDeviceClassIcons[dclass];\n }\n if (dclass === \"battery\") {\n const battery = Number(state.state);\n if (isNaN(battery)) {\n return \"mdi:battery-unknown\";\n }\n const batteryRound = Math.round(battery / 10) * 10;\n if (batteryRound >= 100) {\n return \"mdi:battery\";\n }\n if (batteryRound <= 0) {\n return \"mdi:battery-alert\";\n }\n // Will return one of the following icons: (listed so extractor picks up)\n // mdi:battery-10\n // mdi:battery-20\n // mdi:battery-30\n // mdi:battery-40\n // mdi:battery-50\n // mdi:battery-60\n // mdi:battery-70\n // mdi:battery-80\n // mdi:battery-90\n // We obscure 'hass' in iconname so this name does not get picked up\n return `${\"hass\"}:battery-${batteryRound}`;\n }\n\n const unit = state.attributes.unit_of_measurement;\n if (unit === UNIT_C || unit === UNIT_F) {\n return \"mdi:thermometer\";\n }\n return domainIcon(\"sensor\");\n};\n","import { HassEntity } from \"home-assistant-js-websocket\";\nimport { computeDomain } from \"./compute-domain\";\nimport { DEFAULT_DOMAIN_ICON } from \"./const\";\nimport { binarySensorIcon } from \"./binary_sensor_icon\";\nimport { coverIcon } from \"./cover_icon\";\nimport { sensorIcon } from \"./sensor_icon\";\nimport { inputDateTimeIcon } from \"./input_datetime_icon\";\nimport { domainIcon } from \"./domain_icons\";\n\nconst domainIcons = {\n binary_sensor: binarySensorIcon,\n cover: coverIcon,\n sensor: sensorIcon,\n input_datetime: inputDateTimeIcon,\n};\n\nexport const stateIcon = (state: HassEntity) => {\n if (!state) {\n return DEFAULT_DOMAIN_ICON;\n }\n if (state.attributes.icon) {\n return state.attributes.icon;\n }\n\n const domain = computeDomain(state.entity_id);\n\n if (domain in domainIcons) {\n return domainIcons[domain](state);\n }\n return domainIcon(domain, state.state);\n};\n","import { HassEntity } from \"home-assistant-js-websocket\";\n\n/** Return an icon representing a binary sensor state. */\n\nexport const binarySensorIcon = (state?: string, stateObj?: HassEntity) => {\n const is_off = state === \"off\";\n switch (stateObj?.attributes.device_class) {\n case \"battery\":\n return is_off ? \"mdi:battery\" : \"mdi:battery-outline\";\n case \"battery_charging\":\n return is_off ? \"mdi:battery\" : \"mdi:battery-charging\";\n case \"cold\":\n return is_off ? \"mdi:thermometer\" : \"mdi:snowflake\";\n case \"connectivity\":\n return is_off ? \"mdi:server-network-off\" : \"mdi:server-network\";\n case \"door\":\n return is_off ? \"mdi:door-closed\" : \"mdi:door-open\";\n case \"garage_door\":\n return is_off ? \"mdi:garage\" : \"mdi:garage-open\";\n case \"power\":\n return is_off ? \"mdi:power-plug-off\" : \"mdi:power-plug\";\n case \"gas\":\n case \"problem\":\n case \"safety\":\n case \"tamper\":\n return is_off ? \"mdi:check-circle\" : \"mdi:alert-circle\";\n case \"smoke\":\n return is_off ? \"mdi:check-circle\" : \"mdi:smoke\";\n case \"heat\":\n return is_off ? \"mdi:thermometer\" : \"mdi:fire\";\n case \"light\":\n return is_off ? \"mdi:brightness-5\" : \"mdi:brightness-7\";\n case \"lock\":\n return is_off ? \"mdi:lock\" : \"mdi:lock-open\";\n case \"moisture\":\n return is_off ? \"mdi:water-off\" : \"mdi:water\";\n case \"motion\":\n return is_off ? \"mdi:walk\" : \"mdi:run\";\n case \"occupancy\":\n return is_off ? \"mdi:home-outline\" : \"mdi:home\";\n case \"opening\":\n return is_off ? \"mdi:square\" : \"mdi:square-outline\";\n case \"plug\":\n return is_off ? \"mdi:power-plug-off\" : \"mdi:power-plug\";\n case \"presence\":\n return is_off ? \"mdi:home-outline\" : \"mdi:home\";\n case \"running\":\n return is_off ? \"mdi:stop\" : \"mdi:play\";\n case \"sound\":\n return is_off ? \"mdi:music-note-off\" : \"mdi:music-note\";\n case \"update\":\n return is_off ? \"mdi:package\" : \"mdi:package-up\";\n case \"vibration\":\n return is_off ? \"mdi:crop-portrait\" : \"mdi:vibrate\";\n case \"window\":\n return is_off ? \"mdi:window-closed\" : \"mdi:window-open\";\n default:\n return is_off ? \"mdi:radiobox-blank\" : \"mdi:checkbox-marked-circle\";\n }\n};\n","/** Return an icon representing a cover state. */\nimport { HassEntity } from \"home-assistant-js-websocket\";\nimport { domainIcon } from \"./domain_icons\";\n\nexport const coverIcon = (state: HassEntity): string => {\n const open = state.state !== \"closed\";\n switch (state.attributes.device_class) {\n case \"garage\":\n return open ? \"mdi:garage-open\" : \"mdi:garage\";\n case \"door\":\n return open ? \"mdi:door-open\" : \"mdi:door-closed\";\n case \"shutter\":\n return open ? \"mdi:window-shutter-open\" : \"mdi:window-shutter\";\n case \"blind\":\n return open ? \"mdi:blinds-open\" : \"mdi:blinds\";\n case \"window\":\n return open ? \"mdi:window-open\" : \"mdi:window-closed\";\n default:\n return domainIcon(\"cover\", state.state);\n }\n};\n","/** Return an icon representing an input datetime state. */\nimport { domainIcon } from \"./domain_icons\";\nimport { HassEntity } from \"home-assistant-js-websocket\";\n\nexport const inputDateTimeIcon = (state: HassEntity): string => {\n if (!state.attributes.has_date) {\n return \"mdi:clock\";\n }\n if (!state.attributes.has_time) {\n return \"mdi:calendar\";\n }\n return domainIcon(\"input_datetime\");\n};\n","/**\n * Apply a theme to an element by setting the CSS variables on it.\n *\n * element: Element to apply theme on.\n * themes: HASS Theme information\n * localTheme: selected theme.\n * updateMeta: boolean if we should update the theme-color meta element.\n */\nexport const applyThemesOnElement = (\n element,\n themes,\n localTheme,\n updateMeta = false\n) => {\n if (!element._themes) {\n element._themes = {};\n }\n let themeName = themes.default_theme;\n if (localTheme === \"default\" || (localTheme && themes.themes[localTheme])) {\n themeName = localTheme;\n }\n const styles = { ...element._themes };\n if (themeName !== \"default\") {\n const theme = themes.themes[themeName];\n Object.keys(theme).forEach((key) => {\n const prefixedKey = \"--\" + key;\n element._themes[prefixedKey] = \"\";\n styles[prefixedKey] = theme[key];\n });\n }\n if (element.updateStyles) {\n element.updateStyles(styles);\n } else if ((window as any).ShadyCSS) {\n // implement updateStyles() method of Polemer elements\n (window as any).ShadyCSS.styleSubtree(/** @type {!HTMLElement} */ (element), styles);\n }\n\n if (!updateMeta) {\n return;\n }\n\n const meta = document.querySelector(\"meta[name=theme-color]\");\n if (meta) {\n if (!meta.hasAttribute(\"default-content\")) {\n meta.setAttribute(\"default-content\", meta.getAttribute(\"content\")!);\n }\n const themeColor =\n styles[\"--primary-color\"] || meta.getAttribute(\"default-content\");\n meta.setAttribute(\"content\", themeColor);\n }\n}\n","import { LovelaceCard } from \"./types\";\n\nexport const computeCardSize = (card: LovelaceCard): number | Promise => {\n return typeof card.getCardSize === \"function\" ? card.getCardSize() : 4;\n};","export function computeEntity(entityId: string): string {\n return entityId.substr(entityId.indexOf(\".\") + 1);\n}\n","import { HassEntity } from \"home-assistant-js-websocket\";\nimport { formatDateTime } from \"./datetime/format_date_time\";\nimport { formatDate } from \"./datetime/format_date\";\nimport { formatTime } from \"./datetime/format_time\";\nimport { LocalizeFunc } from \"./translations/localize\";\nimport { computeStateDomain } from \"./compute-state-domain\";\nimport { FrontendLocaleData } from \"./types\";\nimport { formatNumber, isNumericState } from \"./format-number\";\n\nexport const computeStateDisplay = (\n localize: LocalizeFunc,\n stateObj: HassEntity,\n locale: FrontendLocaleData,\n state?: string\n): string => {\n const compareState = state !== undefined ? state : stateObj.state;\n\n if (compareState === \"unknown\" || compareState === \"unavailable\") {\n return localize(`state.default.${compareState}`);\n }\n\n // Entities with a `unit_of_measurement` or `state_class` are numeric values and should use `formatNumber`\n if (isNumericState(stateObj)) {\n if (stateObj.attributes.device_class === \"monetary\") {\n try {\n return formatNumber(compareState, locale, {\n style: \"currency\",\n currency: stateObj.attributes.unit_of_measurement,\n });\n } catch (_err) {\n // fallback to default\n }\n }\n return `${formatNumber(compareState, locale)}${\n stateObj.attributes.unit_of_measurement\n ? \" \" + stateObj.attributes.unit_of_measurement\n : \"\"\n }`;\n }\n\n const domain = computeStateDomain(stateObj);\n\n if (domain === \"input_datetime\") {\n if (state !== undefined) {\n // If trying to display an explicit state, need to parse the explict state to `Date` then format.\n // Attributes aren't available, we have to use `state`.\n try {\n const components = state.split(\" \");\n if (components.length === 2) {\n // Date and time.\n return formatDateTime(new Date(components.join(\"T\")), locale);\n }\n if (components.length === 1) {\n if (state.includes(\"-\")) {\n // Date only.\n return formatDate(new Date(`${state}T00:00`), locale);\n }\n if (state.includes(\":\")) {\n // Time only.\n const now = new Date();\n return formatTime(\n new Date(`${now.toISOString().split(\"T\")[0]}T${state}`),\n locale\n );\n }\n }\n return state;\n } catch (_e) {\n // Formatting methods may throw error if date parsing doesn't go well,\n // just return the state string in that case.\n return state;\n }\n } else {\n // If not trying to display an explicit state, create `Date` object from `stateObj`'s attributes then format.\n let date: Date;\n if (stateObj.attributes.has_date && stateObj.attributes.has_time) {\n date = new Date(\n stateObj.attributes.year,\n stateObj.attributes.month - 1,\n stateObj.attributes.day,\n stateObj.attributes.hour,\n stateObj.attributes.minute\n );\n return formatDateTime(date, locale);\n }\n if (stateObj.attributes.has_date) {\n date = new Date(\n stateObj.attributes.year,\n stateObj.attributes.month - 1,\n stateObj.attributes.day\n );\n return formatDate(date, locale);\n }\n if (stateObj.attributes.has_time) {\n date = new Date();\n date.setHours(stateObj.attributes.hour, stateObj.attributes.minute);\n return formatTime(date, locale);\n }\n return stateObj.state;\n }\n }\n\n if (domain === \"humidifier\") {\n if (compareState === \"on\" && stateObj.attributes.humidity) {\n return `${stateObj.attributes.humidity} %`;\n }\n }\n\n // `counter` `number` and `input_number` domains do not have a unit of measurement but should still use `formatNumber`\n if (\n domain === \"counter\" ||\n domain === \"number\" ||\n domain === \"input_number\"\n ) {\n return formatNumber(compareState, locale);\n }\n\n return (\n // Return device class translation\n (stateObj.attributes.device_class &&\n localize(\n `component.${domain}.state.${stateObj.attributes.device_class}.${compareState}`\n )) ||\n // Return default translation\n localize(`component.${domain}.state._.${compareState}`) ||\n // We don't know! Return the raw state.\n compareState\n );\n};","/**\r\n * Returns a function, that, as long as it continues to be invoked, will not be triggered. It will be called after it stops being called for `wait` ms.\r\n * This can be usefull for ResizeObservers for example.\r\n * @param func The function you want to debounce\r\n * @param wait Period to wait in ms\r\n * @param immediate Triggering on the leading edge instead of the trailing\r\n * @returns Debounced Function\r\n */\r\n// eslint-disable-next-line: ban-types\r\nexport const debounce = unknown>(\r\n func: T,\r\n wait: number,\r\n immediate = false\r\n): T => {\r\n let timeout;\r\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\r\n // @ts-ignore\r\n return function (...args) {\r\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\r\n // @ts-ignore\r\n // eslint-disable-next-line @typescript-eslint/no-this-alias\r\n const context = this;\r\n const later = () => {\r\n timeout = null;\r\n if (!immediate) {\r\n func.apply(context, args);\r\n }\r\n };\r\n const callNow = immediate && !timeout;\r\n clearTimeout(timeout);\r\n timeout = setTimeout(later, wait);\r\n if (callNow) {\r\n func.apply(context, args);\r\n }\r\n };\r\n};\r\n","export const getLovelace = () => {\n let root: any = document.querySelector('home-assistant');\n root = root && root.shadowRoot;\n root = root && root.querySelector('home-assistant-main');\n root = root && root.shadowRoot;\n root = root && root.querySelector('app-drawer-layout partial-panel-resolver');\n root = root && root.shadowRoot || root;\n root = root && root.querySelector('ha-panel-lovelace');\n root = root && root.shadowRoot;\n root = root && root.querySelector('hui-root');\n if (root) {\n const ll = root.lovelace;\n ll.current_view = root.___curView;\n return ll;\n }\n return null;\n}\n","import { HomeAssistant, ActionConfig } from \"./types\";\nimport { fireEvent } from \"./fire-event\";\nimport { forwardHaptic } from \"./haptic\";\nimport { navigate } from \"./navigate\";\nimport { toggleEntity } from \"./toggle-entity\";\n\nexport const handleClick = (\n node: HTMLElement,\n hass: HomeAssistant,\n config: {\n entity?: string;\n camera_image?: string;\n hold_action?: ActionConfig;\n tap_action?: ActionConfig;\n double_tap_action?: ActionConfig;\n },\n hold: boolean,\n dblClick: boolean\n): void => {\n let actionConfig: ActionConfig | undefined;\n\n if (dblClick && config.double_tap_action) {\n actionConfig = config.double_tap_action;\n } else if (hold && config.hold_action) {\n actionConfig = config.hold_action;\n } else if (!hold && config.tap_action) {\n actionConfig = config.tap_action;\n }\n\n if (!actionConfig) {\n actionConfig = {\n action: \"more-info\"\n };\n }\n\n if (\n actionConfig.confirmation &&\n (!actionConfig.confirmation.exemptions ||\n !actionConfig.confirmation.exemptions.some(\n e => e.user === hass!.user!.id\n ))\n ) {\n if (\n !confirm(\n actionConfig.confirmation.text ||\n `Are you sure you want to ${actionConfig.action}?`\n )\n ) {\n return;\n }\n }\n\n switch (actionConfig.action) {\n case \"more-info\":\n if (actionConfig.entity || config.entity || config.camera_image) {\n fireEvent(node, \"hass-more-info\", {\n entityId: actionConfig.entity\n ? actionConfig.entity\n : config.entity\n ? config.entity\n : config.camera_image\n });\n if (actionConfig.haptic) forwardHaptic(actionConfig.haptic);\n }\n break;\n case \"navigate\":\n if (actionConfig.navigation_path) {\n navigate(node, actionConfig.navigation_path);\n if (actionConfig.haptic) forwardHaptic(actionConfig.haptic);\n }\n break;\n case \"url\":\n actionConfig.url_path && window.open(actionConfig.url_path);\n if (actionConfig.haptic) forwardHaptic(actionConfig.haptic);\n break;\n case \"toggle\":\n if (config.entity) {\n toggleEntity(hass, config.entity!);\n if (actionConfig.haptic) forwardHaptic(actionConfig.haptic);\n }\n break;\n case \"call-service\": {\n if (!actionConfig.service) {\n return;\n }\n const [domain, service] = actionConfig.service.split(\".\", 2);\n const serviceData = { ...actionConfig.data };\n if (serviceData.entity_id === \"entity\") {\n serviceData.entity_id = config.entity;\n }\n hass.callService(domain, service, serviceData, actionConfig.target);\n if (actionConfig.haptic) forwardHaptic(actionConfig.haptic);\n break;\n }\n case \"fire-dom-event\": {\n fireEvent(node, \"ll-custom\", actionConfig);\n if (actionConfig.haptic) forwardHaptic(actionConfig.haptic);\n break;\n }\n }\n};\n","import { ActionConfig } from \"./types\";\n\nexport function hasAction(config?: ActionConfig): boolean {\n return config !== undefined && config.action !== \"none\";\n}\n","import { PropertyValues } from \"lit\";\n\nimport { HomeAssistant } from \"./types\";\n\n// Check if config or Entity changed\nexport function hasConfigOrEntityChanged(\n element: any,\n changedProps: PropertyValues,\n forceUpdate: Boolean,\n): boolean {\n if (changedProps.has('config') || forceUpdate) {\n return true;\n }\n\n if (element.config!.entity) {\n const oldHass = changedProps.get('hass') as HomeAssistant | undefined;\n if (oldHass) {\n return (\n oldHass.states[element.config!.entity]\n !== element.hass!.states[element.config!.entity]\n );\n }\n return true;\n } else {\n return false;\n }\n}","import { ActionConfig } from \"./types\";\n\n// Check if config or Entity changed\nexport function hasDoubleClick(config?: ActionConfig): boolean {\n return config !== undefined && config.action !== \"none\";\n}","//REF: https://github.com/home-assistant/frontend/blob/dev/src/common/datetime/relative_time.ts\n\nimport { selectUnit } from \"@formatjs/intl-utils\";\nimport { FrontendLocaleData } from \"../types\";\n\n const formatRelTimeMem =\n (locale: FrontendLocaleData) =>\n new Intl.RelativeTimeFormat(locale.language, { numeric: \"auto\" });\n\n/**\n * Calculate a string representing a date object as relative time from now.\n *\n * Example output: 5 minutes ago, in 3 days.\n */\n export const relativeTime = (\n from: Date,\n locale: FrontendLocaleData,\n to?: Date,\n includeTense = true\n): string => {\n const diff = selectUnit(from, to);\n if (includeTense) {\n return formatRelTimeMem(locale).format(diff.value, diff.unit);\n }\n return Intl.NumberFormat(locale.language, {\n style: \"unit\",\n unit: diff.unit,\n unitDisplay: \"long\",\n }).format(Math.abs(diff.value));\n};\n","import { HassEntity } from \"home-assistant-js-websocket\";\nimport durationToSeconds from \"../datetime/duration_to_seconds\";\n\nexport function timerTimeRemaining(stateObj: HassEntity) {\n let timeRemaining = durationToSeconds(stateObj.attributes.remaining);\n\n if (stateObj.state === \"active\") {\n const now = new Date().getTime();\n const madeActive = new Date(stateObj.last_changed).getTime();\n timeRemaining = Math.max(timeRemaining - (now - madeActive) / 1000, 0);\n }\n\n return timeRemaining;\n}\n","/**\n * Convert a Duration hh:mm:ss format to seconds\n * @param duration hh:mm:ss formated duration\n * @returns duration in seconds\n */\n export default function durationToSeconds(duration: string): number {\n const parts = duration.split(\":\").map(Number);\n return parts[0] * 3600 + parts[1] * 60 + parts[2];\n}\n","import { HomeAssistant } from \"./types\";\nimport { STATES_OFF } from \"./const\";\nimport { computeDomain } from \"./compute-domain\";\n\nexport const turnOnOffEntities = (\n hass: HomeAssistant,\n entityIds: string[],\n turnOn = true\n): void => {\n const domainsToCall = {};\n entityIds.forEach((entityId) => {\n if (STATES_OFF.includes(hass.states[entityId].state) === turnOn) {\n const stateDomain = computeDomain(entityId);\n const serviceDomain = [\"cover\", \"lock\"].includes(stateDomain)\n ? stateDomain\n : \"homeassistant\";\n\n if (!(serviceDomain in domainsToCall)) {\n domainsToCall[serviceDomain] = [];\n }\n domainsToCall[serviceDomain].push(entityId);\n }\n });\n\n Object.keys(domainsToCall).forEach((domain) => {\n let service;\n switch (domain) {\n case \"lock\":\n service = turnOn ? \"unlock\" : \"lock\";\n break;\n case \"cover\":\n service = turnOn ? \"open_cover\" : \"close_cover\";\n break;\n default:\n service = turnOn ? \"turn_on\" : \"turn_off\";\n }\n\n const entities = domainsToCall[domain];\n hass.callService(domain, service, { entity_id: entities });\n });\n};\n"],"names":["NumberFormat","TimeFormat","formatDate","dateObj","locale","formatDateMem","format","Intl","DateTimeFormat","language","year","month","day","useAmPm","time_format","system","testLanguage","undefined","test","Date","toLocaleString","includes","am_pm","formatDateTime","formatDateTimeMem","hour","minute","hour12","formatTime","formatTimeMem","computeDomain","entityId","substr","indexOf","computeRTL","hass","lang","translationMetadata","translations","isRTL","computeStateDomain","stateObj","entity_id","isNumericState","attributes","unit_of_measurement","state_class","numberFormatToLocale","localeOptions","number_format","comma_decimal","decimal_comma","space_comma","round","value","precision","Math","formatNumber","num","options","Number","isNaN","input","none","getDefaultFormatOptions","err","console","error","maximumFractionDigits","toString","style","currency","defaultOptions","minimumFractionDigits","digits","split","length","STATES_OFF","DOMAINS_TOGGLE","Set","fireEvent","node","type","detail","event","Event","bubbles","cancelable","Boolean","composed","dispatchEvent","SPECIAL_TYPES","DOMAIN_TO_ELEMENT_TYPE","alert","automation","climate","cover","fan","group","input_boolean","input_number","input_select","input_text","light","lock","media_player","remote","scene","script","sensor","timer","switch","vacuum","water_heater","input_datetime","fixedIcons","calendar","camera","configurator","conversation","device_tracker","history_graph","homeassistant","homekit","image_processing","mailbox","notify","person","plant","proximity","simple_alarm","sun","updater","weblink","domainIcon","domain","state","warn","evaluateFilter","forwardHaptic","hapticType","window","navigate","_node","path","replace","history","replaceState","pushState","turnOnOffEntity","turnOn","service","stateDomain","serviceDomain","callService","toggleEntity","states","handleActionConfig","config","actionConfig","action","confirmation","exemptions","some","e","user","id","confirm","text","entity","camera_image","navigation_path","url_path","open","data","target","fixedDeviceClassIcons","humidity","illuminance","temperature","pressure","power","signal_strength","domainIcons","binary_sensor","is_off","device_class","dclass","battery","batteryRound","unit","has_date","has_time","element","themes","localTheme","updateMeta","_themes","themeName","default_theme","styles","theme","Object","keys","forEach","key","prefixedKey","updateStyles","ShadyCSS","styleSubtree","meta","document","querySelector","hasAttribute","setAttribute","getAttribute","themeColor","card","getCardSize","localize","compareState","_err","date","setHours","components","join","now","toISOString","_e","cardConfig","isRow","_createError","_createThing","tag","createElement","setConfig","message","startsWith","has","customElements","get","display","setTimeout","whenDefined","then","clearTimeout","func","wait","immediate","timeout","args","context","this","later","apply","callNow","filter","attribute","operator","match","formatDateMonthMem","formatDateMonthYearMem","formatDateNumericMem","formatDateShortMem","formatDateTimeNumericMem","second","formatDateTimeWithSecondsMem","weekday","formatDateWeekdayMem","formatDateYearMem","formatTimeWeekdayMem","formatTimeWithSecondsMem","root","shadowRoot","ll","lovelace","current_view","___curView","double_tap_action","hold_action","tap_action","hold","dblClick","haptic","serviceData","changedProps","forceUpdate","oldHass","from","to","includeTense","diff","selectUnit","RelativeTimeFormat","numeric","formatRelTimeMem","unitDisplay","abs","icon","parts","timeRemaining","remaining","map","getTime","madeActive","last_changed","max","entityIds","domainsToCall","push"],"mappings":"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"} \ No newline at end of file diff --git a/dist/index.m.js b/dist/index.m.js index e373792..b7eee10 100644 --- a/dist/index.m.js +++ b/dist/index.m.js @@ -1,2 +1,2 @@ -import{selectUnit as e}from"@formatjs/intl-utils";var t,r,n=function(e,t){return i(t).format(e)},i=function(e){return new Intl.DateTimeFormat(e.language,{weekday:"long",month:"long",day:"numeric"})},a=function(e,t){return o(t).format(e)},o=function(e){return new Intl.DateTimeFormat(e.language,{year:"numeric",month:"long",day:"numeric"})},u=function(e,t){return c(t).format(e)},c=function(e){return new Intl.DateTimeFormat(e.language,{year:"numeric",month:"numeric",day:"numeric"})},m=function(e,t){return s(t).format(e)},s=function(e){return new Intl.DateTimeFormat(e.language,{day:"numeric",month:"short"})},l=function(e,t){return d(t).format(e)},d=function(e){return new Intl.DateTimeFormat(e.language,{month:"long",year:"numeric"})},f=function(e,t){return g(t).format(e)},g=function(e){return new Intl.DateTimeFormat(e.language,{month:"long"})},p=function(e,t){return h(t).format(e)},h=function(e){return new Intl.DateTimeFormat(e.language,{year:"numeric"})};!function(e){e.language="language",e.system="system",e.comma_decimal="comma_decimal",e.decimal_comma="decimal_comma",e.space_comma="space_comma",e.none="none"}(t||(t={})),function(e){e.language="language",e.system="system",e.am_pm="12",e.twenty_four="24"}(r||(r={}));var b=function(e){if(e.time_format===r.language||e.time_format===r.system){var t=e.time_format===r.language?e.language:void 0,n=(new Date).toLocaleString(t);return n.includes("AM")||n.includes("PM")}return e.time_format===r.am_pm},v=function(e,t){return _(t).format(e)},_=function(e){return new Intl.DateTimeFormat(e.language,{year:"numeric",month:"long",day:"numeric",hour:b(e)?"numeric":"2-digit",minute:"2-digit",hour12:b(e)})},y=function(e,t){return w(t).format(e)},w=function(e){return new Intl.DateTimeFormat(e.language,{year:"numeric",month:"long",day:"numeric",hour:b(e)?"numeric":"2-digit",minute:"2-digit",second:"2-digit",hour12:b(e)})},k=function(e,t){return x(t).format(e)},x=function(e){return new Intl.DateTimeFormat(e.language,{year:"numeric",month:"numeric",day:"numeric",hour:"numeric",minute:"2-digit",hour12:b(e)})},D=function(e,t){return S(t).format(e)},S=function(e){return new Intl.DateTimeFormat(e.language,{hour:"numeric",minute:"2-digit",hour12:b(e)})},F=function(e,t){return T(t).format(e)},T=function(e){return new Intl.DateTimeFormat(e.language,{hour:b(e)?"numeric":"2-digit",minute:"2-digit",second:"2-digit",hour12:b(e)})},I=function(e,t){return N(t).format(e)},N=function(e){return new Intl.DateTimeFormat(e.language,{hour:b(e)?"numeric":"2-digit",minute:"2-digit",second:"2-digit",hour12:b(e)})},M=function(t,r,n,i){void 0===i&&(i=!0);var a=e(t,n);return i?function(e){return new Intl.RelativeTimeFormat(e.language,{numeric:"auto"})}(r).format(a.value,a.unit):Intl.NumberFormat(r.language,{style:"unit",unit:a.unit,unitDisplay:"long"}).format(Math.abs(a.value))};function C(e){var t,r=3600*(t=e.attributes.remaining.split(":").map(Number))[0]+60*t[1]+t[2];if("active"===e.state){var n=(new Date).getTime(),i=new Date(e.last_changed).getTime();r=Math.max(r-(n-i)/1e3,0)}return r}function O(){return(O=Object.assign||function(e){for(var t=1;t-1?e.split(".")[1].length:0;r.minimumFractionDigits=n,r.maximumFractionDigits=n}return r},W=function(e,t,r,n){var i=void 0!==n?n:t.state;if("unknown"===i||"unavailable"===i)return e("state.default."+i);if(P(t)){if("monetary"===t.attributes.device_class)try{return H(i,r,{style:"currency",currency:t.attributes.unit_of_measurement})}catch(e){}return H(i,r)+(t.attributes.unit_of_measurement?" "+t.attributes.unit_of_measurement:"")}var o=L(t);if("input_datetime"===o){var u;if(void 0===n)return t.attributes.has_date&&t.attributes.has_time?(u=new Date(t.attributes.year,t.attributes.month-1,t.attributes.day,t.attributes.hour,t.attributes.minute),v(u,r)):t.attributes.has_date?(u=new Date(t.attributes.year,t.attributes.month-1,t.attributes.day),a(u,r)):t.attributes.has_time?((u=new Date).setHours(t.attributes.hour,t.attributes.minute),D(u,r)):t.state;try{var c=n.split(" ");if(2===c.length)return v(new Date(c.join("T")),r);if(1===c.length){if(n.includes("-"))return a(new Date(n+"T00:00"),r);if(n.includes(":")){var m=new Date;return D(new Date(m.toISOString().split("T")[0]+"T"+n),r)}}return n}catch(e){return n}}return"humidifier"===o&&"on"===i&&t.attributes.humidity?t.attributes.humidity+" %":"counter"===o||"number"===o||"input_number"===o?H(i,r):t.attributes.device_class&&e("component."+o+".state."+t.attributes.device_class+"."+i)||e("component."+o+".state._."+i)||i},G="mdi:bookmark",J="lovelace",K=["climate","cover","configurator","input_select","input_number","input_text","lock","media_player","scene","script","timer","vacuum","water_heater","weblink"],Q=["alarm_control_panel","automation","camera","climate","configurator","cover","fan","group","history_graph","input_datetime","light","lock","media_player","script","sun","updater","vacuum","water_heater","weather"],X=["input_number","input_select","input_text","scene","weblink"],Y=["camera","configurator","history_graph","scene"],Z=["closed","locked","off"],$=new Set(["fan","input_boolean","light","switch","group","automation"]),ee="°C",te="°F",re="group.default_view",ne=function(e,t,r,n){n=n||{},r=null==r?{}:r;var i=new Event(t,{bubbles:void 0===n.bubbles||n.bubbles,cancelable:Boolean(n.cancelable),composed:void 0===n.composed||n.composed});return i.detail=r,e.dispatchEvent(i),i},ie=new Set(["call-service","divider","section","weblink","cast","select"]),ae={alert:"toggle",automation:"toggle",climate:"climate",cover:"cover",fan:"toggle",group:"group",input_boolean:"toggle",input_number:"input-number",input_select:"input-select",input_text:"input-text",light:"toggle",lock:"lock",media_player:"media-player",remote:"toggle",scene:"scene",script:"script",sensor:"sensor",timer:"timer",switch:"toggle",vacuum:"toggle",water_heater:"climate",input_datetime:"input-datetime"},oe=function(e,t){void 0===t&&(t=!1);var r=function(e,t){return n("hui-error-card",{type:"error",error:e,config:t})},n=function(e,t){var n=window.document.createElement(e);try{if(!n.setConfig)return;n.setConfig(t)}catch(n){return console.error(e,n),r(n.message,t)}return n};if(!e||"object"!=typeof e||!t&&!e.type)return r("No type defined",e);var i=e.type;if(i&&i.startsWith("custom:"))i=i.substr("custom:".length);else if(t)if(ie.has(i))i="hui-"+i+"-row";else{if(!e.entity)return r("Invalid config given.",e);var a=e.entity.split(".",1)[0];i="hui-"+(ae[a]||"text")+"-entity-row"}else i="hui-"+i+"-card";if(customElements.get(i))return n(i,e);var o=r("Custom element doesn't exist: "+e.type+".",e);o.style.display="None";var u=setTimeout(function(){o.style.display=""},2e3);return customElements.whenDefined(e.type).then(function(){clearTimeout(u),ne(o,"ll-rebuild",{},o)}),o},ue=function(e,t,r){var n;return void 0===r&&(r=!1),function(){var i=[].slice.call(arguments),a=this,o=function(){n=null,r||e.apply(a,i)},u=r&&!n;clearTimeout(n),n=setTimeout(o,t),u&&e.apply(a,i)}},ce={alert:"mdi:alert",automation:"mdi:playlist-play",calendar:"mdi:calendar",camera:"mdi:video",climate:"mdi:thermostat",configurator:"mdi:settings",conversation:"mdi:text-to-speech",device_tracker:"mdi:account",fan:"mdi:fan",group:"mdi:google-circles-communities",history_graph:"mdi:chart-line",homeassistant:"mdi:home-assistant",homekit:"mdi:home-automation",image_processing:"mdi:image-filter-frames",input_boolean:"mdi:drawing",input_datetime:"mdi:calendar-clock",input_number:"mdi:ray-vertex",input_select:"mdi:format-list-bulleted",input_text:"mdi:textbox",light:"mdi:lightbulb",mailbox:"mdi:mailbox",notify:"mdi:comment-alert",person:"mdi:account",plant:"mdi:flower",proximity:"mdi:apple-safari",remote:"mdi:remote",scene:"mdi:google-pages",script:"mdi:file-document",sensor:"mdi:eye",simple_alarm:"mdi:bell",sun:"mdi:white-balance-sunny",switch:"mdi:flash",timer:"mdi:timer",updater:"mdi:cloud-upload",vacuum:"mdi:robot-vacuum",water_heater:"mdi:thermometer",weblink:"mdi:open-in-new"};function me(e,t){if(e in ce)return ce[e];switch(e){case"alarm_control_panel":switch(t){case"armed_home":return"mdi:bell-plus";case"armed_night":return"mdi:bell-sleep";case"disarmed":return"mdi:bell-outline";case"triggered":return"mdi:bell-ring";default:return"mdi:bell"}case"binary_sensor":return t&&"off"===t?"mdi:radiobox-blank":"mdi:checkbox-marked-circle";case"cover":return"closed"===t?"mdi:window-closed":"mdi:window-open";case"lock":return t&&"unlocked"===t?"mdi:lock-open":"mdi:lock";case"media_player":return t&&"off"!==t&&"idle"!==t?"mdi:cast-connected":"mdi:cast";case"zwave":switch(t){case"dead":return"mdi:emoticon-dead";case"sleeping":return"mdi:sleep";case"initializing":return"mdi:timer-sand";default:return"mdi:z-wave"}default:return console.warn("Unable to find icon for domain "+e+" ("+t+")"),"mdi:bookmark"}}var se=function(e,t){var r=t.value||t,n=t.attribute?e.attributes[t.attribute]:e.state;switch(t.operator||"=="){case"==":return n===r;case"<=":return n<=r;case"<":return n=":return n>=r;case">":return n>r;case"!=":return n!==r;case"regex":return n.match(r);default:return!1}},le=function(e){ne(window,"haptic",e)},de=function(e,t,r){void 0===r&&(r=!1),r?history.replaceState(null,"",t):history.pushState(null,"",t),ne(window,"location-changed",{replace:r})},fe=function(e,t,r){void 0===r&&(r=!0);var n,i=E(t),a="group"===i?"homeassistant":i;switch(i){case"lock":n=r?"unlock":"lock";break;case"cover":n=r?"open_cover":"close_cover";break;default:n=r?"turn_on":"turn_off"}return e.callService(a,n,{entity_id:t})},ge=function(e,t){var r=Z.includes(e.states[t].state);return fe(e,t,r)},pe=function(e,t,r,n){if(n||(n={action:"more-info"}),!n.confirmation||n.confirmation.exemptions&&n.confirmation.exemptions.some(function(e){return e.user===t.user.id})||(le("warning"),confirm(n.confirmation.text||"Are you sure you want to "+n.action+"?")))switch(n.action){case"more-info":(r.entity||r.camera_image)&&ne(e,"hass-more-info",{entityId:r.entity?r.entity:r.camera_image});break;case"navigate":n.navigation_path&&de(0,n.navigation_path);break;case"url":n.url_path&&window.open(n.url_path);break;case"toggle":r.entity&&(ge(t,r.entity),le("success"));break;case"call-service":if(!n.service)return void le("failure");var i=n.service.split(".",2);t.callService(i[0],i[1],n.service_data,n.target),le("success");break;case"fire-dom-event":ne(e,"ll-custom",n)}},he=function(e,t,r,n){var i;"double_tap"===n&&r.double_tap_action?i=r.double_tap_action:"hold"===n&&r.hold_action?i=r.hold_action:"tap"===n&&r.tap_action&&(i=r.tap_action),pe(e,t,r,i)},be=function(e,t,r,n,i){var a;if(i&&r.double_tap_action?a=r.double_tap_action:n&&r.hold_action?a=r.hold_action:!n&&r.tap_action&&(a=r.tap_action),a||(a={action:"more-info"}),!a.confirmation||a.confirmation.exemptions&&a.confirmation.exemptions.some(function(e){return e.user===t.user.id})||confirm(a.confirmation.text||"Are you sure you want to "+a.action+"?"))switch(a.action){case"more-info":(a.entity||r.entity||r.camera_image)&&(ne(e,"hass-more-info",{entityId:a.entity?a.entity:r.entity?r.entity:r.camera_image}),a.haptic&&le(a.haptic));break;case"navigate":a.navigation_path&&(de(0,a.navigation_path),a.haptic&&le(a.haptic));break;case"url":a.url_path&&window.open(a.url_path),a.haptic&&le(a.haptic);break;case"toggle":r.entity&&(ge(t,r.entity),a.haptic&&le(a.haptic));break;case"call-service":if(!a.service)return;var o=a.service.split(".",2),u=o[0],c=o[1],m=O({},a.service_data);"entity"===m.entity_id&&(m.entity_id=r.entity),t.callService(u,c,m,a.target),a.haptic&&le(a.haptic);break;case"fire-dom-event":ne(e,"ll-custom",a),a.haptic&&le(a.haptic)}};function ve(e){return void 0!==e&&"none"!==e.action}function _e(e,t,r){if(t.has("config")||r)return!0;if(e.config.entity){var n=t.get("hass");return!n||n.states[e.config.entity]!==e.hass.states[e.config.entity]}return!1}function ye(e){return void 0!==e&&"none"!==e.action}var we=function(e,t,r){void 0===r&&(r=!0);var n={};t.forEach(function(t){if(Z.includes(e.states[t].state)===r){var i=E(t),a=["cover","lock"].includes(i)?i:"homeassistant";a in n||(n[a]=[]),n[a].push(t)}}),Object.keys(n).forEach(function(t){var i;switch(t){case"lock":i=r?"unlock":"lock";break;case"cover":i=r?"open_cover":"close_cover";break;default:i=r?"turn_on":"turn_off"}e.callService(t,i,{entity_id:n[t]})})},ke=function(){var e=document.querySelector("home-assistant");if(e=(e=(e=(e=(e=(e=(e=(e=e&&e.shadowRoot)&&e.querySelector("home-assistant-main"))&&e.shadowRoot)&&e.querySelector("app-drawer-layout partial-panel-resolver"))&&e.shadowRoot||e)&&e.querySelector("ha-panel-lovelace"))&&e.shadowRoot)&&e.querySelector("hui-root")){var t=e.lovelace;return t.current_view=e.___curView,t}return null},xe={humidity:"mdi:water-percent",illuminance:"mdi:brightness-5",temperature:"mdi:thermometer",pressure:"mdi:gauge",power:"mdi:flash",signal_strength:"mdi:wifi"},De={binary_sensor:function(e,t){var r="off"===e;switch(null==t?void 0:t.attributes.device_class){case"battery":return r?"mdi:battery":"mdi:battery-outline";case"battery_charging":return r?"mdi:battery":"mdi:battery-charging";case"cold":return r?"mdi:thermometer":"mdi:snowflake";case"connectivity":return r?"mdi:server-network-off":"mdi:server-network";case"door":return r?"mdi:door-closed":"mdi:door-open";case"garage_door":return r?"mdi:garage":"mdi:garage-open";case"power":return r?"mdi:power-plug-off":"mdi:power-plug";case"gas":case"problem":case"safety":case"tamper":return r?"mdi:check-circle":"mdi:alert-circle";case"smoke":return r?"mdi:check-circle":"mdi:smoke";case"heat":return r?"mdi:thermometer":"mdi:fire";case"light":return r?"mdi:brightness-5":"mdi:brightness-7";case"lock":return r?"mdi:lock":"mdi:lock-open";case"moisture":return r?"mdi:water-off":"mdi:water";case"motion":return r?"mdi:walk":"mdi:run";case"occupancy":return r?"mdi:home-outline":"mdi:home";case"opening":return r?"mdi:square":"mdi:square-outline";case"plug":return r?"mdi:power-plug-off":"mdi:power-plug";case"presence":return r?"mdi:home-outline":"mdi:home";case"running":return r?"mdi:stop":"mdi:play";case"sound":return r?"mdi:music-note-off":"mdi:music-note";case"update":return r?"mdi:package":"mdi:package-up";case"vibration":return r?"mdi:crop-portrait":"mdi:vibrate";case"window":return r?"mdi:window-closed":"mdi:window-open";default:return r?"mdi:radiobox-blank":"mdi:checkbox-marked-circle"}},cover:function(e){var t="closed"!==e.state;switch(e.attributes.device_class){case"garage":return t?"mdi:garage-open":"mdi:garage";case"door":return t?"mdi:door-open":"mdi:door-closed";case"shutter":return t?"mdi:window-shutter-open":"mdi:window-shutter";case"blind":return t?"mdi:blinds-open":"mdi:blinds";case"window":return t?"mdi:window-open":"mdi:window-closed";default:return me("cover",e.state)}},sensor:function(e){var t=e.attributes.device_class;if(t&&t in xe)return xe[t];if("battery"===t){var r=Number(e.state);if(isNaN(r))return"mdi:battery-unknown";var n=10*Math.round(r/10);return n>=100?"mdi:battery":n<=0?"mdi:battery-alert":"hass:battery-"+n}var i=e.attributes.unit_of_measurement;return"°C"===i||"°F"===i?"mdi:thermometer":me("sensor")},input_datetime:function(e){return e.attributes.has_date?e.attributes.has_time?me("input_datetime"):"mdi:calendar":"mdi:clock"}},Se=function(e){if(!e)return"mdi:bookmark";if(e.attributes.icon)return e.attributes.icon;var t=E(e.entity_id);return t in De?De[t](e):me(t,e.state)};export{G as DEFAULT_DOMAIN_ICON,J as DEFAULT_PANEL,re as DEFAULT_VIEW_ENTITY_ID,X as DOMAINS_HIDE_MORE_INFO,Y as DOMAINS_MORE_INFO_NO_HISTORY,$ as DOMAINS_TOGGLE,K as DOMAINS_WITH_CARD,Q as DOMAINS_WITH_MORE_INFO,t as NumberFormat,Z as STATES_OFF,r as TimeFormat,ee as UNIT_C,te as UNIT_F,q as applyThemesOnElement,A as computeCardSize,E as computeDomain,j as computeEntity,R as computeRTL,z as computeRTLDirection,W as computeStateDisplay,L as computeStateDomain,oe as createThing,ue as debounce,me as domainIcon,se as evaluateFilter,ne as fireEvent,ce as fixedIcons,a as formatDate,f as formatDateMonth,l as formatDateMonthYear,u as formatDateNumeric,m as formatDateShort,v as formatDateTime,k as formatDateTimeNumeric,y as formatDateTimeWithSeconds,n as formatDateWeekday,p as formatDateYear,H as formatNumber,D as formatTime,I as formatTimeWeekday,F as formatTimeWithSeconds,le as forwardHaptic,ke as getLovelace,he as handleAction,pe as handleActionConfig,be as handleClick,ve as hasAction,_e as hasConfigOrEntityChanged,ye as hasDoubleClick,P as isNumericState,de as navigate,U as numberFormatToLocale,M as relativeTime,B as round,Se as stateIcon,C as timerTimeRemaining,ge as toggleEntity,we as turnOnOffEntities,fe as turnOnOffEntity}; +import{selectUnit as e}from"@formatjs/intl-utils";var t,r,n=function(e,t){return i(t).format(e)},i=function(e){return new Intl.DateTimeFormat(e.language,{weekday:"long",month:"long",day:"numeric"})},a=function(e,t){return o(t).format(e)},o=function(e){return new Intl.DateTimeFormat(e.language,{year:"numeric",month:"long",day:"numeric"})},u=function(e,t){return c(t).format(e)},c=function(e){return new Intl.DateTimeFormat(e.language,{year:"numeric",month:"numeric",day:"numeric"})},m=function(e,t){return s(t).format(e)},s=function(e){return new Intl.DateTimeFormat(e.language,{day:"numeric",month:"short"})},l=function(e,t){return d(t).format(e)},d=function(e){return new Intl.DateTimeFormat(e.language,{month:"long",year:"numeric"})},f=function(e,t){return g(t).format(e)},g=function(e){return new Intl.DateTimeFormat(e.language,{month:"long"})},p=function(e,t){return h(t).format(e)},h=function(e){return new Intl.DateTimeFormat(e.language,{year:"numeric"})};!function(e){e.language="language",e.system="system",e.comma_decimal="comma_decimal",e.decimal_comma="decimal_comma",e.space_comma="space_comma",e.none="none"}(t||(t={})),function(e){e.language="language",e.system="system",e.am_pm="12",e.twenty_four="24"}(r||(r={}));var b=function(e){if(e.time_format===r.language||e.time_format===r.system){var t=e.time_format===r.language?e.language:void 0,n=(new Date).toLocaleString(t);return n.includes("AM")||n.includes("PM")}return e.time_format===r.am_pm},v=function(e,t){return y(t).format(e)},y=function(e){return new Intl.DateTimeFormat(e.language,{year:"numeric",month:"long",day:"numeric",hour:b(e)?"numeric":"2-digit",minute:"2-digit",hour12:b(e)})},_=function(e,t){return w(t).format(e)},w=function(e){return new Intl.DateTimeFormat(e.language,{year:"numeric",month:"long",day:"numeric",hour:b(e)?"numeric":"2-digit",minute:"2-digit",second:"2-digit",hour12:b(e)})},k=function(e,t){return x(t).format(e)},x=function(e){return new Intl.DateTimeFormat(e.language,{year:"numeric",month:"numeric",day:"numeric",hour:"numeric",minute:"2-digit",hour12:b(e)})},D=function(e,t){return S(t).format(e)},S=function(e){return new Intl.DateTimeFormat(e.language,{hour:"numeric",minute:"2-digit",hour12:b(e)})},F=function(e,t){return T(t).format(e)},T=function(e){return new Intl.DateTimeFormat(e.language,{hour:b(e)?"numeric":"2-digit",minute:"2-digit",second:"2-digit",hour12:b(e)})},I=function(e,t){return N(t).format(e)},N=function(e){return new Intl.DateTimeFormat(e.language,{hour:b(e)?"numeric":"2-digit",minute:"2-digit",second:"2-digit",hour12:b(e)})},M=function(t,r,n,i){void 0===i&&(i=!0);var a=e(t,n);return i?function(e){return new Intl.RelativeTimeFormat(e.language,{numeric:"auto"})}(r).format(a.value,a.unit):Intl.NumberFormat(r.language,{style:"unit",unit:a.unit,unitDisplay:"long"}).format(Math.abs(a.value))};function C(e){var t,r=3600*(t=e.attributes.remaining.split(":").map(Number))[0]+60*t[1]+t[2];if("active"===e.state){var n=(new Date).getTime(),i=new Date(e.last_changed).getTime();r=Math.max(r-(n-i)/1e3,0)}return r}function O(){return(O=Object.assign||function(e){for(var t=1;t-1?e.split(".")[1].length:0;r.minimumFractionDigits=n,r.maximumFractionDigits=n}return r},W=function(e,t,r,n){var i=void 0!==n?n:t.state;if("unknown"===i||"unavailable"===i)return e("state.default."+i);if(P(t)){if("monetary"===t.attributes.device_class)try{return H(i,r,{style:"currency",currency:t.attributes.unit_of_measurement})}catch(e){}return H(i,r)+(t.attributes.unit_of_measurement?" "+t.attributes.unit_of_measurement:"")}var o=L(t);if("input_datetime"===o){var u;if(void 0===n)return t.attributes.has_date&&t.attributes.has_time?(u=new Date(t.attributes.year,t.attributes.month-1,t.attributes.day,t.attributes.hour,t.attributes.minute),v(u,r)):t.attributes.has_date?(u=new Date(t.attributes.year,t.attributes.month-1,t.attributes.day),a(u,r)):t.attributes.has_time?((u=new Date).setHours(t.attributes.hour,t.attributes.minute),D(u,r)):t.state;try{var c=n.split(" ");if(2===c.length)return v(new Date(c.join("T")),r);if(1===c.length){if(n.includes("-"))return a(new Date(n+"T00:00"),r);if(n.includes(":")){var m=new Date;return D(new Date(m.toISOString().split("T")[0]+"T"+n),r)}}return n}catch(e){return n}}return"humidifier"===o&&"on"===i&&t.attributes.humidity?t.attributes.humidity+" %":"counter"===o||"number"===o||"input_number"===o?H(i,r):t.attributes.device_class&&e("component."+o+".state."+t.attributes.device_class+"."+i)||e("component."+o+".state._."+i)||i},G="mdi:bookmark",J="lovelace",K=["climate","cover","configurator","input_select","input_number","input_text","lock","media_player","scene","script","timer","vacuum","water_heater","weblink"],Q=["alarm_control_panel","automation","camera","climate","configurator","cover","fan","group","history_graph","input_datetime","light","lock","media_player","script","sun","updater","vacuum","water_heater","weather"],X=["input_number","input_select","input_text","scene","weblink"],Y=["camera","configurator","history_graph","scene"],Z=["closed","locked","off"],$=new Set(["fan","input_boolean","light","switch","group","automation"]),ee="°C",te="°F",re="group.default_view",ne=function(e,t,r,n){n=n||{},r=null==r?{}:r;var i=new Event(t,{bubbles:void 0===n.bubbles||n.bubbles,cancelable:Boolean(n.cancelable),composed:void 0===n.composed||n.composed});return i.detail=r,e.dispatchEvent(i),i},ie=new Set(["call-service","divider","section","weblink","cast","select"]),ae={alert:"toggle",automation:"toggle",climate:"climate",cover:"cover",fan:"toggle",group:"group",input_boolean:"toggle",input_number:"input-number",input_select:"input-select",input_text:"input-text",light:"toggle",lock:"lock",media_player:"media-player",remote:"toggle",scene:"scene",script:"script",sensor:"sensor",timer:"timer",switch:"toggle",vacuum:"toggle",water_heater:"climate",input_datetime:"input-datetime"},oe=function(e,t){void 0===t&&(t=!1);var r=function(e,t){return n("hui-error-card",{type:"error",error:e,config:t})},n=function(e,t){var n=window.document.createElement(e);try{if(!n.setConfig)return;n.setConfig(t)}catch(n){return console.error(e,n),r(n.message,t)}return n};if(!e||"object"!=typeof e||!t&&!e.type)return r("No type defined",e);var i=e.type;if(i&&i.startsWith("custom:"))i=i.substr("custom:".length);else if(t)if(ie.has(i))i="hui-"+i+"-row";else{if(!e.entity)return r("Invalid config given.",e);var a=e.entity.split(".",1)[0];i="hui-"+(ae[a]||"text")+"-entity-row"}else i="hui-"+i+"-card";if(customElements.get(i))return n(i,e);var o=r("Custom element doesn't exist: "+e.type+".",e);o.style.display="None";var u=setTimeout(function(){o.style.display=""},2e3);return customElements.whenDefined(e.type).then(function(){clearTimeout(u),ne(o,"ll-rebuild",{},o)}),o},ue=function(e,t,r){var n;return void 0===r&&(r=!1),function(){var i=[].slice.call(arguments),a=this,o=function(){n=null,r||e.apply(a,i)},u=r&&!n;clearTimeout(n),n=setTimeout(o,t),u&&e.apply(a,i)}},ce={alert:"mdi:alert",automation:"mdi:playlist-play",calendar:"mdi:calendar",camera:"mdi:video",climate:"mdi:thermostat",configurator:"mdi:settings",conversation:"mdi:text-to-speech",device_tracker:"mdi:account",fan:"mdi:fan",group:"mdi:google-circles-communities",history_graph:"mdi:chart-line",homeassistant:"mdi:home-assistant",homekit:"mdi:home-automation",image_processing:"mdi:image-filter-frames",input_boolean:"mdi:drawing",input_datetime:"mdi:calendar-clock",input_number:"mdi:ray-vertex",input_select:"mdi:format-list-bulleted",input_text:"mdi:textbox",light:"mdi:lightbulb",mailbox:"mdi:mailbox",notify:"mdi:comment-alert",person:"mdi:account",plant:"mdi:flower",proximity:"mdi:apple-safari",remote:"mdi:remote",scene:"mdi:google-pages",script:"mdi:file-document",sensor:"mdi:eye",simple_alarm:"mdi:bell",sun:"mdi:white-balance-sunny",switch:"mdi:flash",timer:"mdi:timer",updater:"mdi:cloud-upload",vacuum:"mdi:robot-vacuum",water_heater:"mdi:thermometer",weblink:"mdi:open-in-new"};function me(e,t){if(e in ce)return ce[e];switch(e){case"alarm_control_panel":switch(t){case"armed_home":return"mdi:bell-plus";case"armed_night":return"mdi:bell-sleep";case"disarmed":return"mdi:bell-outline";case"triggered":return"mdi:bell-ring";default:return"mdi:bell"}case"binary_sensor":return t&&"off"===t?"mdi:radiobox-blank":"mdi:checkbox-marked-circle";case"cover":return"closed"===t?"mdi:window-closed":"mdi:window-open";case"lock":return t&&"unlocked"===t?"mdi:lock-open":"mdi:lock";case"media_player":return t&&"off"!==t&&"idle"!==t?"mdi:cast-connected":"mdi:cast";case"zwave":switch(t){case"dead":return"mdi:emoticon-dead";case"sleeping":return"mdi:sleep";case"initializing":return"mdi:timer-sand";default:return"mdi:z-wave"}default:return console.warn("Unable to find icon for domain "+e+" ("+t+")"),"mdi:bookmark"}}var se=function(e,t){var r=t.value||t,n=t.attribute?e.attributes[t.attribute]:e.state;switch(t.operator||"=="){case"==":return n===r;case"<=":return n<=r;case"<":return n=":return n>=r;case">":return n>r;case"!=":return n!==r;case"regex":return n.match(r);default:return!1}},le=function(e){ne(window,"haptic",e)},de=function(e,t,r){void 0===r&&(r=!1),r?history.replaceState(null,"",t):history.pushState(null,"",t),ne(window,"location-changed",{replace:r})},fe=function(e,t,r){void 0===r&&(r=!0);var n,i=E(t),a="group"===i?"homeassistant":i;switch(i){case"lock":n=r?"unlock":"lock";break;case"cover":n=r?"open_cover":"close_cover";break;default:n=r?"turn_on":"turn_off"}return e.callService(a,n,{entity_id:t})},ge=function(e,t){var r=Z.includes(e.states[t].state);return fe(e,t,r)},pe=function(e,t,r,n){if(n||(n={action:"more-info"}),!n.confirmation||n.confirmation.exemptions&&n.confirmation.exemptions.some(function(e){return e.user===t.user.id})||(le("warning"),confirm(n.confirmation.text||"Are you sure you want to "+n.action+"?")))switch(n.action){case"more-info":(r.entity||r.camera_image)&&ne(e,"hass-more-info",{entityId:r.entity?r.entity:r.camera_image});break;case"navigate":n.navigation_path&&de(0,n.navigation_path);break;case"url":n.url_path&&window.open(n.url_path);break;case"toggle":r.entity&&(ge(t,r.entity),le("success"));break;case"call-service":if(!n.service)return void le("failure");var i=n.service.split(".",2);t.callService(i[0],i[1],n.data,n.target),le("success");break;case"fire-dom-event":ne(e,"ll-custom",n)}},he=function(e,t,r,n){var i;"double_tap"===n&&r.double_tap_action?i=r.double_tap_action:"hold"===n&&r.hold_action?i=r.hold_action:"tap"===n&&r.tap_action&&(i=r.tap_action),pe(e,t,r,i)},be=function(e,t,r,n,i){var a;if(i&&r.double_tap_action?a=r.double_tap_action:n&&r.hold_action?a=r.hold_action:!n&&r.tap_action&&(a=r.tap_action),a||(a={action:"more-info"}),!a.confirmation||a.confirmation.exemptions&&a.confirmation.exemptions.some(function(e){return e.user===t.user.id})||confirm(a.confirmation.text||"Are you sure you want to "+a.action+"?"))switch(a.action){case"more-info":(a.entity||r.entity||r.camera_image)&&(ne(e,"hass-more-info",{entityId:a.entity?a.entity:r.entity?r.entity:r.camera_image}),a.haptic&&le(a.haptic));break;case"navigate":a.navigation_path&&(de(0,a.navigation_path),a.haptic&&le(a.haptic));break;case"url":a.url_path&&window.open(a.url_path),a.haptic&&le(a.haptic);break;case"toggle":r.entity&&(ge(t,r.entity),a.haptic&&le(a.haptic));break;case"call-service":if(!a.service)return;var o=a.service.split(".",2),u=o[0],c=o[1],m=O({},a.data);"entity"===m.entity_id&&(m.entity_id=r.entity),t.callService(u,c,m,a.target),a.haptic&&le(a.haptic);break;case"fire-dom-event":ne(e,"ll-custom",a),a.haptic&&le(a.haptic)}};function ve(e){return void 0!==e&&"none"!==e.action}function ye(e,t,r){if(t.has("config")||r)return!0;if(e.config.entity){var n=t.get("hass");return!n||n.states[e.config.entity]!==e.hass.states[e.config.entity]}return!1}function _e(e){return void 0!==e&&"none"!==e.action}var we=function(e,t,r){void 0===r&&(r=!0);var n={};t.forEach(function(t){if(Z.includes(e.states[t].state)===r){var i=E(t),a=["cover","lock"].includes(i)?i:"homeassistant";a in n||(n[a]=[]),n[a].push(t)}}),Object.keys(n).forEach(function(t){var i;switch(t){case"lock":i=r?"unlock":"lock";break;case"cover":i=r?"open_cover":"close_cover";break;default:i=r?"turn_on":"turn_off"}e.callService(t,i,{entity_id:n[t]})})},ke=function(){var e=document.querySelector("home-assistant");if(e=(e=(e=(e=(e=(e=(e=(e=e&&e.shadowRoot)&&e.querySelector("home-assistant-main"))&&e.shadowRoot)&&e.querySelector("app-drawer-layout partial-panel-resolver"))&&e.shadowRoot||e)&&e.querySelector("ha-panel-lovelace"))&&e.shadowRoot)&&e.querySelector("hui-root")){var t=e.lovelace;return t.current_view=e.___curView,t}return null},xe={humidity:"mdi:water-percent",illuminance:"mdi:brightness-5",temperature:"mdi:thermometer",pressure:"mdi:gauge",power:"mdi:flash",signal_strength:"mdi:wifi"},De={binary_sensor:function(e,t){var r="off"===e;switch(null==t?void 0:t.attributes.device_class){case"battery":return r?"mdi:battery":"mdi:battery-outline";case"battery_charging":return r?"mdi:battery":"mdi:battery-charging";case"cold":return r?"mdi:thermometer":"mdi:snowflake";case"connectivity":return r?"mdi:server-network-off":"mdi:server-network";case"door":return r?"mdi:door-closed":"mdi:door-open";case"garage_door":return r?"mdi:garage":"mdi:garage-open";case"power":return r?"mdi:power-plug-off":"mdi:power-plug";case"gas":case"problem":case"safety":case"tamper":return r?"mdi:check-circle":"mdi:alert-circle";case"smoke":return r?"mdi:check-circle":"mdi:smoke";case"heat":return r?"mdi:thermometer":"mdi:fire";case"light":return r?"mdi:brightness-5":"mdi:brightness-7";case"lock":return r?"mdi:lock":"mdi:lock-open";case"moisture":return r?"mdi:water-off":"mdi:water";case"motion":return r?"mdi:walk":"mdi:run";case"occupancy":return r?"mdi:home-outline":"mdi:home";case"opening":return r?"mdi:square":"mdi:square-outline";case"plug":return r?"mdi:power-plug-off":"mdi:power-plug";case"presence":return r?"mdi:home-outline":"mdi:home";case"running":return r?"mdi:stop":"mdi:play";case"sound":return r?"mdi:music-note-off":"mdi:music-note";case"update":return r?"mdi:package":"mdi:package-up";case"vibration":return r?"mdi:crop-portrait":"mdi:vibrate";case"window":return r?"mdi:window-closed":"mdi:window-open";default:return r?"mdi:radiobox-blank":"mdi:checkbox-marked-circle"}},cover:function(e){var t="closed"!==e.state;switch(e.attributes.device_class){case"garage":return t?"mdi:garage-open":"mdi:garage";case"door":return t?"mdi:door-open":"mdi:door-closed";case"shutter":return t?"mdi:window-shutter-open":"mdi:window-shutter";case"blind":return t?"mdi:blinds-open":"mdi:blinds";case"window":return t?"mdi:window-open":"mdi:window-closed";default:return me("cover",e.state)}},sensor:function(e){var t=e.attributes.device_class;if(t&&t in xe)return xe[t];if("battery"===t){var r=Number(e.state);if(isNaN(r))return"mdi:battery-unknown";var n=10*Math.round(r/10);return n>=100?"mdi:battery":n<=0?"mdi:battery-alert":"hass:battery-"+n}var i=e.attributes.unit_of_measurement;return"°C"===i||"°F"===i?"mdi:thermometer":me("sensor")},input_datetime:function(e){return e.attributes.has_date?e.attributes.has_time?me("input_datetime"):"mdi:calendar":"mdi:clock"}},Se=function(e){if(!e)return"mdi:bookmark";if(e.attributes.icon)return e.attributes.icon;var t=E(e.entity_id);return t in De?De[t](e):me(t,e.state)};export{G as DEFAULT_DOMAIN_ICON,J as DEFAULT_PANEL,re as DEFAULT_VIEW_ENTITY_ID,X as DOMAINS_HIDE_MORE_INFO,Y as DOMAINS_MORE_INFO_NO_HISTORY,$ as DOMAINS_TOGGLE,K as DOMAINS_WITH_CARD,Q as DOMAINS_WITH_MORE_INFO,t as NumberFormat,Z as STATES_OFF,r as TimeFormat,ee as UNIT_C,te as UNIT_F,q as applyThemesOnElement,A as computeCardSize,E as computeDomain,j as computeEntity,R as computeRTL,z as computeRTLDirection,W as computeStateDisplay,L as computeStateDomain,oe as createThing,ue as debounce,me as domainIcon,se as evaluateFilter,ne as fireEvent,ce as fixedIcons,a as formatDate,f as formatDateMonth,l as formatDateMonthYear,u as formatDateNumeric,m as formatDateShort,v as formatDateTime,k as formatDateTimeNumeric,_ as formatDateTimeWithSeconds,n as formatDateWeekday,p as formatDateYear,H as formatNumber,D as formatTime,I as formatTimeWeekday,F as formatTimeWithSeconds,le as forwardHaptic,ke as getLovelace,he as handleAction,pe as handleActionConfig,be as handleClick,ve as hasAction,ye as hasConfigOrEntityChanged,_e as hasDoubleClick,P as isNumericState,de as navigate,U as numberFormatToLocale,M as relativeTime,B as round,Se as stateIcon,C as timerTimeRemaining,ge as toggleEntity,we as turnOnOffEntities,fe as turnOnOffEntity}; //# sourceMappingURL=index.m.js.map diff --git a/dist/index.m.js.map b/dist/index.m.js.map index ddf739b..8371fa6 100644 --- a/dist/index.m.js.map +++ b/dist/index.m.js.map @@ -1 +1 @@ -{"version":3,"file":"index.m.js","sources":["../src/datetime/format_date.ts","../src/types.ts","../src/datetime/use_am_pm.ts","../src/datetime/format_date_time.ts","../src/datetime/format_time.ts","../src/datetime/relative_time.ts","../src/datetime/timer_time_remaining.ts","../src/datetime/duration_to_seconds.ts","../src/apply_themes_on_element.ts","../src/compute-card-size.ts","../src/compute-domain.ts","../src/compute-entity.ts","../src/compute-rtl.ts","../src/compute-state-domain.ts","../src/format-number.ts","../src/compute-state-display.ts","../src/const.ts","../src/fire-event.ts","../src/create-thing.ts","../src/debounce.ts","../src/domain_icons.ts","../src/evaluate-filter.ts","../src/haptic.ts","../src/navigate.ts","../src/turn-on-off-entity.ts","../src/toggle-entity.ts","../src/handle-action.ts","../src/handle-click.ts","../src/has-action.ts","../src/has-changed.ts","../src/has-double-click.ts","../src/turn-on-off-entities.ts","../src/get-lovelace.ts","../src/sensor_icon.ts","../src/state_icon.ts","../src/binary_sensor_icon.ts","../src/cover_icon.ts","../src/input_datetime_icon.ts"],"sourcesContent":["//REF: https://github.com/home-assistant/frontend/blob/dev/src/common/datetime/format_date.ts\n\nimport { FrontendLocaleData } from \"../types\";\n\n/**\n * Formatting a Date to the dddd, mmmm yy format e.g. Tuesday, August 10\n * @param dateObj The date to convert\n * @param locale The users's locale settings\n * @returns date string like \"Tuesday, August 10\"\n */\nexport const formatDateWeekday = (dateObj: Date, locale: FrontendLocaleData) =>\n formatDateWeekdayMem(locale).format(dateObj);\n\nconst formatDateWeekdayMem =\n (locale: FrontendLocaleData) =>\n new Intl.DateTimeFormat(locale.language, {\n weekday: \"long\",\n month: \"long\",\n day: \"numeric\",\n });\n\n/**\n * Formatting a Date to the mmmm dd, yyyy format e.g. August 10, 2021\n * @param dateObj The date to convert\n * @param locale The users's locale settings\n * @returns date string like \"August 10, 2021\"\n */\nexport const formatDate = (dateObj: Date, locale: FrontendLocaleData) =>\n formatDateMem(locale).format(dateObj);\n\nconst formatDateMem =\n (locale: FrontendLocaleData) =>\n new Intl.DateTimeFormat(locale.language, {\n year: \"numeric\",\n month: \"long\",\n day: \"numeric\",\n });\n\n/**\n * Formatting a Date to the classic date format e.g. 10/08/2021\n * @param dateObj The date to convert\n * @param locale The users's locale settings\n * @returns classic date format \"10/08/2021\"\n */\nexport const formatDateNumeric = (dateObj: Date, locale: FrontendLocaleData) =>\n formatDateNumericMem(locale).format(dateObj);\n\nconst formatDateNumericMem =\n (locale: FrontendLocaleData) =>\n new Intl.DateTimeFormat(locale.language, {\n year: \"numeric\",\n month: \"numeric\",\n day: \"numeric\",\n });\n\n\n/**\n * Formatting a Date to just a month with days e.g. Aug 10\n * @param dateObj The date to convert\n * @param locale The users's locale settings\n * @returns month and day like \"Aug 10\"\n */\nexport const formatDateShort = (dateObj: Date, locale: FrontendLocaleData) =>\nformatDateShortMem(locale).format(dateObj);\n\nconst formatDateShortMem =\n(locale: FrontendLocaleData) =>\n new Intl.DateTimeFormat(locale.language, {\n day: \"numeric\",\n month: \"short\",\n });\n\n\n/**\n * Formatting a Date to just a month with year e.g. August 2021\n * @param dateObj The date to convert\n * @param locale The users's locale settings\n * @returns month and year like \"August 2021\"\n */\nexport const formatDateMonthYear = (\ndateObj: Date,\nlocale: FrontendLocaleData\n) => formatDateMonthYearMem(locale).format(dateObj);\n\nconst formatDateMonthYearMem = (locale: FrontendLocaleData) =>\n new Intl.DateTimeFormat(locale.language, {\n month: \"long\",\n year: \"numeric\",\n });\n\n\n/**\n * Formatting a Date to just a month e.g. August\n * @param dateObj The date to convert\n * @param locale The users's locale settings\n * @returns the written out months of the date\n */\nexport const formatDateMonth = (dateObj: Date, locale: FrontendLocaleData) =>\nformatDateMonthMem(locale).format(dateObj);\n\nconst formatDateMonthMem = (locale: FrontendLocaleData) =>\n new Intl.DateTimeFormat(locale.language, {\n month: \"long\",\n });\n\n\n/**\n * Formatting a Date to just a year e.g. 2021\n * @param dateObj The date to convert\n * @param locale The users's locale settings\n * @returns the year of the date in yyyy\n */\nexport const formatDateYear = (dateObj: Date, locale: FrontendLocaleData) =>\nformatDateYearMem(locale).format(dateObj);\n\nconst formatDateYearMem = (locale: FrontendLocaleData) =>\n new Intl.DateTimeFormat(locale.language, {\n year: \"numeric\",\n });\n","import {\n HassEntities,\n HassConfig,\n Auth,\n Connection,\n MessageBase,\n HassServices,\n HassServiceTarget,\n} from \"home-assistant-js-websocket\";\nimport { HapticType } from \"./haptic\";\nimport { HASSDomEvent } from \"./fire-event\";\n\nexport interface ToggleMenuActionConfig extends BaseActionConfig {\n action: \"toggle-menu\";\n}\n\nexport interface ToggleActionConfig extends BaseActionConfig {\n action: \"toggle\";\n}\n\nexport interface CallServiceActionConfig extends BaseActionConfig {\n action: \"call-service\";\n service: string;\n service_data?: {\n entity_id?: string | [string];\n [key: string]: any;\n };\n\n target?: HassServiceTarget;\n repeat?: number;\n haptic?: HapticType;\n}\n\nexport interface NavigateActionConfig extends BaseActionConfig {\n action: \"navigate\";\n navigation_path: string;\n}\n\nexport interface UrlActionConfig extends BaseActionConfig {\n action: \"url\";\n url_path: string;\n}\n\nexport interface MoreInfoActionConfig extends BaseActionConfig {\n action: \"more-info\";\n entity?: string;\n}\n\nexport interface NoActionConfig extends BaseActionConfig {\n action: \"none\";\n}\n\nexport interface CustomActionConfig extends BaseActionConfig {\n action: \"fire-dom-event\";\n}\n\n/**\n * `repeat` and `haptic` are specifically for use in custom cards like the Button-Card\n */\nexport interface BaseActionConfig {\n confirmation?: ConfirmationRestrictionConfig;\n repeat?: number;\n haptic?: HapticType;\n}\n\nexport interface ConfirmationRestrictionConfig {\n text?: string;\n exemptions?: RestrictionConfig[];\n}\n\nexport interface RestrictionConfig {\n user: string;\n}\n\nexport type ActionConfig =\n | ToggleActionConfig\n | CallServiceActionConfig\n | NavigateActionConfig\n | UrlActionConfig\n | MoreInfoActionConfig\n | NoActionConfig\n | CustomActionConfig\n | ToggleMenuActionConfig;\n\nexport interface Window {\n // Custom panel entry point url\n customPanelJS: string;\n ShadyCSS: {\n nativeCss: boolean;\n nativeShadow: boolean;\n prepareTemplate(templateElement, elementName, elementExtension);\n styleElement(element);\n styleSubtree(element, overrideProperties);\n styleDocument(overrideProperties);\n getComputedStyleValue(element, propertyName);\n };\n}\n\ndeclare global {\n // for fire event\n interface HASSDomEvents {\n \"value-changed\": {\n value: unknown;\n };\n \"config-changed\": {\n config: any;\n };\n \"hass-more-info\": {\n entityId: string | undefined;\n };\n \"ll-rebuild\": {};\n \"ll-custom\": {};\n \"location-changed\": {\n replace: boolean;\n };\n \"show-dialog\": {};\n undefined;\n action: {\n action: string;\n };\n }\n}\n\ntype ValidHassDomEvent = keyof HASSDomEvents;\n\nexport type LocalizeFunc = (key: string, ...args: any[]) => string;\n\nexport interface Credential {\n auth_provider_type: string;\n auth_provider_id: string;\n}\n\nexport interface MFAModule {\n id: string;\n name: string;\n enabled: boolean;\n}\n\nexport interface CurrentUser {\n id: string;\n is_owner: boolean;\n is_admin: boolean;\n name: string;\n credentials: Credential[];\n mfa_modules: MFAModule[];\n}\n\nexport interface Theme {\n // Incomplete\n \"primary-color\": string;\n \"text-primary-color\": string;\n \"accent-color\": string;\n}\n\nexport interface Themes {\n default_theme: string;\n themes: { [key: string]: Theme };\n}\n\nexport interface Panel {\n component_name: string;\n config: { [key: string]: any } | null;\n icon: string | null;\n title: string | null;\n url_path: string;\n}\n\nexport interface Panels {\n [name: string]: Panel;\n}\n\nexport interface Resources {\n [language: string]: { [key: string]: string };\n}\n\nexport interface Translation {\n nativeName: string;\n isRTL: boolean;\n fingerprints: { [fragment: string]: string };\n}\n\nexport interface ServiceCallRequest {\n domain: string;\n service: string;\n serviceData?: Record;\n target?: HassServiceTarget;\n}\n\nexport interface HomeAssistant {\n auth: Auth;\n connection: Connection;\n connected: boolean;\n states: HassEntities;\n services: HassServices;\n config: HassConfig;\n themes: Themes;\n selectedTheme?: string | null;\n panels: Panels;\n panelUrl: string;\n\n // i18n\n // current effective language, in that order:\n // - backend saved user selected lanugage\n // - language in local appstorage\n // - browser language\n // - english (en)\n language: string;\n locale: FrontendLocaleData;\n // local stored language, keep that name for backward compability\n selectedLanguage: string | null;\n resources: Resources;\n localize: LocalizeFunc;\n translationMetadata: {\n fragments: string[];\n translations: {\n [lang: string]: Translation;\n };\n };\n\n dockedSidebar: boolean;\n moreInfoEntityId: string;\n user: CurrentUser;\n callService: (\n domain: ServiceCallRequest[\"domain\"],\n service: ServiceCallRequest[\"service\"],\n serviceData?: ServiceCallRequest[\"serviceData\"],\n target?: ServiceCallRequest[\"target\"]\n ) => Promise;\n callApi: (\n method: \"GET\" | \"POST\" | \"PUT\" | \"DELETE\",\n path: string,\n parameters?: { [key: string]: any }\n ) => Promise;\n fetchWithAuth: (\n path: string,\n init?: { [key: string]: any }\n ) => Promise;\n sendWS: (msg: MessageBase) => Promise;\n callWS: (msg: MessageBase) => Promise;\n}\n\nexport enum NumberFormat {\n language = \"language\",\n system = \"system\",\n comma_decimal = \"comma_decimal\",\n decimal_comma = \"decimal_comma\",\n space_comma = \"space_comma\",\n none = \"none\",\n}\n\nexport enum TimeFormat {\n language = \"language\",\n system = \"system\",\n am_pm = \"12\",\n twenty_four = \"24\",\n}\n\nexport interface FrontendLocaleData {\n language: string;\n number_format: NumberFormat;\n time_format: TimeFormat;\n}\n\nexport interface LovelaceCardConfig {\n index?: number;\n view_index?: number;\n type: string;\n [key: string]: any;\n}\n\nexport interface LovelaceCard extends HTMLElement {\n hass?: HomeAssistant;\n isPanel?: boolean;\n editMode?: boolean;\n getCardSize(): number | Promise;\n setConfig(config: LovelaceCardConfig): void;\n}\n\nexport interface LovelaceCardEditor extends HTMLElement {\n hass?: HomeAssistant;\n lovelace?: LovelaceConfig;\n setConfig(config: LovelaceCardConfig): void;\n}\n\nexport interface LovelaceConfig {\n title?: string;\n views: LovelaceViewConfig[];\n background?: string;\n}\n\nexport interface LovelaceViewConfig {\n index?: number;\n title?: string;\n badges?: Array;\n cards?: LovelaceCardConfig[];\n path?: string;\n icon?: string;\n theme?: string;\n panel?: boolean;\n background?: string;\n visible?: boolean | ShowViewConfig[];\n}\n\nexport interface ShowViewConfig {\n user?: string;\n}\n\nexport interface LovelaceBadgeConfig {\n type?: string;\n [key: string]: any;\n}\n\nexport interface ActionHandlerDetail {\n action: string;\n}\n\nexport type ActionHandlerEvent = HASSDomEvent;\n\nexport interface ActionHandlerOptions {\n hasHold?: boolean;\n hasDoubleClick?: boolean;\n}\n\nexport interface EntitiesCardEntityConfig extends EntityConfig {\n type?: string;\n secondary_info?:\n | \"entity-id\"\n | \"last-changed\"\n | \"last-triggered\"\n | \"last-updated\"\n | \"position\"\n | \"tilt-position\"\n | \"brightness\";\n action_name?: string;\n service?: string;\n service_data?: Record;\n url?: string;\n tap_action?: ActionConfig;\n hold_action?: ActionConfig;\n double_tap_action?: ActionConfig;\n state_color?: boolean;\n show_name?: boolean;\n show_icon?: boolean;\n}\n\nexport interface EntityConfig {\n entity: string;\n type?: string;\n name?: string;\n icon?: string;\n image?: string;\n}\n\nexport interface LovelaceElementConfigBase {\n type: string;\n style: Record;\n}\n","// REF: https://github.com/home-assistant/frontend/blob/dev/src/common/datetime/use_am_pm.ts\r\n\r\nimport { FrontendLocaleData, TimeFormat } from \"../types\"\r\n\r\n/**\r\n * Checking if AM/PM time format is used within the browser.\r\n * @param locale Homeassistant frontend locale data\r\n * @returns \r\n */\r\nexport const useAmPm = (locale: FrontendLocaleData): boolean => {\r\n if (\r\n locale.time_format === TimeFormat.language ||\r\n locale.time_format === TimeFormat.system\r\n ) {\r\n const testLanguage =\r\n locale.time_format === TimeFormat.language ? locale.language : undefined;\r\n const test = new Date().toLocaleString(testLanguage);\r\n return test.includes(\"AM\") || test.includes(\"PM\");\r\n }\r\n\r\n return locale.time_format === TimeFormat.am_pm;\r\n};\r\n","//REF: https://github.com/home-assistant/frontend/blob/dev/src/common/datetime/format_date_time.ts\n\nimport { FrontendLocaleData } from \"../types\";\nimport { useAmPm } from \"./use_am_pm\";\n\n// August 9, 2021, 8:23 AM\n/**\n * Formatting a dateObject to date with time e.g. August 9, 2021, 8:23 AM\n * @param dateObj The date to convert\n * @param locale The users's locale settings\n * @returns month and day like \"August 9, 2021, 8:23 AM\"\n */\nexport const formatDateTime = (dateObj: Date, locale: FrontendLocaleData) =>\n formatDateTimeMem(locale).format(dateObj);\n\nconst formatDateTimeMem = (locale: FrontendLocaleData) =>\n new Intl.DateTimeFormat(locale.language, {\n year: \"numeric\",\n month: \"long\",\n day: \"numeric\",\n hour: useAmPm(locale) ? \"numeric\" : \"2-digit\",\n minute: \"2-digit\",\n hour12: useAmPm(locale),\n });\n\n\n/**\n * Formatting a dateObject to date with time e.g. August 9, 2021, 8:23:15 AM\n * @param dateObj The date to convert\n * @param locale The users's locale settings\n * @returns month and day like \"August 9, 2021, 8:23:15 AM\"\n */\nexport const formatDateTimeWithSeconds = (\n dateObj: Date,\n locale: FrontendLocaleData\n) => formatDateTimeWithSecondsMem(locale).format(dateObj);\n\nconst formatDateTimeWithSecondsMem =\n (locale: FrontendLocaleData) =>\n new Intl.DateTimeFormat(locale.language, {\n year: \"numeric\",\n month: \"long\",\n day: \"numeric\",\n hour: useAmPm(locale) ? \"numeric\" : \"2-digit\",\n minute: \"2-digit\",\n second: \"2-digit\",\n hour12: useAmPm(locale),\n });\n\n/**\n * Formatting a Date to just date with AM/PM time e.g. 9/8/2021, 8:23 AM\n * @param dateObj The date to convert\n * @param locale The users's locale settings\n * @returns month and day like \"9/8/2021, 8:23 AM\"\n */\nexport const formatDateTimeNumeric = (\n dateObj: Date,\n locale: FrontendLocaleData\n) => formatDateTimeNumericMem(locale).format(dateObj);\n\nconst formatDateTimeNumericMem =\n (locale: FrontendLocaleData) =>\n new Intl.DateTimeFormat(locale.language, {\n year: \"numeric\",\n month: \"numeric\",\n day: \"numeric\",\n hour: \"numeric\",\n minute: \"2-digit\",\n hour12: useAmPm(locale),\n });","//REF: https://github.com/home-assistant/frontend/blob/dev/src/common/datetime/format_time.ts\n\nimport { FrontendLocaleData } from \"../types\";\nimport { useAmPm } from \"./use_am_pm\";\n\n/**\n * 9:15 PM or 21:15\n * @param dateObj The time to convert\n * @param locale The users's locale settings\n * @returns Reformated time in hh:mm\n */\n export const formatTime = (dateObj: Date, locale: FrontendLocaleData) =>\n formatTimeMem(locale).format(dateObj);\n\n const formatTimeMem =\n (locale: FrontendLocaleData) =>\n new Intl.DateTimeFormat(locale.language, {\n hour: \"numeric\",\n minute: \"2-digit\",\n hour12: useAmPm(locale),\n });\n\n/**\n* 9:15:24 PM or 21:15:24\n* @param dateObj The time to convert\n* @param locale The users's locale settings\n* @returns Reformated time in hh:mm:ss\n*/\nexport const formatTimeWithSeconds = (\n dateObj: Date,\n locale: FrontendLocaleData\n) => formatTimeWithSecondsMem(locale).format(dateObj);\n\nconst formatTimeWithSecondsMem =\n (locale: FrontendLocaleData) =>\n new Intl.DateTimeFormat(locale.language, {\n hour: useAmPm(locale) ? \"numeric\" : \"2-digit\",\n minute: \"2-digit\",\n second: \"2-digit\",\n hour12: useAmPm(locale),\n });\n\n/**\n* Tuesday 7:00 PM or Tuesday 19:00\n* @param dateObj The datetime to convert\n* @param locale The users's locale settings\n* @returns Reformated weekday/time in dddd hh:mm\n*/\nexport const formatTimeWeekday = (dateObj: Date, locale: FrontendLocaleData) =>\n formatTimeWeekdayMem(locale).format(dateObj);\n\nconst formatTimeWeekdayMem =\n (locale: FrontendLocaleData) =>\n new Intl.DateTimeFormat(locale.language, {\n hour: useAmPm(locale) ? \"numeric\" : \"2-digit\",\n minute: \"2-digit\",\n second: \"2-digit\",\n hour12: useAmPm(locale),\n }); \n","//REF: https://github.com/home-assistant/frontend/blob/dev/src/common/datetime/relative_time.ts\n\nimport { selectUnit } from \"@formatjs/intl-utils\";\nimport { FrontendLocaleData } from \"../types\";\n\n const formatRelTimeMem =\n (locale: FrontendLocaleData) =>\n new Intl.RelativeTimeFormat(locale.language, { numeric: \"auto\" });\n\n/**\n * Calculate a string representing a date object as relative time from now.\n *\n * Example output: 5 minutes ago, in 3 days.\n */\n export const relativeTime = (\n from: Date,\n locale: FrontendLocaleData,\n to?: Date,\n includeTense = true\n): string => {\n const diff = selectUnit(from, to);\n if (includeTense) {\n return formatRelTimeMem(locale).format(diff.value, diff.unit);\n }\n return Intl.NumberFormat(locale.language, {\n style: \"unit\",\n unit: diff.unit,\n unitDisplay: \"long\",\n }).format(Math.abs(diff.value));\n};\n","import { HassEntity } from \"home-assistant-js-websocket\";\nimport durationToSeconds from \"../datetime/duration_to_seconds\";\n\nexport function timerTimeRemaining(stateObj: HassEntity) {\n let timeRemaining = durationToSeconds(stateObj.attributes.remaining);\n\n if (stateObj.state === \"active\") {\n const now = new Date().getTime();\n const madeActive = new Date(stateObj.last_changed).getTime();\n timeRemaining = Math.max(timeRemaining - (now - madeActive) / 1000, 0);\n }\n\n return timeRemaining;\n}\n","/**\n * Convert a Duration hh:mm:ss format to seconds\n * @param duration hh:mm:ss formated duration\n * @returns duration in seconds\n */\n export default function durationToSeconds(duration: string): number {\n const parts = duration.split(\":\").map(Number);\n return parts[0] * 3600 + parts[1] * 60 + parts[2];\n}\n","/**\n * Apply a theme to an element by setting the CSS variables on it.\n *\n * element: Element to apply theme on.\n * themes: HASS Theme information\n * localTheme: selected theme.\n * updateMeta: boolean if we should update the theme-color meta element.\n */\nexport const applyThemesOnElement = (\n element,\n themes,\n localTheme,\n updateMeta = false\n) => {\n if (!element._themes) {\n element._themes = {};\n }\n let themeName = themes.default_theme;\n if (localTheme === \"default\" || (localTheme && themes.themes[localTheme])) {\n themeName = localTheme;\n }\n const styles = { ...element._themes };\n if (themeName !== \"default\") {\n const theme = themes.themes[themeName];\n Object.keys(theme).forEach((key) => {\n const prefixedKey = \"--\" + key;\n element._themes[prefixedKey] = \"\";\n styles[prefixedKey] = theme[key];\n });\n }\n if (element.updateStyles) {\n element.updateStyles(styles);\n } else if ((window as any).ShadyCSS) {\n // implement updateStyles() method of Polemer elements\n (window as any).ShadyCSS.styleSubtree(/** @type {!HTMLElement} */ (element), styles);\n }\n\n if (!updateMeta) {\n return;\n }\n\n const meta = document.querySelector(\"meta[name=theme-color]\");\n if (meta) {\n if (!meta.hasAttribute(\"default-content\")) {\n meta.setAttribute(\"default-content\", meta.getAttribute(\"content\")!);\n }\n const themeColor =\n styles[\"--primary-color\"] || meta.getAttribute(\"default-content\");\n meta.setAttribute(\"content\", themeColor);\n }\n}\n","import { LovelaceCard } from \"./types\";\n\nexport const computeCardSize = (card: LovelaceCard): number | Promise => {\n return typeof card.getCardSize === \"function\" ? card.getCardSize() : 4;\n};","export function computeDomain(entityId: string): string {\n return entityId.substr(0, entityId.indexOf(\".\"));\n}\n","export function computeEntity(entityId: string): string {\n return entityId.substr(entityId.indexOf(\".\") + 1);\n}\n","import { HomeAssistant } from \"./types\";\n\nexport function computeRTL(hass: HomeAssistant) {\n const lang = hass?.locale?.language || \"en\";\n if (hass.translationMetadata.translations[lang]) {\n return hass.translationMetadata.translations[lang].isRTL || false;\n }\n return false;\n}\n\nexport function computeRTLDirection(hass: HomeAssistant) {\n return computeRTL(hass) ? \"rtl\" : \"ltr\";\n}\n","import { HassEntity } from \"home-assistant-js-websocket\";\nimport { computeDomain } from \"./compute-domain\";\n\nexport function computeStateDomain(stateObj: HassEntity) {\n return computeDomain(stateObj.entity_id);\n}\n","//REF: https://github.com/home-assistant/frontend/blob/dev/src/common/number/format_number.ts\n\nimport { HassEntity } from \"home-assistant-js-websocket\";\nimport { FrontendLocaleData, NumberFormat } from \"./types\";\n\n/**\n * Returns true if the entity is considered numeric based on the attributes it has\n * @param stateObj The entity state object\n */\n export const isNumericState = (stateObj: HassEntity): boolean =>\n !!stateObj.attributes.unit_of_measurement ||\n !!stateObj.attributes.state_class;\n\nexport const numberFormatToLocale = (\n localeOptions: FrontendLocaleData\n): string | string[] | undefined => {\n switch (localeOptions.number_format) {\n case NumberFormat.comma_decimal:\n return [\"en-US\", \"en\"]; // Use United States with fallback to English formatting 1,234,567.89\n case NumberFormat.decimal_comma:\n return [\"de\", \"es\", \"it\"]; // Use German with fallback to Spanish then Italian formatting 1.234.567,89\n case NumberFormat.space_comma:\n return [\"fr\", \"sv\", \"cs\"]; // Use French with fallback to Swedish and Czech formatting 1 234 567,89\n case NumberFormat.system:\n return undefined;\n default:\n return localeOptions.language;\n }\n};\n\nexport const round = (value: number, precision = 2): number =>\n Math.round(value * 10 ** precision) / 10 ** precision;\n\n/**\n * Formats a number based on the specified language with thousands separator(s) and decimal character for better legibility.\n * @param num The number to format\n * @param locale The user-selected language and number format, from `hass.locale`\n * @param options Intl.NumberFormatOptions to use\n */\nexport const formatNumber = (\n num: string | number,\n localeOptions?: FrontendLocaleData,\n options?: Intl.NumberFormatOptions\n): string => {\n const locale = localeOptions\n ? numberFormatToLocale(localeOptions)\n : undefined;\n\n // Polyfill for Number.isNaN, which is more reliable than the global isNaN()\n Number.isNaN =\n Number.isNaN ||\n function isNaN(input) {\n return typeof input === \"number\" && isNaN(input);\n };\n\n if (\n localeOptions?.number_format !== NumberFormat.none &&\n !Number.isNaN(Number(num)) &&\n Intl\n ) {\n try {\n return new Intl.NumberFormat(\n locale,\n getDefaultFormatOptions(num, options)\n ).format(Number(num));\n } catch (err: any) {\n // Don't fail when using \"TEST\" language\n // eslint-disable-next-line no-console\n console.error(err);\n return new Intl.NumberFormat(\n undefined,\n getDefaultFormatOptions(num, options)\n ).format(Number(num));\n }\n }\n if (typeof num === \"string\") {\n return num;\n }\n return `${round(num, options?.maximumFractionDigits).toString()}${\n options?.style === \"currency\" ? ` ${options.currency}` : \"\"\n }`;\n};\n\n/**\n * Generates default options for Intl.NumberFormat\n * @param num The number to be formatted\n * @param options The Intl.NumberFormatOptions that should be included in the returned options\n */\nconst getDefaultFormatOptions = (\n num: string | number,\n options?: Intl.NumberFormatOptions\n): Intl.NumberFormatOptions => {\n const defaultOptions: Intl.NumberFormatOptions = {\n maximumFractionDigits: 2,\n ...options,\n };\n\n if (typeof num !== \"string\") {\n return defaultOptions;\n }\n\n // Keep decimal trailing zeros if they are present in a string numeric value\n if (\n !options ||\n (!options.minimumFractionDigits && !options.maximumFractionDigits)\n ) {\n const digits = num.indexOf(\".\") > -1 ? num.split(\".\")[1].length : 0;\n defaultOptions.minimumFractionDigits = digits;\n defaultOptions.maximumFractionDigits = digits;\n }\n\n return defaultOptions;\n};\n","import { HassEntity } from \"home-assistant-js-websocket\";\nimport { formatDateTime } from \"./datetime/format_date_time\";\nimport { formatDate } from \"./datetime/format_date\";\nimport { formatTime } from \"./datetime/format_time\";\nimport { LocalizeFunc } from \"./translations/localize\";\nimport { computeStateDomain } from \"./compute-state-domain\";\nimport { FrontendLocaleData } from \"./types\";\nimport { formatNumber, isNumericState } from \"./format-number\";\n\nexport const computeStateDisplay = (\n localize: LocalizeFunc,\n stateObj: HassEntity,\n locale: FrontendLocaleData,\n state?: string\n): string => {\n const compareState = state !== undefined ? state : stateObj.state;\n\n if (compareState === \"unknown\" || compareState === \"unavailable\") {\n return localize(`state.default.${compareState}`);\n }\n\n // Entities with a `unit_of_measurement` or `state_class` are numeric values and should use `formatNumber`\n if (isNumericState(stateObj)) {\n if (stateObj.attributes.device_class === \"monetary\") {\n try {\n return formatNumber(compareState, locale, {\n style: \"currency\",\n currency: stateObj.attributes.unit_of_measurement,\n });\n } catch (_err) {\n // fallback to default\n }\n }\n return `${formatNumber(compareState, locale)}${\n stateObj.attributes.unit_of_measurement\n ? \" \" + stateObj.attributes.unit_of_measurement\n : \"\"\n }`;\n }\n\n const domain = computeStateDomain(stateObj);\n\n if (domain === \"input_datetime\") {\n if (state !== undefined) {\n // If trying to display an explicit state, need to parse the explict state to `Date` then format.\n // Attributes aren't available, we have to use `state`.\n try {\n const components = state.split(\" \");\n if (components.length === 2) {\n // Date and time.\n return formatDateTime(new Date(components.join(\"T\")), locale);\n }\n if (components.length === 1) {\n if (state.includes(\"-\")) {\n // Date only.\n return formatDate(new Date(`${state}T00:00`), locale);\n }\n if (state.includes(\":\")) {\n // Time only.\n const now = new Date();\n return formatTime(\n new Date(`${now.toISOString().split(\"T\")[0]}T${state}`),\n locale\n );\n }\n }\n return state;\n } catch (_e) {\n // Formatting methods may throw error if date parsing doesn't go well,\n // just return the state string in that case.\n return state;\n }\n } else {\n // If not trying to display an explicit state, create `Date` object from `stateObj`'s attributes then format.\n let date: Date;\n if (stateObj.attributes.has_date && stateObj.attributes.has_time) {\n date = new Date(\n stateObj.attributes.year,\n stateObj.attributes.month - 1,\n stateObj.attributes.day,\n stateObj.attributes.hour,\n stateObj.attributes.minute\n );\n return formatDateTime(date, locale);\n }\n if (stateObj.attributes.has_date) {\n date = new Date(\n stateObj.attributes.year,\n stateObj.attributes.month - 1,\n stateObj.attributes.day\n );\n return formatDate(date, locale);\n }\n if (stateObj.attributes.has_time) {\n date = new Date();\n date.setHours(stateObj.attributes.hour, stateObj.attributes.minute);\n return formatTime(date, locale);\n }\n return stateObj.state;\n }\n }\n\n if (domain === \"humidifier\") {\n if (compareState === \"on\" && stateObj.attributes.humidity) {\n return `${stateObj.attributes.humidity} %`;\n }\n }\n\n // `counter` `number` and `input_number` domains do not have a unit of measurement but should still use `formatNumber`\n if (\n domain === \"counter\" ||\n domain === \"number\" ||\n domain === \"input_number\"\n ) {\n return formatNumber(compareState, locale);\n }\n\n return (\n // Return device class translation\n (stateObj.attributes.device_class &&\n localize(\n `component.${domain}.state.${stateObj.attributes.device_class}.${compareState}`\n )) ||\n // Return default translation\n localize(`component.${domain}.state._.${compareState}`) ||\n // We don't know! Return the raw state.\n compareState\n );\n};","/** Constants to be used in the frontend. */\n\n// Constants should be alphabetically sorted by name.\n// Arrays with values should be alphabetically sorted if order doesn't matter.\n// Each constant should have a description what it is supposed to be used for.\n\n/** Icon to use when no icon specified for domain. */\nexport const DEFAULT_DOMAIN_ICON = \"mdi:bookmark\";\n\n/** Panel to show when no panel is picked. */\nexport const DEFAULT_PANEL = \"lovelace\";\n\n/** Domains that have a state card. */\nexport const DOMAINS_WITH_CARD = [\n \"climate\",\n \"cover\",\n \"configurator\",\n \"input_select\",\n \"input_number\",\n \"input_text\",\n \"lock\",\n \"media_player\",\n \"scene\",\n \"script\",\n \"timer\",\n \"vacuum\",\n \"water_heater\",\n \"weblink\"\n];\n\n/** Domains with separate more info dialog. */\nexport const DOMAINS_WITH_MORE_INFO = [\n \"alarm_control_panel\",\n \"automation\",\n \"camera\",\n \"climate\",\n \"configurator\",\n \"cover\",\n \"fan\",\n \"group\",\n \"history_graph\",\n \"input_datetime\",\n \"light\",\n \"lock\",\n \"media_player\",\n \"script\",\n \"sun\",\n \"updater\",\n \"vacuum\",\n \"water_heater\",\n \"weather\"\n];\n\n/** Domains that show no more info dialog. */\nexport const DOMAINS_HIDE_MORE_INFO = [\n \"input_number\",\n \"input_select\",\n \"input_text\",\n \"scene\",\n \"weblink\"\n];\n\n/** Domains that should have the history hidden in the more info dialog. */\nexport const DOMAINS_MORE_INFO_NO_HISTORY = [\n \"camera\",\n \"configurator\",\n \"history_graph\",\n \"scene\"\n];\n\n/** States that we consider \"off\". */\nexport const STATES_OFF = [\"closed\", \"locked\", \"off\"];\n\n/** Domains where we allow toggle in Lovelace. */\nexport const DOMAINS_TOGGLE = new Set([\n \"fan\",\n \"input_boolean\",\n \"light\",\n \"switch\",\n \"group\",\n \"automation\"\n]);\n\n/** Temperature units. */\nexport const UNIT_C = \"°C\";\nexport const UNIT_F = \"°F\";\n\n/** Entity ID of the default view. */\nexport const DEFAULT_VIEW_ENTITY_ID = \"group.default_view\";\n","// Polymer legacy event helpers used courtesy of the Polymer project.\n//\n// Copyright (c) 2017 The Polymer Authors. All rights reserved.\n//\n// Redistribution and use in source and binary forms, with or without\n// modification, are permitted provided that the following conditions are\n// met:\n//\n// * Redistributions of source code must retain the above copyright\n// notice, this list of conditions and the following disclaimer.\n// * Redistributions in binary form must reproduce the above\n// copyright notice, this list of conditions and the following disclaimer\n// in the documentation and/or other materials provided with the\n// distribution.\n// * Neither the name of Google Inc. nor the names of its\n// contributors may be used to endorse or promote products derived from\n// this software without specific prior written permission.\n//\n// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n// \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\ndeclare global {\n // tslint:disable-next-line\n interface HASSDomEvents {}\n}\n\nexport type ValidHassDomEvent = keyof HASSDomEvents;\n\nexport interface HASSDomEvent extends Event {\n detail: T;\n}\n\n/**\n * Dispatches a custom event with an optional detail value.\n *\n * @param {string} type Name of event type.\n * @param {*=} detail Detail value containing event-specific\n * payload.\n * @param {{ bubbles: (boolean|undefined),\n * cancelable: (boolean|undefined),\n * composed: (boolean|undefined) }=}\n * options Object specifying options. These may include:\n * `bubbles` (boolean, defaults to `true`),\n * `cancelable` (boolean, defaults to false), and\n * `node` on which to fire the event (HTMLElement, defaults to `this`).\n * @return {Event} The new event that was fired.\n */\nexport const fireEvent = (\n node: HTMLElement | Window,\n type: HassEvent,\n detail?: HASSDomEvents[HassEvent],\n options?: {\n bubbles?: boolean;\n cancelable?: boolean;\n composed?: boolean;\n }\n) => {\n options = options || {};\n // @ts-ignore\n detail = detail === null || detail === undefined ? {} : detail;\n const event = new Event(type, {\n bubbles: options.bubbles === undefined ? true : options.bubbles,\n cancelable: Boolean(options.cancelable),\n composed: options.composed === undefined ? true : options.composed\n });\n (event as any).detail = detail;\n node.dispatchEvent(event);\n return event;\n};\n","import { fireEvent } from \"./fire-event\";\n\nconst SPECIAL_TYPES = new Set([\n \"call-service\",\n \"divider\",\n \"section\",\n \"weblink\",\n \"cast\",\n \"select\"\n]);\nconst DOMAIN_TO_ELEMENT_TYPE = {\n alert: \"toggle\",\n automation: \"toggle\",\n climate: \"climate\",\n cover: \"cover\",\n fan: \"toggle\",\n group: \"group\",\n input_boolean: \"toggle\",\n input_number: \"input-number\",\n input_select: \"input-select\",\n input_text: \"input-text\",\n light: \"toggle\",\n lock: \"lock\",\n media_player: \"media-player\",\n remote: \"toggle\",\n scene: \"scene\",\n script: \"script\",\n sensor: \"sensor\",\n timer: \"timer\",\n switch: \"toggle\",\n vacuum: \"toggle\",\n // Temporary. Once climate is rewritten,\n // water heater should get it's own row.\n water_heater: \"climate\",\n input_datetime: \"input-datetime\"\n};\n\nexport const createThing = (cardConfig, isRow = false) => {\n const _createError = (error, config) => {\n return _createThing(\n \"hui-error-card\",\n {\n type: \"error\",\n error,\n config\n }\n );\n };\n\n const _createThing = (tag, config) => {\n const element = window.document.createElement(tag);\n try {\n // Preventing an error-card infinity loop: https://github.com/custom-cards/custom-card-helpers/issues/54\n if (!element.setConfig) return;\n element.setConfig(config);\n } catch (err) {\n console.error(tag, err);\n return _createError((err as Error).message, config);\n }\n return element;\n };\n\n if (!cardConfig || typeof cardConfig !== \"object\" || (!isRow && !cardConfig.type))\n return _createError(\"No type defined\", cardConfig);\n let tag = cardConfig.type;\n if (tag && tag.startsWith(\"custom:\")) {\n tag = tag.substr(\"custom:\".length);\n } else if (isRow) {\n if (SPECIAL_TYPES.has(tag)) {\n tag = `hui-${tag}-row`;\n } else {\n if (!cardConfig.entity) {\n return _createError(\"Invalid config given.\", cardConfig);\n }\n \n const domain = cardConfig.entity.split(\".\", 1)[0];\n tag = `hui-${DOMAIN_TO_ELEMENT_TYPE[domain] || \"text\"}-entity-row`;\n }\n } else {\n tag = `hui-${tag}-card`;\n }\n\n if (customElements.get(tag)) return _createThing(tag, cardConfig);\n\n // If element doesn't exist (yet) create an error\n const element = _createError(\n `Custom element doesn't exist: ${cardConfig.type}.`,\n cardConfig\n );\n element.style.display = \"None\";\n const timer = setTimeout(() => {\n element.style.display = \"\";\n }, 2000);\n // Remove error if element is defined later\n customElements.whenDefined(cardConfig.type).then(() => {\n clearTimeout(timer);\n fireEvent(element, \"ll-rebuild\", {}, element);\n });\n\n return element;\n};\n","/**\r\n * Returns a function, that, as long as it continues to be invoked, will not be triggered. It will be called after it stops being called for `wait` ms.\r\n * This can be usefull for ResizeObservers for example.\r\n * @param func The function you want to debounce\r\n * @param wait Period to wait in ms\r\n * @param immediate Triggering on the leading edge instead of the trailing\r\n * @returns Debounced Function\r\n */\r\n// eslint-disable-next-line: ban-types\r\nexport const debounce = unknown>(\r\n func: T,\r\n wait: number,\r\n immediate = false\r\n): T => {\r\n let timeout;\r\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\r\n // @ts-ignore\r\n return function (...args) {\r\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\r\n // @ts-ignore\r\n // eslint-disable-next-line @typescript-eslint/no-this-alias\r\n const context = this;\r\n const later = () => {\r\n timeout = null;\r\n if (!immediate) {\r\n func.apply(context, args);\r\n }\r\n };\r\n const callNow = immediate && !timeout;\r\n clearTimeout(timeout);\r\n timeout = setTimeout(later, wait);\r\n if (callNow) {\r\n func.apply(context, args);\r\n }\r\n };\r\n};\r\n","/**\n * Return the icon to be used for a domain.\n *\n * Optionally pass in a state to influence the domain icon.\n */\nimport { DEFAULT_DOMAIN_ICON } from \"./const\";\n\nexport const fixedIcons = {\n alert: \"mdi:alert\",\n automation: \"mdi:playlist-play\",\n calendar: \"mdi:calendar\",\n camera: \"mdi:video\",\n climate: \"mdi:thermostat\",\n configurator: \"mdi:settings\",\n conversation: \"mdi:text-to-speech\",\n device_tracker: \"mdi:account\",\n fan: \"mdi:fan\",\n group: \"mdi:google-circles-communities\",\n history_graph: \"mdi:chart-line\",\n homeassistant: \"mdi:home-assistant\",\n homekit: \"mdi:home-automation\",\n image_processing: \"mdi:image-filter-frames\",\n input_boolean: \"mdi:drawing\",\n input_datetime: \"mdi:calendar-clock\",\n input_number: \"mdi:ray-vertex\",\n input_select: \"mdi:format-list-bulleted\",\n input_text: \"mdi:textbox\",\n light: \"mdi:lightbulb\",\n mailbox: \"mdi:mailbox\",\n notify: \"mdi:comment-alert\",\n person: \"mdi:account\",\n plant: \"mdi:flower\",\n proximity: \"mdi:apple-safari\",\n remote: \"mdi:remote\",\n scene: \"mdi:google-pages\",\n script: \"mdi:file-document\",\n sensor: \"mdi:eye\",\n simple_alarm: \"mdi:bell\",\n sun: \"mdi:white-balance-sunny\",\n switch: \"mdi:flash\",\n timer: \"mdi:timer\",\n updater: \"mdi:cloud-upload\",\n vacuum: \"mdi:robot-vacuum\",\n water_heater: \"mdi:thermometer\",\n weblink: \"mdi:open-in-new\"\n};\n\nexport function domainIcon(domain: string, state?: string): string {\n if (domain in fixedIcons) {\n return fixedIcons[domain];\n }\n\n switch (domain) {\n case \"alarm_control_panel\":\n switch (state) {\n case \"armed_home\":\n return \"mdi:bell-plus\";\n case \"armed_night\":\n return \"mdi:bell-sleep\";\n case \"disarmed\":\n return \"mdi:bell-outline\";\n case \"triggered\":\n return \"mdi:bell-ring\";\n default:\n return \"mdi:bell\";\n }\n\n case \"binary_sensor\":\n return state && state === \"off\"\n ? \"mdi:radiobox-blank\"\n : \"mdi:checkbox-marked-circle\";\n\n case \"cover\":\n return state === \"closed\" ? \"mdi:window-closed\" : \"mdi:window-open\";\n\n case \"lock\":\n return state && state === \"unlocked\" ? \"mdi:lock-open\" : \"mdi:lock\";\n\n case \"media_player\":\n return state && state !== \"off\" && state !== \"idle\"\n ? \"mdi:cast-connected\"\n : \"mdi:cast\";\n\n case \"zwave\":\n switch (state) {\n case \"dead\":\n return \"mdi:emoticon-dead\";\n case \"sleeping\":\n return \"mdi:sleep\";\n case \"initializing\":\n return \"mdi:timer-sand\";\n default:\n return \"mdi:z-wave\";\n }\n\n default:\n // tslint:disable-next-line\n console.warn(\n \"Unable to find icon for domain \" + domain + \" (\" + state + \")\"\n );\n return DEFAULT_DOMAIN_ICON;\n }\n}\n","import { HassEntity } from \"home-assistant-js-websocket\";\n\nexport const evaluateFilter = (stateObj: HassEntity, filter: any): boolean => {\n const operator = filter.operator || \"==\";\n const value = filter.value || filter;\n const state = filter.attribute\n ? stateObj.attributes[filter.attribute]\n : stateObj.state;\n\n switch (operator) {\n case \"==\":\n return state === value;\n case \"<=\":\n return state <= value;\n case \"<\":\n return state < value;\n case \">=\":\n return state >= value;\n case \">\":\n return state > value;\n case \"!=\":\n return state !== value;\n case \"regex\": {\n return state.match(value);\n }\n default:\n return false;\n }\n};\n","import { HASSDomEvent, fireEvent } from \"./fire-event\";\n\n/**\n * Broadcast haptic feedback requests\n */\n\n\n// Allowed types are from iOS HIG.\n// https://developer.apple.com/design/human-interface-guidelines/ios/user-interaction/feedback/#haptics\n// Implementors on platforms other than iOS should attempt to match the patterns (shown in HIG) as closely as possible.\nexport type HapticType =\n | \"success\"\n | \"warning\"\n | \"failure\"\n | \"light\"\n | \"medium\"\n | \"heavy\"\n | \"selection\";\n\ndeclare global {\n // for fire event\n interface HASSDomEvents {\n haptic: HapticType;\n }\n\n interface GlobalEventHandlersEventMap {\n haptic: HASSDomEvent;\n }\n}\n\nexport const forwardHaptic = (hapticType: HapticType) => {\n fireEvent(window, \"haptic\", hapticType);\n};\n","import { fireEvent } from \"./fire-event\";\n\ndeclare global {\n // for fire event\n interface HASSDomEvents {\n \"location-changed\": {\n replace: boolean;\n };\n }\n}\n\nexport const navigate = (\n _node: any,\n path: string,\n replace: boolean = false\n) => {\n if (replace) {\n history.replaceState(null, \"\", path);\n } else {\n history.pushState(null, \"\", path);\n }\n fireEvent(window, \"location-changed\", {\n replace\n });\n};\n","import { HomeAssistant } from \"./types\";\nimport { computeDomain } from \"./compute-domain\";\n\nexport const turnOnOffEntity = (\n hass: HomeAssistant,\n entityId: string,\n turnOn = true\n): Promise => {\n const stateDomain = computeDomain(entityId);\n const serviceDomain = stateDomain === \"group\" ? \"homeassistant\" : stateDomain;\n\n let service;\n switch (stateDomain) {\n case \"lock\":\n service = turnOn ? \"unlock\" : \"lock\";\n break;\n case \"cover\":\n service = turnOn ? \"open_cover\" : \"close_cover\";\n break;\n default:\n service = turnOn ? \"turn_on\" : \"turn_off\";\n }\n\n return hass.callService(serviceDomain, service, { entity_id: entityId });\n};\n","import { STATES_OFF } from \"./const\";\nimport { turnOnOffEntity } from \"./turn-on-off-entity\";\nimport { HomeAssistant } from \"./types\";\n\nexport const toggleEntity = (\n hass: HomeAssistant,\n entityId: string\n): Promise => {\n const turnOn = STATES_OFF.includes(hass.states[entityId].state);\n return turnOnOffEntity(hass, entityId, turnOn);\n};\n","import { HomeAssistant, ActionConfig } from \"./types\";\nimport { forwardHaptic } from \"./haptic\";\nimport { fireEvent } from \"./fire-event\";\nimport { navigate } from \"./navigate\";\nimport { toggleEntity } from \"./toggle-entity\";\n\nexport const handleActionConfig = (\n node: HTMLElement,\n hass: HomeAssistant,\n config: {\n entity?: string;\n camera_image?: string;\n hold_action?: ActionConfig;\n tap_action?: ActionConfig;\n double_tap_action?: ActionConfig;\n },\n actionConfig: ActionConfig | undefined\n): void => {\n if (!actionConfig) {\n actionConfig = {\n action: \"more-info\",\n };\n }\n\n if (\n actionConfig.confirmation &&\n (!actionConfig.confirmation.exemptions ||\n !actionConfig.confirmation.exemptions.some(\n (e) => e.user === hass!.user!.id\n ))\n ) {\n forwardHaptic(\"warning\");\n\n if (\n !confirm(\n actionConfig.confirmation.text ||\n `Are you sure you want to ${actionConfig.action}?`\n )\n ) {\n return;\n }\n }\n\n switch (actionConfig.action) {\n case \"more-info\":\n if (config.entity || config.camera_image) {\n fireEvent(node, \"hass-more-info\", {\n entityId: config.entity ? config.entity : config.camera_image!,\n });\n }\n break;\n case \"navigate\":\n if (actionConfig.navigation_path) {\n navigate(node, actionConfig.navigation_path);\n }\n break;\n case \"url\":\n if (actionConfig.url_path) {\n window.open(actionConfig.url_path);\n }\n break;\n case \"toggle\":\n if (config.entity) {\n toggleEntity(hass, config.entity!);\n forwardHaptic(\"success\");\n }\n break;\n case \"call-service\": {\n if (!actionConfig.service) {\n forwardHaptic(\"failure\");\n return;\n }\n const [domain, service] = actionConfig.service.split(\".\", 2);\n hass.callService(domain, service, actionConfig.service_data, actionConfig.target);\n forwardHaptic(\"success\");\n break;\n }\n case \"fire-dom-event\": {\n fireEvent(node, \"ll-custom\", actionConfig);\n }\n }\n};\n\nexport const handleAction = (\n node: HTMLElement,\n hass: HomeAssistant,\n config: {\n entity?: string;\n camera_image?: string;\n hold_action?: ActionConfig;\n tap_action?: ActionConfig;\n double_tap_action?: ActionConfig;\n },\n action: string\n): void => {\n let actionConfig: ActionConfig | undefined;\n\n if (action === \"double_tap\" && config.double_tap_action) {\n actionConfig = config.double_tap_action;\n } else if (action === \"hold\" && config.hold_action) {\n actionConfig = config.hold_action;\n } else if (action === \"tap\" && config.tap_action) {\n actionConfig = config.tap_action;\n }\n\n handleActionConfig(node, hass, config, actionConfig);\n};\n","import { HomeAssistant, ActionConfig } from \"./types\";\nimport { fireEvent } from \"./fire-event\";\nimport { forwardHaptic } from \"./haptic\";\nimport { navigate } from \"./navigate\";\nimport { toggleEntity } from \"./toggle-entity\";\n\nexport const handleClick = (\n node: HTMLElement,\n hass: HomeAssistant,\n config: {\n entity?: string;\n camera_image?: string;\n hold_action?: ActionConfig;\n tap_action?: ActionConfig;\n double_tap_action?: ActionConfig;\n },\n hold: boolean,\n dblClick: boolean\n): void => {\n let actionConfig: ActionConfig | undefined;\n\n if (dblClick && config.double_tap_action) {\n actionConfig = config.double_tap_action;\n } else if (hold && config.hold_action) {\n actionConfig = config.hold_action;\n } else if (!hold && config.tap_action) {\n actionConfig = config.tap_action;\n }\n\n if (!actionConfig) {\n actionConfig = {\n action: \"more-info\"\n };\n }\n\n if (\n actionConfig.confirmation &&\n (!actionConfig.confirmation.exemptions ||\n !actionConfig.confirmation.exemptions.some(\n e => e.user === hass!.user!.id\n ))\n ) {\n if (\n !confirm(\n actionConfig.confirmation.text ||\n `Are you sure you want to ${actionConfig.action}?`\n )\n ) {\n return;\n }\n }\n\n switch (actionConfig.action) {\n case \"more-info\":\n if (actionConfig.entity || config.entity || config.camera_image) {\n fireEvent(node, \"hass-more-info\", {\n entityId: actionConfig.entity\n ? actionConfig.entity\n : config.entity\n ? config.entity\n : config.camera_image\n });\n if (actionConfig.haptic) forwardHaptic(actionConfig.haptic);\n }\n break;\n case \"navigate\":\n if (actionConfig.navigation_path) {\n navigate(node, actionConfig.navigation_path);\n if (actionConfig.haptic) forwardHaptic(actionConfig.haptic);\n }\n break;\n case \"url\":\n actionConfig.url_path && window.open(actionConfig.url_path);\n if (actionConfig.haptic) forwardHaptic(actionConfig.haptic);\n break;\n case \"toggle\":\n if (config.entity) {\n toggleEntity(hass, config.entity!);\n if (actionConfig.haptic) forwardHaptic(actionConfig.haptic);\n }\n break;\n case \"call-service\": {\n if (!actionConfig.service) {\n return;\n }\n const [domain, service] = actionConfig.service.split(\".\", 2);\n const serviceData = { ...actionConfig.service_data };\n if (serviceData.entity_id === \"entity\") {\n serviceData.entity_id = config.entity;\n }\n hass.callService(domain, service, serviceData, actionConfig.target);\n if (actionConfig.haptic) forwardHaptic(actionConfig.haptic);\n break;\n }\n case \"fire-dom-event\": {\n fireEvent(node, \"ll-custom\", actionConfig);\n if (actionConfig.haptic) forwardHaptic(actionConfig.haptic);\n break;\n }\n }\n};\n","import { ActionConfig } from \"./types\";\n\nexport function hasAction(config?: ActionConfig): boolean {\n return config !== undefined && config.action !== \"none\";\n}\n","import { PropertyValues } from \"lit\";\n\nimport { HomeAssistant } from \"./types\";\n\n// Check if config or Entity changed\nexport function hasConfigOrEntityChanged(\n element: any,\n changedProps: PropertyValues,\n forceUpdate: Boolean,\n): boolean {\n if (changedProps.has('config') || forceUpdate) {\n return true;\n }\n\n if (element.config!.entity) {\n const oldHass = changedProps.get('hass') as HomeAssistant | undefined;\n if (oldHass) {\n return (\n oldHass.states[element.config!.entity]\n !== element.hass!.states[element.config!.entity]\n );\n }\n return true;\n } else {\n return false;\n }\n}","import { ActionConfig } from \"./types\";\n\n// Check if config or Entity changed\nexport function hasDoubleClick(config?: ActionConfig): boolean {\n return config !== undefined && config.action !== \"none\";\n}","import { HomeAssistant } from \"./types\";\nimport { STATES_OFF } from \"./const\";\nimport { computeDomain } from \"./compute-domain\";\n\nexport const turnOnOffEntities = (\n hass: HomeAssistant,\n entityIds: string[],\n turnOn = true\n): void => {\n const domainsToCall = {};\n entityIds.forEach((entityId) => {\n if (STATES_OFF.includes(hass.states[entityId].state) === turnOn) {\n const stateDomain = computeDomain(entityId);\n const serviceDomain = [\"cover\", \"lock\"].includes(stateDomain)\n ? stateDomain\n : \"homeassistant\";\n\n if (!(serviceDomain in domainsToCall)) {\n domainsToCall[serviceDomain] = [];\n }\n domainsToCall[serviceDomain].push(entityId);\n }\n });\n\n Object.keys(domainsToCall).forEach((domain) => {\n let service;\n switch (domain) {\n case \"lock\":\n service = turnOn ? \"unlock\" : \"lock\";\n break;\n case \"cover\":\n service = turnOn ? \"open_cover\" : \"close_cover\";\n break;\n default:\n service = turnOn ? \"turn_on\" : \"turn_off\";\n }\n\n const entities = domainsToCall[domain];\n hass.callService(domain, service, { entity_id: entities });\n });\n};\n","export const getLovelace = () => {\n let root: any = document.querySelector('home-assistant');\n root = root && root.shadowRoot;\n root = root && root.querySelector('home-assistant-main');\n root = root && root.shadowRoot;\n root = root && root.querySelector('app-drawer-layout partial-panel-resolver');\n root = root && root.shadowRoot || root;\n root = root && root.querySelector('ha-panel-lovelace');\n root = root && root.shadowRoot;\n root = root && root.querySelector('hui-root');\n if (root) {\n const ll = root.lovelace;\n ll.current_view = root.___curView;\n return ll;\n }\n return null;\n}\n","/** Return an icon representing a sensor state. */\nimport { HassEntity } from \"home-assistant-js-websocket\";\nimport { UNIT_C, UNIT_F } from \"./const\";\nimport { domainIcon } from \"./domain_icons\";\n\nconst fixedDeviceClassIcons = {\n humidity: \"mdi:water-percent\",\n illuminance: \"mdi:brightness-5\",\n temperature: \"mdi:thermometer\",\n pressure: \"mdi:gauge\",\n power: \"mdi:flash\",\n signal_strength: \"mdi:wifi\",\n};\n\nexport const sensorIcon = (state: HassEntity) => {\n const dclass = state.attributes.device_class;\n\n if (dclass && dclass in fixedDeviceClassIcons) {\n return fixedDeviceClassIcons[dclass];\n }\n if (dclass === \"battery\") {\n const battery = Number(state.state);\n if (isNaN(battery)) {\n return \"mdi:battery-unknown\";\n }\n const batteryRound = Math.round(battery / 10) * 10;\n if (batteryRound >= 100) {\n return \"mdi:battery\";\n }\n if (batteryRound <= 0) {\n return \"mdi:battery-alert\";\n }\n // Will return one of the following icons: (listed so extractor picks up)\n // mdi:battery-10\n // mdi:battery-20\n // mdi:battery-30\n // mdi:battery-40\n // mdi:battery-50\n // mdi:battery-60\n // mdi:battery-70\n // mdi:battery-80\n // mdi:battery-90\n // We obscure 'hass' in iconname so this name does not get picked up\n return `${\"hass\"}:battery-${batteryRound}`;\n }\n\n const unit = state.attributes.unit_of_measurement;\n if (unit === UNIT_C || unit === UNIT_F) {\n return \"mdi:thermometer\";\n }\n return domainIcon(\"sensor\");\n};\n","import { HassEntity } from \"home-assistant-js-websocket\";\nimport { computeDomain } from \"./compute-domain\";\nimport { DEFAULT_DOMAIN_ICON } from \"./const\";\nimport { binarySensorIcon } from \"./binary_sensor_icon\";\nimport { coverIcon } from \"./cover_icon\";\nimport { sensorIcon } from \"./sensor_icon\";\nimport { inputDateTimeIcon } from \"./input_datetime_icon\";\nimport { domainIcon } from \"./domain_icons\";\n\nconst domainIcons = {\n binary_sensor: binarySensorIcon,\n cover: coverIcon,\n sensor: sensorIcon,\n input_datetime: inputDateTimeIcon,\n};\n\nexport const stateIcon = (state: HassEntity) => {\n if (!state) {\n return DEFAULT_DOMAIN_ICON;\n }\n if (state.attributes.icon) {\n return state.attributes.icon;\n }\n\n const domain = computeDomain(state.entity_id);\n\n if (domain in domainIcons) {\n return domainIcons[domain](state);\n }\n return domainIcon(domain, state.state);\n};\n","import { HassEntity } from \"home-assistant-js-websocket\";\n\n/** Return an icon representing a binary sensor state. */\n\nexport const binarySensorIcon = (state?: string, stateObj?: HassEntity) => {\n const is_off = state === \"off\";\n switch (stateObj?.attributes.device_class) {\n case \"battery\":\n return is_off ? \"mdi:battery\" : \"mdi:battery-outline\";\n case \"battery_charging\":\n return is_off ? \"mdi:battery\" : \"mdi:battery-charging\";\n case \"cold\":\n return is_off ? \"mdi:thermometer\" : \"mdi:snowflake\";\n case \"connectivity\":\n return is_off ? \"mdi:server-network-off\" : \"mdi:server-network\";\n case \"door\":\n return is_off ? \"mdi:door-closed\" : \"mdi:door-open\";\n case \"garage_door\":\n return is_off ? \"mdi:garage\" : \"mdi:garage-open\";\n case \"power\":\n return is_off ? \"mdi:power-plug-off\" : \"mdi:power-plug\";\n case \"gas\":\n case \"problem\":\n case \"safety\":\n case \"tamper\":\n return is_off ? \"mdi:check-circle\" : \"mdi:alert-circle\";\n case \"smoke\":\n return is_off ? \"mdi:check-circle\" : \"mdi:smoke\";\n case \"heat\":\n return is_off ? \"mdi:thermometer\" : \"mdi:fire\";\n case \"light\":\n return is_off ? \"mdi:brightness-5\" : \"mdi:brightness-7\";\n case \"lock\":\n return is_off ? \"mdi:lock\" : \"mdi:lock-open\";\n case \"moisture\":\n return is_off ? \"mdi:water-off\" : \"mdi:water\";\n case \"motion\":\n return is_off ? \"mdi:walk\" : \"mdi:run\";\n case \"occupancy\":\n return is_off ? \"mdi:home-outline\" : \"mdi:home\";\n case \"opening\":\n return is_off ? \"mdi:square\" : \"mdi:square-outline\";\n case \"plug\":\n return is_off ? \"mdi:power-plug-off\" : \"mdi:power-plug\";\n case \"presence\":\n return is_off ? \"mdi:home-outline\" : \"mdi:home\";\n case \"running\":\n return is_off ? \"mdi:stop\" : \"mdi:play\";\n case \"sound\":\n return is_off ? \"mdi:music-note-off\" : \"mdi:music-note\";\n case \"update\":\n return is_off ? \"mdi:package\" : \"mdi:package-up\";\n case \"vibration\":\n return is_off ? \"mdi:crop-portrait\" : \"mdi:vibrate\";\n case \"window\":\n return is_off ? \"mdi:window-closed\" : \"mdi:window-open\";\n default:\n return is_off ? \"mdi:radiobox-blank\" : \"mdi:checkbox-marked-circle\";\n }\n};\n","/** Return an icon representing a cover state. */\nimport { HassEntity } from \"home-assistant-js-websocket\";\nimport { domainIcon } from \"./domain_icons\";\n\nexport const coverIcon = (state: HassEntity): string => {\n const open = state.state !== \"closed\";\n switch (state.attributes.device_class) {\n case \"garage\":\n return open ? \"mdi:garage-open\" : \"mdi:garage\";\n case \"door\":\n return open ? \"mdi:door-open\" : \"mdi:door-closed\";\n case \"shutter\":\n return open ? \"mdi:window-shutter-open\" : \"mdi:window-shutter\";\n case \"blind\":\n return open ? \"mdi:blinds-open\" : \"mdi:blinds\";\n case \"window\":\n return open ? \"mdi:window-open\" : \"mdi:window-closed\";\n default:\n return domainIcon(\"cover\", state.state);\n }\n};\n","/** Return an icon representing an input datetime state. */\nimport { domainIcon } from \"./domain_icons\";\nimport { HassEntity } from \"home-assistant-js-websocket\";\n\nexport const inputDateTimeIcon = (state: HassEntity): string => {\n if (!state.attributes.has_date) {\n return \"mdi:clock\";\n }\n if (!state.attributes.has_time) {\n return \"mdi:calendar\";\n }\n return domainIcon(\"input_datetime\");\n};\n"],"names":["formatDateWeekday","NumberFormat","TimeFormat","dateObj","locale","formatDateWeekdayMem","format","Intl","DateTimeFormat","language","weekday","month","day","formatDate","formatDateMem","year","formatDateNumeric","formatDateNumericMem","formatDateShort","formatDateShortMem","formatDateMonthYear","formatDateMonthYearMem","formatDateMonth","formatDateMonthMem","formatDateYear","formatDateYearMem","useAmPm","time_format","system","testLanguage","undefined","test","Date","toLocaleString","includes","am_pm","formatDateTime","formatDateTimeMem","hour","minute","hour12","formatDateTimeWithSeconds","formatDateTimeWithSecondsMem","second","formatDateTimeNumeric","formatDateTimeNumericMem","formatTime","formatTimeMem","formatTimeWithSeconds","formatTimeWithSecondsMem","formatTimeWeekday","formatTimeWeekdayMem","relativeTime","from","to","includeTense","diff","selectUnit","RelativeTimeFormat","numeric","formatRelTimeMem","value","unit","style","unitDisplay","Math","abs","timerTimeRemaining","stateObj","parts","timeRemaining","attributes","remaining","split","map","Number","state","now","getTime","madeActive","last_changed","max","applyThemesOnElement","element","themes","localTheme","updateMeta","_themes","themeName","default_theme","styles","theme","Object","keys","forEach","key","prefixedKey","updateStyles","window","ShadyCSS","styleSubtree","meta","document","querySelector","hasAttribute","setAttribute","getAttribute","themeColor","computeCardSize","card","getCardSize","computeDomain","entityId","substr","indexOf","computeEntity","computeRTL","hass","lang","translationMetadata","translations","isRTL","computeRTLDirection","computeStateDomain","entity_id","isNumericState","unit_of_measurement","state_class","numberFormatToLocale","localeOptions","number_format","comma_decimal","decimal_comma","space_comma","round","precision","formatNumber","num","options","isNaN","input","none","getDefaultFormatOptions","err","console","error","maximumFractionDigits","toString","currency","defaultOptions","minimumFractionDigits","digits","length","computeStateDisplay","localize","compareState","device_class","_err","domain","date","has_date","has_time","setHours","components","join","toISOString","_e","humidity","DEFAULT_DOMAIN_ICON","DEFAULT_PANEL","DOMAINS_WITH_CARD","DOMAINS_WITH_MORE_INFO","DOMAINS_HIDE_MORE_INFO","DOMAINS_MORE_INFO_NO_HISTORY","STATES_OFF","DOMAINS_TOGGLE","Set","UNIT_C","UNIT_F","DEFAULT_VIEW_ENTITY_ID","fireEvent","node","type","detail","event","Event","bubbles","cancelable","Boolean","composed","dispatchEvent","SPECIAL_TYPES","DOMAIN_TO_ELEMENT_TYPE","alert","automation","climate","cover","fan","group","input_boolean","input_number","input_select","input_text","light","lock","media_player","remote","scene","script","sensor","timer","switch","vacuum","water_heater","input_datetime","createThing","cardConfig","isRow","_createError","config","_createThing","tag","createElement","setConfig","message","startsWith","has","entity","customElements","get","display","setTimeout","whenDefined","then","clearTimeout","debounce","func","wait","immediate","timeout","args","context","this","later","apply","callNow","fixedIcons","calendar","camera","configurator","conversation","device_tracker","history_graph","homeassistant","homekit","image_processing","mailbox","notify","person","plant","proximity","simple_alarm","sun","updater","weblink","domainIcon","warn","evaluateFilter","filter","attribute","operator","match","forwardHaptic","hapticType","navigate","_node","path","replace","history","replaceState","pushState","turnOnOffEntity","turnOn","service","stateDomain","serviceDomain","callService","toggleEntity","states","handleActionConfig","actionConfig","action","confirmation","exemptions","some","e","user","id","confirm","text","camera_image","navigation_path","url_path","open","service_data","target","handleAction","double_tap_action","hold_action","tap_action","handleClick","hold","dblClick","haptic","serviceData","hasAction","hasConfigOrEntityChanged","changedProps","forceUpdate","oldHass","hasDoubleClick","turnOnOffEntities","entityIds","domainsToCall","push","getLovelace","root","shadowRoot","ll","lovelace","current_view","___curView","fixedDeviceClassIcons","illuminance","temperature","pressure","power","signal_strength","domainIcons","binary_sensor","is_off","dclass","battery","batteryRound","stateIcon","icon"],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"index.m.js","sources":["../src/datetime/format_date.ts","../src/types.ts","../src/datetime/use_am_pm.ts","../src/datetime/format_date_time.ts","../src/datetime/format_time.ts","../src/datetime/relative_time.ts","../src/datetime/timer_time_remaining.ts","../src/datetime/duration_to_seconds.ts","../src/apply_themes_on_element.ts","../src/compute-card-size.ts","../src/compute-domain.ts","../src/compute-entity.ts","../src/compute-rtl.ts","../src/compute-state-domain.ts","../src/format-number.ts","../src/compute-state-display.ts","../src/const.ts","../src/fire-event.ts","../src/create-thing.ts","../src/debounce.ts","../src/domain_icons.ts","../src/evaluate-filter.ts","../src/haptic.ts","../src/navigate.ts","../src/turn-on-off-entity.ts","../src/toggle-entity.ts","../src/handle-action.ts","../src/handle-click.ts","../src/has-action.ts","../src/has-changed.ts","../src/has-double-click.ts","../src/turn-on-off-entities.ts","../src/get-lovelace.ts","../src/sensor_icon.ts","../src/state_icon.ts","../src/binary_sensor_icon.ts","../src/cover_icon.ts","../src/input_datetime_icon.ts"],"sourcesContent":["//REF: https://github.com/home-assistant/frontend/blob/dev/src/common/datetime/format_date.ts\n\nimport { FrontendLocaleData } from \"../types\";\n\n/**\n * Formatting a Date to the dddd, mmmm yy format e.g. Tuesday, August 10\n * @param dateObj The date to convert\n * @param locale The users's locale settings\n * @returns date string like \"Tuesday, August 10\"\n */\nexport const formatDateWeekday = (dateObj: Date, locale: FrontendLocaleData) =>\n formatDateWeekdayMem(locale).format(dateObj);\n\nconst formatDateWeekdayMem =\n (locale: FrontendLocaleData) =>\n new Intl.DateTimeFormat(locale.language, {\n weekday: \"long\",\n month: \"long\",\n day: \"numeric\",\n });\n\n/**\n * Formatting a Date to the mmmm dd, yyyy format e.g. August 10, 2021\n * @param dateObj The date to convert\n * @param locale The users's locale settings\n * @returns date string like \"August 10, 2021\"\n */\nexport const formatDate = (dateObj: Date, locale: FrontendLocaleData) =>\n formatDateMem(locale).format(dateObj);\n\nconst formatDateMem =\n (locale: FrontendLocaleData) =>\n new Intl.DateTimeFormat(locale.language, {\n year: \"numeric\",\n month: \"long\",\n day: \"numeric\",\n });\n\n/**\n * Formatting a Date to the classic date format e.g. 10/08/2021\n * @param dateObj The date to convert\n * @param locale The users's locale settings\n * @returns classic date format \"10/08/2021\"\n */\nexport const formatDateNumeric = (dateObj: Date, locale: FrontendLocaleData) =>\n formatDateNumericMem(locale).format(dateObj);\n\nconst formatDateNumericMem =\n (locale: FrontendLocaleData) =>\n new Intl.DateTimeFormat(locale.language, {\n year: \"numeric\",\n month: \"numeric\",\n day: \"numeric\",\n });\n\n\n/**\n * Formatting a Date to just a month with days e.g. Aug 10\n * @param dateObj The date to convert\n * @param locale The users's locale settings\n * @returns month and day like \"Aug 10\"\n */\nexport const formatDateShort = (dateObj: Date, locale: FrontendLocaleData) =>\nformatDateShortMem(locale).format(dateObj);\n\nconst formatDateShortMem =\n(locale: FrontendLocaleData) =>\n new Intl.DateTimeFormat(locale.language, {\n day: \"numeric\",\n month: \"short\",\n });\n\n\n/**\n * Formatting a Date to just a month with year e.g. August 2021\n * @param dateObj The date to convert\n * @param locale The users's locale settings\n * @returns month and year like \"August 2021\"\n */\nexport const formatDateMonthYear = (\ndateObj: Date,\nlocale: FrontendLocaleData\n) => formatDateMonthYearMem(locale).format(dateObj);\n\nconst formatDateMonthYearMem = (locale: FrontendLocaleData) =>\n new Intl.DateTimeFormat(locale.language, {\n month: \"long\",\n year: \"numeric\",\n });\n\n\n/**\n * Formatting a Date to just a month e.g. August\n * @param dateObj The date to convert\n * @param locale The users's locale settings\n * @returns the written out months of the date\n */\nexport const formatDateMonth = (dateObj: Date, locale: FrontendLocaleData) =>\nformatDateMonthMem(locale).format(dateObj);\n\nconst formatDateMonthMem = (locale: FrontendLocaleData) =>\n new Intl.DateTimeFormat(locale.language, {\n month: \"long\",\n });\n\n\n/**\n * Formatting a Date to just a year e.g. 2021\n * @param dateObj The date to convert\n * @param locale The users's locale settings\n * @returns the year of the date in yyyy\n */\nexport const formatDateYear = (dateObj: Date, locale: FrontendLocaleData) =>\nformatDateYearMem(locale).format(dateObj);\n\nconst formatDateYearMem = (locale: FrontendLocaleData) =>\n new Intl.DateTimeFormat(locale.language, {\n year: \"numeric\",\n });\n","import {\n HassEntities,\n HassConfig,\n Auth,\n Connection,\n MessageBase,\n HassServices,\n HassServiceTarget,\n} from \"home-assistant-js-websocket\";\nimport { HapticType } from \"./haptic\";\nimport { HASSDomEvent } from \"./fire-event\";\n\nexport interface ToggleMenuActionConfig extends BaseActionConfig {\n action: \"toggle-menu\";\n}\n\nexport interface ToggleActionConfig extends BaseActionConfig {\n action: \"toggle\";\n}\n\nexport interface CallServiceActionConfig extends BaseActionConfig {\n action: \"call-service\";\n service: string;\n data?: {\n entity_id?: string | [string];\n [key: string]: any;\n };\n\n target?: HassServiceTarget;\n repeat?: number;\n haptic?: HapticType;\n}\n\nexport interface NavigateActionConfig extends BaseActionConfig {\n action: \"navigate\";\n navigation_path: string;\n}\n\nexport interface UrlActionConfig extends BaseActionConfig {\n action: \"url\";\n url_path: string;\n}\n\nexport interface MoreInfoActionConfig extends BaseActionConfig {\n action: \"more-info\";\n entity?: string;\n}\n\nexport interface NoActionConfig extends BaseActionConfig {\n action: \"none\";\n}\n\nexport interface CustomActionConfig extends BaseActionConfig {\n action: \"fire-dom-event\";\n}\n\n/**\n * `repeat` and `haptic` are specifically for use in custom cards like the Button-Card\n */\nexport interface BaseActionConfig {\n confirmation?: ConfirmationRestrictionConfig;\n repeat?: number;\n haptic?: HapticType;\n}\n\nexport interface ConfirmationRestrictionConfig {\n text?: string;\n exemptions?: RestrictionConfig[];\n}\n\nexport interface RestrictionConfig {\n user: string;\n}\n\nexport type ActionConfig =\n | ToggleActionConfig\n | CallServiceActionConfig\n | NavigateActionConfig\n | UrlActionConfig\n | MoreInfoActionConfig\n | NoActionConfig\n | CustomActionConfig\n | ToggleMenuActionConfig;\n\nexport interface Window {\n // Custom panel entry point url\n customPanelJS: string;\n ShadyCSS: {\n nativeCss: boolean;\n nativeShadow: boolean;\n prepareTemplate(templateElement, elementName, elementExtension);\n styleElement(element);\n styleSubtree(element, overrideProperties);\n styleDocument(overrideProperties);\n getComputedStyleValue(element, propertyName);\n };\n}\n\ndeclare global {\n // for fire event\n interface HASSDomEvents {\n \"value-changed\": {\n value: unknown;\n };\n \"config-changed\": {\n config: any;\n };\n \"hass-more-info\": {\n entityId: string | undefined;\n };\n \"ll-rebuild\": {};\n \"ll-custom\": {};\n \"location-changed\": {\n replace: boolean;\n };\n \"show-dialog\": {};\n undefined;\n action: {\n action: string;\n };\n }\n}\n\ntype ValidHassDomEvent = keyof HASSDomEvents;\n\nexport type LocalizeFunc = (key: string, ...args: any[]) => string;\n\nexport interface Credential {\n auth_provider_type: string;\n auth_provider_id: string;\n}\n\nexport interface MFAModule {\n id: string;\n name: string;\n enabled: boolean;\n}\n\nexport interface CurrentUser {\n id: string;\n is_owner: boolean;\n is_admin: boolean;\n name: string;\n credentials: Credential[];\n mfa_modules: MFAModule[];\n}\n\nexport interface Theme {\n // Incomplete\n \"primary-color\": string;\n \"text-primary-color\": string;\n \"accent-color\": string;\n}\n\nexport interface Themes {\n default_theme: string;\n themes: { [key: string]: Theme };\n}\n\nexport interface Panel {\n component_name: string;\n config: { [key: string]: any } | null;\n icon: string | null;\n title: string | null;\n url_path: string;\n}\n\nexport interface Panels {\n [name: string]: Panel;\n}\n\nexport interface Resources {\n [language: string]: { [key: string]: string };\n}\n\nexport interface Translation {\n nativeName: string;\n isRTL: boolean;\n fingerprints: { [fragment: string]: string };\n}\n\nexport interface ServiceCallRequest {\n domain: string;\n service: string;\n serviceData?: Record;\n target?: HassServiceTarget;\n}\n\nexport interface HomeAssistant {\n auth: Auth;\n connection: Connection;\n connected: boolean;\n states: HassEntities;\n services: HassServices;\n config: HassConfig;\n themes: Themes;\n selectedTheme?: string | null;\n panels: Panels;\n panelUrl: string;\n\n // i18n\n // current effective language, in that order:\n // - backend saved user selected lanugage\n // - language in local appstorage\n // - browser language\n // - english (en)\n language: string;\n locale: FrontendLocaleData;\n // local stored language, keep that name for backward compability\n selectedLanguage: string | null;\n resources: Resources;\n localize: LocalizeFunc;\n translationMetadata: {\n fragments: string[];\n translations: {\n [lang: string]: Translation;\n };\n };\n\n dockedSidebar: boolean;\n moreInfoEntityId: string;\n user: CurrentUser;\n callService: (\n domain: ServiceCallRequest[\"domain\"],\n service: ServiceCallRequest[\"service\"],\n serviceData?: ServiceCallRequest[\"serviceData\"],\n target?: ServiceCallRequest[\"target\"]\n ) => Promise;\n callApi: (\n method: \"GET\" | \"POST\" | \"PUT\" | \"DELETE\",\n path: string,\n parameters?: { [key: string]: any }\n ) => Promise;\n fetchWithAuth: (\n path: string,\n init?: { [key: string]: any }\n ) => Promise;\n sendWS: (msg: MessageBase) => Promise;\n callWS: (msg: MessageBase) => Promise;\n}\n\nexport enum NumberFormat {\n language = \"language\",\n system = \"system\",\n comma_decimal = \"comma_decimal\",\n decimal_comma = \"decimal_comma\",\n space_comma = \"space_comma\",\n none = \"none\",\n}\n\nexport enum TimeFormat {\n language = \"language\",\n system = \"system\",\n am_pm = \"12\",\n twenty_four = \"24\",\n}\n\nexport interface FrontendLocaleData {\n language: string;\n number_format: NumberFormat;\n time_format: TimeFormat;\n}\n\nexport interface LovelaceCardConfig {\n index?: number;\n view_index?: number;\n type: string;\n [key: string]: any;\n}\n\nexport interface LovelaceCard extends HTMLElement {\n hass?: HomeAssistant;\n isPanel?: boolean;\n editMode?: boolean;\n getCardSize(): number | Promise;\n setConfig(config: LovelaceCardConfig): void;\n}\n\nexport interface LovelaceCardEditor extends HTMLElement {\n hass?: HomeAssistant;\n lovelace?: LovelaceConfig;\n setConfig(config: LovelaceCardConfig): void;\n}\n\nexport interface LovelaceConfig {\n title?: string;\n views: LovelaceViewConfig[];\n background?: string;\n}\n\nexport interface LovelaceViewConfig {\n index?: number;\n title?: string;\n badges?: Array;\n cards?: LovelaceCardConfig[];\n path?: string;\n icon?: string;\n theme?: string;\n panel?: boolean;\n background?: string;\n visible?: boolean | ShowViewConfig[];\n}\n\nexport interface ShowViewConfig {\n user?: string;\n}\n\nexport interface LovelaceBadgeConfig {\n type?: string;\n [key: string]: any;\n}\n\nexport interface ActionHandlerDetail {\n action: string;\n}\n\nexport type ActionHandlerEvent = HASSDomEvent;\n\nexport interface ActionHandlerOptions {\n hasHold?: boolean;\n hasDoubleClick?: boolean;\n}\n\nexport interface EntitiesCardEntityConfig extends EntityConfig {\n type?: string;\n secondary_info?:\n | \"entity-id\"\n | \"last-changed\"\n | \"last-triggered\"\n | \"last-updated\"\n | \"position\"\n | \"tilt-position\"\n | \"brightness\";\n action_name?: string;\n service?: string;\n data?: Record;\n url?: string;\n tap_action?: ActionConfig;\n hold_action?: ActionConfig;\n double_tap_action?: ActionConfig;\n state_color?: boolean;\n show_name?: boolean;\n show_icon?: boolean;\n}\n\nexport interface EntityConfig {\n entity: string;\n type?: string;\n name?: string;\n icon?: string;\n image?: string;\n}\n\nexport interface LovelaceElementConfigBase {\n type: string;\n style: Record;\n}\n","// REF: https://github.com/home-assistant/frontend/blob/dev/src/common/datetime/use_am_pm.ts\r\n\r\nimport { FrontendLocaleData, TimeFormat } from \"../types\"\r\n\r\n/**\r\n * Checking if AM/PM time format is used within the browser.\r\n * @param locale Homeassistant frontend locale data\r\n * @returns \r\n */\r\nexport const useAmPm = (locale: FrontendLocaleData): boolean => {\r\n if (\r\n locale.time_format === TimeFormat.language ||\r\n locale.time_format === TimeFormat.system\r\n ) {\r\n const testLanguage =\r\n locale.time_format === TimeFormat.language ? locale.language : undefined;\r\n const test = new Date().toLocaleString(testLanguage);\r\n return test.includes(\"AM\") || test.includes(\"PM\");\r\n }\r\n\r\n return locale.time_format === TimeFormat.am_pm;\r\n};\r\n","//REF: https://github.com/home-assistant/frontend/blob/dev/src/common/datetime/format_date_time.ts\n\nimport { FrontendLocaleData } from \"../types\";\nimport { useAmPm } from \"./use_am_pm\";\n\n// August 9, 2021, 8:23 AM\n/**\n * Formatting a dateObject to date with time e.g. August 9, 2021, 8:23 AM\n * @param dateObj The date to convert\n * @param locale The users's locale settings\n * @returns month and day like \"August 9, 2021, 8:23 AM\"\n */\nexport const formatDateTime = (dateObj: Date, locale: FrontendLocaleData) =>\n formatDateTimeMem(locale).format(dateObj);\n\nconst formatDateTimeMem = (locale: FrontendLocaleData) =>\n new Intl.DateTimeFormat(locale.language, {\n year: \"numeric\",\n month: \"long\",\n day: \"numeric\",\n hour: useAmPm(locale) ? \"numeric\" : \"2-digit\",\n minute: \"2-digit\",\n hour12: useAmPm(locale),\n });\n\n\n/**\n * Formatting a dateObject to date with time e.g. August 9, 2021, 8:23:15 AM\n * @param dateObj The date to convert\n * @param locale The users's locale settings\n * @returns month and day like \"August 9, 2021, 8:23:15 AM\"\n */\nexport const formatDateTimeWithSeconds = (\n dateObj: Date,\n locale: FrontendLocaleData\n) => formatDateTimeWithSecondsMem(locale).format(dateObj);\n\nconst formatDateTimeWithSecondsMem =\n (locale: FrontendLocaleData) =>\n new Intl.DateTimeFormat(locale.language, {\n year: \"numeric\",\n month: \"long\",\n day: \"numeric\",\n hour: useAmPm(locale) ? \"numeric\" : \"2-digit\",\n minute: \"2-digit\",\n second: \"2-digit\",\n hour12: useAmPm(locale),\n });\n\n/**\n * Formatting a Date to just date with AM/PM time e.g. 9/8/2021, 8:23 AM\n * @param dateObj The date to convert\n * @param locale The users's locale settings\n * @returns month and day like \"9/8/2021, 8:23 AM\"\n */\nexport const formatDateTimeNumeric = (\n dateObj: Date,\n locale: FrontendLocaleData\n) => formatDateTimeNumericMem(locale).format(dateObj);\n\nconst formatDateTimeNumericMem =\n (locale: FrontendLocaleData) =>\n new Intl.DateTimeFormat(locale.language, {\n year: \"numeric\",\n month: \"numeric\",\n day: \"numeric\",\n hour: \"numeric\",\n minute: \"2-digit\",\n hour12: useAmPm(locale),\n });","//REF: https://github.com/home-assistant/frontend/blob/dev/src/common/datetime/format_time.ts\n\nimport { FrontendLocaleData } from \"../types\";\nimport { useAmPm } from \"./use_am_pm\";\n\n/**\n * 9:15 PM or 21:15\n * @param dateObj The time to convert\n * @param locale The users's locale settings\n * @returns Reformated time in hh:mm\n */\n export const formatTime = (dateObj: Date, locale: FrontendLocaleData) =>\n formatTimeMem(locale).format(dateObj);\n\n const formatTimeMem =\n (locale: FrontendLocaleData) =>\n new Intl.DateTimeFormat(locale.language, {\n hour: \"numeric\",\n minute: \"2-digit\",\n hour12: useAmPm(locale),\n });\n\n/**\n* 9:15:24 PM or 21:15:24\n* @param dateObj The time to convert\n* @param locale The users's locale settings\n* @returns Reformated time in hh:mm:ss\n*/\nexport const formatTimeWithSeconds = (\n dateObj: Date,\n locale: FrontendLocaleData\n) => formatTimeWithSecondsMem(locale).format(dateObj);\n\nconst formatTimeWithSecondsMem =\n (locale: FrontendLocaleData) =>\n new Intl.DateTimeFormat(locale.language, {\n hour: useAmPm(locale) ? \"numeric\" : \"2-digit\",\n minute: \"2-digit\",\n second: \"2-digit\",\n hour12: useAmPm(locale),\n });\n\n/**\n* Tuesday 7:00 PM or Tuesday 19:00\n* @param dateObj The datetime to convert\n* @param locale The users's locale settings\n* @returns Reformated weekday/time in dddd hh:mm\n*/\nexport const formatTimeWeekday = (dateObj: Date, locale: FrontendLocaleData) =>\n formatTimeWeekdayMem(locale).format(dateObj);\n\nconst formatTimeWeekdayMem =\n (locale: FrontendLocaleData) =>\n new Intl.DateTimeFormat(locale.language, {\n hour: useAmPm(locale) ? \"numeric\" : \"2-digit\",\n minute: \"2-digit\",\n second: \"2-digit\",\n hour12: useAmPm(locale),\n }); \n","//REF: https://github.com/home-assistant/frontend/blob/dev/src/common/datetime/relative_time.ts\n\nimport { selectUnit } from \"@formatjs/intl-utils\";\nimport { FrontendLocaleData } from \"../types\";\n\n const formatRelTimeMem =\n (locale: FrontendLocaleData) =>\n new Intl.RelativeTimeFormat(locale.language, { numeric: \"auto\" });\n\n/**\n * Calculate a string representing a date object as relative time from now.\n *\n * Example output: 5 minutes ago, in 3 days.\n */\n export const relativeTime = (\n from: Date,\n locale: FrontendLocaleData,\n to?: Date,\n includeTense = true\n): string => {\n const diff = selectUnit(from, to);\n if (includeTense) {\n return formatRelTimeMem(locale).format(diff.value, diff.unit);\n }\n return Intl.NumberFormat(locale.language, {\n style: \"unit\",\n unit: diff.unit,\n unitDisplay: \"long\",\n }).format(Math.abs(diff.value));\n};\n","import { HassEntity } from \"home-assistant-js-websocket\";\nimport durationToSeconds from \"../datetime/duration_to_seconds\";\n\nexport function timerTimeRemaining(stateObj: HassEntity) {\n let timeRemaining = durationToSeconds(stateObj.attributes.remaining);\n\n if (stateObj.state === \"active\") {\n const now = new Date().getTime();\n const madeActive = new Date(stateObj.last_changed).getTime();\n timeRemaining = Math.max(timeRemaining - (now - madeActive) / 1000, 0);\n }\n\n return timeRemaining;\n}\n","/**\n * Convert a Duration hh:mm:ss format to seconds\n * @param duration hh:mm:ss formated duration\n * @returns duration in seconds\n */\n export default function durationToSeconds(duration: string): number {\n const parts = duration.split(\":\").map(Number);\n return parts[0] * 3600 + parts[1] * 60 + parts[2];\n}\n","/**\n * Apply a theme to an element by setting the CSS variables on it.\n *\n * element: Element to apply theme on.\n * themes: HASS Theme information\n * localTheme: selected theme.\n * updateMeta: boolean if we should update the theme-color meta element.\n */\nexport const applyThemesOnElement = (\n element,\n themes,\n localTheme,\n updateMeta = false\n) => {\n if (!element._themes) {\n element._themes = {};\n }\n let themeName = themes.default_theme;\n if (localTheme === \"default\" || (localTheme && themes.themes[localTheme])) {\n themeName = localTheme;\n }\n const styles = { ...element._themes };\n if (themeName !== \"default\") {\n const theme = themes.themes[themeName];\n Object.keys(theme).forEach((key) => {\n const prefixedKey = \"--\" + key;\n element._themes[prefixedKey] = \"\";\n styles[prefixedKey] = theme[key];\n });\n }\n if (element.updateStyles) {\n element.updateStyles(styles);\n } else if ((window as any).ShadyCSS) {\n // implement updateStyles() method of Polemer elements\n (window as any).ShadyCSS.styleSubtree(/** @type {!HTMLElement} */ (element), styles);\n }\n\n if (!updateMeta) {\n return;\n }\n\n const meta = document.querySelector(\"meta[name=theme-color]\");\n if (meta) {\n if (!meta.hasAttribute(\"default-content\")) {\n meta.setAttribute(\"default-content\", meta.getAttribute(\"content\")!);\n }\n const themeColor =\n styles[\"--primary-color\"] || meta.getAttribute(\"default-content\");\n meta.setAttribute(\"content\", themeColor);\n }\n}\n","import { LovelaceCard } from \"./types\";\n\nexport const computeCardSize = (card: LovelaceCard): number | Promise => {\n return typeof card.getCardSize === \"function\" ? card.getCardSize() : 4;\n};","export function computeDomain(entityId: string): string {\n return entityId.substr(0, entityId.indexOf(\".\"));\n}\n","export function computeEntity(entityId: string): string {\n return entityId.substr(entityId.indexOf(\".\") + 1);\n}\n","import { HomeAssistant } from \"./types\";\n\nexport function computeRTL(hass: HomeAssistant) {\n const lang = hass?.locale?.language || \"en\";\n if (hass.translationMetadata.translations[lang]) {\n return hass.translationMetadata.translations[lang].isRTL || false;\n }\n return false;\n}\n\nexport function computeRTLDirection(hass: HomeAssistant) {\n return computeRTL(hass) ? \"rtl\" : \"ltr\";\n}\n","import { HassEntity } from \"home-assistant-js-websocket\";\nimport { computeDomain } from \"./compute-domain\";\n\nexport function computeStateDomain(stateObj: HassEntity) {\n return computeDomain(stateObj.entity_id);\n}\n","//REF: https://github.com/home-assistant/frontend/blob/dev/src/common/number/format_number.ts\n\nimport { HassEntity } from \"home-assistant-js-websocket\";\nimport { FrontendLocaleData, NumberFormat } from \"./types\";\n\n/**\n * Returns true if the entity is considered numeric based on the attributes it has\n * @param stateObj The entity state object\n */\n export const isNumericState = (stateObj: HassEntity): boolean =>\n !!stateObj.attributes.unit_of_measurement ||\n !!stateObj.attributes.state_class;\n\nexport const numberFormatToLocale = (\n localeOptions: FrontendLocaleData\n): string | string[] | undefined => {\n switch (localeOptions.number_format) {\n case NumberFormat.comma_decimal:\n return [\"en-US\", \"en\"]; // Use United States with fallback to English formatting 1,234,567.89\n case NumberFormat.decimal_comma:\n return [\"de\", \"es\", \"it\"]; // Use German with fallback to Spanish then Italian formatting 1.234.567,89\n case NumberFormat.space_comma:\n return [\"fr\", \"sv\", \"cs\"]; // Use French with fallback to Swedish and Czech formatting 1 234 567,89\n case NumberFormat.system:\n return undefined;\n default:\n return localeOptions.language;\n }\n};\n\nexport const round = (value: number, precision = 2): number =>\n Math.round(value * 10 ** precision) / 10 ** precision;\n\n/**\n * Formats a number based on the specified language with thousands separator(s) and decimal character for better legibility.\n * @param num The number to format\n * @param locale The user-selected language and number format, from `hass.locale`\n * @param options Intl.NumberFormatOptions to use\n */\nexport const formatNumber = (\n num: string | number,\n localeOptions?: FrontendLocaleData,\n options?: Intl.NumberFormatOptions\n): string => {\n const locale = localeOptions\n ? numberFormatToLocale(localeOptions)\n : undefined;\n\n // Polyfill for Number.isNaN, which is more reliable than the global isNaN()\n Number.isNaN =\n Number.isNaN ||\n function isNaN(input) {\n return typeof input === \"number\" && isNaN(input);\n };\n\n if (\n localeOptions?.number_format !== NumberFormat.none &&\n !Number.isNaN(Number(num)) &&\n Intl\n ) {\n try {\n return new Intl.NumberFormat(\n locale,\n getDefaultFormatOptions(num, options)\n ).format(Number(num));\n } catch (err: any) {\n // Don't fail when using \"TEST\" language\n // eslint-disable-next-line no-console\n console.error(err);\n return new Intl.NumberFormat(\n undefined,\n getDefaultFormatOptions(num, options)\n ).format(Number(num));\n }\n }\n if (typeof num === \"string\") {\n return num;\n }\n return `${round(num, options?.maximumFractionDigits).toString()}${\n options?.style === \"currency\" ? ` ${options.currency}` : \"\"\n }`;\n};\n\n/**\n * Generates default options for Intl.NumberFormat\n * @param num The number to be formatted\n * @param options The Intl.NumberFormatOptions that should be included in the returned options\n */\nconst getDefaultFormatOptions = (\n num: string | number,\n options?: Intl.NumberFormatOptions\n): Intl.NumberFormatOptions => {\n const defaultOptions: Intl.NumberFormatOptions = {\n maximumFractionDigits: 2,\n ...options,\n };\n\n if (typeof num !== \"string\") {\n return defaultOptions;\n }\n\n // Keep decimal trailing zeros if they are present in a string numeric value\n if (\n !options ||\n (!options.minimumFractionDigits && !options.maximumFractionDigits)\n ) {\n const digits = num.indexOf(\".\") > -1 ? num.split(\".\")[1].length : 0;\n defaultOptions.minimumFractionDigits = digits;\n defaultOptions.maximumFractionDigits = digits;\n }\n\n return defaultOptions;\n};\n","import { HassEntity } from \"home-assistant-js-websocket\";\nimport { formatDateTime } from \"./datetime/format_date_time\";\nimport { formatDate } from \"./datetime/format_date\";\nimport { formatTime } from \"./datetime/format_time\";\nimport { LocalizeFunc } from \"./translations/localize\";\nimport { computeStateDomain } from \"./compute-state-domain\";\nimport { FrontendLocaleData } from \"./types\";\nimport { formatNumber, isNumericState } from \"./format-number\";\n\nexport const computeStateDisplay = (\n localize: LocalizeFunc,\n stateObj: HassEntity,\n locale: FrontendLocaleData,\n state?: string\n): string => {\n const compareState = state !== undefined ? state : stateObj.state;\n\n if (compareState === \"unknown\" || compareState === \"unavailable\") {\n return localize(`state.default.${compareState}`);\n }\n\n // Entities with a `unit_of_measurement` or `state_class` are numeric values and should use `formatNumber`\n if (isNumericState(stateObj)) {\n if (stateObj.attributes.device_class === \"monetary\") {\n try {\n return formatNumber(compareState, locale, {\n style: \"currency\",\n currency: stateObj.attributes.unit_of_measurement,\n });\n } catch (_err) {\n // fallback to default\n }\n }\n return `${formatNumber(compareState, locale)}${\n stateObj.attributes.unit_of_measurement\n ? \" \" + stateObj.attributes.unit_of_measurement\n : \"\"\n }`;\n }\n\n const domain = computeStateDomain(stateObj);\n\n if (domain === \"input_datetime\") {\n if (state !== undefined) {\n // If trying to display an explicit state, need to parse the explict state to `Date` then format.\n // Attributes aren't available, we have to use `state`.\n try {\n const components = state.split(\" \");\n if (components.length === 2) {\n // Date and time.\n return formatDateTime(new Date(components.join(\"T\")), locale);\n }\n if (components.length === 1) {\n if (state.includes(\"-\")) {\n // Date only.\n return formatDate(new Date(`${state}T00:00`), locale);\n }\n if (state.includes(\":\")) {\n // Time only.\n const now = new Date();\n return formatTime(\n new Date(`${now.toISOString().split(\"T\")[0]}T${state}`),\n locale\n );\n }\n }\n return state;\n } catch (_e) {\n // Formatting methods may throw error if date parsing doesn't go well,\n // just return the state string in that case.\n return state;\n }\n } else {\n // If not trying to display an explicit state, create `Date` object from `stateObj`'s attributes then format.\n let date: Date;\n if (stateObj.attributes.has_date && stateObj.attributes.has_time) {\n date = new Date(\n stateObj.attributes.year,\n stateObj.attributes.month - 1,\n stateObj.attributes.day,\n stateObj.attributes.hour,\n stateObj.attributes.minute\n );\n return formatDateTime(date, locale);\n }\n if (stateObj.attributes.has_date) {\n date = new Date(\n stateObj.attributes.year,\n stateObj.attributes.month - 1,\n stateObj.attributes.day\n );\n return formatDate(date, locale);\n }\n if (stateObj.attributes.has_time) {\n date = new Date();\n date.setHours(stateObj.attributes.hour, stateObj.attributes.minute);\n return formatTime(date, locale);\n }\n return stateObj.state;\n }\n }\n\n if (domain === \"humidifier\") {\n if (compareState === \"on\" && stateObj.attributes.humidity) {\n return `${stateObj.attributes.humidity} %`;\n }\n }\n\n // `counter` `number` and `input_number` domains do not have a unit of measurement but should still use `formatNumber`\n if (\n domain === \"counter\" ||\n domain === \"number\" ||\n domain === \"input_number\"\n ) {\n return formatNumber(compareState, locale);\n }\n\n return (\n // Return device class translation\n (stateObj.attributes.device_class &&\n localize(\n `component.${domain}.state.${stateObj.attributes.device_class}.${compareState}`\n )) ||\n // Return default translation\n localize(`component.${domain}.state._.${compareState}`) ||\n // We don't know! Return the raw state.\n compareState\n );\n};","/** Constants to be used in the frontend. */\n\n// Constants should be alphabetically sorted by name.\n// Arrays with values should be alphabetically sorted if order doesn't matter.\n// Each constant should have a description what it is supposed to be used for.\n\n/** Icon to use when no icon specified for domain. */\nexport const DEFAULT_DOMAIN_ICON = \"mdi:bookmark\";\n\n/** Panel to show when no panel is picked. */\nexport const DEFAULT_PANEL = \"lovelace\";\n\n/** Domains that have a state card. */\nexport const DOMAINS_WITH_CARD = [\n \"climate\",\n \"cover\",\n \"configurator\",\n \"input_select\",\n \"input_number\",\n \"input_text\",\n \"lock\",\n \"media_player\",\n \"scene\",\n \"script\",\n \"timer\",\n \"vacuum\",\n \"water_heater\",\n \"weblink\"\n];\n\n/** Domains with separate more info dialog. */\nexport const DOMAINS_WITH_MORE_INFO = [\n \"alarm_control_panel\",\n \"automation\",\n \"camera\",\n \"climate\",\n \"configurator\",\n \"cover\",\n \"fan\",\n \"group\",\n \"history_graph\",\n \"input_datetime\",\n \"light\",\n \"lock\",\n \"media_player\",\n \"script\",\n \"sun\",\n \"updater\",\n \"vacuum\",\n \"water_heater\",\n \"weather\"\n];\n\n/** Domains that show no more info dialog. */\nexport const DOMAINS_HIDE_MORE_INFO = [\n \"input_number\",\n \"input_select\",\n \"input_text\",\n \"scene\",\n \"weblink\"\n];\n\n/** Domains that should have the history hidden in the more info dialog. */\nexport const DOMAINS_MORE_INFO_NO_HISTORY = [\n \"camera\",\n \"configurator\",\n \"history_graph\",\n \"scene\"\n];\n\n/** States that we consider \"off\". */\nexport const STATES_OFF = [\"closed\", \"locked\", \"off\"];\n\n/** Domains where we allow toggle in Lovelace. */\nexport const DOMAINS_TOGGLE = new Set([\n \"fan\",\n \"input_boolean\",\n \"light\",\n \"switch\",\n \"group\",\n \"automation\"\n]);\n\n/** Temperature units. */\nexport const UNIT_C = \"°C\";\nexport const UNIT_F = \"°F\";\n\n/** Entity ID of the default view. */\nexport const DEFAULT_VIEW_ENTITY_ID = \"group.default_view\";\n","// Polymer legacy event helpers used courtesy of the Polymer project.\n//\n// Copyright (c) 2017 The Polymer Authors. All rights reserved.\n//\n// Redistribution and use in source and binary forms, with or without\n// modification, are permitted provided that the following conditions are\n// met:\n//\n// * Redistributions of source code must retain the above copyright\n// notice, this list of conditions and the following disclaimer.\n// * Redistributions in binary form must reproduce the above\n// copyright notice, this list of conditions and the following disclaimer\n// in the documentation and/or other materials provided with the\n// distribution.\n// * Neither the name of Google Inc. nor the names of its\n// contributors may be used to endorse or promote products derived from\n// this software without specific prior written permission.\n//\n// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n// \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\ndeclare global {\n // tslint:disable-next-line\n interface HASSDomEvents {}\n}\n\nexport type ValidHassDomEvent = keyof HASSDomEvents;\n\nexport interface HASSDomEvent extends Event {\n detail: T;\n}\n\n/**\n * Dispatches a custom event with an optional detail value.\n *\n * @param {string} type Name of event type.\n * @param {*=} detail Detail value containing event-specific\n * payload.\n * @param {{ bubbles: (boolean|undefined),\n * cancelable: (boolean|undefined),\n * composed: (boolean|undefined) }=}\n * options Object specifying options. These may include:\n * `bubbles` (boolean, defaults to `true`),\n * `cancelable` (boolean, defaults to false), and\n * `node` on which to fire the event (HTMLElement, defaults to `this`).\n * @return {Event} The new event that was fired.\n */\nexport const fireEvent = (\n node: HTMLElement | Window,\n type: HassEvent,\n detail?: HASSDomEvents[HassEvent],\n options?: {\n bubbles?: boolean;\n cancelable?: boolean;\n composed?: boolean;\n }\n) => {\n options = options || {};\n // @ts-ignore\n detail = detail === null || detail === undefined ? {} : detail;\n const event = new Event(type, {\n bubbles: options.bubbles === undefined ? true : options.bubbles,\n cancelable: Boolean(options.cancelable),\n composed: options.composed === undefined ? true : options.composed\n });\n (event as any).detail = detail;\n node.dispatchEvent(event);\n return event;\n};\n","import { fireEvent } from \"./fire-event\";\n\nconst SPECIAL_TYPES = new Set([\n \"call-service\",\n \"divider\",\n \"section\",\n \"weblink\",\n \"cast\",\n \"select\"\n]);\nconst DOMAIN_TO_ELEMENT_TYPE = {\n alert: \"toggle\",\n automation: \"toggle\",\n climate: \"climate\",\n cover: \"cover\",\n fan: \"toggle\",\n group: \"group\",\n input_boolean: \"toggle\",\n input_number: \"input-number\",\n input_select: \"input-select\",\n input_text: \"input-text\",\n light: \"toggle\",\n lock: \"lock\",\n media_player: \"media-player\",\n remote: \"toggle\",\n scene: \"scene\",\n script: \"script\",\n sensor: \"sensor\",\n timer: \"timer\",\n switch: \"toggle\",\n vacuum: \"toggle\",\n // Temporary. Once climate is rewritten,\n // water heater should get it's own row.\n water_heater: \"climate\",\n input_datetime: \"input-datetime\"\n};\n\nexport const createThing = (cardConfig, isRow = false) => {\n const _createError = (error, config) => {\n return _createThing(\n \"hui-error-card\",\n {\n type: \"error\",\n error,\n config\n }\n );\n };\n\n const _createThing = (tag, config) => {\n const element = window.document.createElement(tag);\n try {\n // Preventing an error-card infinity loop: https://github.com/custom-cards/custom-card-helpers/issues/54\n if (!element.setConfig) return;\n element.setConfig(config);\n } catch (err) {\n console.error(tag, err);\n return _createError((err as Error).message, config);\n }\n return element;\n };\n\n if (!cardConfig || typeof cardConfig !== \"object\" || (!isRow && !cardConfig.type))\n return _createError(\"No type defined\", cardConfig);\n let tag = cardConfig.type;\n if (tag && tag.startsWith(\"custom:\")) {\n tag = tag.substr(\"custom:\".length);\n } else if (isRow) {\n if (SPECIAL_TYPES.has(tag)) {\n tag = `hui-${tag}-row`;\n } else {\n if (!cardConfig.entity) {\n return _createError(\"Invalid config given.\", cardConfig);\n }\n \n const domain = cardConfig.entity.split(\".\", 1)[0];\n tag = `hui-${DOMAIN_TO_ELEMENT_TYPE[domain] || \"text\"}-entity-row`;\n }\n } else {\n tag = `hui-${tag}-card`;\n }\n\n if (customElements.get(tag)) return _createThing(tag, cardConfig);\n\n // If element doesn't exist (yet) create an error\n const element = _createError(\n `Custom element doesn't exist: ${cardConfig.type}.`,\n cardConfig\n );\n element.style.display = \"None\";\n const timer = setTimeout(() => {\n element.style.display = \"\";\n }, 2000);\n // Remove error if element is defined later\n customElements.whenDefined(cardConfig.type).then(() => {\n clearTimeout(timer);\n fireEvent(element, \"ll-rebuild\", {}, element);\n });\n\n return element;\n};\n","/**\r\n * Returns a function, that, as long as it continues to be invoked, will not be triggered. It will be called after it stops being called for `wait` ms.\r\n * This can be usefull for ResizeObservers for example.\r\n * @param func The function you want to debounce\r\n * @param wait Period to wait in ms\r\n * @param immediate Triggering on the leading edge instead of the trailing\r\n * @returns Debounced Function\r\n */\r\n// eslint-disable-next-line: ban-types\r\nexport const debounce = unknown>(\r\n func: T,\r\n wait: number,\r\n immediate = false\r\n): T => {\r\n let timeout;\r\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\r\n // @ts-ignore\r\n return function (...args) {\r\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\r\n // @ts-ignore\r\n // eslint-disable-next-line @typescript-eslint/no-this-alias\r\n const context = this;\r\n const later = () => {\r\n timeout = null;\r\n if (!immediate) {\r\n func.apply(context, args);\r\n }\r\n };\r\n const callNow = immediate && !timeout;\r\n clearTimeout(timeout);\r\n timeout = setTimeout(later, wait);\r\n if (callNow) {\r\n func.apply(context, args);\r\n }\r\n };\r\n};\r\n","/**\n * Return the icon to be used for a domain.\n *\n * Optionally pass in a state to influence the domain icon.\n */\nimport { DEFAULT_DOMAIN_ICON } from \"./const\";\n\nexport const fixedIcons = {\n alert: \"mdi:alert\",\n automation: \"mdi:playlist-play\",\n calendar: \"mdi:calendar\",\n camera: \"mdi:video\",\n climate: \"mdi:thermostat\",\n configurator: \"mdi:settings\",\n conversation: \"mdi:text-to-speech\",\n device_tracker: \"mdi:account\",\n fan: \"mdi:fan\",\n group: \"mdi:google-circles-communities\",\n history_graph: \"mdi:chart-line\",\n homeassistant: \"mdi:home-assistant\",\n homekit: \"mdi:home-automation\",\n image_processing: \"mdi:image-filter-frames\",\n input_boolean: \"mdi:drawing\",\n input_datetime: \"mdi:calendar-clock\",\n input_number: \"mdi:ray-vertex\",\n input_select: \"mdi:format-list-bulleted\",\n input_text: \"mdi:textbox\",\n light: \"mdi:lightbulb\",\n mailbox: \"mdi:mailbox\",\n notify: \"mdi:comment-alert\",\n person: \"mdi:account\",\n plant: \"mdi:flower\",\n proximity: \"mdi:apple-safari\",\n remote: \"mdi:remote\",\n scene: \"mdi:google-pages\",\n script: \"mdi:file-document\",\n sensor: \"mdi:eye\",\n simple_alarm: \"mdi:bell\",\n sun: \"mdi:white-balance-sunny\",\n switch: \"mdi:flash\",\n timer: \"mdi:timer\",\n updater: \"mdi:cloud-upload\",\n vacuum: \"mdi:robot-vacuum\",\n water_heater: \"mdi:thermometer\",\n weblink: \"mdi:open-in-new\"\n};\n\nexport function domainIcon(domain: string, state?: string): string {\n if (domain in fixedIcons) {\n return fixedIcons[domain];\n }\n\n switch (domain) {\n case \"alarm_control_panel\":\n switch (state) {\n case \"armed_home\":\n return \"mdi:bell-plus\";\n case \"armed_night\":\n return \"mdi:bell-sleep\";\n case \"disarmed\":\n return \"mdi:bell-outline\";\n case \"triggered\":\n return \"mdi:bell-ring\";\n default:\n return \"mdi:bell\";\n }\n\n case \"binary_sensor\":\n return state && state === \"off\"\n ? \"mdi:radiobox-blank\"\n : \"mdi:checkbox-marked-circle\";\n\n case \"cover\":\n return state === \"closed\" ? \"mdi:window-closed\" : \"mdi:window-open\";\n\n case \"lock\":\n return state && state === \"unlocked\" ? \"mdi:lock-open\" : \"mdi:lock\";\n\n case \"media_player\":\n return state && state !== \"off\" && state !== \"idle\"\n ? \"mdi:cast-connected\"\n : \"mdi:cast\";\n\n case \"zwave\":\n switch (state) {\n case \"dead\":\n return \"mdi:emoticon-dead\";\n case \"sleeping\":\n return \"mdi:sleep\";\n case \"initializing\":\n return \"mdi:timer-sand\";\n default:\n return \"mdi:z-wave\";\n }\n\n default:\n // tslint:disable-next-line\n console.warn(\n \"Unable to find icon for domain \" + domain + \" (\" + state + \")\"\n );\n return DEFAULT_DOMAIN_ICON;\n }\n}\n","import { HassEntity } from \"home-assistant-js-websocket\";\n\nexport const evaluateFilter = (stateObj: HassEntity, filter: any): boolean => {\n const operator = filter.operator || \"==\";\n const value = filter.value || filter;\n const state = filter.attribute\n ? stateObj.attributes[filter.attribute]\n : stateObj.state;\n\n switch (operator) {\n case \"==\":\n return state === value;\n case \"<=\":\n return state <= value;\n case \"<\":\n return state < value;\n case \">=\":\n return state >= value;\n case \">\":\n return state > value;\n case \"!=\":\n return state !== value;\n case \"regex\": {\n return state.match(value);\n }\n default:\n return false;\n }\n};\n","import { HASSDomEvent, fireEvent } from \"./fire-event\";\n\n/**\n * Broadcast haptic feedback requests\n */\n\n\n// Allowed types are from iOS HIG.\n// https://developer.apple.com/design/human-interface-guidelines/ios/user-interaction/feedback/#haptics\n// Implementors on platforms other than iOS should attempt to match the patterns (shown in HIG) as closely as possible.\nexport type HapticType =\n | \"success\"\n | \"warning\"\n | \"failure\"\n | \"light\"\n | \"medium\"\n | \"heavy\"\n | \"selection\";\n\ndeclare global {\n // for fire event\n interface HASSDomEvents {\n haptic: HapticType;\n }\n\n interface GlobalEventHandlersEventMap {\n haptic: HASSDomEvent;\n }\n}\n\nexport const forwardHaptic = (hapticType: HapticType) => {\n fireEvent(window, \"haptic\", hapticType);\n};\n","import { fireEvent } from \"./fire-event\";\n\ndeclare global {\n // for fire event\n interface HASSDomEvents {\n \"location-changed\": {\n replace: boolean;\n };\n }\n}\n\nexport const navigate = (\n _node: any,\n path: string,\n replace: boolean = false\n) => {\n if (replace) {\n history.replaceState(null, \"\", path);\n } else {\n history.pushState(null, \"\", path);\n }\n fireEvent(window, \"location-changed\", {\n replace\n });\n};\n","import { HomeAssistant } from \"./types\";\nimport { computeDomain } from \"./compute-domain\";\n\nexport const turnOnOffEntity = (\n hass: HomeAssistant,\n entityId: string,\n turnOn = true\n): Promise => {\n const stateDomain = computeDomain(entityId);\n const serviceDomain = stateDomain === \"group\" ? \"homeassistant\" : stateDomain;\n\n let service;\n switch (stateDomain) {\n case \"lock\":\n service = turnOn ? \"unlock\" : \"lock\";\n break;\n case \"cover\":\n service = turnOn ? \"open_cover\" : \"close_cover\";\n break;\n default:\n service = turnOn ? \"turn_on\" : \"turn_off\";\n }\n\n return hass.callService(serviceDomain, service, { entity_id: entityId });\n};\n","import { STATES_OFF } from \"./const\";\nimport { turnOnOffEntity } from \"./turn-on-off-entity\";\nimport { HomeAssistant } from \"./types\";\n\nexport const toggleEntity = (\n hass: HomeAssistant,\n entityId: string\n): Promise => {\n const turnOn = STATES_OFF.includes(hass.states[entityId].state);\n return turnOnOffEntity(hass, entityId, turnOn);\n};\n","import { HomeAssistant, ActionConfig } from \"./types\";\nimport { forwardHaptic } from \"./haptic\";\nimport { fireEvent } from \"./fire-event\";\nimport { navigate } from \"./navigate\";\nimport { toggleEntity } from \"./toggle-entity\";\n\nexport const handleActionConfig = (\n node: HTMLElement,\n hass: HomeAssistant,\n config: {\n entity?: string;\n camera_image?: string;\n hold_action?: ActionConfig;\n tap_action?: ActionConfig;\n double_tap_action?: ActionConfig;\n },\n actionConfig: ActionConfig | undefined\n): void => {\n if (!actionConfig) {\n actionConfig = {\n action: \"more-info\",\n };\n }\n\n if (\n actionConfig.confirmation &&\n (!actionConfig.confirmation.exemptions ||\n !actionConfig.confirmation.exemptions.some(\n (e) => e.user === hass!.user!.id\n ))\n ) {\n forwardHaptic(\"warning\");\n\n if (\n !confirm(\n actionConfig.confirmation.text ||\n `Are you sure you want to ${actionConfig.action}?`\n )\n ) {\n return;\n }\n }\n\n switch (actionConfig.action) {\n case \"more-info\":\n if (config.entity || config.camera_image) {\n fireEvent(node, \"hass-more-info\", {\n entityId: config.entity ? config.entity : config.camera_image!,\n });\n }\n break;\n case \"navigate\":\n if (actionConfig.navigation_path) {\n navigate(node, actionConfig.navigation_path);\n }\n break;\n case \"url\":\n if (actionConfig.url_path) {\n window.open(actionConfig.url_path);\n }\n break;\n case \"toggle\":\n if (config.entity) {\n toggleEntity(hass, config.entity!);\n forwardHaptic(\"success\");\n }\n break;\n case \"call-service\": {\n if (!actionConfig.service) {\n forwardHaptic(\"failure\");\n return;\n }\n const [domain, service] = actionConfig.service.split(\".\", 2);\n hass.callService(domain, service, actionConfig.data, actionConfig.target);\n forwardHaptic(\"success\");\n break;\n }\n case \"fire-dom-event\": {\n fireEvent(node, \"ll-custom\", actionConfig);\n }\n }\n};\n\nexport const handleAction = (\n node: HTMLElement,\n hass: HomeAssistant,\n config: {\n entity?: string;\n camera_image?: string;\n hold_action?: ActionConfig;\n tap_action?: ActionConfig;\n double_tap_action?: ActionConfig;\n },\n action: string\n): void => {\n let actionConfig: ActionConfig | undefined;\n\n if (action === \"double_tap\" && config.double_tap_action) {\n actionConfig = config.double_tap_action;\n } else if (action === \"hold\" && config.hold_action) {\n actionConfig = config.hold_action;\n } else if (action === \"tap\" && config.tap_action) {\n actionConfig = config.tap_action;\n }\n\n handleActionConfig(node, hass, config, actionConfig);\n};\n","import { HomeAssistant, ActionConfig } from \"./types\";\nimport { fireEvent } from \"./fire-event\";\nimport { forwardHaptic } from \"./haptic\";\nimport { navigate } from \"./navigate\";\nimport { toggleEntity } from \"./toggle-entity\";\n\nexport const handleClick = (\n node: HTMLElement,\n hass: HomeAssistant,\n config: {\n entity?: string;\n camera_image?: string;\n hold_action?: ActionConfig;\n tap_action?: ActionConfig;\n double_tap_action?: ActionConfig;\n },\n hold: boolean,\n dblClick: boolean\n): void => {\n let actionConfig: ActionConfig | undefined;\n\n if (dblClick && config.double_tap_action) {\n actionConfig = config.double_tap_action;\n } else if (hold && config.hold_action) {\n actionConfig = config.hold_action;\n } else if (!hold && config.tap_action) {\n actionConfig = config.tap_action;\n }\n\n if (!actionConfig) {\n actionConfig = {\n action: \"more-info\"\n };\n }\n\n if (\n actionConfig.confirmation &&\n (!actionConfig.confirmation.exemptions ||\n !actionConfig.confirmation.exemptions.some(\n e => e.user === hass!.user!.id\n ))\n ) {\n if (\n !confirm(\n actionConfig.confirmation.text ||\n `Are you sure you want to ${actionConfig.action}?`\n )\n ) {\n return;\n }\n }\n\n switch (actionConfig.action) {\n case \"more-info\":\n if (actionConfig.entity || config.entity || config.camera_image) {\n fireEvent(node, \"hass-more-info\", {\n entityId: actionConfig.entity\n ? actionConfig.entity\n : config.entity\n ? config.entity\n : config.camera_image\n });\n if (actionConfig.haptic) forwardHaptic(actionConfig.haptic);\n }\n break;\n case \"navigate\":\n if (actionConfig.navigation_path) {\n navigate(node, actionConfig.navigation_path);\n if (actionConfig.haptic) forwardHaptic(actionConfig.haptic);\n }\n break;\n case \"url\":\n actionConfig.url_path && window.open(actionConfig.url_path);\n if (actionConfig.haptic) forwardHaptic(actionConfig.haptic);\n break;\n case \"toggle\":\n if (config.entity) {\n toggleEntity(hass, config.entity!);\n if (actionConfig.haptic) forwardHaptic(actionConfig.haptic);\n }\n break;\n case \"call-service\": {\n if (!actionConfig.service) {\n return;\n }\n const [domain, service] = actionConfig.service.split(\".\", 2);\n const serviceData = { ...actionConfig.data };\n if (serviceData.entity_id === \"entity\") {\n serviceData.entity_id = config.entity;\n }\n hass.callService(domain, service, serviceData, actionConfig.target);\n if (actionConfig.haptic) forwardHaptic(actionConfig.haptic);\n break;\n }\n case \"fire-dom-event\": {\n fireEvent(node, \"ll-custom\", actionConfig);\n if (actionConfig.haptic) forwardHaptic(actionConfig.haptic);\n break;\n }\n }\n};\n","import { ActionConfig } from \"./types\";\n\nexport function hasAction(config?: ActionConfig): boolean {\n return config !== undefined && config.action !== \"none\";\n}\n","import { PropertyValues } from \"lit\";\n\nimport { HomeAssistant } from \"./types\";\n\n// Check if config or Entity changed\nexport function hasConfigOrEntityChanged(\n element: any,\n changedProps: PropertyValues,\n forceUpdate: Boolean,\n): boolean {\n if (changedProps.has('config') || forceUpdate) {\n return true;\n }\n\n if (element.config!.entity) {\n const oldHass = changedProps.get('hass') as HomeAssistant | undefined;\n if (oldHass) {\n return (\n oldHass.states[element.config!.entity]\n !== element.hass!.states[element.config!.entity]\n );\n }\n return true;\n } else {\n return false;\n }\n}","import { ActionConfig } from \"./types\";\n\n// Check if config or Entity changed\nexport function hasDoubleClick(config?: ActionConfig): boolean {\n return config !== undefined && config.action !== \"none\";\n}","import { HomeAssistant } from \"./types\";\nimport { STATES_OFF } from \"./const\";\nimport { computeDomain } from \"./compute-domain\";\n\nexport const turnOnOffEntities = (\n hass: HomeAssistant,\n entityIds: string[],\n turnOn = true\n): void => {\n const domainsToCall = {};\n entityIds.forEach((entityId) => {\n if (STATES_OFF.includes(hass.states[entityId].state) === turnOn) {\n const stateDomain = computeDomain(entityId);\n const serviceDomain = [\"cover\", \"lock\"].includes(stateDomain)\n ? stateDomain\n : \"homeassistant\";\n\n if (!(serviceDomain in domainsToCall)) {\n domainsToCall[serviceDomain] = [];\n }\n domainsToCall[serviceDomain].push(entityId);\n }\n });\n\n Object.keys(domainsToCall).forEach((domain) => {\n let service;\n switch (domain) {\n case \"lock\":\n service = turnOn ? \"unlock\" : \"lock\";\n break;\n case \"cover\":\n service = turnOn ? \"open_cover\" : \"close_cover\";\n break;\n default:\n service = turnOn ? \"turn_on\" : \"turn_off\";\n }\n\n const entities = domainsToCall[domain];\n hass.callService(domain, service, { entity_id: entities });\n });\n};\n","export const getLovelace = () => {\n let root: any = document.querySelector('home-assistant');\n root = root && root.shadowRoot;\n root = root && root.querySelector('home-assistant-main');\n root = root && root.shadowRoot;\n root = root && root.querySelector('app-drawer-layout partial-panel-resolver');\n root = root && root.shadowRoot || root;\n root = root && root.querySelector('ha-panel-lovelace');\n root = root && root.shadowRoot;\n root = root && root.querySelector('hui-root');\n if (root) {\n const ll = root.lovelace;\n ll.current_view = root.___curView;\n return ll;\n }\n return null;\n}\n","/** Return an icon representing a sensor state. */\nimport { HassEntity } from \"home-assistant-js-websocket\";\nimport { UNIT_C, UNIT_F } from \"./const\";\nimport { domainIcon } from \"./domain_icons\";\n\nconst fixedDeviceClassIcons = {\n humidity: \"mdi:water-percent\",\n illuminance: \"mdi:brightness-5\",\n temperature: \"mdi:thermometer\",\n pressure: \"mdi:gauge\",\n power: \"mdi:flash\",\n signal_strength: \"mdi:wifi\",\n};\n\nexport const sensorIcon = (state: HassEntity) => {\n const dclass = state.attributes.device_class;\n\n if (dclass && dclass in fixedDeviceClassIcons) {\n return fixedDeviceClassIcons[dclass];\n }\n if (dclass === \"battery\") {\n const battery = Number(state.state);\n if (isNaN(battery)) {\n return \"mdi:battery-unknown\";\n }\n const batteryRound = Math.round(battery / 10) * 10;\n if (batteryRound >= 100) {\n return \"mdi:battery\";\n }\n if (batteryRound <= 0) {\n return \"mdi:battery-alert\";\n }\n // Will return one of the following icons: (listed so extractor picks up)\n // mdi:battery-10\n // mdi:battery-20\n // mdi:battery-30\n // mdi:battery-40\n // mdi:battery-50\n // mdi:battery-60\n // mdi:battery-70\n // mdi:battery-80\n // mdi:battery-90\n // We obscure 'hass' in iconname so this name does not get picked up\n return `${\"hass\"}:battery-${batteryRound}`;\n }\n\n const unit = state.attributes.unit_of_measurement;\n if (unit === UNIT_C || unit === UNIT_F) {\n return \"mdi:thermometer\";\n }\n return domainIcon(\"sensor\");\n};\n","import { HassEntity } from \"home-assistant-js-websocket\";\nimport { computeDomain } from \"./compute-domain\";\nimport { DEFAULT_DOMAIN_ICON } from \"./const\";\nimport { binarySensorIcon } from \"./binary_sensor_icon\";\nimport { coverIcon } from \"./cover_icon\";\nimport { sensorIcon } from \"./sensor_icon\";\nimport { inputDateTimeIcon } from \"./input_datetime_icon\";\nimport { domainIcon } from \"./domain_icons\";\n\nconst domainIcons = {\n binary_sensor: binarySensorIcon,\n cover: coverIcon,\n sensor: sensorIcon,\n input_datetime: inputDateTimeIcon,\n};\n\nexport const stateIcon = (state: HassEntity) => {\n if (!state) {\n return DEFAULT_DOMAIN_ICON;\n }\n if (state.attributes.icon) {\n return state.attributes.icon;\n }\n\n const domain = computeDomain(state.entity_id);\n\n if (domain in domainIcons) {\n return domainIcons[domain](state);\n }\n return domainIcon(domain, state.state);\n};\n","import { HassEntity } from \"home-assistant-js-websocket\";\n\n/** Return an icon representing a binary sensor state. */\n\nexport const binarySensorIcon = (state?: string, stateObj?: HassEntity) => {\n const is_off = state === \"off\";\n switch (stateObj?.attributes.device_class) {\n case \"battery\":\n return is_off ? \"mdi:battery\" : \"mdi:battery-outline\";\n case \"battery_charging\":\n return is_off ? \"mdi:battery\" : \"mdi:battery-charging\";\n case \"cold\":\n return is_off ? \"mdi:thermometer\" : \"mdi:snowflake\";\n case \"connectivity\":\n return is_off ? \"mdi:server-network-off\" : \"mdi:server-network\";\n case \"door\":\n return is_off ? \"mdi:door-closed\" : \"mdi:door-open\";\n case \"garage_door\":\n return is_off ? \"mdi:garage\" : \"mdi:garage-open\";\n case \"power\":\n return is_off ? \"mdi:power-plug-off\" : \"mdi:power-plug\";\n case \"gas\":\n case \"problem\":\n case \"safety\":\n case \"tamper\":\n return is_off ? \"mdi:check-circle\" : \"mdi:alert-circle\";\n case \"smoke\":\n return is_off ? \"mdi:check-circle\" : \"mdi:smoke\";\n case \"heat\":\n return is_off ? \"mdi:thermometer\" : \"mdi:fire\";\n case \"light\":\n return is_off ? \"mdi:brightness-5\" : \"mdi:brightness-7\";\n case \"lock\":\n return is_off ? \"mdi:lock\" : \"mdi:lock-open\";\n case \"moisture\":\n return is_off ? \"mdi:water-off\" : \"mdi:water\";\n case \"motion\":\n return is_off ? \"mdi:walk\" : \"mdi:run\";\n case \"occupancy\":\n return is_off ? \"mdi:home-outline\" : \"mdi:home\";\n case \"opening\":\n return is_off ? \"mdi:square\" : \"mdi:square-outline\";\n case \"plug\":\n return is_off ? \"mdi:power-plug-off\" : \"mdi:power-plug\";\n case \"presence\":\n return is_off ? \"mdi:home-outline\" : \"mdi:home\";\n case \"running\":\n return is_off ? \"mdi:stop\" : \"mdi:play\";\n case \"sound\":\n return is_off ? \"mdi:music-note-off\" : \"mdi:music-note\";\n case \"update\":\n return is_off ? \"mdi:package\" : \"mdi:package-up\";\n case \"vibration\":\n return is_off ? \"mdi:crop-portrait\" : \"mdi:vibrate\";\n case \"window\":\n return is_off ? \"mdi:window-closed\" : \"mdi:window-open\";\n default:\n return is_off ? \"mdi:radiobox-blank\" : \"mdi:checkbox-marked-circle\";\n }\n};\n","/** Return an icon representing a cover state. */\nimport { HassEntity } from \"home-assistant-js-websocket\";\nimport { domainIcon } from \"./domain_icons\";\n\nexport const coverIcon = (state: HassEntity): string => {\n const open = state.state !== \"closed\";\n switch (state.attributes.device_class) {\n case \"garage\":\n return open ? \"mdi:garage-open\" : \"mdi:garage\";\n case \"door\":\n return open ? \"mdi:door-open\" : \"mdi:door-closed\";\n case \"shutter\":\n return open ? \"mdi:window-shutter-open\" : \"mdi:window-shutter\";\n case \"blind\":\n return open ? \"mdi:blinds-open\" : \"mdi:blinds\";\n case \"window\":\n return open ? \"mdi:window-open\" : \"mdi:window-closed\";\n default:\n return domainIcon(\"cover\", state.state);\n }\n};\n","/** Return an icon representing an input datetime state. */\nimport { domainIcon } from \"./domain_icons\";\nimport { HassEntity } from \"home-assistant-js-websocket\";\n\nexport const inputDateTimeIcon = (state: HassEntity): string => {\n if (!state.attributes.has_date) {\n return \"mdi:clock\";\n }\n if (!state.attributes.has_time) {\n return \"mdi:calendar\";\n }\n return domainIcon(\"input_datetime\");\n};\n"],"names":["formatDateWeekday","NumberFormat","TimeFormat","dateObj","locale","formatDateWeekdayMem","format","Intl","DateTimeFormat","language","weekday","month","day","formatDate","formatDateMem","year","formatDateNumeric","formatDateNumericMem","formatDateShort","formatDateShortMem","formatDateMonthYear","formatDateMonthYearMem","formatDateMonth","formatDateMonthMem","formatDateYear","formatDateYearMem","useAmPm","time_format","system","testLanguage","undefined","test","Date","toLocaleString","includes","am_pm","formatDateTime","formatDateTimeMem","hour","minute","hour12","formatDateTimeWithSeconds","formatDateTimeWithSecondsMem","second","formatDateTimeNumeric","formatDateTimeNumericMem","formatTime","formatTimeMem","formatTimeWithSeconds","formatTimeWithSecondsMem","formatTimeWeekday","formatTimeWeekdayMem","relativeTime","from","to","includeTense","diff","selectUnit","RelativeTimeFormat","numeric","formatRelTimeMem","value","unit","style","unitDisplay","Math","abs","timerTimeRemaining","stateObj","parts","timeRemaining","attributes","remaining","split","map","Number","state","now","getTime","madeActive","last_changed","max","applyThemesOnElement","element","themes","localTheme","updateMeta","_themes","themeName","default_theme","styles","theme","Object","keys","forEach","key","prefixedKey","updateStyles","window","ShadyCSS","styleSubtree","meta","document","querySelector","hasAttribute","setAttribute","getAttribute","themeColor","computeCardSize","card","getCardSize","computeDomain","entityId","substr","indexOf","computeEntity","computeRTL","hass","lang","translationMetadata","translations","isRTL","computeRTLDirection","computeStateDomain","entity_id","isNumericState","unit_of_measurement","state_class","numberFormatToLocale","localeOptions","number_format","comma_decimal","decimal_comma","space_comma","round","precision","formatNumber","num","options","isNaN","input","none","getDefaultFormatOptions","err","console","error","maximumFractionDigits","toString","currency","defaultOptions","minimumFractionDigits","digits","length","computeStateDisplay","localize","compareState","device_class","_err","domain","date","has_date","has_time","setHours","components","join","toISOString","_e","humidity","DEFAULT_DOMAIN_ICON","DEFAULT_PANEL","DOMAINS_WITH_CARD","DOMAINS_WITH_MORE_INFO","DOMAINS_HIDE_MORE_INFO","DOMAINS_MORE_INFO_NO_HISTORY","STATES_OFF","DOMAINS_TOGGLE","Set","UNIT_C","UNIT_F","DEFAULT_VIEW_ENTITY_ID","fireEvent","node","type","detail","event","Event","bubbles","cancelable","Boolean","composed","dispatchEvent","SPECIAL_TYPES","DOMAIN_TO_ELEMENT_TYPE","alert","automation","climate","cover","fan","group","input_boolean","input_number","input_select","input_text","light","lock","media_player","remote","scene","script","sensor","timer","switch","vacuum","water_heater","input_datetime","createThing","cardConfig","isRow","_createError","config","_createThing","tag","createElement","setConfig","message","startsWith","has","entity","customElements","get","display","setTimeout","whenDefined","then","clearTimeout","debounce","func","wait","immediate","timeout","args","context","this","later","apply","callNow","fixedIcons","calendar","camera","configurator","conversation","device_tracker","history_graph","homeassistant","homekit","image_processing","mailbox","notify","person","plant","proximity","simple_alarm","sun","updater","weblink","domainIcon","warn","evaluateFilter","filter","attribute","operator","match","forwardHaptic","hapticType","navigate","_node","path","replace","history","replaceState","pushState","turnOnOffEntity","turnOn","service","stateDomain","serviceDomain","callService","toggleEntity","states","handleActionConfig","actionConfig","action","confirmation","exemptions","some","e","user","id","confirm","text","camera_image","navigation_path","url_path","open","data","target","handleAction","double_tap_action","hold_action","tap_action","handleClick","hold","dblClick","haptic","serviceData","hasAction","hasConfigOrEntityChanged","changedProps","forceUpdate","oldHass","hasDoubleClick","turnOnOffEntities","entityIds","domainsToCall","push","getLovelace","root","shadowRoot","ll","lovelace","current_view","___curView","fixedDeviceClassIcons","illuminance","temperature","pressure","power","signal_strength","domainIcons","binary_sensor","is_off","dclass","battery","batteryRound","stateIcon","icon"],"mappings":"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"} \ No newline at end of file diff --git a/dist/index.modern.js b/dist/index.modern.js index 88f5d9c..7edb48b 100644 --- a/dist/index.modern.js +++ b/dist/index.modern.js @@ -1,2 +1,2 @@ -import{selectUnit as e}from"@formatjs/intl-utils";const t=(e,t)=>i(t).format(e),i=e=>new Intl.DateTimeFormat(e.language,{weekday:"long",month:"long",day:"numeric"}),r=(e,t)=>n(t).format(e),n=e=>new Intl.DateTimeFormat(e.language,{year:"numeric",month:"long",day:"numeric"}),a=(e,t)=>o(t).format(e),o=e=>new Intl.DateTimeFormat(e.language,{year:"numeric",month:"numeric",day:"numeric"}),c=(e,t)=>s(t).format(e),s=e=>new Intl.DateTimeFormat(e.language,{day:"numeric",month:"short"}),u=(e,t)=>m(t).format(e),m=e=>new Intl.DateTimeFormat(e.language,{month:"long",year:"numeric"}),l=(e,t)=>d(t).format(e),d=e=>new Intl.DateTimeFormat(e.language,{month:"long"}),g=(e,t)=>p(t).format(e),p=e=>new Intl.DateTimeFormat(e.language,{year:"numeric"});var f,h;!function(e){e.language="language",e.system="system",e.comma_decimal="comma_decimal",e.decimal_comma="decimal_comma",e.space_comma="space_comma",e.none="none"}(f||(f={})),function(e){e.language="language",e.system="system",e.am_pm="12",e.twenty_four="24"}(h||(h={}));const b=e=>{if(e.time_format===h.language||e.time_format===h.system){const t=e.time_format===h.language?e.language:void 0,i=(new Date).toLocaleString(t);return i.includes("AM")||i.includes("PM")}return e.time_format===h.am_pm},_=(e,t)=>y(t).format(e),y=e=>new Intl.DateTimeFormat(e.language,{year:"numeric",month:"long",day:"numeric",hour:b(e)?"numeric":"2-digit",minute:"2-digit",hour12:b(e)}),w=(e,t)=>v(t).format(e),v=e=>new Intl.DateTimeFormat(e.language,{year:"numeric",month:"long",day:"numeric",hour:b(e)?"numeric":"2-digit",minute:"2-digit",second:"2-digit",hour12:b(e)}),k=(e,t)=>x(t).format(e),x=e=>new Intl.DateTimeFormat(e.language,{year:"numeric",month:"numeric",day:"numeric",hour:"numeric",minute:"2-digit",hour12:b(e)}),D=(e,t)=>S(t).format(e),S=e=>new Intl.DateTimeFormat(e.language,{hour:"numeric",minute:"2-digit",hour12:b(e)}),F=(e,t)=>T(t).format(e),T=e=>new Intl.DateTimeFormat(e.language,{hour:b(e)?"numeric":"2-digit",minute:"2-digit",second:"2-digit",hour12:b(e)}),I=(e,t)=>$(t).format(e),$=e=>new Intl.DateTimeFormat(e.language,{hour:b(e)?"numeric":"2-digit",minute:"2-digit",second:"2-digit",hour12:b(e)}),N=(t,i,r,n=!0)=>{const a=e(t,r);return n?(e=>new Intl.RelativeTimeFormat(e.language,{numeric:"auto"}))(i).format(a.value,a.unit):Intl.NumberFormat(i.language,{style:"unit",unit:a.unit,unitDisplay:"long"}).format(Math.abs(a.value))};function C(e){let t=function(e){const t=e.split(":").map(Number);return 3600*t[0]+60*t[1]+t[2]}(e.attributes.remaining);if("active"===e.state){const i=(new Date).getTime(),r=new Date(e.last_changed).getTime();t=Math.max(t-(i-r)/1e3,0)}return t}function O(){return(O=Object.assign||function(e){for(var t=1;t{e._themes||(e._themes={});let n=t.default_theme;("default"===i||i&&t.themes[i])&&(n=i);const a=O({},e._themes);if("default"!==n){const i=t.themes[n];Object.keys(i).forEach(t=>{const r="--"+t;e._themes[r]="",a[r]=i[t]})}if(e.updateStyles?e.updateStyles(a):window.ShadyCSS&&window.ShadyCSS.styleSubtree(e,a),!r)return;const o=document.querySelector("meta[name=theme-color]");if(o){o.hasAttribute("default-content")||o.setAttribute("default-content",o.getAttribute("content"));const e=a["--primary-color"]||o.getAttribute("default-content");o.setAttribute("content",e)}},A=e=>"function"==typeof e.getCardSize?e.getCardSize():4;function E(e){return e.substr(0,e.indexOf("."))}function M(e){return e.substr(e.indexOf(".")+1)}function j(e){var t;const i=(null==e||null==(t=e.locale)?void 0:t.language)||"en";return e.translationMetadata.translations[i]&&e.translationMetadata.translations[i].isRTL||!1}function R(e){return j(e)?"rtl":"ltr"}function z(e){return E(e.entity_id)}const L=e=>!!e.attributes.unit_of_measurement||!!e.attributes.state_class,P=e=>{switch(e.number_format){case f.comma_decimal:return["en-US","en"];case f.decimal_comma:return["de","es","it"];case f.space_comma:return["fr","sv","cs"];case f.system:return;default:return e.language}},U=(e,t=2)=>Math.round(e*10**t)/10**t,B=(e,t,i)=>{const r=t?P(t):void 0;if(Number.isNaN=Number.isNaN||function e(t){return"number"==typeof t&&e(t)},(null==t?void 0:t.number_format)!==f.none&&!Number.isNaN(Number(e))&&Intl)try{return new Intl.NumberFormat(r,H(e,i)).format(Number(e))}catch(t){return console.error(t),new Intl.NumberFormat(void 0,H(e,i)).format(Number(e))}return"string"==typeof e?e:`${U(e,null==i?void 0:i.maximumFractionDigits).toString()}${"currency"===(null==i?void 0:i.style)?` ${i.currency}`:""}`},H=(e,t)=>{const i=O({maximumFractionDigits:2},t);if("string"!=typeof e)return i;if(!t||!t.minimumFractionDigits&&!t.maximumFractionDigits){const t=e.indexOf(".")>-1?e.split(".")[1].length:0;i.minimumFractionDigits=t,i.maximumFractionDigits=t}return i},V=(e,t,i,n)=>{const a=void 0!==n?n:t.state;if("unknown"===a||"unavailable"===a)return e(`state.default.${a}`);if(L(t)){if("monetary"===t.attributes.device_class)try{return B(a,i,{style:"currency",currency:t.attributes.unit_of_measurement})}catch(e){}return`${B(a,i)}${t.attributes.unit_of_measurement?" "+t.attributes.unit_of_measurement:""}`}const o=z(t);if("input_datetime"===o){if(void 0===n){let e;return t.attributes.has_date&&t.attributes.has_time?(e=new Date(t.attributes.year,t.attributes.month-1,t.attributes.day,t.attributes.hour,t.attributes.minute),_(e,i)):t.attributes.has_date?(e=new Date(t.attributes.year,t.attributes.month-1,t.attributes.day),r(e,i)):t.attributes.has_time?(e=new Date,e.setHours(t.attributes.hour,t.attributes.minute),D(e,i)):t.state}try{const e=n.split(" ");if(2===e.length)return _(new Date(e.join("T")),i);if(1===e.length){if(n.includes("-"))return r(new Date(`${n}T00:00`),i);if(n.includes(":")){const e=new Date;return D(new Date(`${e.toISOString().split("T")[0]}T${n}`),i)}}return n}catch(e){return n}}return"humidifier"===o&&"on"===a&&t.attributes.humidity?`${t.attributes.humidity} %`:"counter"===o||"number"===o||"input_number"===o?B(a,i):t.attributes.device_class&&e(`component.${o}.state.${t.attributes.device_class}.${a}`)||e(`component.${o}.state._.${a}`)||a},W="mdi:bookmark",G="lovelace",J=["climate","cover","configurator","input_select","input_number","input_text","lock","media_player","scene","script","timer","vacuum","water_heater","weblink"],K=["alarm_control_panel","automation","camera","climate","configurator","cover","fan","group","history_graph","input_datetime","light","lock","media_player","script","sun","updater","vacuum","water_heater","weather"],Q=["input_number","input_select","input_text","scene","weblink"],X=["camera","configurator","history_graph","scene"],Y=["closed","locked","off"],Z=new Set(["fan","input_boolean","light","switch","group","automation"]),ee="°C",te="°F",ie="group.default_view",re=(e,t,i,r)=>{r=r||{},i=null==i?{}:i;const n=new Event(t,{bubbles:void 0===r.bubbles||r.bubbles,cancelable:Boolean(r.cancelable),composed:void 0===r.composed||r.composed});return n.detail=i,e.dispatchEvent(n),n},ne=new Set(["call-service","divider","section","weblink","cast","select"]),ae={alert:"toggle",automation:"toggle",climate:"climate",cover:"cover",fan:"toggle",group:"group",input_boolean:"toggle",input_number:"input-number",input_select:"input-select",input_text:"input-text",light:"toggle",lock:"lock",media_player:"media-player",remote:"toggle",scene:"scene",script:"script",sensor:"sensor",timer:"timer",switch:"toggle",vacuum:"toggle",water_heater:"climate",input_datetime:"input-datetime"},oe=(e,t=!1)=>{const i=(e,t)=>r("hui-error-card",{type:"error",error:e,config:t}),r=(e,t)=>{const r=window.document.createElement(e);try{if(!r.setConfig)return;r.setConfig(t)}catch(r){return console.error(e,r),i(r.message,t)}return r};if(!e||"object"!=typeof e||!t&&!e.type)return i("No type defined",e);let n=e.type;if(n&&n.startsWith("custom:"))n=n.substr("custom:".length);else if(t)if(ne.has(n))n=`hui-${n}-row`;else{if(!e.entity)return i("Invalid config given.",e);const t=e.entity.split(".",1)[0];n=`hui-${ae[t]||"text"}-entity-row`}else n=`hui-${n}-card`;if(customElements.get(n))return r(n,e);const a=i(`Custom element doesn't exist: ${e.type}.`,e);a.style.display="None";const o=setTimeout(()=>{a.style.display=""},2e3);return customElements.whenDefined(e.type).then(()=>{clearTimeout(o),re(a,"ll-rebuild",{},a)}),a},ce=(e,t,i=!1)=>{let r;return function(...n){const a=this,o=i&&!r;clearTimeout(r),r=setTimeout(()=>{r=null,i||e.apply(a,n)},t),o&&e.apply(a,n)}},se={alert:"mdi:alert",automation:"mdi:playlist-play",calendar:"mdi:calendar",camera:"mdi:video",climate:"mdi:thermostat",configurator:"mdi:settings",conversation:"mdi:text-to-speech",device_tracker:"mdi:account",fan:"mdi:fan",group:"mdi:google-circles-communities",history_graph:"mdi:chart-line",homeassistant:"mdi:home-assistant",homekit:"mdi:home-automation",image_processing:"mdi:image-filter-frames",input_boolean:"mdi:drawing",input_datetime:"mdi:calendar-clock",input_number:"mdi:ray-vertex",input_select:"mdi:format-list-bulleted",input_text:"mdi:textbox",light:"mdi:lightbulb",mailbox:"mdi:mailbox",notify:"mdi:comment-alert",person:"mdi:account",plant:"mdi:flower",proximity:"mdi:apple-safari",remote:"mdi:remote",scene:"mdi:google-pages",script:"mdi:file-document",sensor:"mdi:eye",simple_alarm:"mdi:bell",sun:"mdi:white-balance-sunny",switch:"mdi:flash",timer:"mdi:timer",updater:"mdi:cloud-upload",vacuum:"mdi:robot-vacuum",water_heater:"mdi:thermometer",weblink:"mdi:open-in-new"};function ue(e,t){if(e in se)return se[e];switch(e){case"alarm_control_panel":switch(t){case"armed_home":return"mdi:bell-plus";case"armed_night":return"mdi:bell-sleep";case"disarmed":return"mdi:bell-outline";case"triggered":return"mdi:bell-ring";default:return"mdi:bell"}case"binary_sensor":return t&&"off"===t?"mdi:radiobox-blank":"mdi:checkbox-marked-circle";case"cover":return"closed"===t?"mdi:window-closed":"mdi:window-open";case"lock":return t&&"unlocked"===t?"mdi:lock-open":"mdi:lock";case"media_player":return t&&"off"!==t&&"idle"!==t?"mdi:cast-connected":"mdi:cast";case"zwave":switch(t){case"dead":return"mdi:emoticon-dead";case"sleeping":return"mdi:sleep";case"initializing":return"mdi:timer-sand";default:return"mdi:z-wave"}default:return console.warn("Unable to find icon for domain "+e+" ("+t+")"),"mdi:bookmark"}}const me=(e,t)=>{const i=t.value||t,r=t.attribute?e.attributes[t.attribute]:e.state;switch(t.operator||"=="){case"==":return r===i;case"<=":return r<=i;case"<":return r=":return r>=i;case">":return r>i;case"!=":return r!==i;case"regex":return r.match(i);default:return!1}},le=e=>{re(window,"haptic",e)},de=(e,t,i=!1)=>{i?history.replaceState(null,"",t):history.pushState(null,"",t),re(window,"location-changed",{replace:i})},ge=(e,t,i=!0)=>{const r=E(t),n="group"===r?"homeassistant":r;let a;switch(r){case"lock":a=i?"unlock":"lock";break;case"cover":a=i?"open_cover":"close_cover";break;default:a=i?"turn_on":"turn_off"}return e.callService(n,a,{entity_id:t})},pe=(e,t)=>{const i=Y.includes(e.states[t].state);return ge(e,t,i)},fe=(e,t,i,r)=>{if(r||(r={action:"more-info"}),!r.confirmation||r.confirmation.exemptions&&r.confirmation.exemptions.some(e=>e.user===t.user.id)||(le("warning"),confirm(r.confirmation.text||`Are you sure you want to ${r.action}?`)))switch(r.action){case"more-info":(i.entity||i.camera_image)&&re(e,"hass-more-info",{entityId:i.entity?i.entity:i.camera_image});break;case"navigate":r.navigation_path&&de(0,r.navigation_path);break;case"url":r.url_path&&window.open(r.url_path);break;case"toggle":i.entity&&(pe(t,i.entity),le("success"));break;case"call-service":{if(!r.service)return void le("failure");const[e,i]=r.service.split(".",2);t.callService(e,i,r.service_data,r.target),le("success");break}case"fire-dom-event":re(e,"ll-custom",r)}},he=(e,t,i,r)=>{let n;"double_tap"===r&&i.double_tap_action?n=i.double_tap_action:"hold"===r&&i.hold_action?n=i.hold_action:"tap"===r&&i.tap_action&&(n=i.tap_action),fe(e,t,i,n)},be=(e,t,i,r,n)=>{let a;if(n&&i.double_tap_action?a=i.double_tap_action:r&&i.hold_action?a=i.hold_action:!r&&i.tap_action&&(a=i.tap_action),a||(a={action:"more-info"}),!a.confirmation||a.confirmation.exemptions&&a.confirmation.exemptions.some(e=>e.user===t.user.id)||confirm(a.confirmation.text||`Are you sure you want to ${a.action}?`))switch(a.action){case"more-info":(a.entity||i.entity||i.camera_image)&&(re(e,"hass-more-info",{entityId:a.entity?a.entity:i.entity?i.entity:i.camera_image}),a.haptic&&le(a.haptic));break;case"navigate":a.navigation_path&&(de(0,a.navigation_path),a.haptic&&le(a.haptic));break;case"url":a.url_path&&window.open(a.url_path),a.haptic&&le(a.haptic);break;case"toggle":i.entity&&(pe(t,i.entity),a.haptic&&le(a.haptic));break;case"call-service":{if(!a.service)return;const[e,r]=a.service.split(".",2),n=O({},a.service_data);"entity"===n.entity_id&&(n.entity_id=i.entity),t.callService(e,r,n,a.target),a.haptic&&le(a.haptic);break}case"fire-dom-event":re(e,"ll-custom",a),a.haptic&&le(a.haptic)}};function _e(e){return void 0!==e&&"none"!==e.action}function ye(e,t,i){if(t.has("config")||i)return!0;if(e.config.entity){const i=t.get("hass");return!i||i.states[e.config.entity]!==e.hass.states[e.config.entity]}return!1}function we(e){return void 0!==e&&"none"!==e.action}const ve=(e,t,i=!0)=>{const r={};t.forEach(t=>{if(Y.includes(e.states[t].state)===i){const e=E(t),i=["cover","lock"].includes(e)?e:"homeassistant";i in r||(r[i]=[]),r[i].push(t)}}),Object.keys(r).forEach(t=>{let n;switch(t){case"lock":n=i?"unlock":"lock";break;case"cover":n=i?"open_cover":"close_cover";break;default:n=i?"turn_on":"turn_off"}e.callService(t,n,{entity_id:r[t]})})},ke=()=>{let e=document.querySelector("home-assistant");if(e=e&&e.shadowRoot,e=e&&e.querySelector("home-assistant-main"),e=e&&e.shadowRoot,e=e&&e.querySelector("app-drawer-layout partial-panel-resolver"),e=e&&e.shadowRoot||e,e=e&&e.querySelector("ha-panel-lovelace"),e=e&&e.shadowRoot,e=e&&e.querySelector("hui-root"),e){const t=e.lovelace;return t.current_view=e.___curView,t}return null},xe={humidity:"mdi:water-percent",illuminance:"mdi:brightness-5",temperature:"mdi:thermometer",pressure:"mdi:gauge",power:"mdi:flash",signal_strength:"mdi:wifi"},De={binary_sensor:(e,t)=>{const i="off"===e;switch(null==t?void 0:t.attributes.device_class){case"battery":return i?"mdi:battery":"mdi:battery-outline";case"battery_charging":return i?"mdi:battery":"mdi:battery-charging";case"cold":return i?"mdi:thermometer":"mdi:snowflake";case"connectivity":return i?"mdi:server-network-off":"mdi:server-network";case"door":return i?"mdi:door-closed":"mdi:door-open";case"garage_door":return i?"mdi:garage":"mdi:garage-open";case"power":return i?"mdi:power-plug-off":"mdi:power-plug";case"gas":case"problem":case"safety":case"tamper":return i?"mdi:check-circle":"mdi:alert-circle";case"smoke":return i?"mdi:check-circle":"mdi:smoke";case"heat":return i?"mdi:thermometer":"mdi:fire";case"light":return i?"mdi:brightness-5":"mdi:brightness-7";case"lock":return i?"mdi:lock":"mdi:lock-open";case"moisture":return i?"mdi:water-off":"mdi:water";case"motion":return i?"mdi:walk":"mdi:run";case"occupancy":return i?"mdi:home-outline":"mdi:home";case"opening":return i?"mdi:square":"mdi:square-outline";case"plug":return i?"mdi:power-plug-off":"mdi:power-plug";case"presence":return i?"mdi:home-outline":"mdi:home";case"running":return i?"mdi:stop":"mdi:play";case"sound":return i?"mdi:music-note-off":"mdi:music-note";case"update":return i?"mdi:package":"mdi:package-up";case"vibration":return i?"mdi:crop-portrait":"mdi:vibrate";case"window":return i?"mdi:window-closed":"mdi:window-open";default:return i?"mdi:radiobox-blank":"mdi:checkbox-marked-circle"}},cover:e=>{const t="closed"!==e.state;switch(e.attributes.device_class){case"garage":return t?"mdi:garage-open":"mdi:garage";case"door":return t?"mdi:door-open":"mdi:door-closed";case"shutter":return t?"mdi:window-shutter-open":"mdi:window-shutter";case"blind":return t?"mdi:blinds-open":"mdi:blinds";case"window":return t?"mdi:window-open":"mdi:window-closed";default:return ue("cover",e.state)}},sensor:e=>{const t=e.attributes.device_class;if(t&&t in xe)return xe[t];if("battery"===t){const t=Number(e.state);if(isNaN(t))return"mdi:battery-unknown";const i=10*Math.round(t/10);return i>=100?"mdi:battery":i<=0?"mdi:battery-alert":`hass:battery-${i}`}const i=e.attributes.unit_of_measurement;return"°C"===i||"°F"===i?"mdi:thermometer":ue("sensor")},input_datetime:e=>e.attributes.has_date?e.attributes.has_time?ue("input_datetime"):"mdi:calendar":"mdi:clock"},Se=e=>{if(!e)return"mdi:bookmark";if(e.attributes.icon)return e.attributes.icon;const t=E(e.entity_id);return t in De?De[t](e):ue(t,e.state)};export{W as DEFAULT_DOMAIN_ICON,G as DEFAULT_PANEL,ie as DEFAULT_VIEW_ENTITY_ID,Q as DOMAINS_HIDE_MORE_INFO,X as DOMAINS_MORE_INFO_NO_HISTORY,Z as DOMAINS_TOGGLE,J as DOMAINS_WITH_CARD,K as DOMAINS_WITH_MORE_INFO,f as NumberFormat,Y as STATES_OFF,h as TimeFormat,ee as UNIT_C,te as UNIT_F,q as applyThemesOnElement,A as computeCardSize,E as computeDomain,M as computeEntity,j as computeRTL,R as computeRTLDirection,V as computeStateDisplay,z as computeStateDomain,oe as createThing,ce as debounce,ue as domainIcon,me as evaluateFilter,re as fireEvent,se as fixedIcons,r as formatDate,l as formatDateMonth,u as formatDateMonthYear,a as formatDateNumeric,c as formatDateShort,_ as formatDateTime,k as formatDateTimeNumeric,w as formatDateTimeWithSeconds,t as formatDateWeekday,g as formatDateYear,B as formatNumber,D as formatTime,I as formatTimeWeekday,F as formatTimeWithSeconds,le as forwardHaptic,ke as getLovelace,he as handleAction,fe as handleActionConfig,be as handleClick,_e as hasAction,ye as hasConfigOrEntityChanged,we as hasDoubleClick,L as isNumericState,de as navigate,P as numberFormatToLocale,N as relativeTime,U as round,Se as stateIcon,C as timerTimeRemaining,pe as toggleEntity,ve as turnOnOffEntities,ge as turnOnOffEntity}; +import{selectUnit as e}from"@formatjs/intl-utils";const t=(e,t)=>i(t).format(e),i=e=>new Intl.DateTimeFormat(e.language,{weekday:"long",month:"long",day:"numeric"}),r=(e,t)=>n(t).format(e),n=e=>new Intl.DateTimeFormat(e.language,{year:"numeric",month:"long",day:"numeric"}),a=(e,t)=>o(t).format(e),o=e=>new Intl.DateTimeFormat(e.language,{year:"numeric",month:"numeric",day:"numeric"}),c=(e,t)=>s(t).format(e),s=e=>new Intl.DateTimeFormat(e.language,{day:"numeric",month:"short"}),u=(e,t)=>m(t).format(e),m=e=>new Intl.DateTimeFormat(e.language,{month:"long",year:"numeric"}),l=(e,t)=>d(t).format(e),d=e=>new Intl.DateTimeFormat(e.language,{month:"long"}),g=(e,t)=>p(t).format(e),p=e=>new Intl.DateTimeFormat(e.language,{year:"numeric"});var f,h;!function(e){e.language="language",e.system="system",e.comma_decimal="comma_decimal",e.decimal_comma="decimal_comma",e.space_comma="space_comma",e.none="none"}(f||(f={})),function(e){e.language="language",e.system="system",e.am_pm="12",e.twenty_four="24"}(h||(h={}));const b=e=>{if(e.time_format===h.language||e.time_format===h.system){const t=e.time_format===h.language?e.language:void 0,i=(new Date).toLocaleString(t);return i.includes("AM")||i.includes("PM")}return e.time_format===h.am_pm},y=(e,t)=>_(t).format(e),_=e=>new Intl.DateTimeFormat(e.language,{year:"numeric",month:"long",day:"numeric",hour:b(e)?"numeric":"2-digit",minute:"2-digit",hour12:b(e)}),w=(e,t)=>v(t).format(e),v=e=>new Intl.DateTimeFormat(e.language,{year:"numeric",month:"long",day:"numeric",hour:b(e)?"numeric":"2-digit",minute:"2-digit",second:"2-digit",hour12:b(e)}),k=(e,t)=>x(t).format(e),x=e=>new Intl.DateTimeFormat(e.language,{year:"numeric",month:"numeric",day:"numeric",hour:"numeric",minute:"2-digit",hour12:b(e)}),D=(e,t)=>S(t).format(e),S=e=>new Intl.DateTimeFormat(e.language,{hour:"numeric",minute:"2-digit",hour12:b(e)}),F=(e,t)=>T(t).format(e),T=e=>new Intl.DateTimeFormat(e.language,{hour:b(e)?"numeric":"2-digit",minute:"2-digit",second:"2-digit",hour12:b(e)}),I=(e,t)=>$(t).format(e),$=e=>new Intl.DateTimeFormat(e.language,{hour:b(e)?"numeric":"2-digit",minute:"2-digit",second:"2-digit",hour12:b(e)}),N=(t,i,r,n=!0)=>{const a=e(t,r);return n?(e=>new Intl.RelativeTimeFormat(e.language,{numeric:"auto"}))(i).format(a.value,a.unit):Intl.NumberFormat(i.language,{style:"unit",unit:a.unit,unitDisplay:"long"}).format(Math.abs(a.value))};function C(e){let t=function(e){const t=e.split(":").map(Number);return 3600*t[0]+60*t[1]+t[2]}(e.attributes.remaining);if("active"===e.state){const i=(new Date).getTime(),r=new Date(e.last_changed).getTime();t=Math.max(t-(i-r)/1e3,0)}return t}function O(){return(O=Object.assign||function(e){for(var t=1;t{e._themes||(e._themes={});let n=t.default_theme;("default"===i||i&&t.themes[i])&&(n=i);const a=O({},e._themes);if("default"!==n){const i=t.themes[n];Object.keys(i).forEach(t=>{const r="--"+t;e._themes[r]="",a[r]=i[t]})}if(e.updateStyles?e.updateStyles(a):window.ShadyCSS&&window.ShadyCSS.styleSubtree(e,a),!r)return;const o=document.querySelector("meta[name=theme-color]");if(o){o.hasAttribute("default-content")||o.setAttribute("default-content",o.getAttribute("content"));const e=a["--primary-color"]||o.getAttribute("default-content");o.setAttribute("content",e)}},A=e=>"function"==typeof e.getCardSize?e.getCardSize():4;function E(e){return e.substr(0,e.indexOf("."))}function M(e){return e.substr(e.indexOf(".")+1)}function j(e){var t;const i=(null==e||null==(t=e.locale)?void 0:t.language)||"en";return e.translationMetadata.translations[i]&&e.translationMetadata.translations[i].isRTL||!1}function R(e){return j(e)?"rtl":"ltr"}function z(e){return E(e.entity_id)}const L=e=>!!e.attributes.unit_of_measurement||!!e.attributes.state_class,P=e=>{switch(e.number_format){case f.comma_decimal:return["en-US","en"];case f.decimal_comma:return["de","es","it"];case f.space_comma:return["fr","sv","cs"];case f.system:return;default:return e.language}},U=(e,t=2)=>Math.round(e*10**t)/10**t,B=(e,t,i)=>{const r=t?P(t):void 0;if(Number.isNaN=Number.isNaN||function e(t){return"number"==typeof t&&e(t)},(null==t?void 0:t.number_format)!==f.none&&!Number.isNaN(Number(e))&&Intl)try{return new Intl.NumberFormat(r,H(e,i)).format(Number(e))}catch(t){return console.error(t),new Intl.NumberFormat(void 0,H(e,i)).format(Number(e))}return"string"==typeof e?e:`${U(e,null==i?void 0:i.maximumFractionDigits).toString()}${"currency"===(null==i?void 0:i.style)?` ${i.currency}`:""}`},H=(e,t)=>{const i=O({maximumFractionDigits:2},t);if("string"!=typeof e)return i;if(!t||!t.minimumFractionDigits&&!t.maximumFractionDigits){const t=e.indexOf(".")>-1?e.split(".")[1].length:0;i.minimumFractionDigits=t,i.maximumFractionDigits=t}return i},V=(e,t,i,n)=>{const a=void 0!==n?n:t.state;if("unknown"===a||"unavailable"===a)return e(`state.default.${a}`);if(L(t)){if("monetary"===t.attributes.device_class)try{return B(a,i,{style:"currency",currency:t.attributes.unit_of_measurement})}catch(e){}return`${B(a,i)}${t.attributes.unit_of_measurement?" "+t.attributes.unit_of_measurement:""}`}const o=z(t);if("input_datetime"===o){if(void 0===n){let e;return t.attributes.has_date&&t.attributes.has_time?(e=new Date(t.attributes.year,t.attributes.month-1,t.attributes.day,t.attributes.hour,t.attributes.minute),y(e,i)):t.attributes.has_date?(e=new Date(t.attributes.year,t.attributes.month-1,t.attributes.day),r(e,i)):t.attributes.has_time?(e=new Date,e.setHours(t.attributes.hour,t.attributes.minute),D(e,i)):t.state}try{const e=n.split(" ");if(2===e.length)return y(new Date(e.join("T")),i);if(1===e.length){if(n.includes("-"))return r(new Date(`${n}T00:00`),i);if(n.includes(":")){const e=new Date;return D(new Date(`${e.toISOString().split("T")[0]}T${n}`),i)}}return n}catch(e){return n}}return"humidifier"===o&&"on"===a&&t.attributes.humidity?`${t.attributes.humidity} %`:"counter"===o||"number"===o||"input_number"===o?B(a,i):t.attributes.device_class&&e(`component.${o}.state.${t.attributes.device_class}.${a}`)||e(`component.${o}.state._.${a}`)||a},W="mdi:bookmark",G="lovelace",J=["climate","cover","configurator","input_select","input_number","input_text","lock","media_player","scene","script","timer","vacuum","water_heater","weblink"],K=["alarm_control_panel","automation","camera","climate","configurator","cover","fan","group","history_graph","input_datetime","light","lock","media_player","script","sun","updater","vacuum","water_heater","weather"],Q=["input_number","input_select","input_text","scene","weblink"],X=["camera","configurator","history_graph","scene"],Y=["closed","locked","off"],Z=new Set(["fan","input_boolean","light","switch","group","automation"]),ee="°C",te="°F",ie="group.default_view",re=(e,t,i,r)=>{r=r||{},i=null==i?{}:i;const n=new Event(t,{bubbles:void 0===r.bubbles||r.bubbles,cancelable:Boolean(r.cancelable),composed:void 0===r.composed||r.composed});return n.detail=i,e.dispatchEvent(n),n},ne=new Set(["call-service","divider","section","weblink","cast","select"]),ae={alert:"toggle",automation:"toggle",climate:"climate",cover:"cover",fan:"toggle",group:"group",input_boolean:"toggle",input_number:"input-number",input_select:"input-select",input_text:"input-text",light:"toggle",lock:"lock",media_player:"media-player",remote:"toggle",scene:"scene",script:"script",sensor:"sensor",timer:"timer",switch:"toggle",vacuum:"toggle",water_heater:"climate",input_datetime:"input-datetime"},oe=(e,t=!1)=>{const i=(e,t)=>r("hui-error-card",{type:"error",error:e,config:t}),r=(e,t)=>{const r=window.document.createElement(e);try{if(!r.setConfig)return;r.setConfig(t)}catch(r){return console.error(e,r),i(r.message,t)}return r};if(!e||"object"!=typeof e||!t&&!e.type)return i("No type defined",e);let n=e.type;if(n&&n.startsWith("custom:"))n=n.substr("custom:".length);else if(t)if(ne.has(n))n=`hui-${n}-row`;else{if(!e.entity)return i("Invalid config given.",e);const t=e.entity.split(".",1)[0];n=`hui-${ae[t]||"text"}-entity-row`}else n=`hui-${n}-card`;if(customElements.get(n))return r(n,e);const a=i(`Custom element doesn't exist: ${e.type}.`,e);a.style.display="None";const o=setTimeout(()=>{a.style.display=""},2e3);return customElements.whenDefined(e.type).then(()=>{clearTimeout(o),re(a,"ll-rebuild",{},a)}),a},ce=(e,t,i=!1)=>{let r;return function(...n){const a=this,o=i&&!r;clearTimeout(r),r=setTimeout(()=>{r=null,i||e.apply(a,n)},t),o&&e.apply(a,n)}},se={alert:"mdi:alert",automation:"mdi:playlist-play",calendar:"mdi:calendar",camera:"mdi:video",climate:"mdi:thermostat",configurator:"mdi:settings",conversation:"mdi:text-to-speech",device_tracker:"mdi:account",fan:"mdi:fan",group:"mdi:google-circles-communities",history_graph:"mdi:chart-line",homeassistant:"mdi:home-assistant",homekit:"mdi:home-automation",image_processing:"mdi:image-filter-frames",input_boolean:"mdi:drawing",input_datetime:"mdi:calendar-clock",input_number:"mdi:ray-vertex",input_select:"mdi:format-list-bulleted",input_text:"mdi:textbox",light:"mdi:lightbulb",mailbox:"mdi:mailbox",notify:"mdi:comment-alert",person:"mdi:account",plant:"mdi:flower",proximity:"mdi:apple-safari",remote:"mdi:remote",scene:"mdi:google-pages",script:"mdi:file-document",sensor:"mdi:eye",simple_alarm:"mdi:bell",sun:"mdi:white-balance-sunny",switch:"mdi:flash",timer:"mdi:timer",updater:"mdi:cloud-upload",vacuum:"mdi:robot-vacuum",water_heater:"mdi:thermometer",weblink:"mdi:open-in-new"};function ue(e,t){if(e in se)return se[e];switch(e){case"alarm_control_panel":switch(t){case"armed_home":return"mdi:bell-plus";case"armed_night":return"mdi:bell-sleep";case"disarmed":return"mdi:bell-outline";case"triggered":return"mdi:bell-ring";default:return"mdi:bell"}case"binary_sensor":return t&&"off"===t?"mdi:radiobox-blank":"mdi:checkbox-marked-circle";case"cover":return"closed"===t?"mdi:window-closed":"mdi:window-open";case"lock":return t&&"unlocked"===t?"mdi:lock-open":"mdi:lock";case"media_player":return t&&"off"!==t&&"idle"!==t?"mdi:cast-connected":"mdi:cast";case"zwave":switch(t){case"dead":return"mdi:emoticon-dead";case"sleeping":return"mdi:sleep";case"initializing":return"mdi:timer-sand";default:return"mdi:z-wave"}default:return console.warn("Unable to find icon for domain "+e+" ("+t+")"),"mdi:bookmark"}}const me=(e,t)=>{const i=t.value||t,r=t.attribute?e.attributes[t.attribute]:e.state;switch(t.operator||"=="){case"==":return r===i;case"<=":return r<=i;case"<":return r=":return r>=i;case">":return r>i;case"!=":return r!==i;case"regex":return r.match(i);default:return!1}},le=e=>{re(window,"haptic",e)},de=(e,t,i=!1)=>{i?history.replaceState(null,"",t):history.pushState(null,"",t),re(window,"location-changed",{replace:i})},ge=(e,t,i=!0)=>{const r=E(t),n="group"===r?"homeassistant":r;let a;switch(r){case"lock":a=i?"unlock":"lock";break;case"cover":a=i?"open_cover":"close_cover";break;default:a=i?"turn_on":"turn_off"}return e.callService(n,a,{entity_id:t})},pe=(e,t)=>{const i=Y.includes(e.states[t].state);return ge(e,t,i)},fe=(e,t,i,r)=>{if(r||(r={action:"more-info"}),!r.confirmation||r.confirmation.exemptions&&r.confirmation.exemptions.some(e=>e.user===t.user.id)||(le("warning"),confirm(r.confirmation.text||`Are you sure you want to ${r.action}?`)))switch(r.action){case"more-info":(i.entity||i.camera_image)&&re(e,"hass-more-info",{entityId:i.entity?i.entity:i.camera_image});break;case"navigate":r.navigation_path&&de(0,r.navigation_path);break;case"url":r.url_path&&window.open(r.url_path);break;case"toggle":i.entity&&(pe(t,i.entity),le("success"));break;case"call-service":{if(!r.service)return void le("failure");const[e,i]=r.service.split(".",2);t.callService(e,i,r.data,r.target),le("success");break}case"fire-dom-event":re(e,"ll-custom",r)}},he=(e,t,i,r)=>{let n;"double_tap"===r&&i.double_tap_action?n=i.double_tap_action:"hold"===r&&i.hold_action?n=i.hold_action:"tap"===r&&i.tap_action&&(n=i.tap_action),fe(e,t,i,n)},be=(e,t,i,r,n)=>{let a;if(n&&i.double_tap_action?a=i.double_tap_action:r&&i.hold_action?a=i.hold_action:!r&&i.tap_action&&(a=i.tap_action),a||(a={action:"more-info"}),!a.confirmation||a.confirmation.exemptions&&a.confirmation.exemptions.some(e=>e.user===t.user.id)||confirm(a.confirmation.text||`Are you sure you want to ${a.action}?`))switch(a.action){case"more-info":(a.entity||i.entity||i.camera_image)&&(re(e,"hass-more-info",{entityId:a.entity?a.entity:i.entity?i.entity:i.camera_image}),a.haptic&&le(a.haptic));break;case"navigate":a.navigation_path&&(de(0,a.navigation_path),a.haptic&&le(a.haptic));break;case"url":a.url_path&&window.open(a.url_path),a.haptic&&le(a.haptic);break;case"toggle":i.entity&&(pe(t,i.entity),a.haptic&&le(a.haptic));break;case"call-service":{if(!a.service)return;const[e,r]=a.service.split(".",2),n=O({},a.data);"entity"===n.entity_id&&(n.entity_id=i.entity),t.callService(e,r,n,a.target),a.haptic&&le(a.haptic);break}case"fire-dom-event":re(e,"ll-custom",a),a.haptic&&le(a.haptic)}};function ye(e){return void 0!==e&&"none"!==e.action}function _e(e,t,i){if(t.has("config")||i)return!0;if(e.config.entity){const i=t.get("hass");return!i||i.states[e.config.entity]!==e.hass.states[e.config.entity]}return!1}function we(e){return void 0!==e&&"none"!==e.action}const ve=(e,t,i=!0)=>{const r={};t.forEach(t=>{if(Y.includes(e.states[t].state)===i){const e=E(t),i=["cover","lock"].includes(e)?e:"homeassistant";i in r||(r[i]=[]),r[i].push(t)}}),Object.keys(r).forEach(t=>{let n;switch(t){case"lock":n=i?"unlock":"lock";break;case"cover":n=i?"open_cover":"close_cover";break;default:n=i?"turn_on":"turn_off"}e.callService(t,n,{entity_id:r[t]})})},ke=()=>{let e=document.querySelector("home-assistant");if(e=e&&e.shadowRoot,e=e&&e.querySelector("home-assistant-main"),e=e&&e.shadowRoot,e=e&&e.querySelector("app-drawer-layout partial-panel-resolver"),e=e&&e.shadowRoot||e,e=e&&e.querySelector("ha-panel-lovelace"),e=e&&e.shadowRoot,e=e&&e.querySelector("hui-root"),e){const t=e.lovelace;return t.current_view=e.___curView,t}return null},xe={humidity:"mdi:water-percent",illuminance:"mdi:brightness-5",temperature:"mdi:thermometer",pressure:"mdi:gauge",power:"mdi:flash",signal_strength:"mdi:wifi"},De={binary_sensor:(e,t)=>{const i="off"===e;switch(null==t?void 0:t.attributes.device_class){case"battery":return i?"mdi:battery":"mdi:battery-outline";case"battery_charging":return i?"mdi:battery":"mdi:battery-charging";case"cold":return i?"mdi:thermometer":"mdi:snowflake";case"connectivity":return i?"mdi:server-network-off":"mdi:server-network";case"door":return i?"mdi:door-closed":"mdi:door-open";case"garage_door":return i?"mdi:garage":"mdi:garage-open";case"power":return i?"mdi:power-plug-off":"mdi:power-plug";case"gas":case"problem":case"safety":case"tamper":return i?"mdi:check-circle":"mdi:alert-circle";case"smoke":return i?"mdi:check-circle":"mdi:smoke";case"heat":return i?"mdi:thermometer":"mdi:fire";case"light":return i?"mdi:brightness-5":"mdi:brightness-7";case"lock":return i?"mdi:lock":"mdi:lock-open";case"moisture":return i?"mdi:water-off":"mdi:water";case"motion":return i?"mdi:walk":"mdi:run";case"occupancy":return i?"mdi:home-outline":"mdi:home";case"opening":return i?"mdi:square":"mdi:square-outline";case"plug":return i?"mdi:power-plug-off":"mdi:power-plug";case"presence":return i?"mdi:home-outline":"mdi:home";case"running":return i?"mdi:stop":"mdi:play";case"sound":return i?"mdi:music-note-off":"mdi:music-note";case"update":return i?"mdi:package":"mdi:package-up";case"vibration":return i?"mdi:crop-portrait":"mdi:vibrate";case"window":return i?"mdi:window-closed":"mdi:window-open";default:return i?"mdi:radiobox-blank":"mdi:checkbox-marked-circle"}},cover:e=>{const t="closed"!==e.state;switch(e.attributes.device_class){case"garage":return t?"mdi:garage-open":"mdi:garage";case"door":return t?"mdi:door-open":"mdi:door-closed";case"shutter":return t?"mdi:window-shutter-open":"mdi:window-shutter";case"blind":return t?"mdi:blinds-open":"mdi:blinds";case"window":return t?"mdi:window-open":"mdi:window-closed";default:return ue("cover",e.state)}},sensor:e=>{const t=e.attributes.device_class;if(t&&t in xe)return xe[t];if("battery"===t){const t=Number(e.state);if(isNaN(t))return"mdi:battery-unknown";const i=10*Math.round(t/10);return i>=100?"mdi:battery":i<=0?"mdi:battery-alert":`hass:battery-${i}`}const i=e.attributes.unit_of_measurement;return"°C"===i||"°F"===i?"mdi:thermometer":ue("sensor")},input_datetime:e=>e.attributes.has_date?e.attributes.has_time?ue("input_datetime"):"mdi:calendar":"mdi:clock"},Se=e=>{if(!e)return"mdi:bookmark";if(e.attributes.icon)return e.attributes.icon;const t=E(e.entity_id);return t in De?De[t](e):ue(t,e.state)};export{W as DEFAULT_DOMAIN_ICON,G as DEFAULT_PANEL,ie as DEFAULT_VIEW_ENTITY_ID,Q as DOMAINS_HIDE_MORE_INFO,X as DOMAINS_MORE_INFO_NO_HISTORY,Z as DOMAINS_TOGGLE,J as DOMAINS_WITH_CARD,K as DOMAINS_WITH_MORE_INFO,f as NumberFormat,Y as STATES_OFF,h as TimeFormat,ee as UNIT_C,te as UNIT_F,q as applyThemesOnElement,A as computeCardSize,E as computeDomain,M as computeEntity,j as computeRTL,R as computeRTLDirection,V as computeStateDisplay,z as computeStateDomain,oe as createThing,ce as debounce,ue as domainIcon,me as evaluateFilter,re as fireEvent,se as fixedIcons,r as formatDate,l as formatDateMonth,u as formatDateMonthYear,a as formatDateNumeric,c as formatDateShort,y as formatDateTime,k as formatDateTimeNumeric,w as formatDateTimeWithSeconds,t as formatDateWeekday,g as formatDateYear,B as formatNumber,D as formatTime,I as formatTimeWeekday,F as formatTimeWithSeconds,le as forwardHaptic,ke as getLovelace,he as handleAction,fe as handleActionConfig,be as handleClick,ye as hasAction,_e as hasConfigOrEntityChanged,we as hasDoubleClick,L as isNumericState,de as navigate,P as numberFormatToLocale,N as relativeTime,U as round,Se as stateIcon,C as timerTimeRemaining,pe as toggleEntity,ve as turnOnOffEntities,ge as turnOnOffEntity}; //# sourceMappingURL=index.modern.js.map diff --git a/dist/index.modern.js.map b/dist/index.modern.js.map index 31b02f3..c966694 100644 --- a/dist/index.modern.js.map +++ b/dist/index.modern.js.map @@ -1 +1 @@ -{"version":3,"file":"index.modern.js","sources":["../src/datetime/format_date.ts","../src/types.ts","../src/datetime/use_am_pm.ts","../src/datetime/format_date_time.ts","../src/datetime/format_time.ts","../src/datetime/relative_time.ts","../src/datetime/timer_time_remaining.ts","../src/datetime/duration_to_seconds.ts","../src/apply_themes_on_element.ts","../src/compute-card-size.ts","../src/compute-domain.ts","../src/compute-entity.ts","../src/compute-rtl.ts","../src/compute-state-domain.ts","../src/format-number.ts","../src/compute-state-display.ts","../src/const.ts","../src/fire-event.ts","../src/create-thing.ts","../src/debounce.ts","../src/domain_icons.ts","../src/evaluate-filter.ts","../src/haptic.ts","../src/navigate.ts","../src/turn-on-off-entity.ts","../src/toggle-entity.ts","../src/handle-action.ts","../src/handle-click.ts","../src/has-action.ts","../src/has-changed.ts","../src/has-double-click.ts","../src/turn-on-off-entities.ts","../src/get-lovelace.ts","../src/sensor_icon.ts","../src/state_icon.ts","../src/binary_sensor_icon.ts","../src/cover_icon.ts","../src/input_datetime_icon.ts"],"sourcesContent":["//REF: https://github.com/home-assistant/frontend/blob/dev/src/common/datetime/format_date.ts\n\nimport { FrontendLocaleData } from \"../types\";\n\n/**\n * Formatting a Date to the dddd, mmmm yy format e.g. Tuesday, August 10\n * @param dateObj The date to convert\n * @param locale The users's locale settings\n * @returns date string like \"Tuesday, August 10\"\n */\nexport const formatDateWeekday = (dateObj: Date, locale: FrontendLocaleData) =>\n formatDateWeekdayMem(locale).format(dateObj);\n\nconst formatDateWeekdayMem =\n (locale: FrontendLocaleData) =>\n new Intl.DateTimeFormat(locale.language, {\n weekday: \"long\",\n month: \"long\",\n day: \"numeric\",\n });\n\n/**\n * Formatting a Date to the mmmm dd, yyyy format e.g. August 10, 2021\n * @param dateObj The date to convert\n * @param locale The users's locale settings\n * @returns date string like \"August 10, 2021\"\n */\nexport const formatDate = (dateObj: Date, locale: FrontendLocaleData) =>\n formatDateMem(locale).format(dateObj);\n\nconst formatDateMem =\n (locale: FrontendLocaleData) =>\n new Intl.DateTimeFormat(locale.language, {\n year: \"numeric\",\n month: \"long\",\n day: \"numeric\",\n });\n\n/**\n * Formatting a Date to the classic date format e.g. 10/08/2021\n * @param dateObj The date to convert\n * @param locale The users's locale settings\n * @returns classic date format \"10/08/2021\"\n */\nexport const formatDateNumeric = (dateObj: Date, locale: FrontendLocaleData) =>\n formatDateNumericMem(locale).format(dateObj);\n\nconst formatDateNumericMem =\n (locale: FrontendLocaleData) =>\n new Intl.DateTimeFormat(locale.language, {\n year: \"numeric\",\n month: \"numeric\",\n day: \"numeric\",\n });\n\n\n/**\n * Formatting a Date to just a month with days e.g. Aug 10\n * @param dateObj The date to convert\n * @param locale The users's locale settings\n * @returns month and day like \"Aug 10\"\n */\nexport const formatDateShort = (dateObj: Date, locale: FrontendLocaleData) =>\nformatDateShortMem(locale).format(dateObj);\n\nconst formatDateShortMem =\n(locale: FrontendLocaleData) =>\n new Intl.DateTimeFormat(locale.language, {\n day: \"numeric\",\n month: \"short\",\n });\n\n\n/**\n * Formatting a Date to just a month with year e.g. August 2021\n * @param dateObj The date to convert\n * @param locale The users's locale settings\n * @returns month and year like \"August 2021\"\n */\nexport const formatDateMonthYear = (\ndateObj: Date,\nlocale: FrontendLocaleData\n) => formatDateMonthYearMem(locale).format(dateObj);\n\nconst formatDateMonthYearMem = (locale: FrontendLocaleData) =>\n new Intl.DateTimeFormat(locale.language, {\n month: \"long\",\n year: \"numeric\",\n });\n\n\n/**\n * Formatting a Date to just a month e.g. August\n * @param dateObj The date to convert\n * @param locale The users's locale settings\n * @returns the written out months of the date\n */\nexport const formatDateMonth = (dateObj: Date, locale: FrontendLocaleData) =>\nformatDateMonthMem(locale).format(dateObj);\n\nconst formatDateMonthMem = (locale: FrontendLocaleData) =>\n new Intl.DateTimeFormat(locale.language, {\n month: \"long\",\n });\n\n\n/**\n * Formatting a Date to just a year e.g. 2021\n * @param dateObj The date to convert\n * @param locale The users's locale settings\n * @returns the year of the date in yyyy\n */\nexport const formatDateYear = (dateObj: Date, locale: FrontendLocaleData) =>\nformatDateYearMem(locale).format(dateObj);\n\nconst formatDateYearMem = (locale: FrontendLocaleData) =>\n new Intl.DateTimeFormat(locale.language, {\n year: \"numeric\",\n });\n","import {\n HassEntities,\n HassConfig,\n Auth,\n Connection,\n MessageBase,\n HassServices,\n HassServiceTarget,\n} from \"home-assistant-js-websocket\";\nimport { HapticType } from \"./haptic\";\nimport { HASSDomEvent } from \"./fire-event\";\n\nexport interface ToggleMenuActionConfig extends BaseActionConfig {\n action: \"toggle-menu\";\n}\n\nexport interface ToggleActionConfig extends BaseActionConfig {\n action: \"toggle\";\n}\n\nexport interface CallServiceActionConfig extends BaseActionConfig {\n action: \"call-service\";\n service: string;\n service_data?: {\n entity_id?: string | [string];\n [key: string]: any;\n };\n\n target?: HassServiceTarget;\n repeat?: number;\n haptic?: HapticType;\n}\n\nexport interface NavigateActionConfig extends BaseActionConfig {\n action: \"navigate\";\n navigation_path: string;\n}\n\nexport interface UrlActionConfig extends BaseActionConfig {\n action: \"url\";\n url_path: string;\n}\n\nexport interface MoreInfoActionConfig extends BaseActionConfig {\n action: \"more-info\";\n entity?: string;\n}\n\nexport interface NoActionConfig extends BaseActionConfig {\n action: \"none\";\n}\n\nexport interface CustomActionConfig extends BaseActionConfig {\n action: \"fire-dom-event\";\n}\n\n/**\n * `repeat` and `haptic` are specifically for use in custom cards like the Button-Card\n */\nexport interface BaseActionConfig {\n confirmation?: ConfirmationRestrictionConfig;\n repeat?: number;\n haptic?: HapticType;\n}\n\nexport interface ConfirmationRestrictionConfig {\n text?: string;\n exemptions?: RestrictionConfig[];\n}\n\nexport interface RestrictionConfig {\n user: string;\n}\n\nexport type ActionConfig =\n | ToggleActionConfig\n | CallServiceActionConfig\n | NavigateActionConfig\n | UrlActionConfig\n | MoreInfoActionConfig\n | NoActionConfig\n | CustomActionConfig\n | ToggleMenuActionConfig;\n\nexport interface Window {\n // Custom panel entry point url\n customPanelJS: string;\n ShadyCSS: {\n nativeCss: boolean;\n nativeShadow: boolean;\n prepareTemplate(templateElement, elementName, elementExtension);\n styleElement(element);\n styleSubtree(element, overrideProperties);\n styleDocument(overrideProperties);\n getComputedStyleValue(element, propertyName);\n };\n}\n\ndeclare global {\n // for fire event\n interface HASSDomEvents {\n \"value-changed\": {\n value: unknown;\n };\n \"config-changed\": {\n config: any;\n };\n \"hass-more-info\": {\n entityId: string | undefined;\n };\n \"ll-rebuild\": {};\n \"ll-custom\": {};\n \"location-changed\": {\n replace: boolean;\n };\n \"show-dialog\": {};\n undefined;\n action: {\n action: string;\n };\n }\n}\n\ntype ValidHassDomEvent = keyof HASSDomEvents;\n\nexport type LocalizeFunc = (key: string, ...args: any[]) => string;\n\nexport interface Credential {\n auth_provider_type: string;\n auth_provider_id: string;\n}\n\nexport interface MFAModule {\n id: string;\n name: string;\n enabled: boolean;\n}\n\nexport interface CurrentUser {\n id: string;\n is_owner: boolean;\n is_admin: boolean;\n name: string;\n credentials: Credential[];\n mfa_modules: MFAModule[];\n}\n\nexport interface Theme {\n // Incomplete\n \"primary-color\": string;\n \"text-primary-color\": string;\n \"accent-color\": string;\n}\n\nexport interface Themes {\n default_theme: string;\n themes: { [key: string]: Theme };\n}\n\nexport interface Panel {\n component_name: string;\n config: { [key: string]: any } | null;\n icon: string | null;\n title: string | null;\n url_path: string;\n}\n\nexport interface Panels {\n [name: string]: Panel;\n}\n\nexport interface Resources {\n [language: string]: { [key: string]: string };\n}\n\nexport interface Translation {\n nativeName: string;\n isRTL: boolean;\n fingerprints: { [fragment: string]: string };\n}\n\nexport interface ServiceCallRequest {\n domain: string;\n service: string;\n serviceData?: Record;\n target?: HassServiceTarget;\n}\n\nexport interface HomeAssistant {\n auth: Auth;\n connection: Connection;\n connected: boolean;\n states: HassEntities;\n services: HassServices;\n config: HassConfig;\n themes: Themes;\n selectedTheme?: string | null;\n panels: Panels;\n panelUrl: string;\n\n // i18n\n // current effective language, in that order:\n // - backend saved user selected lanugage\n // - language in local appstorage\n // - browser language\n // - english (en)\n language: string;\n locale: FrontendLocaleData;\n // local stored language, keep that name for backward compability\n selectedLanguage: string | null;\n resources: Resources;\n localize: LocalizeFunc;\n translationMetadata: {\n fragments: string[];\n translations: {\n [lang: string]: Translation;\n };\n };\n\n dockedSidebar: boolean;\n moreInfoEntityId: string;\n user: CurrentUser;\n callService: (\n domain: ServiceCallRequest[\"domain\"],\n service: ServiceCallRequest[\"service\"],\n serviceData?: ServiceCallRequest[\"serviceData\"],\n target?: ServiceCallRequest[\"target\"]\n ) => Promise;\n callApi: (\n method: \"GET\" | \"POST\" | \"PUT\" | \"DELETE\",\n path: string,\n parameters?: { [key: string]: any }\n ) => Promise;\n fetchWithAuth: (\n path: string,\n init?: { [key: string]: any }\n ) => Promise;\n sendWS: (msg: MessageBase) => Promise;\n callWS: (msg: MessageBase) => Promise;\n}\n\nexport enum NumberFormat {\n language = \"language\",\n system = \"system\",\n comma_decimal = \"comma_decimal\",\n decimal_comma = \"decimal_comma\",\n space_comma = \"space_comma\",\n none = \"none\",\n}\n\nexport enum TimeFormat {\n language = \"language\",\n system = \"system\",\n am_pm = \"12\",\n twenty_four = \"24\",\n}\n\nexport interface FrontendLocaleData {\n language: string;\n number_format: NumberFormat;\n time_format: TimeFormat;\n}\n\nexport interface LovelaceCardConfig {\n index?: number;\n view_index?: number;\n type: string;\n [key: string]: any;\n}\n\nexport interface LovelaceCard extends HTMLElement {\n hass?: HomeAssistant;\n isPanel?: boolean;\n editMode?: boolean;\n getCardSize(): number | Promise;\n setConfig(config: LovelaceCardConfig): void;\n}\n\nexport interface LovelaceCardEditor extends HTMLElement {\n hass?: HomeAssistant;\n lovelace?: LovelaceConfig;\n setConfig(config: LovelaceCardConfig): void;\n}\n\nexport interface LovelaceConfig {\n title?: string;\n views: LovelaceViewConfig[];\n background?: string;\n}\n\nexport interface LovelaceViewConfig {\n index?: number;\n title?: string;\n badges?: Array;\n cards?: LovelaceCardConfig[];\n path?: string;\n icon?: string;\n theme?: string;\n panel?: boolean;\n background?: string;\n visible?: boolean | ShowViewConfig[];\n}\n\nexport interface ShowViewConfig {\n user?: string;\n}\n\nexport interface LovelaceBadgeConfig {\n type?: string;\n [key: string]: any;\n}\n\nexport interface ActionHandlerDetail {\n action: string;\n}\n\nexport type ActionHandlerEvent = HASSDomEvent;\n\nexport interface ActionHandlerOptions {\n hasHold?: boolean;\n hasDoubleClick?: boolean;\n}\n\nexport interface EntitiesCardEntityConfig extends EntityConfig {\n type?: string;\n secondary_info?:\n | \"entity-id\"\n | \"last-changed\"\n | \"last-triggered\"\n | \"last-updated\"\n | \"position\"\n | \"tilt-position\"\n | \"brightness\";\n action_name?: string;\n service?: string;\n service_data?: Record;\n url?: string;\n tap_action?: ActionConfig;\n hold_action?: ActionConfig;\n double_tap_action?: ActionConfig;\n state_color?: boolean;\n show_name?: boolean;\n show_icon?: boolean;\n}\n\nexport interface EntityConfig {\n entity: string;\n type?: string;\n name?: string;\n icon?: string;\n image?: string;\n}\n\nexport interface LovelaceElementConfigBase {\n type: string;\n style: Record;\n}\n","// REF: https://github.com/home-assistant/frontend/blob/dev/src/common/datetime/use_am_pm.ts\r\n\r\nimport { FrontendLocaleData, TimeFormat } from \"../types\"\r\n\r\n/**\r\n * Checking if AM/PM time format is used within the browser.\r\n * @param locale Homeassistant frontend locale data\r\n * @returns \r\n */\r\nexport const useAmPm = (locale: FrontendLocaleData): boolean => {\r\n if (\r\n locale.time_format === TimeFormat.language ||\r\n locale.time_format === TimeFormat.system\r\n ) {\r\n const testLanguage =\r\n locale.time_format === TimeFormat.language ? locale.language : undefined;\r\n const test = new Date().toLocaleString(testLanguage);\r\n return test.includes(\"AM\") || test.includes(\"PM\");\r\n }\r\n\r\n return locale.time_format === TimeFormat.am_pm;\r\n};\r\n","//REF: https://github.com/home-assistant/frontend/blob/dev/src/common/datetime/format_date_time.ts\n\nimport { FrontendLocaleData } from \"../types\";\nimport { useAmPm } from \"./use_am_pm\";\n\n// August 9, 2021, 8:23 AM\n/**\n * Formatting a dateObject to date with time e.g. August 9, 2021, 8:23 AM\n * @param dateObj The date to convert\n * @param locale The users's locale settings\n * @returns month and day like \"August 9, 2021, 8:23 AM\"\n */\nexport const formatDateTime = (dateObj: Date, locale: FrontendLocaleData) =>\n formatDateTimeMem(locale).format(dateObj);\n\nconst formatDateTimeMem = (locale: FrontendLocaleData) =>\n new Intl.DateTimeFormat(locale.language, {\n year: \"numeric\",\n month: \"long\",\n day: \"numeric\",\n hour: useAmPm(locale) ? \"numeric\" : \"2-digit\",\n minute: \"2-digit\",\n hour12: useAmPm(locale),\n });\n\n\n/**\n * Formatting a dateObject to date with time e.g. August 9, 2021, 8:23:15 AM\n * @param dateObj The date to convert\n * @param locale The users's locale settings\n * @returns month and day like \"August 9, 2021, 8:23:15 AM\"\n */\nexport const formatDateTimeWithSeconds = (\n dateObj: Date,\n locale: FrontendLocaleData\n) => formatDateTimeWithSecondsMem(locale).format(dateObj);\n\nconst formatDateTimeWithSecondsMem =\n (locale: FrontendLocaleData) =>\n new Intl.DateTimeFormat(locale.language, {\n year: \"numeric\",\n month: \"long\",\n day: \"numeric\",\n hour: useAmPm(locale) ? \"numeric\" : \"2-digit\",\n minute: \"2-digit\",\n second: \"2-digit\",\n hour12: useAmPm(locale),\n });\n\n/**\n * Formatting a Date to just date with AM/PM time e.g. 9/8/2021, 8:23 AM\n * @param dateObj The date to convert\n * @param locale The users's locale settings\n * @returns month and day like \"9/8/2021, 8:23 AM\"\n */\nexport const formatDateTimeNumeric = (\n dateObj: Date,\n locale: FrontendLocaleData\n) => formatDateTimeNumericMem(locale).format(dateObj);\n\nconst formatDateTimeNumericMem =\n (locale: FrontendLocaleData) =>\n new Intl.DateTimeFormat(locale.language, {\n year: \"numeric\",\n month: \"numeric\",\n day: \"numeric\",\n hour: \"numeric\",\n minute: \"2-digit\",\n hour12: useAmPm(locale),\n });","//REF: https://github.com/home-assistant/frontend/blob/dev/src/common/datetime/format_time.ts\n\nimport { FrontendLocaleData } from \"../types\";\nimport { useAmPm } from \"./use_am_pm\";\n\n/**\n * 9:15 PM or 21:15\n * @param dateObj The time to convert\n * @param locale The users's locale settings\n * @returns Reformated time in hh:mm\n */\n export const formatTime = (dateObj: Date, locale: FrontendLocaleData) =>\n formatTimeMem(locale).format(dateObj);\n\n const formatTimeMem =\n (locale: FrontendLocaleData) =>\n new Intl.DateTimeFormat(locale.language, {\n hour: \"numeric\",\n minute: \"2-digit\",\n hour12: useAmPm(locale),\n });\n\n/**\n* 9:15:24 PM or 21:15:24\n* @param dateObj The time to convert\n* @param locale The users's locale settings\n* @returns Reformated time in hh:mm:ss\n*/\nexport const formatTimeWithSeconds = (\n dateObj: Date,\n locale: FrontendLocaleData\n) => formatTimeWithSecondsMem(locale).format(dateObj);\n\nconst formatTimeWithSecondsMem =\n (locale: FrontendLocaleData) =>\n new Intl.DateTimeFormat(locale.language, {\n hour: useAmPm(locale) ? \"numeric\" : \"2-digit\",\n minute: \"2-digit\",\n second: \"2-digit\",\n hour12: useAmPm(locale),\n });\n\n/**\n* Tuesday 7:00 PM or Tuesday 19:00\n* @param dateObj The datetime to convert\n* @param locale The users's locale settings\n* @returns Reformated weekday/time in dddd hh:mm\n*/\nexport const formatTimeWeekday = (dateObj: Date, locale: FrontendLocaleData) =>\n formatTimeWeekdayMem(locale).format(dateObj);\n\nconst formatTimeWeekdayMem =\n (locale: FrontendLocaleData) =>\n new Intl.DateTimeFormat(locale.language, {\n hour: useAmPm(locale) ? \"numeric\" : \"2-digit\",\n minute: \"2-digit\",\n second: \"2-digit\",\n hour12: useAmPm(locale),\n }); \n","//REF: https://github.com/home-assistant/frontend/blob/dev/src/common/datetime/relative_time.ts\n\nimport { selectUnit } from \"@formatjs/intl-utils\";\nimport { FrontendLocaleData } from \"../types\";\n\n const formatRelTimeMem =\n (locale: FrontendLocaleData) =>\n new Intl.RelativeTimeFormat(locale.language, { numeric: \"auto\" });\n\n/**\n * Calculate a string representing a date object as relative time from now.\n *\n * Example output: 5 minutes ago, in 3 days.\n */\n export const relativeTime = (\n from: Date,\n locale: FrontendLocaleData,\n to?: Date,\n includeTense = true\n): string => {\n const diff = selectUnit(from, to);\n if (includeTense) {\n return formatRelTimeMem(locale).format(diff.value, diff.unit);\n }\n return Intl.NumberFormat(locale.language, {\n style: \"unit\",\n unit: diff.unit,\n unitDisplay: \"long\",\n }).format(Math.abs(diff.value));\n};\n","import { HassEntity } from \"home-assistant-js-websocket\";\nimport durationToSeconds from \"../datetime/duration_to_seconds\";\n\nexport function timerTimeRemaining(stateObj: HassEntity) {\n let timeRemaining = durationToSeconds(stateObj.attributes.remaining);\n\n if (stateObj.state === \"active\") {\n const now = new Date().getTime();\n const madeActive = new Date(stateObj.last_changed).getTime();\n timeRemaining = Math.max(timeRemaining - (now - madeActive) / 1000, 0);\n }\n\n return timeRemaining;\n}\n","/**\n * Convert a Duration hh:mm:ss format to seconds\n * @param duration hh:mm:ss formated duration\n * @returns duration in seconds\n */\n export default function durationToSeconds(duration: string): number {\n const parts = duration.split(\":\").map(Number);\n return parts[0] * 3600 + parts[1] * 60 + parts[2];\n}\n","/**\n * Apply a theme to an element by setting the CSS variables on it.\n *\n * element: Element to apply theme on.\n * themes: HASS Theme information\n * localTheme: selected theme.\n * updateMeta: boolean if we should update the theme-color meta element.\n */\nexport const applyThemesOnElement = (\n element,\n themes,\n localTheme,\n updateMeta = false\n) => {\n if (!element._themes) {\n element._themes = {};\n }\n let themeName = themes.default_theme;\n if (localTheme === \"default\" || (localTheme && themes.themes[localTheme])) {\n themeName = localTheme;\n }\n const styles = { ...element._themes };\n if (themeName !== \"default\") {\n const theme = themes.themes[themeName];\n Object.keys(theme).forEach((key) => {\n const prefixedKey = \"--\" + key;\n element._themes[prefixedKey] = \"\";\n styles[prefixedKey] = theme[key];\n });\n }\n if (element.updateStyles) {\n element.updateStyles(styles);\n } else if ((window as any).ShadyCSS) {\n // implement updateStyles() method of Polemer elements\n (window as any).ShadyCSS.styleSubtree(/** @type {!HTMLElement} */ (element), styles);\n }\n\n if (!updateMeta) {\n return;\n }\n\n const meta = document.querySelector(\"meta[name=theme-color]\");\n if (meta) {\n if (!meta.hasAttribute(\"default-content\")) {\n meta.setAttribute(\"default-content\", meta.getAttribute(\"content\")!);\n }\n const themeColor =\n styles[\"--primary-color\"] || meta.getAttribute(\"default-content\");\n meta.setAttribute(\"content\", themeColor);\n }\n}\n","import { LovelaceCard } from \"./types\";\n\nexport const computeCardSize = (card: LovelaceCard): number | Promise => {\n return typeof card.getCardSize === \"function\" ? card.getCardSize() : 4;\n};","export function computeDomain(entityId: string): string {\n return entityId.substr(0, entityId.indexOf(\".\"));\n}\n","export function computeEntity(entityId: string): string {\n return entityId.substr(entityId.indexOf(\".\") + 1);\n}\n","import { HomeAssistant } from \"./types\";\n\nexport function computeRTL(hass: HomeAssistant) {\n const lang = hass?.locale?.language || \"en\";\n if (hass.translationMetadata.translations[lang]) {\n return hass.translationMetadata.translations[lang].isRTL || false;\n }\n return false;\n}\n\nexport function computeRTLDirection(hass: HomeAssistant) {\n return computeRTL(hass) ? \"rtl\" : \"ltr\";\n}\n","import { HassEntity } from \"home-assistant-js-websocket\";\nimport { computeDomain } from \"./compute-domain\";\n\nexport function computeStateDomain(stateObj: HassEntity) {\n return computeDomain(stateObj.entity_id);\n}\n","//REF: https://github.com/home-assistant/frontend/blob/dev/src/common/number/format_number.ts\n\nimport { HassEntity } from \"home-assistant-js-websocket\";\nimport { FrontendLocaleData, NumberFormat } from \"./types\";\n\n/**\n * Returns true if the entity is considered numeric based on the attributes it has\n * @param stateObj The entity state object\n */\n export const isNumericState = (stateObj: HassEntity): boolean =>\n !!stateObj.attributes.unit_of_measurement ||\n !!stateObj.attributes.state_class;\n\nexport const numberFormatToLocale = (\n localeOptions: FrontendLocaleData\n): string | string[] | undefined => {\n switch (localeOptions.number_format) {\n case NumberFormat.comma_decimal:\n return [\"en-US\", \"en\"]; // Use United States with fallback to English formatting 1,234,567.89\n case NumberFormat.decimal_comma:\n return [\"de\", \"es\", \"it\"]; // Use German with fallback to Spanish then Italian formatting 1.234.567,89\n case NumberFormat.space_comma:\n return [\"fr\", \"sv\", \"cs\"]; // Use French with fallback to Swedish and Czech formatting 1 234 567,89\n case NumberFormat.system:\n return undefined;\n default:\n return localeOptions.language;\n }\n};\n\nexport const round = (value: number, precision = 2): number =>\n Math.round(value * 10 ** precision) / 10 ** precision;\n\n/**\n * Formats a number based on the specified language with thousands separator(s) and decimal character for better legibility.\n * @param num The number to format\n * @param locale The user-selected language and number format, from `hass.locale`\n * @param options Intl.NumberFormatOptions to use\n */\nexport const formatNumber = (\n num: string | number,\n localeOptions?: FrontendLocaleData,\n options?: Intl.NumberFormatOptions\n): string => {\n const locale = localeOptions\n ? numberFormatToLocale(localeOptions)\n : undefined;\n\n // Polyfill for Number.isNaN, which is more reliable than the global isNaN()\n Number.isNaN =\n Number.isNaN ||\n function isNaN(input) {\n return typeof input === \"number\" && isNaN(input);\n };\n\n if (\n localeOptions?.number_format !== NumberFormat.none &&\n !Number.isNaN(Number(num)) &&\n Intl\n ) {\n try {\n return new Intl.NumberFormat(\n locale,\n getDefaultFormatOptions(num, options)\n ).format(Number(num));\n } catch (err: any) {\n // Don't fail when using \"TEST\" language\n // eslint-disable-next-line no-console\n console.error(err);\n return new Intl.NumberFormat(\n undefined,\n getDefaultFormatOptions(num, options)\n ).format(Number(num));\n }\n }\n if (typeof num === \"string\") {\n return num;\n }\n return `${round(num, options?.maximumFractionDigits).toString()}${\n options?.style === \"currency\" ? ` ${options.currency}` : \"\"\n }`;\n};\n\n/**\n * Generates default options for Intl.NumberFormat\n * @param num The number to be formatted\n * @param options The Intl.NumberFormatOptions that should be included in the returned options\n */\nconst getDefaultFormatOptions = (\n num: string | number,\n options?: Intl.NumberFormatOptions\n): Intl.NumberFormatOptions => {\n const defaultOptions: Intl.NumberFormatOptions = {\n maximumFractionDigits: 2,\n ...options,\n };\n\n if (typeof num !== \"string\") {\n return defaultOptions;\n }\n\n // Keep decimal trailing zeros if they are present in a string numeric value\n if (\n !options ||\n (!options.minimumFractionDigits && !options.maximumFractionDigits)\n ) {\n const digits = num.indexOf(\".\") > -1 ? num.split(\".\")[1].length : 0;\n defaultOptions.minimumFractionDigits = digits;\n defaultOptions.maximumFractionDigits = digits;\n }\n\n return defaultOptions;\n};\n","import { HassEntity } from \"home-assistant-js-websocket\";\nimport { formatDateTime } from \"./datetime/format_date_time\";\nimport { formatDate } from \"./datetime/format_date\";\nimport { formatTime } from \"./datetime/format_time\";\nimport { LocalizeFunc } from \"./translations/localize\";\nimport { computeStateDomain } from \"./compute-state-domain\";\nimport { FrontendLocaleData } from \"./types\";\nimport { formatNumber, isNumericState } from \"./format-number\";\n\nexport const computeStateDisplay = (\n localize: LocalizeFunc,\n stateObj: HassEntity,\n locale: FrontendLocaleData,\n state?: string\n): string => {\n const compareState = state !== undefined ? state : stateObj.state;\n\n if (compareState === \"unknown\" || compareState === \"unavailable\") {\n return localize(`state.default.${compareState}`);\n }\n\n // Entities with a `unit_of_measurement` or `state_class` are numeric values and should use `formatNumber`\n if (isNumericState(stateObj)) {\n if (stateObj.attributes.device_class === \"monetary\") {\n try {\n return formatNumber(compareState, locale, {\n style: \"currency\",\n currency: stateObj.attributes.unit_of_measurement,\n });\n } catch (_err) {\n // fallback to default\n }\n }\n return `${formatNumber(compareState, locale)}${\n stateObj.attributes.unit_of_measurement\n ? \" \" + stateObj.attributes.unit_of_measurement\n : \"\"\n }`;\n }\n\n const domain = computeStateDomain(stateObj);\n\n if (domain === \"input_datetime\") {\n if (state !== undefined) {\n // If trying to display an explicit state, need to parse the explict state to `Date` then format.\n // Attributes aren't available, we have to use `state`.\n try {\n const components = state.split(\" \");\n if (components.length === 2) {\n // Date and time.\n return formatDateTime(new Date(components.join(\"T\")), locale);\n }\n if (components.length === 1) {\n if (state.includes(\"-\")) {\n // Date only.\n return formatDate(new Date(`${state}T00:00`), locale);\n }\n if (state.includes(\":\")) {\n // Time only.\n const now = new Date();\n return formatTime(\n new Date(`${now.toISOString().split(\"T\")[0]}T${state}`),\n locale\n );\n }\n }\n return state;\n } catch (_e) {\n // Formatting methods may throw error if date parsing doesn't go well,\n // just return the state string in that case.\n return state;\n }\n } else {\n // If not trying to display an explicit state, create `Date` object from `stateObj`'s attributes then format.\n let date: Date;\n if (stateObj.attributes.has_date && stateObj.attributes.has_time) {\n date = new Date(\n stateObj.attributes.year,\n stateObj.attributes.month - 1,\n stateObj.attributes.day,\n stateObj.attributes.hour,\n stateObj.attributes.minute\n );\n return formatDateTime(date, locale);\n }\n if (stateObj.attributes.has_date) {\n date = new Date(\n stateObj.attributes.year,\n stateObj.attributes.month - 1,\n stateObj.attributes.day\n );\n return formatDate(date, locale);\n }\n if (stateObj.attributes.has_time) {\n date = new Date();\n date.setHours(stateObj.attributes.hour, stateObj.attributes.minute);\n return formatTime(date, locale);\n }\n return stateObj.state;\n }\n }\n\n if (domain === \"humidifier\") {\n if (compareState === \"on\" && stateObj.attributes.humidity) {\n return `${stateObj.attributes.humidity} %`;\n }\n }\n\n // `counter` `number` and `input_number` domains do not have a unit of measurement but should still use `formatNumber`\n if (\n domain === \"counter\" ||\n domain === \"number\" ||\n domain === \"input_number\"\n ) {\n return formatNumber(compareState, locale);\n }\n\n return (\n // Return device class translation\n (stateObj.attributes.device_class &&\n localize(\n `component.${domain}.state.${stateObj.attributes.device_class}.${compareState}`\n )) ||\n // Return default translation\n localize(`component.${domain}.state._.${compareState}`) ||\n // We don't know! Return the raw state.\n compareState\n );\n};","/** Constants to be used in the frontend. */\n\n// Constants should be alphabetically sorted by name.\n// Arrays with values should be alphabetically sorted if order doesn't matter.\n// Each constant should have a description what it is supposed to be used for.\n\n/** Icon to use when no icon specified for domain. */\nexport const DEFAULT_DOMAIN_ICON = \"mdi:bookmark\";\n\n/** Panel to show when no panel is picked. */\nexport const DEFAULT_PANEL = \"lovelace\";\n\n/** Domains that have a state card. */\nexport const DOMAINS_WITH_CARD = [\n \"climate\",\n \"cover\",\n \"configurator\",\n \"input_select\",\n \"input_number\",\n \"input_text\",\n \"lock\",\n \"media_player\",\n \"scene\",\n \"script\",\n \"timer\",\n \"vacuum\",\n \"water_heater\",\n \"weblink\"\n];\n\n/** Domains with separate more info dialog. */\nexport const DOMAINS_WITH_MORE_INFO = [\n \"alarm_control_panel\",\n \"automation\",\n \"camera\",\n \"climate\",\n \"configurator\",\n \"cover\",\n \"fan\",\n \"group\",\n \"history_graph\",\n \"input_datetime\",\n \"light\",\n \"lock\",\n \"media_player\",\n \"script\",\n \"sun\",\n \"updater\",\n \"vacuum\",\n \"water_heater\",\n \"weather\"\n];\n\n/** Domains that show no more info dialog. */\nexport const DOMAINS_HIDE_MORE_INFO = [\n \"input_number\",\n \"input_select\",\n \"input_text\",\n \"scene\",\n \"weblink\"\n];\n\n/** Domains that should have the history hidden in the more info dialog. */\nexport const DOMAINS_MORE_INFO_NO_HISTORY = [\n \"camera\",\n \"configurator\",\n \"history_graph\",\n \"scene\"\n];\n\n/** States that we consider \"off\". */\nexport const STATES_OFF = [\"closed\", \"locked\", \"off\"];\n\n/** Domains where we allow toggle in Lovelace. */\nexport const DOMAINS_TOGGLE = new Set([\n \"fan\",\n \"input_boolean\",\n \"light\",\n \"switch\",\n \"group\",\n \"automation\"\n]);\n\n/** Temperature units. */\nexport const UNIT_C = \"°C\";\nexport const UNIT_F = \"°F\";\n\n/** Entity ID of the default view. */\nexport const DEFAULT_VIEW_ENTITY_ID = \"group.default_view\";\n","// Polymer legacy event helpers used courtesy of the Polymer project.\n//\n// Copyright (c) 2017 The Polymer Authors. All rights reserved.\n//\n// Redistribution and use in source and binary forms, with or without\n// modification, are permitted provided that the following conditions are\n// met:\n//\n// * Redistributions of source code must retain the above copyright\n// notice, this list of conditions and the following disclaimer.\n// * Redistributions in binary form must reproduce the above\n// copyright notice, this list of conditions and the following disclaimer\n// in the documentation and/or other materials provided with the\n// distribution.\n// * Neither the name of Google Inc. nor the names of its\n// contributors may be used to endorse or promote products derived from\n// this software without specific prior written permission.\n//\n// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n// \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\ndeclare global {\n // tslint:disable-next-line\n interface HASSDomEvents {}\n}\n\nexport type ValidHassDomEvent = keyof HASSDomEvents;\n\nexport interface HASSDomEvent extends Event {\n detail: T;\n}\n\n/**\n * Dispatches a custom event with an optional detail value.\n *\n * @param {string} type Name of event type.\n * @param {*=} detail Detail value containing event-specific\n * payload.\n * @param {{ bubbles: (boolean|undefined),\n * cancelable: (boolean|undefined),\n * composed: (boolean|undefined) }=}\n * options Object specifying options. These may include:\n * `bubbles` (boolean, defaults to `true`),\n * `cancelable` (boolean, defaults to false), and\n * `node` on which to fire the event (HTMLElement, defaults to `this`).\n * @return {Event} The new event that was fired.\n */\nexport const fireEvent = (\n node: HTMLElement | Window,\n type: HassEvent,\n detail?: HASSDomEvents[HassEvent],\n options?: {\n bubbles?: boolean;\n cancelable?: boolean;\n composed?: boolean;\n }\n) => {\n options = options || {};\n // @ts-ignore\n detail = detail === null || detail === undefined ? {} : detail;\n const event = new Event(type, {\n bubbles: options.bubbles === undefined ? true : options.bubbles,\n cancelable: Boolean(options.cancelable),\n composed: options.composed === undefined ? true : options.composed\n });\n (event as any).detail = detail;\n node.dispatchEvent(event);\n return event;\n};\n","import { fireEvent } from \"./fire-event\";\n\nconst SPECIAL_TYPES = new Set([\n \"call-service\",\n \"divider\",\n \"section\",\n \"weblink\",\n \"cast\",\n \"select\"\n]);\nconst DOMAIN_TO_ELEMENT_TYPE = {\n alert: \"toggle\",\n automation: \"toggle\",\n climate: \"climate\",\n cover: \"cover\",\n fan: \"toggle\",\n group: \"group\",\n input_boolean: \"toggle\",\n input_number: \"input-number\",\n input_select: \"input-select\",\n input_text: \"input-text\",\n light: \"toggle\",\n lock: \"lock\",\n media_player: \"media-player\",\n remote: \"toggle\",\n scene: \"scene\",\n script: \"script\",\n sensor: \"sensor\",\n timer: \"timer\",\n switch: \"toggle\",\n vacuum: \"toggle\",\n // Temporary. Once climate is rewritten,\n // water heater should get it's own row.\n water_heater: \"climate\",\n input_datetime: \"input-datetime\"\n};\n\nexport const createThing = (cardConfig, isRow = false) => {\n const _createError = (error, config) => {\n return _createThing(\n \"hui-error-card\",\n {\n type: \"error\",\n error,\n config\n }\n );\n };\n\n const _createThing = (tag, config) => {\n const element = window.document.createElement(tag);\n try {\n // Preventing an error-card infinity loop: https://github.com/custom-cards/custom-card-helpers/issues/54\n if (!element.setConfig) return;\n element.setConfig(config);\n } catch (err) {\n console.error(tag, err);\n return _createError((err as Error).message, config);\n }\n return element;\n };\n\n if (!cardConfig || typeof cardConfig !== \"object\" || (!isRow && !cardConfig.type))\n return _createError(\"No type defined\", cardConfig);\n let tag = cardConfig.type;\n if (tag && tag.startsWith(\"custom:\")) {\n tag = tag.substr(\"custom:\".length);\n } else if (isRow) {\n if (SPECIAL_TYPES.has(tag)) {\n tag = `hui-${tag}-row`;\n } else {\n if (!cardConfig.entity) {\n return _createError(\"Invalid config given.\", cardConfig);\n }\n \n const domain = cardConfig.entity.split(\".\", 1)[0];\n tag = `hui-${DOMAIN_TO_ELEMENT_TYPE[domain] || \"text\"}-entity-row`;\n }\n } else {\n tag = `hui-${tag}-card`;\n }\n\n if (customElements.get(tag)) return _createThing(tag, cardConfig);\n\n // If element doesn't exist (yet) create an error\n const element = _createError(\n `Custom element doesn't exist: ${cardConfig.type}.`,\n cardConfig\n );\n element.style.display = \"None\";\n const timer = setTimeout(() => {\n element.style.display = \"\";\n }, 2000);\n // Remove error if element is defined later\n customElements.whenDefined(cardConfig.type).then(() => {\n clearTimeout(timer);\n fireEvent(element, \"ll-rebuild\", {}, element);\n });\n\n return element;\n};\n","/**\r\n * Returns a function, that, as long as it continues to be invoked, will not be triggered. It will be called after it stops being called for `wait` ms.\r\n * This can be usefull for ResizeObservers for example.\r\n * @param func The function you want to debounce\r\n * @param wait Period to wait in ms\r\n * @param immediate Triggering on the leading edge instead of the trailing\r\n * @returns Debounced Function\r\n */\r\n// eslint-disable-next-line: ban-types\r\nexport const debounce = unknown>(\r\n func: T,\r\n wait: number,\r\n immediate = false\r\n): T => {\r\n let timeout;\r\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\r\n // @ts-ignore\r\n return function (...args) {\r\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\r\n // @ts-ignore\r\n // eslint-disable-next-line @typescript-eslint/no-this-alias\r\n const context = this;\r\n const later = () => {\r\n timeout = null;\r\n if (!immediate) {\r\n func.apply(context, args);\r\n }\r\n };\r\n const callNow = immediate && !timeout;\r\n clearTimeout(timeout);\r\n timeout = setTimeout(later, wait);\r\n if (callNow) {\r\n func.apply(context, args);\r\n }\r\n };\r\n};\r\n","/**\n * Return the icon to be used for a domain.\n *\n * Optionally pass in a state to influence the domain icon.\n */\nimport { DEFAULT_DOMAIN_ICON } from \"./const\";\n\nexport const fixedIcons = {\n alert: \"mdi:alert\",\n automation: \"mdi:playlist-play\",\n calendar: \"mdi:calendar\",\n camera: \"mdi:video\",\n climate: \"mdi:thermostat\",\n configurator: \"mdi:settings\",\n conversation: \"mdi:text-to-speech\",\n device_tracker: \"mdi:account\",\n fan: \"mdi:fan\",\n group: \"mdi:google-circles-communities\",\n history_graph: \"mdi:chart-line\",\n homeassistant: \"mdi:home-assistant\",\n homekit: \"mdi:home-automation\",\n image_processing: \"mdi:image-filter-frames\",\n input_boolean: \"mdi:drawing\",\n input_datetime: \"mdi:calendar-clock\",\n input_number: \"mdi:ray-vertex\",\n input_select: \"mdi:format-list-bulleted\",\n input_text: \"mdi:textbox\",\n light: \"mdi:lightbulb\",\n mailbox: \"mdi:mailbox\",\n notify: \"mdi:comment-alert\",\n person: \"mdi:account\",\n plant: \"mdi:flower\",\n proximity: \"mdi:apple-safari\",\n remote: \"mdi:remote\",\n scene: \"mdi:google-pages\",\n script: \"mdi:file-document\",\n sensor: \"mdi:eye\",\n simple_alarm: \"mdi:bell\",\n sun: \"mdi:white-balance-sunny\",\n switch: \"mdi:flash\",\n timer: \"mdi:timer\",\n updater: \"mdi:cloud-upload\",\n vacuum: \"mdi:robot-vacuum\",\n water_heater: \"mdi:thermometer\",\n weblink: \"mdi:open-in-new\"\n};\n\nexport function domainIcon(domain: string, state?: string): string {\n if (domain in fixedIcons) {\n return fixedIcons[domain];\n }\n\n switch (domain) {\n case \"alarm_control_panel\":\n switch (state) {\n case \"armed_home\":\n return \"mdi:bell-plus\";\n case \"armed_night\":\n return \"mdi:bell-sleep\";\n case \"disarmed\":\n return \"mdi:bell-outline\";\n case \"triggered\":\n return \"mdi:bell-ring\";\n default:\n return \"mdi:bell\";\n }\n\n case \"binary_sensor\":\n return state && state === \"off\"\n ? \"mdi:radiobox-blank\"\n : \"mdi:checkbox-marked-circle\";\n\n case \"cover\":\n return state === \"closed\" ? \"mdi:window-closed\" : \"mdi:window-open\";\n\n case \"lock\":\n return state && state === \"unlocked\" ? \"mdi:lock-open\" : \"mdi:lock\";\n\n case \"media_player\":\n return state && state !== \"off\" && state !== \"idle\"\n ? \"mdi:cast-connected\"\n : \"mdi:cast\";\n\n case \"zwave\":\n switch (state) {\n case \"dead\":\n return \"mdi:emoticon-dead\";\n case \"sleeping\":\n return \"mdi:sleep\";\n case \"initializing\":\n return \"mdi:timer-sand\";\n default:\n return \"mdi:z-wave\";\n }\n\n default:\n // tslint:disable-next-line\n console.warn(\n \"Unable to find icon for domain \" + domain + \" (\" + state + \")\"\n );\n return DEFAULT_DOMAIN_ICON;\n }\n}\n","import { HassEntity } from \"home-assistant-js-websocket\";\n\nexport const evaluateFilter = (stateObj: HassEntity, filter: any): boolean => {\n const operator = filter.operator || \"==\";\n const value = filter.value || filter;\n const state = filter.attribute\n ? stateObj.attributes[filter.attribute]\n : stateObj.state;\n\n switch (operator) {\n case \"==\":\n return state === value;\n case \"<=\":\n return state <= value;\n case \"<\":\n return state < value;\n case \">=\":\n return state >= value;\n case \">\":\n return state > value;\n case \"!=\":\n return state !== value;\n case \"regex\": {\n return state.match(value);\n }\n default:\n return false;\n }\n};\n","import { HASSDomEvent, fireEvent } from \"./fire-event\";\n\n/**\n * Broadcast haptic feedback requests\n */\n\n\n// Allowed types are from iOS HIG.\n// https://developer.apple.com/design/human-interface-guidelines/ios/user-interaction/feedback/#haptics\n// Implementors on platforms other than iOS should attempt to match the patterns (shown in HIG) as closely as possible.\nexport type HapticType =\n | \"success\"\n | \"warning\"\n | \"failure\"\n | \"light\"\n | \"medium\"\n | \"heavy\"\n | \"selection\";\n\ndeclare global {\n // for fire event\n interface HASSDomEvents {\n haptic: HapticType;\n }\n\n interface GlobalEventHandlersEventMap {\n haptic: HASSDomEvent;\n }\n}\n\nexport const forwardHaptic = (hapticType: HapticType) => {\n fireEvent(window, \"haptic\", hapticType);\n};\n","import { fireEvent } from \"./fire-event\";\n\ndeclare global {\n // for fire event\n interface HASSDomEvents {\n \"location-changed\": {\n replace: boolean;\n };\n }\n}\n\nexport const navigate = (\n _node: any,\n path: string,\n replace: boolean = false\n) => {\n if (replace) {\n history.replaceState(null, \"\", path);\n } else {\n history.pushState(null, \"\", path);\n }\n fireEvent(window, \"location-changed\", {\n replace\n });\n};\n","import { HomeAssistant } from \"./types\";\nimport { computeDomain } from \"./compute-domain\";\n\nexport const turnOnOffEntity = (\n hass: HomeAssistant,\n entityId: string,\n turnOn = true\n): Promise => {\n const stateDomain = computeDomain(entityId);\n const serviceDomain = stateDomain === \"group\" ? \"homeassistant\" : stateDomain;\n\n let service;\n switch (stateDomain) {\n case \"lock\":\n service = turnOn ? \"unlock\" : \"lock\";\n break;\n case \"cover\":\n service = turnOn ? \"open_cover\" : \"close_cover\";\n break;\n default:\n service = turnOn ? \"turn_on\" : \"turn_off\";\n }\n\n return hass.callService(serviceDomain, service, { entity_id: entityId });\n};\n","import { STATES_OFF } from \"./const\";\nimport { turnOnOffEntity } from \"./turn-on-off-entity\";\nimport { HomeAssistant } from \"./types\";\n\nexport const toggleEntity = (\n hass: HomeAssistant,\n entityId: string\n): Promise => {\n const turnOn = STATES_OFF.includes(hass.states[entityId].state);\n return turnOnOffEntity(hass, entityId, turnOn);\n};\n","import { HomeAssistant, ActionConfig } from \"./types\";\nimport { forwardHaptic } from \"./haptic\";\nimport { fireEvent } from \"./fire-event\";\nimport { navigate } from \"./navigate\";\nimport { toggleEntity } from \"./toggle-entity\";\n\nexport const handleActionConfig = (\n node: HTMLElement,\n hass: HomeAssistant,\n config: {\n entity?: string;\n camera_image?: string;\n hold_action?: ActionConfig;\n tap_action?: ActionConfig;\n double_tap_action?: ActionConfig;\n },\n actionConfig: ActionConfig | undefined\n): void => {\n if (!actionConfig) {\n actionConfig = {\n action: \"more-info\",\n };\n }\n\n if (\n actionConfig.confirmation &&\n (!actionConfig.confirmation.exemptions ||\n !actionConfig.confirmation.exemptions.some(\n (e) => e.user === hass!.user!.id\n ))\n ) {\n forwardHaptic(\"warning\");\n\n if (\n !confirm(\n actionConfig.confirmation.text ||\n `Are you sure you want to ${actionConfig.action}?`\n )\n ) {\n return;\n }\n }\n\n switch (actionConfig.action) {\n case \"more-info\":\n if (config.entity || config.camera_image) {\n fireEvent(node, \"hass-more-info\", {\n entityId: config.entity ? config.entity : config.camera_image!,\n });\n }\n break;\n case \"navigate\":\n if (actionConfig.navigation_path) {\n navigate(node, actionConfig.navigation_path);\n }\n break;\n case \"url\":\n if (actionConfig.url_path) {\n window.open(actionConfig.url_path);\n }\n break;\n case \"toggle\":\n if (config.entity) {\n toggleEntity(hass, config.entity!);\n forwardHaptic(\"success\");\n }\n break;\n case \"call-service\": {\n if (!actionConfig.service) {\n forwardHaptic(\"failure\");\n return;\n }\n const [domain, service] = actionConfig.service.split(\".\", 2);\n hass.callService(domain, service, actionConfig.service_data, actionConfig.target);\n forwardHaptic(\"success\");\n break;\n }\n case \"fire-dom-event\": {\n fireEvent(node, \"ll-custom\", actionConfig);\n }\n }\n};\n\nexport const handleAction = (\n node: HTMLElement,\n hass: HomeAssistant,\n config: {\n entity?: string;\n camera_image?: string;\n hold_action?: ActionConfig;\n tap_action?: ActionConfig;\n double_tap_action?: ActionConfig;\n },\n action: string\n): void => {\n let actionConfig: ActionConfig | undefined;\n\n if (action === \"double_tap\" && config.double_tap_action) {\n actionConfig = config.double_tap_action;\n } else if (action === \"hold\" && config.hold_action) {\n actionConfig = config.hold_action;\n } else if (action === \"tap\" && config.tap_action) {\n actionConfig = config.tap_action;\n }\n\n handleActionConfig(node, hass, config, actionConfig);\n};\n","import { HomeAssistant, ActionConfig } from \"./types\";\nimport { fireEvent } from \"./fire-event\";\nimport { forwardHaptic } from \"./haptic\";\nimport { navigate } from \"./navigate\";\nimport { toggleEntity } from \"./toggle-entity\";\n\nexport const handleClick = (\n node: HTMLElement,\n hass: HomeAssistant,\n config: {\n entity?: string;\n camera_image?: string;\n hold_action?: ActionConfig;\n tap_action?: ActionConfig;\n double_tap_action?: ActionConfig;\n },\n hold: boolean,\n dblClick: boolean\n): void => {\n let actionConfig: ActionConfig | undefined;\n\n if (dblClick && config.double_tap_action) {\n actionConfig = config.double_tap_action;\n } else if (hold && config.hold_action) {\n actionConfig = config.hold_action;\n } else if (!hold && config.tap_action) {\n actionConfig = config.tap_action;\n }\n\n if (!actionConfig) {\n actionConfig = {\n action: \"more-info\"\n };\n }\n\n if (\n actionConfig.confirmation &&\n (!actionConfig.confirmation.exemptions ||\n !actionConfig.confirmation.exemptions.some(\n e => e.user === hass!.user!.id\n ))\n ) {\n if (\n !confirm(\n actionConfig.confirmation.text ||\n `Are you sure you want to ${actionConfig.action}?`\n )\n ) {\n return;\n }\n }\n\n switch (actionConfig.action) {\n case \"more-info\":\n if (actionConfig.entity || config.entity || config.camera_image) {\n fireEvent(node, \"hass-more-info\", {\n entityId: actionConfig.entity\n ? actionConfig.entity\n : config.entity\n ? config.entity\n : config.camera_image\n });\n if (actionConfig.haptic) forwardHaptic(actionConfig.haptic);\n }\n break;\n case \"navigate\":\n if (actionConfig.navigation_path) {\n navigate(node, actionConfig.navigation_path);\n if (actionConfig.haptic) forwardHaptic(actionConfig.haptic);\n }\n break;\n case \"url\":\n actionConfig.url_path && window.open(actionConfig.url_path);\n if (actionConfig.haptic) forwardHaptic(actionConfig.haptic);\n break;\n case \"toggle\":\n if (config.entity) {\n toggleEntity(hass, config.entity!);\n if (actionConfig.haptic) forwardHaptic(actionConfig.haptic);\n }\n break;\n case \"call-service\": {\n if (!actionConfig.service) {\n return;\n }\n const [domain, service] = actionConfig.service.split(\".\", 2);\n const serviceData = { ...actionConfig.service_data };\n if (serviceData.entity_id === \"entity\") {\n serviceData.entity_id = config.entity;\n }\n hass.callService(domain, service, serviceData, actionConfig.target);\n if (actionConfig.haptic) forwardHaptic(actionConfig.haptic);\n break;\n }\n case \"fire-dom-event\": {\n fireEvent(node, \"ll-custom\", actionConfig);\n if (actionConfig.haptic) forwardHaptic(actionConfig.haptic);\n break;\n }\n }\n};\n","import { ActionConfig } from \"./types\";\n\nexport function hasAction(config?: ActionConfig): boolean {\n return config !== undefined && config.action !== \"none\";\n}\n","import { PropertyValues } from \"lit\";\n\nimport { HomeAssistant } from \"./types\";\n\n// Check if config or Entity changed\nexport function hasConfigOrEntityChanged(\n element: any,\n changedProps: PropertyValues,\n forceUpdate: Boolean,\n): boolean {\n if (changedProps.has('config') || forceUpdate) {\n return true;\n }\n\n if (element.config!.entity) {\n const oldHass = changedProps.get('hass') as HomeAssistant | undefined;\n if (oldHass) {\n return (\n oldHass.states[element.config!.entity]\n !== element.hass!.states[element.config!.entity]\n );\n }\n return true;\n } else {\n return false;\n }\n}","import { ActionConfig } from \"./types\";\n\n// Check if config or Entity changed\nexport function hasDoubleClick(config?: ActionConfig): boolean {\n return config !== undefined && config.action !== \"none\";\n}","import { HomeAssistant } from \"./types\";\nimport { STATES_OFF } from \"./const\";\nimport { computeDomain } from \"./compute-domain\";\n\nexport const turnOnOffEntities = (\n hass: HomeAssistant,\n entityIds: string[],\n turnOn = true\n): void => {\n const domainsToCall = {};\n entityIds.forEach((entityId) => {\n if (STATES_OFF.includes(hass.states[entityId].state) === turnOn) {\n const stateDomain = computeDomain(entityId);\n const serviceDomain = [\"cover\", \"lock\"].includes(stateDomain)\n ? stateDomain\n : \"homeassistant\";\n\n if (!(serviceDomain in domainsToCall)) {\n domainsToCall[serviceDomain] = [];\n }\n domainsToCall[serviceDomain].push(entityId);\n }\n });\n\n Object.keys(domainsToCall).forEach((domain) => {\n let service;\n switch (domain) {\n case \"lock\":\n service = turnOn ? \"unlock\" : \"lock\";\n break;\n case \"cover\":\n service = turnOn ? \"open_cover\" : \"close_cover\";\n break;\n default:\n service = turnOn ? \"turn_on\" : \"turn_off\";\n }\n\n const entities = domainsToCall[domain];\n hass.callService(domain, service, { entity_id: entities });\n });\n};\n","export const getLovelace = () => {\n let root: any = document.querySelector('home-assistant');\n root = root && root.shadowRoot;\n root = root && root.querySelector('home-assistant-main');\n root = root && root.shadowRoot;\n root = root && root.querySelector('app-drawer-layout partial-panel-resolver');\n root = root && root.shadowRoot || root;\n root = root && root.querySelector('ha-panel-lovelace');\n root = root && root.shadowRoot;\n root = root && root.querySelector('hui-root');\n if (root) {\n const ll = root.lovelace;\n ll.current_view = root.___curView;\n return ll;\n }\n return null;\n}\n","/** Return an icon representing a sensor state. */\nimport { HassEntity } from \"home-assistant-js-websocket\";\nimport { UNIT_C, UNIT_F } from \"./const\";\nimport { domainIcon } from \"./domain_icons\";\n\nconst fixedDeviceClassIcons = {\n humidity: \"mdi:water-percent\",\n illuminance: \"mdi:brightness-5\",\n temperature: \"mdi:thermometer\",\n pressure: \"mdi:gauge\",\n power: \"mdi:flash\",\n signal_strength: \"mdi:wifi\",\n};\n\nexport const sensorIcon = (state: HassEntity) => {\n const dclass = state.attributes.device_class;\n\n if (dclass && dclass in fixedDeviceClassIcons) {\n return fixedDeviceClassIcons[dclass];\n }\n if (dclass === \"battery\") {\n const battery = Number(state.state);\n if (isNaN(battery)) {\n return \"mdi:battery-unknown\";\n }\n const batteryRound = Math.round(battery / 10) * 10;\n if (batteryRound >= 100) {\n return \"mdi:battery\";\n }\n if (batteryRound <= 0) {\n return \"mdi:battery-alert\";\n }\n // Will return one of the following icons: (listed so extractor picks up)\n // mdi:battery-10\n // mdi:battery-20\n // mdi:battery-30\n // mdi:battery-40\n // mdi:battery-50\n // mdi:battery-60\n // mdi:battery-70\n // mdi:battery-80\n // mdi:battery-90\n // We obscure 'hass' in iconname so this name does not get picked up\n return `${\"hass\"}:battery-${batteryRound}`;\n }\n\n const unit = state.attributes.unit_of_measurement;\n if (unit === UNIT_C || unit === UNIT_F) {\n return \"mdi:thermometer\";\n }\n return domainIcon(\"sensor\");\n};\n","import { HassEntity } from \"home-assistant-js-websocket\";\nimport { computeDomain } from \"./compute-domain\";\nimport { DEFAULT_DOMAIN_ICON } from \"./const\";\nimport { binarySensorIcon } from \"./binary_sensor_icon\";\nimport { coverIcon } from \"./cover_icon\";\nimport { sensorIcon } from \"./sensor_icon\";\nimport { inputDateTimeIcon } from \"./input_datetime_icon\";\nimport { domainIcon } from \"./domain_icons\";\n\nconst domainIcons = {\n binary_sensor: binarySensorIcon,\n cover: coverIcon,\n sensor: sensorIcon,\n input_datetime: inputDateTimeIcon,\n};\n\nexport const stateIcon = (state: HassEntity) => {\n if (!state) {\n return DEFAULT_DOMAIN_ICON;\n }\n if (state.attributes.icon) {\n return state.attributes.icon;\n }\n\n const domain = computeDomain(state.entity_id);\n\n if (domain in domainIcons) {\n return domainIcons[domain](state);\n }\n return domainIcon(domain, state.state);\n};\n","import { HassEntity } from \"home-assistant-js-websocket\";\n\n/** Return an icon representing a binary sensor state. */\n\nexport const binarySensorIcon = (state?: string, stateObj?: HassEntity) => {\n const is_off = state === \"off\";\n switch (stateObj?.attributes.device_class) {\n case \"battery\":\n return is_off ? \"mdi:battery\" : \"mdi:battery-outline\";\n case \"battery_charging\":\n return is_off ? \"mdi:battery\" : \"mdi:battery-charging\";\n case \"cold\":\n return is_off ? \"mdi:thermometer\" : \"mdi:snowflake\";\n case \"connectivity\":\n return is_off ? \"mdi:server-network-off\" : \"mdi:server-network\";\n case \"door\":\n return is_off ? \"mdi:door-closed\" : \"mdi:door-open\";\n case \"garage_door\":\n return is_off ? \"mdi:garage\" : \"mdi:garage-open\";\n case \"power\":\n return is_off ? \"mdi:power-plug-off\" : \"mdi:power-plug\";\n case \"gas\":\n case \"problem\":\n case \"safety\":\n case \"tamper\":\n return is_off ? \"mdi:check-circle\" : \"mdi:alert-circle\";\n case \"smoke\":\n return is_off ? \"mdi:check-circle\" : \"mdi:smoke\";\n case \"heat\":\n return is_off ? \"mdi:thermometer\" : \"mdi:fire\";\n case \"light\":\n return is_off ? \"mdi:brightness-5\" : \"mdi:brightness-7\";\n case \"lock\":\n return is_off ? \"mdi:lock\" : \"mdi:lock-open\";\n case \"moisture\":\n return is_off ? \"mdi:water-off\" : \"mdi:water\";\n case \"motion\":\n return is_off ? \"mdi:walk\" : \"mdi:run\";\n case \"occupancy\":\n return is_off ? \"mdi:home-outline\" : \"mdi:home\";\n case \"opening\":\n return is_off ? \"mdi:square\" : \"mdi:square-outline\";\n case \"plug\":\n return is_off ? \"mdi:power-plug-off\" : \"mdi:power-plug\";\n case \"presence\":\n return is_off ? \"mdi:home-outline\" : \"mdi:home\";\n case \"running\":\n return is_off ? \"mdi:stop\" : \"mdi:play\";\n case \"sound\":\n return is_off ? \"mdi:music-note-off\" : \"mdi:music-note\";\n case \"update\":\n return is_off ? \"mdi:package\" : \"mdi:package-up\";\n case \"vibration\":\n return is_off ? \"mdi:crop-portrait\" : \"mdi:vibrate\";\n case \"window\":\n return is_off ? \"mdi:window-closed\" : \"mdi:window-open\";\n default:\n return is_off ? \"mdi:radiobox-blank\" : \"mdi:checkbox-marked-circle\";\n }\n};\n","/** Return an icon representing a cover state. */\nimport { HassEntity } from \"home-assistant-js-websocket\";\nimport { domainIcon } from \"./domain_icons\";\n\nexport const coverIcon = (state: HassEntity): string => {\n const open = state.state !== \"closed\";\n switch (state.attributes.device_class) {\n case \"garage\":\n return open ? \"mdi:garage-open\" : \"mdi:garage\";\n case \"door\":\n return open ? \"mdi:door-open\" : \"mdi:door-closed\";\n case \"shutter\":\n return open ? \"mdi:window-shutter-open\" : \"mdi:window-shutter\";\n case \"blind\":\n return open ? \"mdi:blinds-open\" : \"mdi:blinds\";\n case \"window\":\n return open ? \"mdi:window-open\" : \"mdi:window-closed\";\n default:\n return domainIcon(\"cover\", state.state);\n }\n};\n","/** Return an icon representing an input datetime state. */\nimport { domainIcon } from \"./domain_icons\";\nimport { HassEntity } from \"home-assistant-js-websocket\";\n\nexport const inputDateTimeIcon = (state: HassEntity): string => {\n if (!state.attributes.has_date) {\n return \"mdi:clock\";\n }\n if (!state.attributes.has_time) {\n return \"mdi:calendar\";\n }\n return domainIcon(\"input_datetime\");\n};\n"],"names":["formatDateWeekday","dateObj","locale","formatDateWeekdayMem","format","Intl","DateTimeFormat","language","weekday","month","day","formatDate","formatDateMem","year","formatDateNumeric","formatDateNumericMem","formatDateShort","formatDateShortMem","formatDateMonthYear","formatDateMonthYearMem","formatDateMonth","formatDateMonthMem","formatDateYear","formatDateYearMem","NumberFormat","TimeFormat","useAmPm","time_format","system","testLanguage","undefined","test","Date","toLocaleString","includes","am_pm","formatDateTime","formatDateTimeMem","hour","minute","hour12","formatDateTimeWithSeconds","formatDateTimeWithSecondsMem","second","formatDateTimeNumeric","formatDateTimeNumericMem","formatTime","formatTimeMem","formatTimeWithSeconds","formatTimeWithSecondsMem","formatTimeWeekday","formatTimeWeekdayMem","relativeTime","from","to","includeTense","diff","selectUnit","RelativeTimeFormat","numeric","formatRelTimeMem","value","unit","style","unitDisplay","Math","abs","timerTimeRemaining","stateObj","timeRemaining","duration","parts","split","map","Number","durationToSeconds","attributes","remaining","state","now","getTime","madeActive","last_changed","max","applyThemesOnElement","element","themes","localTheme","updateMeta","_themes","themeName","default_theme","styles","theme","Object","keys","forEach","key","prefixedKey","updateStyles","window","ShadyCSS","styleSubtree","meta","document","querySelector","hasAttribute","setAttribute","getAttribute","themeColor","computeCardSize","card","getCardSize","computeDomain","entityId","substr","indexOf","computeEntity","computeRTL","hass","lang","translationMetadata","translations","isRTL","computeRTLDirection","computeStateDomain","entity_id","isNumericState","unit_of_measurement","state_class","numberFormatToLocale","localeOptions","number_format","comma_decimal","decimal_comma","space_comma","round","precision","formatNumber","num","options","isNaN","input","none","getDefaultFormatOptions","err","console","error","maximumFractionDigits","toString","currency","defaultOptions","minimumFractionDigits","digits","length","computeStateDisplay","localize","compareState","device_class","_err","domain","date","has_date","has_time","setHours","components","join","toISOString","_e","humidity","DEFAULT_DOMAIN_ICON","DEFAULT_PANEL","DOMAINS_WITH_CARD","DOMAINS_WITH_MORE_INFO","DOMAINS_HIDE_MORE_INFO","DOMAINS_MORE_INFO_NO_HISTORY","STATES_OFF","DOMAINS_TOGGLE","Set","UNIT_C","UNIT_F","DEFAULT_VIEW_ENTITY_ID","fireEvent","node","type","detail","event","Event","bubbles","cancelable","Boolean","composed","dispatchEvent","SPECIAL_TYPES","DOMAIN_TO_ELEMENT_TYPE","alert","automation","climate","cover","fan","group","input_boolean","input_number","input_select","input_text","light","lock","media_player","remote","scene","script","sensor","timer","switch","vacuum","water_heater","input_datetime","createThing","cardConfig","isRow","_createError","config","_createThing","tag","createElement","setConfig","message","startsWith","has","entity","customElements","get","display","setTimeout","whenDefined","then","clearTimeout","debounce","func","wait","immediate","timeout","args","context","this","callNow","apply","fixedIcons","calendar","camera","configurator","conversation","device_tracker","history_graph","homeassistant","homekit","image_processing","mailbox","notify","person","plant","proximity","simple_alarm","sun","updater","weblink","domainIcon","warn","evaluateFilter","filter","attribute","operator","match","forwardHaptic","hapticType","navigate","_node","path","replace","history","replaceState","pushState","turnOnOffEntity","turnOn","stateDomain","serviceDomain","service","callService","toggleEntity","states","handleActionConfig","actionConfig","action","confirmation","exemptions","some","e","user","id","confirm","text","camera_image","navigation_path","url_path","open","service_data","target","handleAction","double_tap_action","hold_action","tap_action","handleClick","hold","dblClick","haptic","serviceData","hasAction","hasConfigOrEntityChanged","changedProps","forceUpdate","oldHass","hasDoubleClick","turnOnOffEntities","entityIds","domainsToCall","push","getLovelace","root","shadowRoot","ll","lovelace","current_view","___curView","fixedDeviceClassIcons","illuminance","temperature","pressure","power","signal_strength","domainIcons","binary_sensor","is_off","dclass","battery","batteryRound","stateIcon","icon"],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"index.modern.js","sources":["../src/datetime/format_date.ts","../src/types.ts","../src/datetime/use_am_pm.ts","../src/datetime/format_date_time.ts","../src/datetime/format_time.ts","../src/datetime/relative_time.ts","../src/datetime/timer_time_remaining.ts","../src/datetime/duration_to_seconds.ts","../src/apply_themes_on_element.ts","../src/compute-card-size.ts","../src/compute-domain.ts","../src/compute-entity.ts","../src/compute-rtl.ts","../src/compute-state-domain.ts","../src/format-number.ts","../src/compute-state-display.ts","../src/const.ts","../src/fire-event.ts","../src/create-thing.ts","../src/debounce.ts","../src/domain_icons.ts","../src/evaluate-filter.ts","../src/haptic.ts","../src/navigate.ts","../src/turn-on-off-entity.ts","../src/toggle-entity.ts","../src/handle-action.ts","../src/handle-click.ts","../src/has-action.ts","../src/has-changed.ts","../src/has-double-click.ts","../src/turn-on-off-entities.ts","../src/get-lovelace.ts","../src/sensor_icon.ts","../src/state_icon.ts","../src/binary_sensor_icon.ts","../src/cover_icon.ts","../src/input_datetime_icon.ts"],"sourcesContent":["//REF: https://github.com/home-assistant/frontend/blob/dev/src/common/datetime/format_date.ts\n\nimport { FrontendLocaleData } from \"../types\";\n\n/**\n * Formatting a Date to the dddd, mmmm yy format e.g. Tuesday, August 10\n * @param dateObj The date to convert\n * @param locale The users's locale settings\n * @returns date string like \"Tuesday, August 10\"\n */\nexport const formatDateWeekday = (dateObj: Date, locale: FrontendLocaleData) =>\n formatDateWeekdayMem(locale).format(dateObj);\n\nconst formatDateWeekdayMem =\n (locale: FrontendLocaleData) =>\n new Intl.DateTimeFormat(locale.language, {\n weekday: \"long\",\n month: \"long\",\n day: \"numeric\",\n });\n\n/**\n * Formatting a Date to the mmmm dd, yyyy format e.g. August 10, 2021\n * @param dateObj The date to convert\n * @param locale The users's locale settings\n * @returns date string like \"August 10, 2021\"\n */\nexport const formatDate = (dateObj: Date, locale: FrontendLocaleData) =>\n formatDateMem(locale).format(dateObj);\n\nconst formatDateMem =\n (locale: FrontendLocaleData) =>\n new Intl.DateTimeFormat(locale.language, {\n year: \"numeric\",\n month: \"long\",\n day: \"numeric\",\n });\n\n/**\n * Formatting a Date to the classic date format e.g. 10/08/2021\n * @param dateObj The date to convert\n * @param locale The users's locale settings\n * @returns classic date format \"10/08/2021\"\n */\nexport const formatDateNumeric = (dateObj: Date, locale: FrontendLocaleData) =>\n formatDateNumericMem(locale).format(dateObj);\n\nconst formatDateNumericMem =\n (locale: FrontendLocaleData) =>\n new Intl.DateTimeFormat(locale.language, {\n year: \"numeric\",\n month: \"numeric\",\n day: \"numeric\",\n });\n\n\n/**\n * Formatting a Date to just a month with days e.g. Aug 10\n * @param dateObj The date to convert\n * @param locale The users's locale settings\n * @returns month and day like \"Aug 10\"\n */\nexport const formatDateShort = (dateObj: Date, locale: FrontendLocaleData) =>\nformatDateShortMem(locale).format(dateObj);\n\nconst formatDateShortMem =\n(locale: FrontendLocaleData) =>\n new Intl.DateTimeFormat(locale.language, {\n day: \"numeric\",\n month: \"short\",\n });\n\n\n/**\n * Formatting a Date to just a month with year e.g. August 2021\n * @param dateObj The date to convert\n * @param locale The users's locale settings\n * @returns month and year like \"August 2021\"\n */\nexport const formatDateMonthYear = (\ndateObj: Date,\nlocale: FrontendLocaleData\n) => formatDateMonthYearMem(locale).format(dateObj);\n\nconst formatDateMonthYearMem = (locale: FrontendLocaleData) =>\n new Intl.DateTimeFormat(locale.language, {\n month: \"long\",\n year: \"numeric\",\n });\n\n\n/**\n * Formatting a Date to just a month e.g. August\n * @param dateObj The date to convert\n * @param locale The users's locale settings\n * @returns the written out months of the date\n */\nexport const formatDateMonth = (dateObj: Date, locale: FrontendLocaleData) =>\nformatDateMonthMem(locale).format(dateObj);\n\nconst formatDateMonthMem = (locale: FrontendLocaleData) =>\n new Intl.DateTimeFormat(locale.language, {\n month: \"long\",\n });\n\n\n/**\n * Formatting a Date to just a year e.g. 2021\n * @param dateObj The date to convert\n * @param locale The users's locale settings\n * @returns the year of the date in yyyy\n */\nexport const formatDateYear = (dateObj: Date, locale: FrontendLocaleData) =>\nformatDateYearMem(locale).format(dateObj);\n\nconst formatDateYearMem = (locale: FrontendLocaleData) =>\n new Intl.DateTimeFormat(locale.language, {\n year: \"numeric\",\n });\n","import {\n HassEntities,\n HassConfig,\n Auth,\n Connection,\n MessageBase,\n HassServices,\n HassServiceTarget,\n} from \"home-assistant-js-websocket\";\nimport { HapticType } from \"./haptic\";\nimport { HASSDomEvent } from \"./fire-event\";\n\nexport interface ToggleMenuActionConfig extends BaseActionConfig {\n action: \"toggle-menu\";\n}\n\nexport interface ToggleActionConfig extends BaseActionConfig {\n action: \"toggle\";\n}\n\nexport interface CallServiceActionConfig extends BaseActionConfig {\n action: \"call-service\";\n service: string;\n data?: {\n entity_id?: string | [string];\n [key: string]: any;\n };\n\n target?: HassServiceTarget;\n repeat?: number;\n haptic?: HapticType;\n}\n\nexport interface NavigateActionConfig extends BaseActionConfig {\n action: \"navigate\";\n navigation_path: string;\n}\n\nexport interface UrlActionConfig extends BaseActionConfig {\n action: \"url\";\n url_path: string;\n}\n\nexport interface MoreInfoActionConfig extends BaseActionConfig {\n action: \"more-info\";\n entity?: string;\n}\n\nexport interface NoActionConfig extends BaseActionConfig {\n action: \"none\";\n}\n\nexport interface CustomActionConfig extends BaseActionConfig {\n action: \"fire-dom-event\";\n}\n\n/**\n * `repeat` and `haptic` are specifically for use in custom cards like the Button-Card\n */\nexport interface BaseActionConfig {\n confirmation?: ConfirmationRestrictionConfig;\n repeat?: number;\n haptic?: HapticType;\n}\n\nexport interface ConfirmationRestrictionConfig {\n text?: string;\n exemptions?: RestrictionConfig[];\n}\n\nexport interface RestrictionConfig {\n user: string;\n}\n\nexport type ActionConfig =\n | ToggleActionConfig\n | CallServiceActionConfig\n | NavigateActionConfig\n | UrlActionConfig\n | MoreInfoActionConfig\n | NoActionConfig\n | CustomActionConfig\n | ToggleMenuActionConfig;\n\nexport interface Window {\n // Custom panel entry point url\n customPanelJS: string;\n ShadyCSS: {\n nativeCss: boolean;\n nativeShadow: boolean;\n prepareTemplate(templateElement, elementName, elementExtension);\n styleElement(element);\n styleSubtree(element, overrideProperties);\n styleDocument(overrideProperties);\n getComputedStyleValue(element, propertyName);\n };\n}\n\ndeclare global {\n // for fire event\n interface HASSDomEvents {\n \"value-changed\": {\n value: unknown;\n };\n \"config-changed\": {\n config: any;\n };\n \"hass-more-info\": {\n entityId: string | undefined;\n };\n \"ll-rebuild\": {};\n \"ll-custom\": {};\n \"location-changed\": {\n replace: boolean;\n };\n \"show-dialog\": {};\n undefined;\n action: {\n action: string;\n };\n }\n}\n\ntype ValidHassDomEvent = keyof HASSDomEvents;\n\nexport type LocalizeFunc = (key: string, ...args: any[]) => string;\n\nexport interface Credential {\n auth_provider_type: string;\n auth_provider_id: string;\n}\n\nexport interface MFAModule {\n id: string;\n name: string;\n enabled: boolean;\n}\n\nexport interface CurrentUser {\n id: string;\n is_owner: boolean;\n is_admin: boolean;\n name: string;\n credentials: Credential[];\n mfa_modules: MFAModule[];\n}\n\nexport interface Theme {\n // Incomplete\n \"primary-color\": string;\n \"text-primary-color\": string;\n \"accent-color\": string;\n}\n\nexport interface Themes {\n default_theme: string;\n themes: { [key: string]: Theme };\n}\n\nexport interface Panel {\n component_name: string;\n config: { [key: string]: any } | null;\n icon: string | null;\n title: string | null;\n url_path: string;\n}\n\nexport interface Panels {\n [name: string]: Panel;\n}\n\nexport interface Resources {\n [language: string]: { [key: string]: string };\n}\n\nexport interface Translation {\n nativeName: string;\n isRTL: boolean;\n fingerprints: { [fragment: string]: string };\n}\n\nexport interface ServiceCallRequest {\n domain: string;\n service: string;\n serviceData?: Record;\n target?: HassServiceTarget;\n}\n\nexport interface HomeAssistant {\n auth: Auth;\n connection: Connection;\n connected: boolean;\n states: HassEntities;\n services: HassServices;\n config: HassConfig;\n themes: Themes;\n selectedTheme?: string | null;\n panels: Panels;\n panelUrl: string;\n\n // i18n\n // current effective language, in that order:\n // - backend saved user selected lanugage\n // - language in local appstorage\n // - browser language\n // - english (en)\n language: string;\n locale: FrontendLocaleData;\n // local stored language, keep that name for backward compability\n selectedLanguage: string | null;\n resources: Resources;\n localize: LocalizeFunc;\n translationMetadata: {\n fragments: string[];\n translations: {\n [lang: string]: Translation;\n };\n };\n\n dockedSidebar: boolean;\n moreInfoEntityId: string;\n user: CurrentUser;\n callService: (\n domain: ServiceCallRequest[\"domain\"],\n service: ServiceCallRequest[\"service\"],\n serviceData?: ServiceCallRequest[\"serviceData\"],\n target?: ServiceCallRequest[\"target\"]\n ) => Promise;\n callApi: (\n method: \"GET\" | \"POST\" | \"PUT\" | \"DELETE\",\n path: string,\n parameters?: { [key: string]: any }\n ) => Promise;\n fetchWithAuth: (\n path: string,\n init?: { [key: string]: any }\n ) => Promise;\n sendWS: (msg: MessageBase) => Promise;\n callWS: (msg: MessageBase) => Promise;\n}\n\nexport enum NumberFormat {\n language = \"language\",\n system = \"system\",\n comma_decimal = \"comma_decimal\",\n decimal_comma = \"decimal_comma\",\n space_comma = \"space_comma\",\n none = \"none\",\n}\n\nexport enum TimeFormat {\n language = \"language\",\n system = \"system\",\n am_pm = \"12\",\n twenty_four = \"24\",\n}\n\nexport interface FrontendLocaleData {\n language: string;\n number_format: NumberFormat;\n time_format: TimeFormat;\n}\n\nexport interface LovelaceCardConfig {\n index?: number;\n view_index?: number;\n type: string;\n [key: string]: any;\n}\n\nexport interface LovelaceCard extends HTMLElement {\n hass?: HomeAssistant;\n isPanel?: boolean;\n editMode?: boolean;\n getCardSize(): number | Promise;\n setConfig(config: LovelaceCardConfig): void;\n}\n\nexport interface LovelaceCardEditor extends HTMLElement {\n hass?: HomeAssistant;\n lovelace?: LovelaceConfig;\n setConfig(config: LovelaceCardConfig): void;\n}\n\nexport interface LovelaceConfig {\n title?: string;\n views: LovelaceViewConfig[];\n background?: string;\n}\n\nexport interface LovelaceViewConfig {\n index?: number;\n title?: string;\n badges?: Array;\n cards?: LovelaceCardConfig[];\n path?: string;\n icon?: string;\n theme?: string;\n panel?: boolean;\n background?: string;\n visible?: boolean | ShowViewConfig[];\n}\n\nexport interface ShowViewConfig {\n user?: string;\n}\n\nexport interface LovelaceBadgeConfig {\n type?: string;\n [key: string]: any;\n}\n\nexport interface ActionHandlerDetail {\n action: string;\n}\n\nexport type ActionHandlerEvent = HASSDomEvent;\n\nexport interface ActionHandlerOptions {\n hasHold?: boolean;\n hasDoubleClick?: boolean;\n}\n\nexport interface EntitiesCardEntityConfig extends EntityConfig {\n type?: string;\n secondary_info?:\n | \"entity-id\"\n | \"last-changed\"\n | \"last-triggered\"\n | \"last-updated\"\n | \"position\"\n | \"tilt-position\"\n | \"brightness\";\n action_name?: string;\n service?: string;\n data?: Record;\n url?: string;\n tap_action?: ActionConfig;\n hold_action?: ActionConfig;\n double_tap_action?: ActionConfig;\n state_color?: boolean;\n show_name?: boolean;\n show_icon?: boolean;\n}\n\nexport interface EntityConfig {\n entity: string;\n type?: string;\n name?: string;\n icon?: string;\n image?: string;\n}\n\nexport interface LovelaceElementConfigBase {\n type: string;\n style: Record;\n}\n","// REF: https://github.com/home-assistant/frontend/blob/dev/src/common/datetime/use_am_pm.ts\r\n\r\nimport { FrontendLocaleData, TimeFormat } from \"../types\"\r\n\r\n/**\r\n * Checking if AM/PM time format is used within the browser.\r\n * @param locale Homeassistant frontend locale data\r\n * @returns \r\n */\r\nexport const useAmPm = (locale: FrontendLocaleData): boolean => {\r\n if (\r\n locale.time_format === TimeFormat.language ||\r\n locale.time_format === TimeFormat.system\r\n ) {\r\n const testLanguage =\r\n locale.time_format === TimeFormat.language ? locale.language : undefined;\r\n const test = new Date().toLocaleString(testLanguage);\r\n return test.includes(\"AM\") || test.includes(\"PM\");\r\n }\r\n\r\n return locale.time_format === TimeFormat.am_pm;\r\n};\r\n","//REF: https://github.com/home-assistant/frontend/blob/dev/src/common/datetime/format_date_time.ts\n\nimport { FrontendLocaleData } from \"../types\";\nimport { useAmPm } from \"./use_am_pm\";\n\n// August 9, 2021, 8:23 AM\n/**\n * Formatting a dateObject to date with time e.g. August 9, 2021, 8:23 AM\n * @param dateObj The date to convert\n * @param locale The users's locale settings\n * @returns month and day like \"August 9, 2021, 8:23 AM\"\n */\nexport const formatDateTime = (dateObj: Date, locale: FrontendLocaleData) =>\n formatDateTimeMem(locale).format(dateObj);\n\nconst formatDateTimeMem = (locale: FrontendLocaleData) =>\n new Intl.DateTimeFormat(locale.language, {\n year: \"numeric\",\n month: \"long\",\n day: \"numeric\",\n hour: useAmPm(locale) ? \"numeric\" : \"2-digit\",\n minute: \"2-digit\",\n hour12: useAmPm(locale),\n });\n\n\n/**\n * Formatting a dateObject to date with time e.g. August 9, 2021, 8:23:15 AM\n * @param dateObj The date to convert\n * @param locale The users's locale settings\n * @returns month and day like \"August 9, 2021, 8:23:15 AM\"\n */\nexport const formatDateTimeWithSeconds = (\n dateObj: Date,\n locale: FrontendLocaleData\n) => formatDateTimeWithSecondsMem(locale).format(dateObj);\n\nconst formatDateTimeWithSecondsMem =\n (locale: FrontendLocaleData) =>\n new Intl.DateTimeFormat(locale.language, {\n year: \"numeric\",\n month: \"long\",\n day: \"numeric\",\n hour: useAmPm(locale) ? \"numeric\" : \"2-digit\",\n minute: \"2-digit\",\n second: \"2-digit\",\n hour12: useAmPm(locale),\n });\n\n/**\n * Formatting a Date to just date with AM/PM time e.g. 9/8/2021, 8:23 AM\n * @param dateObj The date to convert\n * @param locale The users's locale settings\n * @returns month and day like \"9/8/2021, 8:23 AM\"\n */\nexport const formatDateTimeNumeric = (\n dateObj: Date,\n locale: FrontendLocaleData\n) => formatDateTimeNumericMem(locale).format(dateObj);\n\nconst formatDateTimeNumericMem =\n (locale: FrontendLocaleData) =>\n new Intl.DateTimeFormat(locale.language, {\n year: \"numeric\",\n month: \"numeric\",\n day: \"numeric\",\n hour: \"numeric\",\n minute: \"2-digit\",\n hour12: useAmPm(locale),\n });","//REF: https://github.com/home-assistant/frontend/blob/dev/src/common/datetime/format_time.ts\n\nimport { FrontendLocaleData } from \"../types\";\nimport { useAmPm } from \"./use_am_pm\";\n\n/**\n * 9:15 PM or 21:15\n * @param dateObj The time to convert\n * @param locale The users's locale settings\n * @returns Reformated time in hh:mm\n */\n export const formatTime = (dateObj: Date, locale: FrontendLocaleData) =>\n formatTimeMem(locale).format(dateObj);\n\n const formatTimeMem =\n (locale: FrontendLocaleData) =>\n new Intl.DateTimeFormat(locale.language, {\n hour: \"numeric\",\n minute: \"2-digit\",\n hour12: useAmPm(locale),\n });\n\n/**\n* 9:15:24 PM or 21:15:24\n* @param dateObj The time to convert\n* @param locale The users's locale settings\n* @returns Reformated time in hh:mm:ss\n*/\nexport const formatTimeWithSeconds = (\n dateObj: Date,\n locale: FrontendLocaleData\n) => formatTimeWithSecondsMem(locale).format(dateObj);\n\nconst formatTimeWithSecondsMem =\n (locale: FrontendLocaleData) =>\n new Intl.DateTimeFormat(locale.language, {\n hour: useAmPm(locale) ? \"numeric\" : \"2-digit\",\n minute: \"2-digit\",\n second: \"2-digit\",\n hour12: useAmPm(locale),\n });\n\n/**\n* Tuesday 7:00 PM or Tuesday 19:00\n* @param dateObj The datetime to convert\n* @param locale The users's locale settings\n* @returns Reformated weekday/time in dddd hh:mm\n*/\nexport const formatTimeWeekday = (dateObj: Date, locale: FrontendLocaleData) =>\n formatTimeWeekdayMem(locale).format(dateObj);\n\nconst formatTimeWeekdayMem =\n (locale: FrontendLocaleData) =>\n new Intl.DateTimeFormat(locale.language, {\n hour: useAmPm(locale) ? \"numeric\" : \"2-digit\",\n minute: \"2-digit\",\n second: \"2-digit\",\n hour12: useAmPm(locale),\n }); \n","//REF: https://github.com/home-assistant/frontend/blob/dev/src/common/datetime/relative_time.ts\n\nimport { selectUnit } from \"@formatjs/intl-utils\";\nimport { FrontendLocaleData } from \"../types\";\n\n const formatRelTimeMem =\n (locale: FrontendLocaleData) =>\n new Intl.RelativeTimeFormat(locale.language, { numeric: \"auto\" });\n\n/**\n * Calculate a string representing a date object as relative time from now.\n *\n * Example output: 5 minutes ago, in 3 days.\n */\n export const relativeTime = (\n from: Date,\n locale: FrontendLocaleData,\n to?: Date,\n includeTense = true\n): string => {\n const diff = selectUnit(from, to);\n if (includeTense) {\n return formatRelTimeMem(locale).format(diff.value, diff.unit);\n }\n return Intl.NumberFormat(locale.language, {\n style: \"unit\",\n unit: diff.unit,\n unitDisplay: \"long\",\n }).format(Math.abs(diff.value));\n};\n","import { HassEntity } from \"home-assistant-js-websocket\";\nimport durationToSeconds from \"../datetime/duration_to_seconds\";\n\nexport function timerTimeRemaining(stateObj: HassEntity) {\n let timeRemaining = durationToSeconds(stateObj.attributes.remaining);\n\n if (stateObj.state === \"active\") {\n const now = new Date().getTime();\n const madeActive = new Date(stateObj.last_changed).getTime();\n timeRemaining = Math.max(timeRemaining - (now - madeActive) / 1000, 0);\n }\n\n return timeRemaining;\n}\n","/**\n * Convert a Duration hh:mm:ss format to seconds\n * @param duration hh:mm:ss formated duration\n * @returns duration in seconds\n */\n export default function durationToSeconds(duration: string): number {\n const parts = duration.split(\":\").map(Number);\n return parts[0] * 3600 + parts[1] * 60 + parts[2];\n}\n","/**\n * Apply a theme to an element by setting the CSS variables on it.\n *\n * element: Element to apply theme on.\n * themes: HASS Theme information\n * localTheme: selected theme.\n * updateMeta: boolean if we should update the theme-color meta element.\n */\nexport const applyThemesOnElement = (\n element,\n themes,\n localTheme,\n updateMeta = false\n) => {\n if (!element._themes) {\n element._themes = {};\n }\n let themeName = themes.default_theme;\n if (localTheme === \"default\" || (localTheme && themes.themes[localTheme])) {\n themeName = localTheme;\n }\n const styles = { ...element._themes };\n if (themeName !== \"default\") {\n const theme = themes.themes[themeName];\n Object.keys(theme).forEach((key) => {\n const prefixedKey = \"--\" + key;\n element._themes[prefixedKey] = \"\";\n styles[prefixedKey] = theme[key];\n });\n }\n if (element.updateStyles) {\n element.updateStyles(styles);\n } else if ((window as any).ShadyCSS) {\n // implement updateStyles() method of Polemer elements\n (window as any).ShadyCSS.styleSubtree(/** @type {!HTMLElement} */ (element), styles);\n }\n\n if (!updateMeta) {\n return;\n }\n\n const meta = document.querySelector(\"meta[name=theme-color]\");\n if (meta) {\n if (!meta.hasAttribute(\"default-content\")) {\n meta.setAttribute(\"default-content\", meta.getAttribute(\"content\")!);\n }\n const themeColor =\n styles[\"--primary-color\"] || meta.getAttribute(\"default-content\");\n meta.setAttribute(\"content\", themeColor);\n }\n}\n","import { LovelaceCard } from \"./types\";\n\nexport const computeCardSize = (card: LovelaceCard): number | Promise => {\n return typeof card.getCardSize === \"function\" ? card.getCardSize() : 4;\n};","export function computeDomain(entityId: string): string {\n return entityId.substr(0, entityId.indexOf(\".\"));\n}\n","export function computeEntity(entityId: string): string {\n return entityId.substr(entityId.indexOf(\".\") + 1);\n}\n","import { HomeAssistant } from \"./types\";\n\nexport function computeRTL(hass: HomeAssistant) {\n const lang = hass?.locale?.language || \"en\";\n if (hass.translationMetadata.translations[lang]) {\n return hass.translationMetadata.translations[lang].isRTL || false;\n }\n return false;\n}\n\nexport function computeRTLDirection(hass: HomeAssistant) {\n return computeRTL(hass) ? \"rtl\" : \"ltr\";\n}\n","import { HassEntity } from \"home-assistant-js-websocket\";\nimport { computeDomain } from \"./compute-domain\";\n\nexport function computeStateDomain(stateObj: HassEntity) {\n return computeDomain(stateObj.entity_id);\n}\n","//REF: https://github.com/home-assistant/frontend/blob/dev/src/common/number/format_number.ts\n\nimport { HassEntity } from \"home-assistant-js-websocket\";\nimport { FrontendLocaleData, NumberFormat } from \"./types\";\n\n/**\n * Returns true if the entity is considered numeric based on the attributes it has\n * @param stateObj The entity state object\n */\n export const isNumericState = (stateObj: HassEntity): boolean =>\n !!stateObj.attributes.unit_of_measurement ||\n !!stateObj.attributes.state_class;\n\nexport const numberFormatToLocale = (\n localeOptions: FrontendLocaleData\n): string | string[] | undefined => {\n switch (localeOptions.number_format) {\n case NumberFormat.comma_decimal:\n return [\"en-US\", \"en\"]; // Use United States with fallback to English formatting 1,234,567.89\n case NumberFormat.decimal_comma:\n return [\"de\", \"es\", \"it\"]; // Use German with fallback to Spanish then Italian formatting 1.234.567,89\n case NumberFormat.space_comma:\n return [\"fr\", \"sv\", \"cs\"]; // Use French with fallback to Swedish and Czech formatting 1 234 567,89\n case NumberFormat.system:\n return undefined;\n default:\n return localeOptions.language;\n }\n};\n\nexport const round = (value: number, precision = 2): number =>\n Math.round(value * 10 ** precision) / 10 ** precision;\n\n/**\n * Formats a number based on the specified language with thousands separator(s) and decimal character for better legibility.\n * @param num The number to format\n * @param locale The user-selected language and number format, from `hass.locale`\n * @param options Intl.NumberFormatOptions to use\n */\nexport const formatNumber = (\n num: string | number,\n localeOptions?: FrontendLocaleData,\n options?: Intl.NumberFormatOptions\n): string => {\n const locale = localeOptions\n ? numberFormatToLocale(localeOptions)\n : undefined;\n\n // Polyfill for Number.isNaN, which is more reliable than the global isNaN()\n Number.isNaN =\n Number.isNaN ||\n function isNaN(input) {\n return typeof input === \"number\" && isNaN(input);\n };\n\n if (\n localeOptions?.number_format !== NumberFormat.none &&\n !Number.isNaN(Number(num)) &&\n Intl\n ) {\n try {\n return new Intl.NumberFormat(\n locale,\n getDefaultFormatOptions(num, options)\n ).format(Number(num));\n } catch (err: any) {\n // Don't fail when using \"TEST\" language\n // eslint-disable-next-line no-console\n console.error(err);\n return new Intl.NumberFormat(\n undefined,\n getDefaultFormatOptions(num, options)\n ).format(Number(num));\n }\n }\n if (typeof num === \"string\") {\n return num;\n }\n return `${round(num, options?.maximumFractionDigits).toString()}${\n options?.style === \"currency\" ? ` ${options.currency}` : \"\"\n }`;\n};\n\n/**\n * Generates default options for Intl.NumberFormat\n * @param num The number to be formatted\n * @param options The Intl.NumberFormatOptions that should be included in the returned options\n */\nconst getDefaultFormatOptions = (\n num: string | number,\n options?: Intl.NumberFormatOptions\n): Intl.NumberFormatOptions => {\n const defaultOptions: Intl.NumberFormatOptions = {\n maximumFractionDigits: 2,\n ...options,\n };\n\n if (typeof num !== \"string\") {\n return defaultOptions;\n }\n\n // Keep decimal trailing zeros if they are present in a string numeric value\n if (\n !options ||\n (!options.minimumFractionDigits && !options.maximumFractionDigits)\n ) {\n const digits = num.indexOf(\".\") > -1 ? num.split(\".\")[1].length : 0;\n defaultOptions.minimumFractionDigits = digits;\n defaultOptions.maximumFractionDigits = digits;\n }\n\n return defaultOptions;\n};\n","import { HassEntity } from \"home-assistant-js-websocket\";\nimport { formatDateTime } from \"./datetime/format_date_time\";\nimport { formatDate } from \"./datetime/format_date\";\nimport { formatTime } from \"./datetime/format_time\";\nimport { LocalizeFunc } from \"./translations/localize\";\nimport { computeStateDomain } from \"./compute-state-domain\";\nimport { FrontendLocaleData } from \"./types\";\nimport { formatNumber, isNumericState } from \"./format-number\";\n\nexport const computeStateDisplay = (\n localize: LocalizeFunc,\n stateObj: HassEntity,\n locale: FrontendLocaleData,\n state?: string\n): string => {\n const compareState = state !== undefined ? state : stateObj.state;\n\n if (compareState === \"unknown\" || compareState === \"unavailable\") {\n return localize(`state.default.${compareState}`);\n }\n\n // Entities with a `unit_of_measurement` or `state_class` are numeric values and should use `formatNumber`\n if (isNumericState(stateObj)) {\n if (stateObj.attributes.device_class === \"monetary\") {\n try {\n return formatNumber(compareState, locale, {\n style: \"currency\",\n currency: stateObj.attributes.unit_of_measurement,\n });\n } catch (_err) {\n // fallback to default\n }\n }\n return `${formatNumber(compareState, locale)}${\n stateObj.attributes.unit_of_measurement\n ? \" \" + stateObj.attributes.unit_of_measurement\n : \"\"\n }`;\n }\n\n const domain = computeStateDomain(stateObj);\n\n if (domain === \"input_datetime\") {\n if (state !== undefined) {\n // If trying to display an explicit state, need to parse the explict state to `Date` then format.\n // Attributes aren't available, we have to use `state`.\n try {\n const components = state.split(\" \");\n if (components.length === 2) {\n // Date and time.\n return formatDateTime(new Date(components.join(\"T\")), locale);\n }\n if (components.length === 1) {\n if (state.includes(\"-\")) {\n // Date only.\n return formatDate(new Date(`${state}T00:00`), locale);\n }\n if (state.includes(\":\")) {\n // Time only.\n const now = new Date();\n return formatTime(\n new Date(`${now.toISOString().split(\"T\")[0]}T${state}`),\n locale\n );\n }\n }\n return state;\n } catch (_e) {\n // Formatting methods may throw error if date parsing doesn't go well,\n // just return the state string in that case.\n return state;\n }\n } else {\n // If not trying to display an explicit state, create `Date` object from `stateObj`'s attributes then format.\n let date: Date;\n if (stateObj.attributes.has_date && stateObj.attributes.has_time) {\n date = new Date(\n stateObj.attributes.year,\n stateObj.attributes.month - 1,\n stateObj.attributes.day,\n stateObj.attributes.hour,\n stateObj.attributes.minute\n );\n return formatDateTime(date, locale);\n }\n if (stateObj.attributes.has_date) {\n date = new Date(\n stateObj.attributes.year,\n stateObj.attributes.month - 1,\n stateObj.attributes.day\n );\n return formatDate(date, locale);\n }\n if (stateObj.attributes.has_time) {\n date = new Date();\n date.setHours(stateObj.attributes.hour, stateObj.attributes.minute);\n return formatTime(date, locale);\n }\n return stateObj.state;\n }\n }\n\n if (domain === \"humidifier\") {\n if (compareState === \"on\" && stateObj.attributes.humidity) {\n return `${stateObj.attributes.humidity} %`;\n }\n }\n\n // `counter` `number` and `input_number` domains do not have a unit of measurement but should still use `formatNumber`\n if (\n domain === \"counter\" ||\n domain === \"number\" ||\n domain === \"input_number\"\n ) {\n return formatNumber(compareState, locale);\n }\n\n return (\n // Return device class translation\n (stateObj.attributes.device_class &&\n localize(\n `component.${domain}.state.${stateObj.attributes.device_class}.${compareState}`\n )) ||\n // Return default translation\n localize(`component.${domain}.state._.${compareState}`) ||\n // We don't know! Return the raw state.\n compareState\n );\n};","/** Constants to be used in the frontend. */\n\n// Constants should be alphabetically sorted by name.\n// Arrays with values should be alphabetically sorted if order doesn't matter.\n// Each constant should have a description what it is supposed to be used for.\n\n/** Icon to use when no icon specified for domain. */\nexport const DEFAULT_DOMAIN_ICON = \"mdi:bookmark\";\n\n/** Panel to show when no panel is picked. */\nexport const DEFAULT_PANEL = \"lovelace\";\n\n/** Domains that have a state card. */\nexport const DOMAINS_WITH_CARD = [\n \"climate\",\n \"cover\",\n \"configurator\",\n \"input_select\",\n \"input_number\",\n \"input_text\",\n \"lock\",\n \"media_player\",\n \"scene\",\n \"script\",\n \"timer\",\n \"vacuum\",\n \"water_heater\",\n \"weblink\"\n];\n\n/** Domains with separate more info dialog. */\nexport const DOMAINS_WITH_MORE_INFO = [\n \"alarm_control_panel\",\n \"automation\",\n \"camera\",\n \"climate\",\n \"configurator\",\n \"cover\",\n \"fan\",\n \"group\",\n \"history_graph\",\n \"input_datetime\",\n \"light\",\n \"lock\",\n \"media_player\",\n \"script\",\n \"sun\",\n \"updater\",\n \"vacuum\",\n \"water_heater\",\n \"weather\"\n];\n\n/** Domains that show no more info dialog. */\nexport const DOMAINS_HIDE_MORE_INFO = [\n \"input_number\",\n \"input_select\",\n \"input_text\",\n \"scene\",\n \"weblink\"\n];\n\n/** Domains that should have the history hidden in the more info dialog. */\nexport const DOMAINS_MORE_INFO_NO_HISTORY = [\n \"camera\",\n \"configurator\",\n \"history_graph\",\n \"scene\"\n];\n\n/** States that we consider \"off\". */\nexport const STATES_OFF = [\"closed\", \"locked\", \"off\"];\n\n/** Domains where we allow toggle in Lovelace. */\nexport const DOMAINS_TOGGLE = new Set([\n \"fan\",\n \"input_boolean\",\n \"light\",\n \"switch\",\n \"group\",\n \"automation\"\n]);\n\n/** Temperature units. */\nexport const UNIT_C = \"°C\";\nexport const UNIT_F = \"°F\";\n\n/** Entity ID of the default view. */\nexport const DEFAULT_VIEW_ENTITY_ID = \"group.default_view\";\n","// Polymer legacy event helpers used courtesy of the Polymer project.\n//\n// Copyright (c) 2017 The Polymer Authors. All rights reserved.\n//\n// Redistribution and use in source and binary forms, with or without\n// modification, are permitted provided that the following conditions are\n// met:\n//\n// * Redistributions of source code must retain the above copyright\n// notice, this list of conditions and the following disclaimer.\n// * Redistributions in binary form must reproduce the above\n// copyright notice, this list of conditions and the following disclaimer\n// in the documentation and/or other materials provided with the\n// distribution.\n// * Neither the name of Google Inc. nor the names of its\n// contributors may be used to endorse or promote products derived from\n// this software without specific prior written permission.\n//\n// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n// \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\ndeclare global {\n // tslint:disable-next-line\n interface HASSDomEvents {}\n}\n\nexport type ValidHassDomEvent = keyof HASSDomEvents;\n\nexport interface HASSDomEvent extends Event {\n detail: T;\n}\n\n/**\n * Dispatches a custom event with an optional detail value.\n *\n * @param {string} type Name of event type.\n * @param {*=} detail Detail value containing event-specific\n * payload.\n * @param {{ bubbles: (boolean|undefined),\n * cancelable: (boolean|undefined),\n * composed: (boolean|undefined) }=}\n * options Object specifying options. These may include:\n * `bubbles` (boolean, defaults to `true`),\n * `cancelable` (boolean, defaults to false), and\n * `node` on which to fire the event (HTMLElement, defaults to `this`).\n * @return {Event} The new event that was fired.\n */\nexport const fireEvent = (\n node: HTMLElement | Window,\n type: HassEvent,\n detail?: HASSDomEvents[HassEvent],\n options?: {\n bubbles?: boolean;\n cancelable?: boolean;\n composed?: boolean;\n }\n) => {\n options = options || {};\n // @ts-ignore\n detail = detail === null || detail === undefined ? {} : detail;\n const event = new Event(type, {\n bubbles: options.bubbles === undefined ? true : options.bubbles,\n cancelable: Boolean(options.cancelable),\n composed: options.composed === undefined ? true : options.composed\n });\n (event as any).detail = detail;\n node.dispatchEvent(event);\n return event;\n};\n","import { fireEvent } from \"./fire-event\";\n\nconst SPECIAL_TYPES = new Set([\n \"call-service\",\n \"divider\",\n \"section\",\n \"weblink\",\n \"cast\",\n \"select\"\n]);\nconst DOMAIN_TO_ELEMENT_TYPE = {\n alert: \"toggle\",\n automation: \"toggle\",\n climate: \"climate\",\n cover: \"cover\",\n fan: \"toggle\",\n group: \"group\",\n input_boolean: \"toggle\",\n input_number: \"input-number\",\n input_select: \"input-select\",\n input_text: \"input-text\",\n light: \"toggle\",\n lock: \"lock\",\n media_player: \"media-player\",\n remote: \"toggle\",\n scene: \"scene\",\n script: \"script\",\n sensor: \"sensor\",\n timer: \"timer\",\n switch: \"toggle\",\n vacuum: \"toggle\",\n // Temporary. Once climate is rewritten,\n // water heater should get it's own row.\n water_heater: \"climate\",\n input_datetime: \"input-datetime\"\n};\n\nexport const createThing = (cardConfig, isRow = false) => {\n const _createError = (error, config) => {\n return _createThing(\n \"hui-error-card\",\n {\n type: \"error\",\n error,\n config\n }\n );\n };\n\n const _createThing = (tag, config) => {\n const element = window.document.createElement(tag);\n try {\n // Preventing an error-card infinity loop: https://github.com/custom-cards/custom-card-helpers/issues/54\n if (!element.setConfig) return;\n element.setConfig(config);\n } catch (err) {\n console.error(tag, err);\n return _createError((err as Error).message, config);\n }\n return element;\n };\n\n if (!cardConfig || typeof cardConfig !== \"object\" || (!isRow && !cardConfig.type))\n return _createError(\"No type defined\", cardConfig);\n let tag = cardConfig.type;\n if (tag && tag.startsWith(\"custom:\")) {\n tag = tag.substr(\"custom:\".length);\n } else if (isRow) {\n if (SPECIAL_TYPES.has(tag)) {\n tag = `hui-${tag}-row`;\n } else {\n if (!cardConfig.entity) {\n return _createError(\"Invalid config given.\", cardConfig);\n }\n \n const domain = cardConfig.entity.split(\".\", 1)[0];\n tag = `hui-${DOMAIN_TO_ELEMENT_TYPE[domain] || \"text\"}-entity-row`;\n }\n } else {\n tag = `hui-${tag}-card`;\n }\n\n if (customElements.get(tag)) return _createThing(tag, cardConfig);\n\n // If element doesn't exist (yet) create an error\n const element = _createError(\n `Custom element doesn't exist: ${cardConfig.type}.`,\n cardConfig\n );\n element.style.display = \"None\";\n const timer = setTimeout(() => {\n element.style.display = \"\";\n }, 2000);\n // Remove error if element is defined later\n customElements.whenDefined(cardConfig.type).then(() => {\n clearTimeout(timer);\n fireEvent(element, \"ll-rebuild\", {}, element);\n });\n\n return element;\n};\n","/**\r\n * Returns a function, that, as long as it continues to be invoked, will not be triggered. It will be called after it stops being called for `wait` ms.\r\n * This can be usefull for ResizeObservers for example.\r\n * @param func The function you want to debounce\r\n * @param wait Period to wait in ms\r\n * @param immediate Triggering on the leading edge instead of the trailing\r\n * @returns Debounced Function\r\n */\r\n// eslint-disable-next-line: ban-types\r\nexport const debounce = unknown>(\r\n func: T,\r\n wait: number,\r\n immediate = false\r\n): T => {\r\n let timeout;\r\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\r\n // @ts-ignore\r\n return function (...args) {\r\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\r\n // @ts-ignore\r\n // eslint-disable-next-line @typescript-eslint/no-this-alias\r\n const context = this;\r\n const later = () => {\r\n timeout = null;\r\n if (!immediate) {\r\n func.apply(context, args);\r\n }\r\n };\r\n const callNow = immediate && !timeout;\r\n clearTimeout(timeout);\r\n timeout = setTimeout(later, wait);\r\n if (callNow) {\r\n func.apply(context, args);\r\n }\r\n };\r\n};\r\n","/**\n * Return the icon to be used for a domain.\n *\n * Optionally pass in a state to influence the domain icon.\n */\nimport { DEFAULT_DOMAIN_ICON } from \"./const\";\n\nexport const fixedIcons = {\n alert: \"mdi:alert\",\n automation: \"mdi:playlist-play\",\n calendar: \"mdi:calendar\",\n camera: \"mdi:video\",\n climate: \"mdi:thermostat\",\n configurator: \"mdi:settings\",\n conversation: \"mdi:text-to-speech\",\n device_tracker: \"mdi:account\",\n fan: \"mdi:fan\",\n group: \"mdi:google-circles-communities\",\n history_graph: \"mdi:chart-line\",\n homeassistant: \"mdi:home-assistant\",\n homekit: \"mdi:home-automation\",\n image_processing: \"mdi:image-filter-frames\",\n input_boolean: \"mdi:drawing\",\n input_datetime: \"mdi:calendar-clock\",\n input_number: \"mdi:ray-vertex\",\n input_select: \"mdi:format-list-bulleted\",\n input_text: \"mdi:textbox\",\n light: \"mdi:lightbulb\",\n mailbox: \"mdi:mailbox\",\n notify: \"mdi:comment-alert\",\n person: \"mdi:account\",\n plant: \"mdi:flower\",\n proximity: \"mdi:apple-safari\",\n remote: \"mdi:remote\",\n scene: \"mdi:google-pages\",\n script: \"mdi:file-document\",\n sensor: \"mdi:eye\",\n simple_alarm: \"mdi:bell\",\n sun: \"mdi:white-balance-sunny\",\n switch: \"mdi:flash\",\n timer: \"mdi:timer\",\n updater: \"mdi:cloud-upload\",\n vacuum: \"mdi:robot-vacuum\",\n water_heater: \"mdi:thermometer\",\n weblink: \"mdi:open-in-new\"\n};\n\nexport function domainIcon(domain: string, state?: string): string {\n if (domain in fixedIcons) {\n return fixedIcons[domain];\n }\n\n switch (domain) {\n case \"alarm_control_panel\":\n switch (state) {\n case \"armed_home\":\n return \"mdi:bell-plus\";\n case \"armed_night\":\n return \"mdi:bell-sleep\";\n case \"disarmed\":\n return \"mdi:bell-outline\";\n case \"triggered\":\n return \"mdi:bell-ring\";\n default:\n return \"mdi:bell\";\n }\n\n case \"binary_sensor\":\n return state && state === \"off\"\n ? \"mdi:radiobox-blank\"\n : \"mdi:checkbox-marked-circle\";\n\n case \"cover\":\n return state === \"closed\" ? \"mdi:window-closed\" : \"mdi:window-open\";\n\n case \"lock\":\n return state && state === \"unlocked\" ? \"mdi:lock-open\" : \"mdi:lock\";\n\n case \"media_player\":\n return state && state !== \"off\" && state !== \"idle\"\n ? \"mdi:cast-connected\"\n : \"mdi:cast\";\n\n case \"zwave\":\n switch (state) {\n case \"dead\":\n return \"mdi:emoticon-dead\";\n case \"sleeping\":\n return \"mdi:sleep\";\n case \"initializing\":\n return \"mdi:timer-sand\";\n default:\n return \"mdi:z-wave\";\n }\n\n default:\n // tslint:disable-next-line\n console.warn(\n \"Unable to find icon for domain \" + domain + \" (\" + state + \")\"\n );\n return DEFAULT_DOMAIN_ICON;\n }\n}\n","import { HassEntity } from \"home-assistant-js-websocket\";\n\nexport const evaluateFilter = (stateObj: HassEntity, filter: any): boolean => {\n const operator = filter.operator || \"==\";\n const value = filter.value || filter;\n const state = filter.attribute\n ? stateObj.attributes[filter.attribute]\n : stateObj.state;\n\n switch (operator) {\n case \"==\":\n return state === value;\n case \"<=\":\n return state <= value;\n case \"<\":\n return state < value;\n case \">=\":\n return state >= value;\n case \">\":\n return state > value;\n case \"!=\":\n return state !== value;\n case \"regex\": {\n return state.match(value);\n }\n default:\n return false;\n }\n};\n","import { HASSDomEvent, fireEvent } from \"./fire-event\";\n\n/**\n * Broadcast haptic feedback requests\n */\n\n\n// Allowed types are from iOS HIG.\n// https://developer.apple.com/design/human-interface-guidelines/ios/user-interaction/feedback/#haptics\n// Implementors on platforms other than iOS should attempt to match the patterns (shown in HIG) as closely as possible.\nexport type HapticType =\n | \"success\"\n | \"warning\"\n | \"failure\"\n | \"light\"\n | \"medium\"\n | \"heavy\"\n | \"selection\";\n\ndeclare global {\n // for fire event\n interface HASSDomEvents {\n haptic: HapticType;\n }\n\n interface GlobalEventHandlersEventMap {\n haptic: HASSDomEvent;\n }\n}\n\nexport const forwardHaptic = (hapticType: HapticType) => {\n fireEvent(window, \"haptic\", hapticType);\n};\n","import { fireEvent } from \"./fire-event\";\n\ndeclare global {\n // for fire event\n interface HASSDomEvents {\n \"location-changed\": {\n replace: boolean;\n };\n }\n}\n\nexport const navigate = (\n _node: any,\n path: string,\n replace: boolean = false\n) => {\n if (replace) {\n history.replaceState(null, \"\", path);\n } else {\n history.pushState(null, \"\", path);\n }\n fireEvent(window, \"location-changed\", {\n replace\n });\n};\n","import { HomeAssistant } from \"./types\";\nimport { computeDomain } from \"./compute-domain\";\n\nexport const turnOnOffEntity = (\n hass: HomeAssistant,\n entityId: string,\n turnOn = true\n): Promise => {\n const stateDomain = computeDomain(entityId);\n const serviceDomain = stateDomain === \"group\" ? \"homeassistant\" : stateDomain;\n\n let service;\n switch (stateDomain) {\n case \"lock\":\n service = turnOn ? \"unlock\" : \"lock\";\n break;\n case \"cover\":\n service = turnOn ? \"open_cover\" : \"close_cover\";\n break;\n default:\n service = turnOn ? \"turn_on\" : \"turn_off\";\n }\n\n return hass.callService(serviceDomain, service, { entity_id: entityId });\n};\n","import { STATES_OFF } from \"./const\";\nimport { turnOnOffEntity } from \"./turn-on-off-entity\";\nimport { HomeAssistant } from \"./types\";\n\nexport const toggleEntity = (\n hass: HomeAssistant,\n entityId: string\n): Promise => {\n const turnOn = STATES_OFF.includes(hass.states[entityId].state);\n return turnOnOffEntity(hass, entityId, turnOn);\n};\n","import { HomeAssistant, ActionConfig } from \"./types\";\nimport { forwardHaptic } from \"./haptic\";\nimport { fireEvent } from \"./fire-event\";\nimport { navigate } from \"./navigate\";\nimport { toggleEntity } from \"./toggle-entity\";\n\nexport const handleActionConfig = (\n node: HTMLElement,\n hass: HomeAssistant,\n config: {\n entity?: string;\n camera_image?: string;\n hold_action?: ActionConfig;\n tap_action?: ActionConfig;\n double_tap_action?: ActionConfig;\n },\n actionConfig: ActionConfig | undefined\n): void => {\n if (!actionConfig) {\n actionConfig = {\n action: \"more-info\",\n };\n }\n\n if (\n actionConfig.confirmation &&\n (!actionConfig.confirmation.exemptions ||\n !actionConfig.confirmation.exemptions.some(\n (e) => e.user === hass!.user!.id\n ))\n ) {\n forwardHaptic(\"warning\");\n\n if (\n !confirm(\n actionConfig.confirmation.text ||\n `Are you sure you want to ${actionConfig.action}?`\n )\n ) {\n return;\n }\n }\n\n switch (actionConfig.action) {\n case \"more-info\":\n if (config.entity || config.camera_image) {\n fireEvent(node, \"hass-more-info\", {\n entityId: config.entity ? config.entity : config.camera_image!,\n });\n }\n break;\n case \"navigate\":\n if (actionConfig.navigation_path) {\n navigate(node, actionConfig.navigation_path);\n }\n break;\n case \"url\":\n if (actionConfig.url_path) {\n window.open(actionConfig.url_path);\n }\n break;\n case \"toggle\":\n if (config.entity) {\n toggleEntity(hass, config.entity!);\n forwardHaptic(\"success\");\n }\n break;\n case \"call-service\": {\n if (!actionConfig.service) {\n forwardHaptic(\"failure\");\n return;\n }\n const [domain, service] = actionConfig.service.split(\".\", 2);\n hass.callService(domain, service, actionConfig.data, actionConfig.target);\n forwardHaptic(\"success\");\n break;\n }\n case \"fire-dom-event\": {\n fireEvent(node, \"ll-custom\", actionConfig);\n }\n }\n};\n\nexport const handleAction = (\n node: HTMLElement,\n hass: HomeAssistant,\n config: {\n entity?: string;\n camera_image?: string;\n hold_action?: ActionConfig;\n tap_action?: ActionConfig;\n double_tap_action?: ActionConfig;\n },\n action: string\n): void => {\n let actionConfig: ActionConfig | undefined;\n\n if (action === \"double_tap\" && config.double_tap_action) {\n actionConfig = config.double_tap_action;\n } else if (action === \"hold\" && config.hold_action) {\n actionConfig = config.hold_action;\n } else if (action === \"tap\" && config.tap_action) {\n actionConfig = config.tap_action;\n }\n\n handleActionConfig(node, hass, config, actionConfig);\n};\n","import { HomeAssistant, ActionConfig } from \"./types\";\nimport { fireEvent } from \"./fire-event\";\nimport { forwardHaptic } from \"./haptic\";\nimport { navigate } from \"./navigate\";\nimport { toggleEntity } from \"./toggle-entity\";\n\nexport const handleClick = (\n node: HTMLElement,\n hass: HomeAssistant,\n config: {\n entity?: string;\n camera_image?: string;\n hold_action?: ActionConfig;\n tap_action?: ActionConfig;\n double_tap_action?: ActionConfig;\n },\n hold: boolean,\n dblClick: boolean\n): void => {\n let actionConfig: ActionConfig | undefined;\n\n if (dblClick && config.double_tap_action) {\n actionConfig = config.double_tap_action;\n } else if (hold && config.hold_action) {\n actionConfig = config.hold_action;\n } else if (!hold && config.tap_action) {\n actionConfig = config.tap_action;\n }\n\n if (!actionConfig) {\n actionConfig = {\n action: \"more-info\"\n };\n }\n\n if (\n actionConfig.confirmation &&\n (!actionConfig.confirmation.exemptions ||\n !actionConfig.confirmation.exemptions.some(\n e => e.user === hass!.user!.id\n ))\n ) {\n if (\n !confirm(\n actionConfig.confirmation.text ||\n `Are you sure you want to ${actionConfig.action}?`\n )\n ) {\n return;\n }\n }\n\n switch (actionConfig.action) {\n case \"more-info\":\n if (actionConfig.entity || config.entity || config.camera_image) {\n fireEvent(node, \"hass-more-info\", {\n entityId: actionConfig.entity\n ? actionConfig.entity\n : config.entity\n ? config.entity\n : config.camera_image\n });\n if (actionConfig.haptic) forwardHaptic(actionConfig.haptic);\n }\n break;\n case \"navigate\":\n if (actionConfig.navigation_path) {\n navigate(node, actionConfig.navigation_path);\n if (actionConfig.haptic) forwardHaptic(actionConfig.haptic);\n }\n break;\n case \"url\":\n actionConfig.url_path && window.open(actionConfig.url_path);\n if (actionConfig.haptic) forwardHaptic(actionConfig.haptic);\n break;\n case \"toggle\":\n if (config.entity) {\n toggleEntity(hass, config.entity!);\n if (actionConfig.haptic) forwardHaptic(actionConfig.haptic);\n }\n break;\n case \"call-service\": {\n if (!actionConfig.service) {\n return;\n }\n const [domain, service] = actionConfig.service.split(\".\", 2);\n const serviceData = { ...actionConfig.data };\n if (serviceData.entity_id === \"entity\") {\n serviceData.entity_id = config.entity;\n }\n hass.callService(domain, service, serviceData, actionConfig.target);\n if (actionConfig.haptic) forwardHaptic(actionConfig.haptic);\n break;\n }\n case \"fire-dom-event\": {\n fireEvent(node, \"ll-custom\", actionConfig);\n if (actionConfig.haptic) forwardHaptic(actionConfig.haptic);\n break;\n }\n }\n};\n","import { ActionConfig } from \"./types\";\n\nexport function hasAction(config?: ActionConfig): boolean {\n return config !== undefined && config.action !== \"none\";\n}\n","import { PropertyValues } from \"lit\";\n\nimport { HomeAssistant } from \"./types\";\n\n// Check if config or Entity changed\nexport function hasConfigOrEntityChanged(\n element: any,\n changedProps: PropertyValues,\n forceUpdate: Boolean,\n): boolean {\n if (changedProps.has('config') || forceUpdate) {\n return true;\n }\n\n if (element.config!.entity) {\n const oldHass = changedProps.get('hass') as HomeAssistant | undefined;\n if (oldHass) {\n return (\n oldHass.states[element.config!.entity]\n !== element.hass!.states[element.config!.entity]\n );\n }\n return true;\n } else {\n return false;\n }\n}","import { ActionConfig } from \"./types\";\n\n// Check if config or Entity changed\nexport function hasDoubleClick(config?: ActionConfig): boolean {\n return config !== undefined && config.action !== \"none\";\n}","import { HomeAssistant } from \"./types\";\nimport { STATES_OFF } from \"./const\";\nimport { computeDomain } from \"./compute-domain\";\n\nexport const turnOnOffEntities = (\n hass: HomeAssistant,\n entityIds: string[],\n turnOn = true\n): void => {\n const domainsToCall = {};\n entityIds.forEach((entityId) => {\n if (STATES_OFF.includes(hass.states[entityId].state) === turnOn) {\n const stateDomain = computeDomain(entityId);\n const serviceDomain = [\"cover\", \"lock\"].includes(stateDomain)\n ? stateDomain\n : \"homeassistant\";\n\n if (!(serviceDomain in domainsToCall)) {\n domainsToCall[serviceDomain] = [];\n }\n domainsToCall[serviceDomain].push(entityId);\n }\n });\n\n Object.keys(domainsToCall).forEach((domain) => {\n let service;\n switch (domain) {\n case \"lock\":\n service = turnOn ? \"unlock\" : \"lock\";\n break;\n case \"cover\":\n service = turnOn ? \"open_cover\" : \"close_cover\";\n break;\n default:\n service = turnOn ? \"turn_on\" : \"turn_off\";\n }\n\n const entities = domainsToCall[domain];\n hass.callService(domain, service, { entity_id: entities });\n });\n};\n","export const getLovelace = () => {\n let root: any = document.querySelector('home-assistant');\n root = root && root.shadowRoot;\n root = root && root.querySelector('home-assistant-main');\n root = root && root.shadowRoot;\n root = root && root.querySelector('app-drawer-layout partial-panel-resolver');\n root = root && root.shadowRoot || root;\n root = root && root.querySelector('ha-panel-lovelace');\n root = root && root.shadowRoot;\n root = root && root.querySelector('hui-root');\n if (root) {\n const ll = root.lovelace;\n ll.current_view = root.___curView;\n return ll;\n }\n return null;\n}\n","/** Return an icon representing a sensor state. */\nimport { HassEntity } from \"home-assistant-js-websocket\";\nimport { UNIT_C, UNIT_F } from \"./const\";\nimport { domainIcon } from \"./domain_icons\";\n\nconst fixedDeviceClassIcons = {\n humidity: \"mdi:water-percent\",\n illuminance: \"mdi:brightness-5\",\n temperature: \"mdi:thermometer\",\n pressure: \"mdi:gauge\",\n power: \"mdi:flash\",\n signal_strength: \"mdi:wifi\",\n};\n\nexport const sensorIcon = (state: HassEntity) => {\n const dclass = state.attributes.device_class;\n\n if (dclass && dclass in fixedDeviceClassIcons) {\n return fixedDeviceClassIcons[dclass];\n }\n if (dclass === \"battery\") {\n const battery = Number(state.state);\n if (isNaN(battery)) {\n return \"mdi:battery-unknown\";\n }\n const batteryRound = Math.round(battery / 10) * 10;\n if (batteryRound >= 100) {\n return \"mdi:battery\";\n }\n if (batteryRound <= 0) {\n return \"mdi:battery-alert\";\n }\n // Will return one of the following icons: (listed so extractor picks up)\n // mdi:battery-10\n // mdi:battery-20\n // mdi:battery-30\n // mdi:battery-40\n // mdi:battery-50\n // mdi:battery-60\n // mdi:battery-70\n // mdi:battery-80\n // mdi:battery-90\n // We obscure 'hass' in iconname so this name does not get picked up\n return `${\"hass\"}:battery-${batteryRound}`;\n }\n\n const unit = state.attributes.unit_of_measurement;\n if (unit === UNIT_C || unit === UNIT_F) {\n return \"mdi:thermometer\";\n }\n return domainIcon(\"sensor\");\n};\n","import { HassEntity } from \"home-assistant-js-websocket\";\nimport { computeDomain } from \"./compute-domain\";\nimport { DEFAULT_DOMAIN_ICON } from \"./const\";\nimport { binarySensorIcon } from \"./binary_sensor_icon\";\nimport { coverIcon } from \"./cover_icon\";\nimport { sensorIcon } from \"./sensor_icon\";\nimport { inputDateTimeIcon } from \"./input_datetime_icon\";\nimport { domainIcon } from \"./domain_icons\";\n\nconst domainIcons = {\n binary_sensor: binarySensorIcon,\n cover: coverIcon,\n sensor: sensorIcon,\n input_datetime: inputDateTimeIcon,\n};\n\nexport const stateIcon = (state: HassEntity) => {\n if (!state) {\n return DEFAULT_DOMAIN_ICON;\n }\n if (state.attributes.icon) {\n return state.attributes.icon;\n }\n\n const domain = computeDomain(state.entity_id);\n\n if (domain in domainIcons) {\n return domainIcons[domain](state);\n }\n return domainIcon(domain, state.state);\n};\n","import { HassEntity } from \"home-assistant-js-websocket\";\n\n/** Return an icon representing a binary sensor state. */\n\nexport const binarySensorIcon = (state?: string, stateObj?: HassEntity) => {\n const is_off = state === \"off\";\n switch (stateObj?.attributes.device_class) {\n case \"battery\":\n return is_off ? \"mdi:battery\" : \"mdi:battery-outline\";\n case \"battery_charging\":\n return is_off ? \"mdi:battery\" : \"mdi:battery-charging\";\n case \"cold\":\n return is_off ? \"mdi:thermometer\" : \"mdi:snowflake\";\n case \"connectivity\":\n return is_off ? \"mdi:server-network-off\" : \"mdi:server-network\";\n case \"door\":\n return is_off ? \"mdi:door-closed\" : \"mdi:door-open\";\n case \"garage_door\":\n return is_off ? \"mdi:garage\" : \"mdi:garage-open\";\n case \"power\":\n return is_off ? \"mdi:power-plug-off\" : \"mdi:power-plug\";\n case \"gas\":\n case \"problem\":\n case \"safety\":\n case \"tamper\":\n return is_off ? \"mdi:check-circle\" : \"mdi:alert-circle\";\n case \"smoke\":\n return is_off ? \"mdi:check-circle\" : \"mdi:smoke\";\n case \"heat\":\n return is_off ? \"mdi:thermometer\" : \"mdi:fire\";\n case \"light\":\n return is_off ? \"mdi:brightness-5\" : \"mdi:brightness-7\";\n case \"lock\":\n return is_off ? \"mdi:lock\" : \"mdi:lock-open\";\n case \"moisture\":\n return is_off ? \"mdi:water-off\" : \"mdi:water\";\n case \"motion\":\n return is_off ? \"mdi:walk\" : \"mdi:run\";\n case \"occupancy\":\n return is_off ? \"mdi:home-outline\" : \"mdi:home\";\n case \"opening\":\n return is_off ? \"mdi:square\" : \"mdi:square-outline\";\n case \"plug\":\n return is_off ? \"mdi:power-plug-off\" : \"mdi:power-plug\";\n case \"presence\":\n return is_off ? \"mdi:home-outline\" : \"mdi:home\";\n case \"running\":\n return is_off ? \"mdi:stop\" : \"mdi:play\";\n case \"sound\":\n return is_off ? \"mdi:music-note-off\" : \"mdi:music-note\";\n case \"update\":\n return is_off ? \"mdi:package\" : \"mdi:package-up\";\n case \"vibration\":\n return is_off ? \"mdi:crop-portrait\" : \"mdi:vibrate\";\n case \"window\":\n return is_off ? \"mdi:window-closed\" : \"mdi:window-open\";\n default:\n return is_off ? \"mdi:radiobox-blank\" : \"mdi:checkbox-marked-circle\";\n }\n};\n","/** Return an icon representing a cover state. */\nimport { HassEntity } from \"home-assistant-js-websocket\";\nimport { domainIcon } from \"./domain_icons\";\n\nexport const coverIcon = (state: HassEntity): string => {\n const open = state.state !== \"closed\";\n switch (state.attributes.device_class) {\n case \"garage\":\n return open ? \"mdi:garage-open\" : \"mdi:garage\";\n case \"door\":\n return open ? \"mdi:door-open\" : \"mdi:door-closed\";\n case \"shutter\":\n return open ? \"mdi:window-shutter-open\" : \"mdi:window-shutter\";\n case \"blind\":\n return open ? \"mdi:blinds-open\" : \"mdi:blinds\";\n case \"window\":\n return open ? \"mdi:window-open\" : \"mdi:window-closed\";\n default:\n return domainIcon(\"cover\", state.state);\n }\n};\n","/** Return an icon representing an input datetime state. */\nimport { domainIcon } from \"./domain_icons\";\nimport { HassEntity } from \"home-assistant-js-websocket\";\n\nexport const inputDateTimeIcon = (state: HassEntity): string => {\n if (!state.attributes.has_date) {\n return \"mdi:clock\";\n }\n if (!state.attributes.has_time) {\n return \"mdi:calendar\";\n }\n return domainIcon(\"input_datetime\");\n};\n"],"names":["formatDateWeekday","dateObj","locale","formatDateWeekdayMem","format","Intl","DateTimeFormat","language","weekday","month","day","formatDate","formatDateMem","year","formatDateNumeric","formatDateNumericMem","formatDateShort","formatDateShortMem","formatDateMonthYear","formatDateMonthYearMem","formatDateMonth","formatDateMonthMem","formatDateYear","formatDateYearMem","NumberFormat","TimeFormat","useAmPm","time_format","system","testLanguage","undefined","test","Date","toLocaleString","includes","am_pm","formatDateTime","formatDateTimeMem","hour","minute","hour12","formatDateTimeWithSeconds","formatDateTimeWithSecondsMem","second","formatDateTimeNumeric","formatDateTimeNumericMem","formatTime","formatTimeMem","formatTimeWithSeconds","formatTimeWithSecondsMem","formatTimeWeekday","formatTimeWeekdayMem","relativeTime","from","to","includeTense","diff","selectUnit","RelativeTimeFormat","numeric","formatRelTimeMem","value","unit","style","unitDisplay","Math","abs","timerTimeRemaining","stateObj","timeRemaining","duration","parts","split","map","Number","durationToSeconds","attributes","remaining","state","now","getTime","madeActive","last_changed","max","applyThemesOnElement","element","themes","localTheme","updateMeta","_themes","themeName","default_theme","styles","theme","Object","keys","forEach","key","prefixedKey","updateStyles","window","ShadyCSS","styleSubtree","meta","document","querySelector","hasAttribute","setAttribute","getAttribute","themeColor","computeCardSize","card","getCardSize","computeDomain","entityId","substr","indexOf","computeEntity","computeRTL","hass","lang","translationMetadata","translations","isRTL","computeRTLDirection","computeStateDomain","entity_id","isNumericState","unit_of_measurement","state_class","numberFormatToLocale","localeOptions","number_format","comma_decimal","decimal_comma","space_comma","round","precision","formatNumber","num","options","isNaN","input","none","getDefaultFormatOptions","err","console","error","maximumFractionDigits","toString","currency","defaultOptions","minimumFractionDigits","digits","length","computeStateDisplay","localize","compareState","device_class","_err","domain","date","has_date","has_time","setHours","components","join","toISOString","_e","humidity","DEFAULT_DOMAIN_ICON","DEFAULT_PANEL","DOMAINS_WITH_CARD","DOMAINS_WITH_MORE_INFO","DOMAINS_HIDE_MORE_INFO","DOMAINS_MORE_INFO_NO_HISTORY","STATES_OFF","DOMAINS_TOGGLE","Set","UNIT_C","UNIT_F","DEFAULT_VIEW_ENTITY_ID","fireEvent","node","type","detail","event","Event","bubbles","cancelable","Boolean","composed","dispatchEvent","SPECIAL_TYPES","DOMAIN_TO_ELEMENT_TYPE","alert","automation","climate","cover","fan","group","input_boolean","input_number","input_select","input_text","light","lock","media_player","remote","scene","script","sensor","timer","switch","vacuum","water_heater","input_datetime","createThing","cardConfig","isRow","_createError","config","_createThing","tag","createElement","setConfig","message","startsWith","has","entity","customElements","get","display","setTimeout","whenDefined","then","clearTimeout","debounce","func","wait","immediate","timeout","args","context","this","callNow","apply","fixedIcons","calendar","camera","configurator","conversation","device_tracker","history_graph","homeassistant","homekit","image_processing","mailbox","notify","person","plant","proximity","simple_alarm","sun","updater","weblink","domainIcon","warn","evaluateFilter","filter","attribute","operator","match","forwardHaptic","hapticType","navigate","_node","path","replace","history","replaceState","pushState","turnOnOffEntity","turnOn","stateDomain","serviceDomain","service","callService","toggleEntity","states","handleActionConfig","actionConfig","action","confirmation","exemptions","some","e","user","id","confirm","text","camera_image","navigation_path","url_path","open","data","target","handleAction","double_tap_action","hold_action","tap_action","handleClick","hold","dblClick","haptic","serviceData","hasAction","hasConfigOrEntityChanged","changedProps","forceUpdate","oldHass","hasDoubleClick","turnOnOffEntities","entityIds","domainsToCall","push","getLovelace","root","shadowRoot","ll","lovelace","current_view","___curView","fixedDeviceClassIcons","illuminance","temperature","pressure","power","signal_strength","domainIcons","binary_sensor","is_off","dclass","battery","batteryRound","stateIcon","icon"],"mappings":"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"} \ No newline at end of file diff --git a/dist/index.umd.js b/dist/index.umd.js index 44a7ab2..03d267d 100644 --- a/dist/index.umd.js +++ b/dist/index.umd.js @@ -1,2 +1,2 @@ -!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("@formatjs/intl-utils")):"function"==typeof define&&define.amd?define(["exports","@formatjs/intl-utils"],t):t((e||self).customCardHelpers={},e.intlUtils)}(this,function(e,t){var r,n,i=function(e,t){return a(t).format(e)},a=function(e){return new Intl.DateTimeFormat(e.language,{year:"numeric",month:"long",day:"numeric"})};e.NumberFormat=void 0,(r=e.NumberFormat||(e.NumberFormat={})).language="language",r.system="system",r.comma_decimal="comma_decimal",r.decimal_comma="decimal_comma",r.space_comma="space_comma",r.none="none",e.TimeFormat=void 0,(n=e.TimeFormat||(e.TimeFormat={})).language="language",n.system="system",n.am_pm="12",n.twenty_four="24";var o=function(t){if(t.time_format===e.TimeFormat.language||t.time_format===e.TimeFormat.system){var r=t.time_format===e.TimeFormat.language?t.language:void 0,n=(new Date).toLocaleString(r);return n.includes("AM")||n.includes("PM")}return t.time_format===e.TimeFormat.am_pm},u=function(e,t){return c(t).format(e)},c=function(e){return new Intl.DateTimeFormat(e.language,{year:"numeric",month:"long",day:"numeric",hour:o(e)?"numeric":"2-digit",minute:"2-digit",hour12:o(e)})},m=function(e,t){return s(t).format(e)},s=function(e){return new Intl.DateTimeFormat(e.language,{hour:"numeric",minute:"2-digit",hour12:o(e)})};function l(){return(l=Object.assign||function(e){for(var t=1;t-1?e.split(".")[1].length:0;r.minimumFractionDigits=n,r.maximumFractionDigits=n}return r},y="mdi:bookmark",w=["closed","locked","off"],k=new Set(["fan","input_boolean","light","switch","group","automation"]),T=function(e,t,r,n){n=n||{},r=null==r?{}:r;var i=new Event(t,{bubbles:void 0===n.bubbles||n.bubbles,cancelable:Boolean(n.cancelable),composed:void 0===n.composed||n.composed});return i.detail=r,e.dispatchEvent(i),i},D=new Set(["call-service","divider","section","weblink","cast","select"]),F={alert:"toggle",automation:"toggle",climate:"climate",cover:"cover",fan:"toggle",group:"group",input_boolean:"toggle",input_number:"input-number",input_select:"input-select",input_text:"input-text",light:"toggle",lock:"lock",media_player:"media-player",remote:"toggle",scene:"scene",script:"script",sensor:"sensor",timer:"timer",switch:"toggle",vacuum:"toggle",water_heater:"climate",input_datetime:"input-datetime"},N={alert:"mdi:alert",automation:"mdi:playlist-play",calendar:"mdi:calendar",camera:"mdi:video",climate:"mdi:thermostat",configurator:"mdi:settings",conversation:"mdi:text-to-speech",device_tracker:"mdi:account",fan:"mdi:fan",group:"mdi:google-circles-communities",history_graph:"mdi:chart-line",homeassistant:"mdi:home-assistant",homekit:"mdi:home-automation",image_processing:"mdi:image-filter-frames",input_boolean:"mdi:drawing",input_datetime:"mdi:calendar-clock",input_number:"mdi:ray-vertex",input_select:"mdi:format-list-bulleted",input_text:"mdi:textbox",light:"mdi:lightbulb",mailbox:"mdi:mailbox",notify:"mdi:comment-alert",person:"mdi:account",plant:"mdi:flower",proximity:"mdi:apple-safari",remote:"mdi:remote",scene:"mdi:google-pages",script:"mdi:file-document",sensor:"mdi:eye",simple_alarm:"mdi:bell",sun:"mdi:white-balance-sunny",switch:"mdi:flash",timer:"mdi:timer",updater:"mdi:cloud-upload",vacuum:"mdi:robot-vacuum",water_heater:"mdi:thermometer",weblink:"mdi:open-in-new"};function S(e,t){if(e in N)return N[e];switch(e){case"alarm_control_panel":switch(t){case"armed_home":return"mdi:bell-plus";case"armed_night":return"mdi:bell-sleep";case"disarmed":return"mdi:bell-outline";case"triggered":return"mdi:bell-ring";default:return"mdi:bell"}case"binary_sensor":return t&&"off"===t?"mdi:radiobox-blank":"mdi:checkbox-marked-circle";case"cover":return"closed"===t?"mdi:window-closed":"mdi:window-open";case"lock":return t&&"unlocked"===t?"mdi:lock-open":"mdi:lock";case"media_player":return t&&"off"!==t&&"idle"!==t?"mdi:cast-connected":"mdi:cast";case"zwave":switch(t){case"dead":return"mdi:emoticon-dead";case"sleeping":return"mdi:sleep";case"initializing":return"mdi:timer-sand";default:return"mdi:z-wave"}default:return console.warn("Unable to find icon for domain "+e+" ("+t+")"),y}}var I=function(e){T(window,"haptic",e)},x=function(e,t,r){void 0===r&&(r=!1),r?history.replaceState(null,"",t):history.pushState(null,"",t),T(window,"location-changed",{replace:r})},O=function(e,t,r){void 0===r&&(r=!0);var n,i=d(t),a="group"===i?"homeassistant":i;switch(i){case"lock":n=r?"unlock":"lock";break;case"cover":n=r?"open_cover":"close_cover";break;default:n=r?"turn_on":"turn_off"}return e.callService(a,n,{entity_id:t})},E=function(e,t){var r=w.includes(e.states[t].state);return O(e,t,r)},A=function(e,t,r,n){if(n||(n={action:"more-info"}),!n.confirmation||n.confirmation.exemptions&&n.confirmation.exemptions.some(function(e){return e.user===t.user.id})||(I("warning"),confirm(n.confirmation.text||"Are you sure you want to "+n.action+"?")))switch(n.action){case"more-info":(r.entity||r.camera_image)&&T(e,"hass-more-info",{entityId:r.entity?r.entity:r.camera_image});break;case"navigate":n.navigation_path&&x(0,n.navigation_path);break;case"url":n.url_path&&window.open(n.url_path);break;case"toggle":r.entity&&(E(t,r.entity),I("success"));break;case"call-service":if(!n.service)return void I("failure");var i=n.service.split(".",2);t.callService(i[0],i[1],n.service_data,n.target),I("success");break;case"fire-dom-event":T(e,"ll-custom",n)}},M={humidity:"mdi:water-percent",illuminance:"mdi:brightness-5",temperature:"mdi:thermometer",pressure:"mdi:gauge",power:"mdi:flash",signal_strength:"mdi:wifi"},C={binary_sensor:function(e,t){var r="off"===e;switch(null==t?void 0:t.attributes.device_class){case"battery":return r?"mdi:battery":"mdi:battery-outline";case"battery_charging":return r?"mdi:battery":"mdi:battery-charging";case"cold":return r?"mdi:thermometer":"mdi:snowflake";case"connectivity":return r?"mdi:server-network-off":"mdi:server-network";case"door":return r?"mdi:door-closed":"mdi:door-open";case"garage_door":return r?"mdi:garage":"mdi:garage-open";case"power":return r?"mdi:power-plug-off":"mdi:power-plug";case"gas":case"problem":case"safety":case"tamper":return r?"mdi:check-circle":"mdi:alert-circle";case"smoke":return r?"mdi:check-circle":"mdi:smoke";case"heat":return r?"mdi:thermometer":"mdi:fire";case"light":return r?"mdi:brightness-5":"mdi:brightness-7";case"lock":return r?"mdi:lock":"mdi:lock-open";case"moisture":return r?"mdi:water-off":"mdi:water";case"motion":return r?"mdi:walk":"mdi:run";case"occupancy":return r?"mdi:home-outline":"mdi:home";case"opening":return r?"mdi:square":"mdi:square-outline";case"plug":return r?"mdi:power-plug-off":"mdi:power-plug";case"presence":return r?"mdi:home-outline":"mdi:home";case"running":return r?"mdi:stop":"mdi:play";case"sound":return r?"mdi:music-note-off":"mdi:music-note";case"update":return r?"mdi:package":"mdi:package-up";case"vibration":return r?"mdi:crop-portrait":"mdi:vibrate";case"window":return r?"mdi:window-closed":"mdi:window-open";default:return r?"mdi:radiobox-blank":"mdi:checkbox-marked-circle"}},cover:function(e){var t="closed"!==e.state;switch(e.attributes.device_class){case"garage":return t?"mdi:garage-open":"mdi:garage";case"door":return t?"mdi:door-open":"mdi:door-closed";case"shutter":return t?"mdi:window-shutter-open":"mdi:window-shutter";case"blind":return t?"mdi:blinds-open":"mdi:blinds";case"window":return t?"mdi:window-open":"mdi:window-closed";default:return S("cover",e.state)}},sensor:function(e){var t=e.attributes.device_class;if(t&&t in M)return M[t];if("battery"===t){var r=Number(e.state);if(isNaN(r))return"mdi:battery-unknown";var n=10*Math.round(r/10);return n>=100?"mdi:battery":n<=0?"mdi:battery-alert":"hass:battery-"+n}var i=e.attributes.unit_of_measurement;return"°C"===i||"°F"===i?"mdi:thermometer":S("sensor")},input_datetime:function(e){return e.attributes.has_date?e.attributes.has_time?S("input_datetime"):"mdi:calendar":"mdi:clock"}};e.DEFAULT_DOMAIN_ICON=y,e.DEFAULT_PANEL="lovelace",e.DEFAULT_VIEW_ENTITY_ID="group.default_view",e.DOMAINS_HIDE_MORE_INFO=["input_number","input_select","input_text","scene","weblink"],e.DOMAINS_MORE_INFO_NO_HISTORY=["camera","configurator","history_graph","scene"],e.DOMAINS_TOGGLE=k,e.DOMAINS_WITH_CARD=["climate","cover","configurator","input_select","input_number","input_text","lock","media_player","scene","script","timer","vacuum","water_heater","weblink"],e.DOMAINS_WITH_MORE_INFO=["alarm_control_panel","automation","camera","climate","configurator","cover","fan","group","history_graph","input_datetime","light","lock","media_player","script","sun","updater","vacuum","water_heater","weather"],e.STATES_OFF=w,e.UNIT_C="°C",e.UNIT_F="°F",e.applyThemesOnElement=function(e,t,r,n){void 0===n&&(n=!1),e._themes||(e._themes={});var i=t.default_theme;("default"===r||r&&t.themes[r])&&(i=r);var a=l({},e._themes);if("default"!==i){var o=t.themes[i];Object.keys(o).forEach(function(t){var r="--"+t;e._themes[r]="",a[r]=o[t]})}if(e.updateStyles?e.updateStyles(a):window.ShadyCSS&&window.ShadyCSS.styleSubtree(e,a),n){var u=document.querySelector("meta[name=theme-color]");if(u){u.hasAttribute("default-content")||u.setAttribute("default-content",u.getAttribute("content"));var c=a["--primary-color"]||u.getAttribute("default-content");u.setAttribute("content",c)}}},e.computeCardSize=function(e){return"function"==typeof e.getCardSize?e.getCardSize():4},e.computeDomain=d,e.computeEntity=function(e){return e.substr(e.indexOf(".")+1)},e.computeRTL=f,e.computeRTLDirection=function(e){return f(e)?"rtl":"ltr"},e.computeStateDisplay=function(e,t,r,n){var a=void 0!==n?n:t.state;if("unknown"===a||"unavailable"===a)return e("state.default."+a);if(p(t)){if("monetary"===t.attributes.device_class)try{return _(a,r,{style:"currency",currency:t.attributes.unit_of_measurement})}catch(e){}return _(a,r)+(t.attributes.unit_of_measurement?" "+t.attributes.unit_of_measurement:"")}var o=g(t);if("input_datetime"===o){var c;if(void 0===n)return t.attributes.has_date&&t.attributes.has_time?(c=new Date(t.attributes.year,t.attributes.month-1,t.attributes.day,t.attributes.hour,t.attributes.minute),u(c,r)):t.attributes.has_date?(c=new Date(t.attributes.year,t.attributes.month-1,t.attributes.day),i(c,r)):t.attributes.has_time?((c=new Date).setHours(t.attributes.hour,t.attributes.minute),m(c,r)):t.state;try{var s=n.split(" ");if(2===s.length)return u(new Date(s.join("T")),r);if(1===s.length){if(n.includes("-"))return i(new Date(n+"T00:00"),r);if(n.includes(":")){var l=new Date;return m(new Date(l.toISOString().split("T")[0]+"T"+n),r)}}return n}catch(e){return n}}return"humidifier"===o&&"on"===a&&t.attributes.humidity?t.attributes.humidity+" %":"counter"===o||"number"===o||"input_number"===o?_(a,r):t.attributes.device_class&&e("component."+o+".state."+t.attributes.device_class+"."+a)||e("component."+o+".state._."+a)||a},e.computeStateDomain=g,e.createThing=function(e,t){void 0===t&&(t=!1);var r=function(e,t){return n("hui-error-card",{type:"error",error:e,config:t})},n=function(e,t){var n=window.document.createElement(e);try{if(!n.setConfig)return;n.setConfig(t)}catch(n){return console.error(e,n),r(n.message,t)}return n};if(!e||"object"!=typeof e||!t&&!e.type)return r("No type defined",e);var i=e.type;if(i&&i.startsWith("custom:"))i=i.substr("custom:".length);else if(t)if(D.has(i))i="hui-"+i+"-row";else{if(!e.entity)return r("Invalid config given.",e);var a=e.entity.split(".",1)[0];i="hui-"+(F[a]||"text")+"-entity-row"}else i="hui-"+i+"-card";if(customElements.get(i))return n(i,e);var o=r("Custom element doesn't exist: "+e.type+".",e);o.style.display="None";var u=setTimeout(function(){o.style.display=""},2e3);return customElements.whenDefined(e.type).then(function(){clearTimeout(u),T(o,"ll-rebuild",{},o)}),o},e.debounce=function(e,t,r){var n;return void 0===r&&(r=!1),function(){var i=[].slice.call(arguments),a=this,o=function(){n=null,r||e.apply(a,i)},u=r&&!n;clearTimeout(n),n=setTimeout(o,t),u&&e.apply(a,i)}},e.domainIcon=S,e.evaluateFilter=function(e,t){var r=t.value||t,n=t.attribute?e.attributes[t.attribute]:e.state;switch(t.operator||"=="){case"==":return n===r;case"<=":return n<=r;case"<":return n=":return n>=r;case">":return n>r;case"!=":return n!==r;case"regex":return n.match(r);default:return!1}},e.fireEvent=T,e.fixedIcons=N,e.formatDate=i,e.formatDateMonth=function(e,t){return function(e){return new Intl.DateTimeFormat(e.language,{month:"long"})}(t).format(e)},e.formatDateMonthYear=function(e,t){return function(e){return new Intl.DateTimeFormat(e.language,{month:"long",year:"numeric"})}(t).format(e)},e.formatDateNumeric=function(e,t){return function(e){return new Intl.DateTimeFormat(e.language,{year:"numeric",month:"numeric",day:"numeric"})}(t).format(e)},e.formatDateShort=function(e,t){return function(e){return new Intl.DateTimeFormat(e.language,{day:"numeric",month:"short"})}(t).format(e)},e.formatDateTime=u,e.formatDateTimeNumeric=function(e,t){return function(e){return new Intl.DateTimeFormat(e.language,{year:"numeric",month:"numeric",day:"numeric",hour:"numeric",minute:"2-digit",hour12:o(e)})}(t).format(e)},e.formatDateTimeWithSeconds=function(e,t){return function(e){return new Intl.DateTimeFormat(e.language,{year:"numeric",month:"long",day:"numeric",hour:o(e)?"numeric":"2-digit",minute:"2-digit",second:"2-digit",hour12:o(e)})}(t).format(e)},e.formatDateWeekday=function(e,t){return function(e){return new Intl.DateTimeFormat(e.language,{weekday:"long",month:"long",day:"numeric"})}(t).format(e)},e.formatDateYear=function(e,t){return function(e){return new Intl.DateTimeFormat(e.language,{year:"numeric"})}(t).format(e)},e.formatNumber=_,e.formatTime=m,e.formatTimeWeekday=function(e,t){return function(e){return new Intl.DateTimeFormat(e.language,{hour:o(e)?"numeric":"2-digit",minute:"2-digit",second:"2-digit",hour12:o(e)})}(t).format(e)},e.formatTimeWithSeconds=function(e,t){return function(e){return new Intl.DateTimeFormat(e.language,{hour:o(e)?"numeric":"2-digit",minute:"2-digit",second:"2-digit",hour12:o(e)})}(t).format(e)},e.forwardHaptic=I,e.getLovelace=function(){var e=document.querySelector("home-assistant");if(e=(e=(e=(e=(e=(e=(e=(e=e&&e.shadowRoot)&&e.querySelector("home-assistant-main"))&&e.shadowRoot)&&e.querySelector("app-drawer-layout partial-panel-resolver"))&&e.shadowRoot||e)&&e.querySelector("ha-panel-lovelace"))&&e.shadowRoot)&&e.querySelector("hui-root")){var t=e.lovelace;return t.current_view=e.___curView,t}return null},e.handleAction=function(e,t,r,n){var i;"double_tap"===n&&r.double_tap_action?i=r.double_tap_action:"hold"===n&&r.hold_action?i=r.hold_action:"tap"===n&&r.tap_action&&(i=r.tap_action),A(e,t,r,i)},e.handleActionConfig=A,e.handleClick=function(e,t,r,n,i){var a;if(i&&r.double_tap_action?a=r.double_tap_action:n&&r.hold_action?a=r.hold_action:!n&&r.tap_action&&(a=r.tap_action),a||(a={action:"more-info"}),!a.confirmation||a.confirmation.exemptions&&a.confirmation.exemptions.some(function(e){return e.user===t.user.id})||confirm(a.confirmation.text||"Are you sure you want to "+a.action+"?"))switch(a.action){case"more-info":(a.entity||r.entity||r.camera_image)&&(T(e,"hass-more-info",{entityId:a.entity?a.entity:r.entity?r.entity:r.camera_image}),a.haptic&&I(a.haptic));break;case"navigate":a.navigation_path&&(x(0,a.navigation_path),a.haptic&&I(a.haptic));break;case"url":a.url_path&&window.open(a.url_path),a.haptic&&I(a.haptic);break;case"toggle":r.entity&&(E(t,r.entity),a.haptic&&I(a.haptic));break;case"call-service":if(!a.service)return;var o=a.service.split(".",2),u=o[0],c=o[1],m=l({},a.service_data);"entity"===m.entity_id&&(m.entity_id=r.entity),t.callService(u,c,m,a.target),a.haptic&&I(a.haptic);break;case"fire-dom-event":T(e,"ll-custom",a),a.haptic&&I(a.haptic)}},e.hasAction=function(e){return void 0!==e&&"none"!==e.action},e.hasConfigOrEntityChanged=function(e,t,r){if(t.has("config")||r)return!0;if(e.config.entity){var n=t.get("hass");return!n||n.states[e.config.entity]!==e.hass.states[e.config.entity]}return!1},e.hasDoubleClick=function(e){return void 0!==e&&"none"!==e.action},e.isNumericState=p,e.navigate=x,e.numberFormatToLocale=h,e.relativeTime=function(e,r,n,i){void 0===i&&(i=!0);var a=t.selectUnit(e,n);return i?function(e){return new Intl.RelativeTimeFormat(e.language,{numeric:"auto"})}(r).format(a.value,a.unit):Intl.NumberFormat(r.language,{style:"unit",unit:a.unit,unitDisplay:"long"}).format(Math.abs(a.value))},e.round=b,e.stateIcon=function(e){if(!e)return y;if(e.attributes.icon)return e.attributes.icon;var t=d(e.entity_id);return t in C?C[t](e):S(t,e.state)},e.timerTimeRemaining=function(e){var t,r=3600*(t=e.attributes.remaining.split(":").map(Number))[0]+60*t[1]+t[2];if("active"===e.state){var n=(new Date).getTime(),i=new Date(e.last_changed).getTime();r=Math.max(r-(n-i)/1e3,0)}return r},e.toggleEntity=E,e.turnOnOffEntities=function(e,t,r){void 0===r&&(r=!0);var n={};t.forEach(function(t){if(w.includes(e.states[t].state)===r){var i=d(t),a=["cover","lock"].includes(i)?i:"homeassistant";a in n||(n[a]=[]),n[a].push(t)}}),Object.keys(n).forEach(function(t){var i;switch(t){case"lock":i=r?"unlock":"lock";break;case"cover":i=r?"open_cover":"close_cover";break;default:i=r?"turn_on":"turn_off"}e.callService(t,i,{entity_id:n[t]})})},e.turnOnOffEntity=O}); +!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("@formatjs/intl-utils")):"function"==typeof define&&define.amd?define(["exports","@formatjs/intl-utils"],t):t((e||self).customCardHelpers={},e.intlUtils)}(this,function(e,t){var r,n,i=function(e,t){return a(t).format(e)},a=function(e){return new Intl.DateTimeFormat(e.language,{year:"numeric",month:"long",day:"numeric"})};e.NumberFormat=void 0,(r=e.NumberFormat||(e.NumberFormat={})).language="language",r.system="system",r.comma_decimal="comma_decimal",r.decimal_comma="decimal_comma",r.space_comma="space_comma",r.none="none",e.TimeFormat=void 0,(n=e.TimeFormat||(e.TimeFormat={})).language="language",n.system="system",n.am_pm="12",n.twenty_four="24";var o=function(t){if(t.time_format===e.TimeFormat.language||t.time_format===e.TimeFormat.system){var r=t.time_format===e.TimeFormat.language?t.language:void 0,n=(new Date).toLocaleString(r);return n.includes("AM")||n.includes("PM")}return t.time_format===e.TimeFormat.am_pm},u=function(e,t){return c(t).format(e)},c=function(e){return new Intl.DateTimeFormat(e.language,{year:"numeric",month:"long",day:"numeric",hour:o(e)?"numeric":"2-digit",minute:"2-digit",hour12:o(e)})},m=function(e,t){return s(t).format(e)},s=function(e){return new Intl.DateTimeFormat(e.language,{hour:"numeric",minute:"2-digit",hour12:o(e)})};function l(){return(l=Object.assign||function(e){for(var t=1;t-1?e.split(".")[1].length:0;r.minimumFractionDigits=n,r.maximumFractionDigits=n}return r},y="mdi:bookmark",w=["closed","locked","off"],k=new Set(["fan","input_boolean","light","switch","group","automation"]),T=function(e,t,r,n){n=n||{},r=null==r?{}:r;var i=new Event(t,{bubbles:void 0===n.bubbles||n.bubbles,cancelable:Boolean(n.cancelable),composed:void 0===n.composed||n.composed});return i.detail=r,e.dispatchEvent(i),i},D=new Set(["call-service","divider","section","weblink","cast","select"]),F={alert:"toggle",automation:"toggle",climate:"climate",cover:"cover",fan:"toggle",group:"group",input_boolean:"toggle",input_number:"input-number",input_select:"input-select",input_text:"input-text",light:"toggle",lock:"lock",media_player:"media-player",remote:"toggle",scene:"scene",script:"script",sensor:"sensor",timer:"timer",switch:"toggle",vacuum:"toggle",water_heater:"climate",input_datetime:"input-datetime"},N={alert:"mdi:alert",automation:"mdi:playlist-play",calendar:"mdi:calendar",camera:"mdi:video",climate:"mdi:thermostat",configurator:"mdi:settings",conversation:"mdi:text-to-speech",device_tracker:"mdi:account",fan:"mdi:fan",group:"mdi:google-circles-communities",history_graph:"mdi:chart-line",homeassistant:"mdi:home-assistant",homekit:"mdi:home-automation",image_processing:"mdi:image-filter-frames",input_boolean:"mdi:drawing",input_datetime:"mdi:calendar-clock",input_number:"mdi:ray-vertex",input_select:"mdi:format-list-bulleted",input_text:"mdi:textbox",light:"mdi:lightbulb",mailbox:"mdi:mailbox",notify:"mdi:comment-alert",person:"mdi:account",plant:"mdi:flower",proximity:"mdi:apple-safari",remote:"mdi:remote",scene:"mdi:google-pages",script:"mdi:file-document",sensor:"mdi:eye",simple_alarm:"mdi:bell",sun:"mdi:white-balance-sunny",switch:"mdi:flash",timer:"mdi:timer",updater:"mdi:cloud-upload",vacuum:"mdi:robot-vacuum",water_heater:"mdi:thermometer",weblink:"mdi:open-in-new"};function S(e,t){if(e in N)return N[e];switch(e){case"alarm_control_panel":switch(t){case"armed_home":return"mdi:bell-plus";case"armed_night":return"mdi:bell-sleep";case"disarmed":return"mdi:bell-outline";case"triggered":return"mdi:bell-ring";default:return"mdi:bell"}case"binary_sensor":return t&&"off"===t?"mdi:radiobox-blank":"mdi:checkbox-marked-circle";case"cover":return"closed"===t?"mdi:window-closed":"mdi:window-open";case"lock":return t&&"unlocked"===t?"mdi:lock-open":"mdi:lock";case"media_player":return t&&"off"!==t&&"idle"!==t?"mdi:cast-connected":"mdi:cast";case"zwave":switch(t){case"dead":return"mdi:emoticon-dead";case"sleeping":return"mdi:sleep";case"initializing":return"mdi:timer-sand";default:return"mdi:z-wave"}default:return console.warn("Unable to find icon for domain "+e+" ("+t+")"),y}}var I=function(e){T(window,"haptic",e)},x=function(e,t,r){void 0===r&&(r=!1),r?history.replaceState(null,"",t):history.pushState(null,"",t),T(window,"location-changed",{replace:r})},O=function(e,t,r){void 0===r&&(r=!0);var n,i=d(t),a="group"===i?"homeassistant":i;switch(i){case"lock":n=r?"unlock":"lock";break;case"cover":n=r?"open_cover":"close_cover";break;default:n=r?"turn_on":"turn_off"}return e.callService(a,n,{entity_id:t})},E=function(e,t){var r=w.includes(e.states[t].state);return O(e,t,r)},A=function(e,t,r,n){if(n||(n={action:"more-info"}),!n.confirmation||n.confirmation.exemptions&&n.confirmation.exemptions.some(function(e){return e.user===t.user.id})||(I("warning"),confirm(n.confirmation.text||"Are you sure you want to "+n.action+"?")))switch(n.action){case"more-info":(r.entity||r.camera_image)&&T(e,"hass-more-info",{entityId:r.entity?r.entity:r.camera_image});break;case"navigate":n.navigation_path&&x(0,n.navigation_path);break;case"url":n.url_path&&window.open(n.url_path);break;case"toggle":r.entity&&(E(t,r.entity),I("success"));break;case"call-service":if(!n.service)return void I("failure");var i=n.service.split(".",2);t.callService(i[0],i[1],n.data,n.target),I("success");break;case"fire-dom-event":T(e,"ll-custom",n)}},M={humidity:"mdi:water-percent",illuminance:"mdi:brightness-5",temperature:"mdi:thermometer",pressure:"mdi:gauge",power:"mdi:flash",signal_strength:"mdi:wifi"},C={binary_sensor:function(e,t){var r="off"===e;switch(null==t?void 0:t.attributes.device_class){case"battery":return r?"mdi:battery":"mdi:battery-outline";case"battery_charging":return r?"mdi:battery":"mdi:battery-charging";case"cold":return r?"mdi:thermometer":"mdi:snowflake";case"connectivity":return r?"mdi:server-network-off":"mdi:server-network";case"door":return r?"mdi:door-closed":"mdi:door-open";case"garage_door":return r?"mdi:garage":"mdi:garage-open";case"power":return r?"mdi:power-plug-off":"mdi:power-plug";case"gas":case"problem":case"safety":case"tamper":return r?"mdi:check-circle":"mdi:alert-circle";case"smoke":return r?"mdi:check-circle":"mdi:smoke";case"heat":return r?"mdi:thermometer":"mdi:fire";case"light":return r?"mdi:brightness-5":"mdi:brightness-7";case"lock":return r?"mdi:lock":"mdi:lock-open";case"moisture":return r?"mdi:water-off":"mdi:water";case"motion":return r?"mdi:walk":"mdi:run";case"occupancy":return r?"mdi:home-outline":"mdi:home";case"opening":return r?"mdi:square":"mdi:square-outline";case"plug":return r?"mdi:power-plug-off":"mdi:power-plug";case"presence":return r?"mdi:home-outline":"mdi:home";case"running":return r?"mdi:stop":"mdi:play";case"sound":return r?"mdi:music-note-off":"mdi:music-note";case"update":return r?"mdi:package":"mdi:package-up";case"vibration":return r?"mdi:crop-portrait":"mdi:vibrate";case"window":return r?"mdi:window-closed":"mdi:window-open";default:return r?"mdi:radiobox-blank":"mdi:checkbox-marked-circle"}},cover:function(e){var t="closed"!==e.state;switch(e.attributes.device_class){case"garage":return t?"mdi:garage-open":"mdi:garage";case"door":return t?"mdi:door-open":"mdi:door-closed";case"shutter":return t?"mdi:window-shutter-open":"mdi:window-shutter";case"blind":return t?"mdi:blinds-open":"mdi:blinds";case"window":return t?"mdi:window-open":"mdi:window-closed";default:return S("cover",e.state)}},sensor:function(e){var t=e.attributes.device_class;if(t&&t in M)return M[t];if("battery"===t){var r=Number(e.state);if(isNaN(r))return"mdi:battery-unknown";var n=10*Math.round(r/10);return n>=100?"mdi:battery":n<=0?"mdi:battery-alert":"hass:battery-"+n}var i=e.attributes.unit_of_measurement;return"°C"===i||"°F"===i?"mdi:thermometer":S("sensor")},input_datetime:function(e){return e.attributes.has_date?e.attributes.has_time?S("input_datetime"):"mdi:calendar":"mdi:clock"}};e.DEFAULT_DOMAIN_ICON=y,e.DEFAULT_PANEL="lovelace",e.DEFAULT_VIEW_ENTITY_ID="group.default_view",e.DOMAINS_HIDE_MORE_INFO=["input_number","input_select","input_text","scene","weblink"],e.DOMAINS_MORE_INFO_NO_HISTORY=["camera","configurator","history_graph","scene"],e.DOMAINS_TOGGLE=k,e.DOMAINS_WITH_CARD=["climate","cover","configurator","input_select","input_number","input_text","lock","media_player","scene","script","timer","vacuum","water_heater","weblink"],e.DOMAINS_WITH_MORE_INFO=["alarm_control_panel","automation","camera","climate","configurator","cover","fan","group","history_graph","input_datetime","light","lock","media_player","script","sun","updater","vacuum","water_heater","weather"],e.STATES_OFF=w,e.UNIT_C="°C",e.UNIT_F="°F",e.applyThemesOnElement=function(e,t,r,n){void 0===n&&(n=!1),e._themes||(e._themes={});var i=t.default_theme;("default"===r||r&&t.themes[r])&&(i=r);var a=l({},e._themes);if("default"!==i){var o=t.themes[i];Object.keys(o).forEach(function(t){var r="--"+t;e._themes[r]="",a[r]=o[t]})}if(e.updateStyles?e.updateStyles(a):window.ShadyCSS&&window.ShadyCSS.styleSubtree(e,a),n){var u=document.querySelector("meta[name=theme-color]");if(u){u.hasAttribute("default-content")||u.setAttribute("default-content",u.getAttribute("content"));var c=a["--primary-color"]||u.getAttribute("default-content");u.setAttribute("content",c)}}},e.computeCardSize=function(e){return"function"==typeof e.getCardSize?e.getCardSize():4},e.computeDomain=d,e.computeEntity=function(e){return e.substr(e.indexOf(".")+1)},e.computeRTL=f,e.computeRTLDirection=function(e){return f(e)?"rtl":"ltr"},e.computeStateDisplay=function(e,t,r,n){var a=void 0!==n?n:t.state;if("unknown"===a||"unavailable"===a)return e("state.default."+a);if(p(t)){if("monetary"===t.attributes.device_class)try{return _(a,r,{style:"currency",currency:t.attributes.unit_of_measurement})}catch(e){}return _(a,r)+(t.attributes.unit_of_measurement?" "+t.attributes.unit_of_measurement:"")}var o=g(t);if("input_datetime"===o){var c;if(void 0===n)return t.attributes.has_date&&t.attributes.has_time?(c=new Date(t.attributes.year,t.attributes.month-1,t.attributes.day,t.attributes.hour,t.attributes.minute),u(c,r)):t.attributes.has_date?(c=new Date(t.attributes.year,t.attributes.month-1,t.attributes.day),i(c,r)):t.attributes.has_time?((c=new Date).setHours(t.attributes.hour,t.attributes.minute),m(c,r)):t.state;try{var s=n.split(" ");if(2===s.length)return u(new Date(s.join("T")),r);if(1===s.length){if(n.includes("-"))return i(new Date(n+"T00:00"),r);if(n.includes(":")){var l=new Date;return m(new Date(l.toISOString().split("T")[0]+"T"+n),r)}}return n}catch(e){return n}}return"humidifier"===o&&"on"===a&&t.attributes.humidity?t.attributes.humidity+" %":"counter"===o||"number"===o||"input_number"===o?_(a,r):t.attributes.device_class&&e("component."+o+".state."+t.attributes.device_class+"."+a)||e("component."+o+".state._."+a)||a},e.computeStateDomain=g,e.createThing=function(e,t){void 0===t&&(t=!1);var r=function(e,t){return n("hui-error-card",{type:"error",error:e,config:t})},n=function(e,t){var n=window.document.createElement(e);try{if(!n.setConfig)return;n.setConfig(t)}catch(n){return console.error(e,n),r(n.message,t)}return n};if(!e||"object"!=typeof e||!t&&!e.type)return r("No type defined",e);var i=e.type;if(i&&i.startsWith("custom:"))i=i.substr("custom:".length);else if(t)if(D.has(i))i="hui-"+i+"-row";else{if(!e.entity)return r("Invalid config given.",e);var a=e.entity.split(".",1)[0];i="hui-"+(F[a]||"text")+"-entity-row"}else i="hui-"+i+"-card";if(customElements.get(i))return n(i,e);var o=r("Custom element doesn't exist: "+e.type+".",e);o.style.display="None";var u=setTimeout(function(){o.style.display=""},2e3);return customElements.whenDefined(e.type).then(function(){clearTimeout(u),T(o,"ll-rebuild",{},o)}),o},e.debounce=function(e,t,r){var n;return void 0===r&&(r=!1),function(){var i=[].slice.call(arguments),a=this,o=function(){n=null,r||e.apply(a,i)},u=r&&!n;clearTimeout(n),n=setTimeout(o,t),u&&e.apply(a,i)}},e.domainIcon=S,e.evaluateFilter=function(e,t){var r=t.value||t,n=t.attribute?e.attributes[t.attribute]:e.state;switch(t.operator||"=="){case"==":return n===r;case"<=":return n<=r;case"<":return n=":return n>=r;case">":return n>r;case"!=":return n!==r;case"regex":return n.match(r);default:return!1}},e.fireEvent=T,e.fixedIcons=N,e.formatDate=i,e.formatDateMonth=function(e,t){return function(e){return new Intl.DateTimeFormat(e.language,{month:"long"})}(t).format(e)},e.formatDateMonthYear=function(e,t){return function(e){return new Intl.DateTimeFormat(e.language,{month:"long",year:"numeric"})}(t).format(e)},e.formatDateNumeric=function(e,t){return function(e){return new Intl.DateTimeFormat(e.language,{year:"numeric",month:"numeric",day:"numeric"})}(t).format(e)},e.formatDateShort=function(e,t){return function(e){return new Intl.DateTimeFormat(e.language,{day:"numeric",month:"short"})}(t).format(e)},e.formatDateTime=u,e.formatDateTimeNumeric=function(e,t){return function(e){return new Intl.DateTimeFormat(e.language,{year:"numeric",month:"numeric",day:"numeric",hour:"numeric",minute:"2-digit",hour12:o(e)})}(t).format(e)},e.formatDateTimeWithSeconds=function(e,t){return function(e){return new Intl.DateTimeFormat(e.language,{year:"numeric",month:"long",day:"numeric",hour:o(e)?"numeric":"2-digit",minute:"2-digit",second:"2-digit",hour12:o(e)})}(t).format(e)},e.formatDateWeekday=function(e,t){return function(e){return new Intl.DateTimeFormat(e.language,{weekday:"long",month:"long",day:"numeric"})}(t).format(e)},e.formatDateYear=function(e,t){return function(e){return new Intl.DateTimeFormat(e.language,{year:"numeric"})}(t).format(e)},e.formatNumber=_,e.formatTime=m,e.formatTimeWeekday=function(e,t){return function(e){return new Intl.DateTimeFormat(e.language,{hour:o(e)?"numeric":"2-digit",minute:"2-digit",second:"2-digit",hour12:o(e)})}(t).format(e)},e.formatTimeWithSeconds=function(e,t){return function(e){return new Intl.DateTimeFormat(e.language,{hour:o(e)?"numeric":"2-digit",minute:"2-digit",second:"2-digit",hour12:o(e)})}(t).format(e)},e.forwardHaptic=I,e.getLovelace=function(){var e=document.querySelector("home-assistant");if(e=(e=(e=(e=(e=(e=(e=(e=e&&e.shadowRoot)&&e.querySelector("home-assistant-main"))&&e.shadowRoot)&&e.querySelector("app-drawer-layout partial-panel-resolver"))&&e.shadowRoot||e)&&e.querySelector("ha-panel-lovelace"))&&e.shadowRoot)&&e.querySelector("hui-root")){var t=e.lovelace;return t.current_view=e.___curView,t}return null},e.handleAction=function(e,t,r,n){var i;"double_tap"===n&&r.double_tap_action?i=r.double_tap_action:"hold"===n&&r.hold_action?i=r.hold_action:"tap"===n&&r.tap_action&&(i=r.tap_action),A(e,t,r,i)},e.handleActionConfig=A,e.handleClick=function(e,t,r,n,i){var a;if(i&&r.double_tap_action?a=r.double_tap_action:n&&r.hold_action?a=r.hold_action:!n&&r.tap_action&&(a=r.tap_action),a||(a={action:"more-info"}),!a.confirmation||a.confirmation.exemptions&&a.confirmation.exemptions.some(function(e){return e.user===t.user.id})||confirm(a.confirmation.text||"Are you sure you want to "+a.action+"?"))switch(a.action){case"more-info":(a.entity||r.entity||r.camera_image)&&(T(e,"hass-more-info",{entityId:a.entity?a.entity:r.entity?r.entity:r.camera_image}),a.haptic&&I(a.haptic));break;case"navigate":a.navigation_path&&(x(0,a.navigation_path),a.haptic&&I(a.haptic));break;case"url":a.url_path&&window.open(a.url_path),a.haptic&&I(a.haptic);break;case"toggle":r.entity&&(E(t,r.entity),a.haptic&&I(a.haptic));break;case"call-service":if(!a.service)return;var o=a.service.split(".",2),u=o[0],c=o[1],m=l({},a.data);"entity"===m.entity_id&&(m.entity_id=r.entity),t.callService(u,c,m,a.target),a.haptic&&I(a.haptic);break;case"fire-dom-event":T(e,"ll-custom",a),a.haptic&&I(a.haptic)}},e.hasAction=function(e){return void 0!==e&&"none"!==e.action},e.hasConfigOrEntityChanged=function(e,t,r){if(t.has("config")||r)return!0;if(e.config.entity){var n=t.get("hass");return!n||n.states[e.config.entity]!==e.hass.states[e.config.entity]}return!1},e.hasDoubleClick=function(e){return void 0!==e&&"none"!==e.action},e.isNumericState=p,e.navigate=x,e.numberFormatToLocale=h,e.relativeTime=function(e,r,n,i){void 0===i&&(i=!0);var a=t.selectUnit(e,n);return i?function(e){return new Intl.RelativeTimeFormat(e.language,{numeric:"auto"})}(r).format(a.value,a.unit):Intl.NumberFormat(r.language,{style:"unit",unit:a.unit,unitDisplay:"long"}).format(Math.abs(a.value))},e.round=b,e.stateIcon=function(e){if(!e)return y;if(e.attributes.icon)return e.attributes.icon;var t=d(e.entity_id);return t in C?C[t](e):S(t,e.state)},e.timerTimeRemaining=function(e){var t,r=3600*(t=e.attributes.remaining.split(":").map(Number))[0]+60*t[1]+t[2];if("active"===e.state){var n=(new Date).getTime(),i=new Date(e.last_changed).getTime();r=Math.max(r-(n-i)/1e3,0)}return r},e.toggleEntity=E,e.turnOnOffEntities=function(e,t,r){void 0===r&&(r=!0);var n={};t.forEach(function(t){if(w.includes(e.states[t].state)===r){var i=d(t),a=["cover","lock"].includes(i)?i:"homeassistant";a in n||(n[a]=[]),n[a].push(t)}}),Object.keys(n).forEach(function(t){var i;switch(t){case"lock":i=r?"unlock":"lock";break;case"cover":i=r?"open_cover":"close_cover";break;default:i=r?"turn_on":"turn_off"}e.callService(t,i,{entity_id:n[t]})})},e.turnOnOffEntity=O}); //# sourceMappingURL=index.umd.js.map diff --git a/dist/index.umd.js.map b/dist/index.umd.js.map index 9b64de1..bd7fdd9 100644 --- a/dist/index.umd.js.map +++ b/dist/index.umd.js.map @@ -1 +1 @@ -{"version":3,"file":"index.umd.js","sources":["../src/types.ts","../src/datetime/format_date.ts","../src/datetime/use_am_pm.ts","../src/datetime/format_date_time.ts","../src/datetime/format_time.ts","../src/compute-domain.ts","../src/compute-rtl.ts","../src/compute-state-domain.ts","../src/format-number.ts","../src/const.ts","../src/fire-event.ts","../src/create-thing.ts","../src/domain_icons.ts","../src/haptic.ts","../src/navigate.ts","../src/turn-on-off-entity.ts","../src/toggle-entity.ts","../src/handle-action.ts","../src/sensor_icon.ts","../src/state_icon.ts","../src/binary_sensor_icon.ts","../src/cover_icon.ts","../src/input_datetime_icon.ts","../src/apply_themes_on_element.ts","../src/compute-card-size.ts","../src/compute-entity.ts","../src/compute-state-display.ts","../src/debounce.ts","../src/evaluate-filter.ts","../src/get-lovelace.ts","../src/handle-click.ts","../src/has-action.ts","../src/has-changed.ts","../src/has-double-click.ts","../src/datetime/relative_time.ts","../src/datetime/timer_time_remaining.ts","../src/datetime/duration_to_seconds.ts","../src/turn-on-off-entities.ts"],"sourcesContent":["import {\n HassEntities,\n HassConfig,\n Auth,\n Connection,\n MessageBase,\n HassServices,\n HassServiceTarget,\n} from \"home-assistant-js-websocket\";\nimport { HapticType } from \"./haptic\";\nimport { HASSDomEvent } from \"./fire-event\";\n\nexport interface ToggleMenuActionConfig extends BaseActionConfig {\n action: \"toggle-menu\";\n}\n\nexport interface ToggleActionConfig extends BaseActionConfig {\n action: \"toggle\";\n}\n\nexport interface CallServiceActionConfig extends BaseActionConfig {\n action: \"call-service\";\n service: string;\n service_data?: {\n entity_id?: string | [string];\n [key: string]: any;\n };\n\n target?: HassServiceTarget;\n repeat?: number;\n haptic?: HapticType;\n}\n\nexport interface NavigateActionConfig extends BaseActionConfig {\n action: \"navigate\";\n navigation_path: string;\n}\n\nexport interface UrlActionConfig extends BaseActionConfig {\n action: \"url\";\n url_path: string;\n}\n\nexport interface MoreInfoActionConfig extends BaseActionConfig {\n action: \"more-info\";\n entity?: string;\n}\n\nexport interface NoActionConfig extends BaseActionConfig {\n action: \"none\";\n}\n\nexport interface CustomActionConfig extends BaseActionConfig {\n action: \"fire-dom-event\";\n}\n\n/**\n * `repeat` and `haptic` are specifically for use in custom cards like the Button-Card\n */\nexport interface BaseActionConfig {\n confirmation?: ConfirmationRestrictionConfig;\n repeat?: number;\n haptic?: HapticType;\n}\n\nexport interface ConfirmationRestrictionConfig {\n text?: string;\n exemptions?: RestrictionConfig[];\n}\n\nexport interface RestrictionConfig {\n user: string;\n}\n\nexport type ActionConfig =\n | ToggleActionConfig\n | CallServiceActionConfig\n | NavigateActionConfig\n | UrlActionConfig\n | MoreInfoActionConfig\n | NoActionConfig\n | CustomActionConfig\n | ToggleMenuActionConfig;\n\nexport interface Window {\n // Custom panel entry point url\n customPanelJS: string;\n ShadyCSS: {\n nativeCss: boolean;\n nativeShadow: boolean;\n prepareTemplate(templateElement, elementName, elementExtension);\n styleElement(element);\n styleSubtree(element, overrideProperties);\n styleDocument(overrideProperties);\n getComputedStyleValue(element, propertyName);\n };\n}\n\ndeclare global {\n // for fire event\n interface HASSDomEvents {\n \"value-changed\": {\n value: unknown;\n };\n \"config-changed\": {\n config: any;\n };\n \"hass-more-info\": {\n entityId: string | undefined;\n };\n \"ll-rebuild\": {};\n \"ll-custom\": {};\n \"location-changed\": {\n replace: boolean;\n };\n \"show-dialog\": {};\n undefined;\n action: {\n action: string;\n };\n }\n}\n\ntype ValidHassDomEvent = keyof HASSDomEvents;\n\nexport type LocalizeFunc = (key: string, ...args: any[]) => string;\n\nexport interface Credential {\n auth_provider_type: string;\n auth_provider_id: string;\n}\n\nexport interface MFAModule {\n id: string;\n name: string;\n enabled: boolean;\n}\n\nexport interface CurrentUser {\n id: string;\n is_owner: boolean;\n is_admin: boolean;\n name: string;\n credentials: Credential[];\n mfa_modules: MFAModule[];\n}\n\nexport interface Theme {\n // Incomplete\n \"primary-color\": string;\n \"text-primary-color\": string;\n \"accent-color\": string;\n}\n\nexport interface Themes {\n default_theme: string;\n themes: { [key: string]: Theme };\n}\n\nexport interface Panel {\n component_name: string;\n config: { [key: string]: any } | null;\n icon: string | null;\n title: string | null;\n url_path: string;\n}\n\nexport interface Panels {\n [name: string]: Panel;\n}\n\nexport interface Resources {\n [language: string]: { [key: string]: string };\n}\n\nexport interface Translation {\n nativeName: string;\n isRTL: boolean;\n fingerprints: { [fragment: string]: string };\n}\n\nexport interface ServiceCallRequest {\n domain: string;\n service: string;\n serviceData?: Record;\n target?: HassServiceTarget;\n}\n\nexport interface HomeAssistant {\n auth: Auth;\n connection: Connection;\n connected: boolean;\n states: HassEntities;\n services: HassServices;\n config: HassConfig;\n themes: Themes;\n selectedTheme?: string | null;\n panels: Panels;\n panelUrl: string;\n\n // i18n\n // current effective language, in that order:\n // - backend saved user selected lanugage\n // - language in local appstorage\n // - browser language\n // - english (en)\n language: string;\n locale: FrontendLocaleData;\n // local stored language, keep that name for backward compability\n selectedLanguage: string | null;\n resources: Resources;\n localize: LocalizeFunc;\n translationMetadata: {\n fragments: string[];\n translations: {\n [lang: string]: Translation;\n };\n };\n\n dockedSidebar: boolean;\n moreInfoEntityId: string;\n user: CurrentUser;\n callService: (\n domain: ServiceCallRequest[\"domain\"],\n service: ServiceCallRequest[\"service\"],\n serviceData?: ServiceCallRequest[\"serviceData\"],\n target?: ServiceCallRequest[\"target\"]\n ) => Promise;\n callApi: (\n method: \"GET\" | \"POST\" | \"PUT\" | \"DELETE\",\n path: string,\n parameters?: { [key: string]: any }\n ) => Promise;\n fetchWithAuth: (\n path: string,\n init?: { [key: string]: any }\n ) => Promise;\n sendWS: (msg: MessageBase) => Promise;\n callWS: (msg: MessageBase) => Promise;\n}\n\nexport enum NumberFormat {\n language = \"language\",\n system = \"system\",\n comma_decimal = \"comma_decimal\",\n decimal_comma = \"decimal_comma\",\n space_comma = \"space_comma\",\n none = \"none\",\n}\n\nexport enum TimeFormat {\n language = \"language\",\n system = \"system\",\n am_pm = \"12\",\n twenty_four = \"24\",\n}\n\nexport interface FrontendLocaleData {\n language: string;\n number_format: NumberFormat;\n time_format: TimeFormat;\n}\n\nexport interface LovelaceCardConfig {\n index?: number;\n view_index?: number;\n type: string;\n [key: string]: any;\n}\n\nexport interface LovelaceCard extends HTMLElement {\n hass?: HomeAssistant;\n isPanel?: boolean;\n editMode?: boolean;\n getCardSize(): number | Promise;\n setConfig(config: LovelaceCardConfig): void;\n}\n\nexport interface LovelaceCardEditor extends HTMLElement {\n hass?: HomeAssistant;\n lovelace?: LovelaceConfig;\n setConfig(config: LovelaceCardConfig): void;\n}\n\nexport interface LovelaceConfig {\n title?: string;\n views: LovelaceViewConfig[];\n background?: string;\n}\n\nexport interface LovelaceViewConfig {\n index?: number;\n title?: string;\n badges?: Array;\n cards?: LovelaceCardConfig[];\n path?: string;\n icon?: string;\n theme?: string;\n panel?: boolean;\n background?: string;\n visible?: boolean | ShowViewConfig[];\n}\n\nexport interface ShowViewConfig {\n user?: string;\n}\n\nexport interface LovelaceBadgeConfig {\n type?: string;\n [key: string]: any;\n}\n\nexport interface ActionHandlerDetail {\n action: string;\n}\n\nexport type ActionHandlerEvent = HASSDomEvent;\n\nexport interface ActionHandlerOptions {\n hasHold?: boolean;\n hasDoubleClick?: boolean;\n}\n\nexport interface EntitiesCardEntityConfig extends EntityConfig {\n type?: string;\n secondary_info?:\n | \"entity-id\"\n | \"last-changed\"\n | \"last-triggered\"\n | \"last-updated\"\n | \"position\"\n | \"tilt-position\"\n | \"brightness\";\n action_name?: string;\n service?: string;\n service_data?: Record;\n url?: string;\n tap_action?: ActionConfig;\n hold_action?: ActionConfig;\n double_tap_action?: ActionConfig;\n state_color?: boolean;\n show_name?: boolean;\n show_icon?: boolean;\n}\n\nexport interface EntityConfig {\n entity: string;\n type?: string;\n name?: string;\n icon?: string;\n image?: string;\n}\n\nexport interface LovelaceElementConfigBase {\n type: string;\n style: Record;\n}\n","//REF: https://github.com/home-assistant/frontend/blob/dev/src/common/datetime/format_date.ts\n\nimport { FrontendLocaleData } from \"../types\";\n\n/**\n * Formatting a Date to the dddd, mmmm yy format e.g. Tuesday, August 10\n * @param dateObj The date to convert\n * @param locale The users's locale settings\n * @returns date string like \"Tuesday, August 10\"\n */\nexport const formatDateWeekday = (dateObj: Date, locale: FrontendLocaleData) =>\n formatDateWeekdayMem(locale).format(dateObj);\n\nconst formatDateWeekdayMem =\n (locale: FrontendLocaleData) =>\n new Intl.DateTimeFormat(locale.language, {\n weekday: \"long\",\n month: \"long\",\n day: \"numeric\",\n });\n\n/**\n * Formatting a Date to the mmmm dd, yyyy format e.g. August 10, 2021\n * @param dateObj The date to convert\n * @param locale The users's locale settings\n * @returns date string like \"August 10, 2021\"\n */\nexport const formatDate = (dateObj: Date, locale: FrontendLocaleData) =>\n formatDateMem(locale).format(dateObj);\n\nconst formatDateMem =\n (locale: FrontendLocaleData) =>\n new Intl.DateTimeFormat(locale.language, {\n year: \"numeric\",\n month: \"long\",\n day: \"numeric\",\n });\n\n/**\n * Formatting a Date to the classic date format e.g. 10/08/2021\n * @param dateObj The date to convert\n * @param locale The users's locale settings\n * @returns classic date format \"10/08/2021\"\n */\nexport const formatDateNumeric = (dateObj: Date, locale: FrontendLocaleData) =>\n formatDateNumericMem(locale).format(dateObj);\n\nconst formatDateNumericMem =\n (locale: FrontendLocaleData) =>\n new Intl.DateTimeFormat(locale.language, {\n year: \"numeric\",\n month: \"numeric\",\n day: \"numeric\",\n });\n\n\n/**\n * Formatting a Date to just a month with days e.g. Aug 10\n * @param dateObj The date to convert\n * @param locale The users's locale settings\n * @returns month and day like \"Aug 10\"\n */\nexport const formatDateShort = (dateObj: Date, locale: FrontendLocaleData) =>\nformatDateShortMem(locale).format(dateObj);\n\nconst formatDateShortMem =\n(locale: FrontendLocaleData) =>\n new Intl.DateTimeFormat(locale.language, {\n day: \"numeric\",\n month: \"short\",\n });\n\n\n/**\n * Formatting a Date to just a month with year e.g. August 2021\n * @param dateObj The date to convert\n * @param locale The users's locale settings\n * @returns month and year like \"August 2021\"\n */\nexport const formatDateMonthYear = (\ndateObj: Date,\nlocale: FrontendLocaleData\n) => formatDateMonthYearMem(locale).format(dateObj);\n\nconst formatDateMonthYearMem = (locale: FrontendLocaleData) =>\n new Intl.DateTimeFormat(locale.language, {\n month: \"long\",\n year: \"numeric\",\n });\n\n\n/**\n * Formatting a Date to just a month e.g. August\n * @param dateObj The date to convert\n * @param locale The users's locale settings\n * @returns the written out months of the date\n */\nexport const formatDateMonth = (dateObj: Date, locale: FrontendLocaleData) =>\nformatDateMonthMem(locale).format(dateObj);\n\nconst formatDateMonthMem = (locale: FrontendLocaleData) =>\n new Intl.DateTimeFormat(locale.language, {\n month: \"long\",\n });\n\n\n/**\n * Formatting a Date to just a year e.g. 2021\n * @param dateObj The date to convert\n * @param locale The users's locale settings\n * @returns the year of the date in yyyy\n */\nexport const formatDateYear = (dateObj: Date, locale: FrontendLocaleData) =>\nformatDateYearMem(locale).format(dateObj);\n\nconst formatDateYearMem = (locale: FrontendLocaleData) =>\n new Intl.DateTimeFormat(locale.language, {\n year: \"numeric\",\n });\n","// REF: https://github.com/home-assistant/frontend/blob/dev/src/common/datetime/use_am_pm.ts\r\n\r\nimport { FrontendLocaleData, TimeFormat } from \"../types\"\r\n\r\n/**\r\n * Checking if AM/PM time format is used within the browser.\r\n * @param locale Homeassistant frontend locale data\r\n * @returns \r\n */\r\nexport const useAmPm = (locale: FrontendLocaleData): boolean => {\r\n if (\r\n locale.time_format === TimeFormat.language ||\r\n locale.time_format === TimeFormat.system\r\n ) {\r\n const testLanguage =\r\n locale.time_format === TimeFormat.language ? locale.language : undefined;\r\n const test = new Date().toLocaleString(testLanguage);\r\n return test.includes(\"AM\") || test.includes(\"PM\");\r\n }\r\n\r\n return locale.time_format === TimeFormat.am_pm;\r\n};\r\n","//REF: https://github.com/home-assistant/frontend/blob/dev/src/common/datetime/format_date_time.ts\n\nimport { FrontendLocaleData } from \"../types\";\nimport { useAmPm } from \"./use_am_pm\";\n\n// August 9, 2021, 8:23 AM\n/**\n * Formatting a dateObject to date with time e.g. August 9, 2021, 8:23 AM\n * @param dateObj The date to convert\n * @param locale The users's locale settings\n * @returns month and day like \"August 9, 2021, 8:23 AM\"\n */\nexport const formatDateTime = (dateObj: Date, locale: FrontendLocaleData) =>\n formatDateTimeMem(locale).format(dateObj);\n\nconst formatDateTimeMem = (locale: FrontendLocaleData) =>\n new Intl.DateTimeFormat(locale.language, {\n year: \"numeric\",\n month: \"long\",\n day: \"numeric\",\n hour: useAmPm(locale) ? \"numeric\" : \"2-digit\",\n minute: \"2-digit\",\n hour12: useAmPm(locale),\n });\n\n\n/**\n * Formatting a dateObject to date with time e.g. August 9, 2021, 8:23:15 AM\n * @param dateObj The date to convert\n * @param locale The users's locale settings\n * @returns month and day like \"August 9, 2021, 8:23:15 AM\"\n */\nexport const formatDateTimeWithSeconds = (\n dateObj: Date,\n locale: FrontendLocaleData\n) => formatDateTimeWithSecondsMem(locale).format(dateObj);\n\nconst formatDateTimeWithSecondsMem =\n (locale: FrontendLocaleData) =>\n new Intl.DateTimeFormat(locale.language, {\n year: \"numeric\",\n month: \"long\",\n day: \"numeric\",\n hour: useAmPm(locale) ? \"numeric\" : \"2-digit\",\n minute: \"2-digit\",\n second: \"2-digit\",\n hour12: useAmPm(locale),\n });\n\n/**\n * Formatting a Date to just date with AM/PM time e.g. 9/8/2021, 8:23 AM\n * @param dateObj The date to convert\n * @param locale The users's locale settings\n * @returns month and day like \"9/8/2021, 8:23 AM\"\n */\nexport const formatDateTimeNumeric = (\n dateObj: Date,\n locale: FrontendLocaleData\n) => formatDateTimeNumericMem(locale).format(dateObj);\n\nconst formatDateTimeNumericMem =\n (locale: FrontendLocaleData) =>\n new Intl.DateTimeFormat(locale.language, {\n year: \"numeric\",\n month: \"numeric\",\n day: \"numeric\",\n hour: \"numeric\",\n minute: \"2-digit\",\n hour12: useAmPm(locale),\n });","//REF: https://github.com/home-assistant/frontend/blob/dev/src/common/datetime/format_time.ts\n\nimport { FrontendLocaleData } from \"../types\";\nimport { useAmPm } from \"./use_am_pm\";\n\n/**\n * 9:15 PM or 21:15\n * @param dateObj The time to convert\n * @param locale The users's locale settings\n * @returns Reformated time in hh:mm\n */\n export const formatTime = (dateObj: Date, locale: FrontendLocaleData) =>\n formatTimeMem(locale).format(dateObj);\n\n const formatTimeMem =\n (locale: FrontendLocaleData) =>\n new Intl.DateTimeFormat(locale.language, {\n hour: \"numeric\",\n minute: \"2-digit\",\n hour12: useAmPm(locale),\n });\n\n/**\n* 9:15:24 PM or 21:15:24\n* @param dateObj The time to convert\n* @param locale The users's locale settings\n* @returns Reformated time in hh:mm:ss\n*/\nexport const formatTimeWithSeconds = (\n dateObj: Date,\n locale: FrontendLocaleData\n) => formatTimeWithSecondsMem(locale).format(dateObj);\n\nconst formatTimeWithSecondsMem =\n (locale: FrontendLocaleData) =>\n new Intl.DateTimeFormat(locale.language, {\n hour: useAmPm(locale) ? \"numeric\" : \"2-digit\",\n minute: \"2-digit\",\n second: \"2-digit\",\n hour12: useAmPm(locale),\n });\n\n/**\n* Tuesday 7:00 PM or Tuesday 19:00\n* @param dateObj The datetime to convert\n* @param locale The users's locale settings\n* @returns Reformated weekday/time in dddd hh:mm\n*/\nexport const formatTimeWeekday = (dateObj: Date, locale: FrontendLocaleData) =>\n formatTimeWeekdayMem(locale).format(dateObj);\n\nconst formatTimeWeekdayMem =\n (locale: FrontendLocaleData) =>\n new Intl.DateTimeFormat(locale.language, {\n hour: useAmPm(locale) ? \"numeric\" : \"2-digit\",\n minute: \"2-digit\",\n second: \"2-digit\",\n hour12: useAmPm(locale),\n }); \n","export function computeDomain(entityId: string): string {\n return entityId.substr(0, entityId.indexOf(\".\"));\n}\n","import { HomeAssistant } from \"./types\";\n\nexport function computeRTL(hass: HomeAssistant) {\n const lang = hass?.locale?.language || \"en\";\n if (hass.translationMetadata.translations[lang]) {\n return hass.translationMetadata.translations[lang].isRTL || false;\n }\n return false;\n}\n\nexport function computeRTLDirection(hass: HomeAssistant) {\n return computeRTL(hass) ? \"rtl\" : \"ltr\";\n}\n","import { HassEntity } from \"home-assistant-js-websocket\";\nimport { computeDomain } from \"./compute-domain\";\n\nexport function computeStateDomain(stateObj: HassEntity) {\n return computeDomain(stateObj.entity_id);\n}\n","//REF: https://github.com/home-assistant/frontend/blob/dev/src/common/number/format_number.ts\n\nimport { HassEntity } from \"home-assistant-js-websocket\";\nimport { FrontendLocaleData, NumberFormat } from \"./types\";\n\n/**\n * Returns true if the entity is considered numeric based on the attributes it has\n * @param stateObj The entity state object\n */\n export const isNumericState = (stateObj: HassEntity): boolean =>\n !!stateObj.attributes.unit_of_measurement ||\n !!stateObj.attributes.state_class;\n\nexport const numberFormatToLocale = (\n localeOptions: FrontendLocaleData\n): string | string[] | undefined => {\n switch (localeOptions.number_format) {\n case NumberFormat.comma_decimal:\n return [\"en-US\", \"en\"]; // Use United States with fallback to English formatting 1,234,567.89\n case NumberFormat.decimal_comma:\n return [\"de\", \"es\", \"it\"]; // Use German with fallback to Spanish then Italian formatting 1.234.567,89\n case NumberFormat.space_comma:\n return [\"fr\", \"sv\", \"cs\"]; // Use French with fallback to Swedish and Czech formatting 1 234 567,89\n case NumberFormat.system:\n return undefined;\n default:\n return localeOptions.language;\n }\n};\n\nexport const round = (value: number, precision = 2): number =>\n Math.round(value * 10 ** precision) / 10 ** precision;\n\n/**\n * Formats a number based on the specified language with thousands separator(s) and decimal character for better legibility.\n * @param num The number to format\n * @param locale The user-selected language and number format, from `hass.locale`\n * @param options Intl.NumberFormatOptions to use\n */\nexport const formatNumber = (\n num: string | number,\n localeOptions?: FrontendLocaleData,\n options?: Intl.NumberFormatOptions\n): string => {\n const locale = localeOptions\n ? numberFormatToLocale(localeOptions)\n : undefined;\n\n // Polyfill for Number.isNaN, which is more reliable than the global isNaN()\n Number.isNaN =\n Number.isNaN ||\n function isNaN(input) {\n return typeof input === \"number\" && isNaN(input);\n };\n\n if (\n localeOptions?.number_format !== NumberFormat.none &&\n !Number.isNaN(Number(num)) &&\n Intl\n ) {\n try {\n return new Intl.NumberFormat(\n locale,\n getDefaultFormatOptions(num, options)\n ).format(Number(num));\n } catch (err: any) {\n // Don't fail when using \"TEST\" language\n // eslint-disable-next-line no-console\n console.error(err);\n return new Intl.NumberFormat(\n undefined,\n getDefaultFormatOptions(num, options)\n ).format(Number(num));\n }\n }\n if (typeof num === \"string\") {\n return num;\n }\n return `${round(num, options?.maximumFractionDigits).toString()}${\n options?.style === \"currency\" ? ` ${options.currency}` : \"\"\n }`;\n};\n\n/**\n * Generates default options for Intl.NumberFormat\n * @param num The number to be formatted\n * @param options The Intl.NumberFormatOptions that should be included in the returned options\n */\nconst getDefaultFormatOptions = (\n num: string | number,\n options?: Intl.NumberFormatOptions\n): Intl.NumberFormatOptions => {\n const defaultOptions: Intl.NumberFormatOptions = {\n maximumFractionDigits: 2,\n ...options,\n };\n\n if (typeof num !== \"string\") {\n return defaultOptions;\n }\n\n // Keep decimal trailing zeros if they are present in a string numeric value\n if (\n !options ||\n (!options.minimumFractionDigits && !options.maximumFractionDigits)\n ) {\n const digits = num.indexOf(\".\") > -1 ? num.split(\".\")[1].length : 0;\n defaultOptions.minimumFractionDigits = digits;\n defaultOptions.maximumFractionDigits = digits;\n }\n\n return defaultOptions;\n};\n","/** Constants to be used in the frontend. */\n\n// Constants should be alphabetically sorted by name.\n// Arrays with values should be alphabetically sorted if order doesn't matter.\n// Each constant should have a description what it is supposed to be used for.\n\n/** Icon to use when no icon specified for domain. */\nexport const DEFAULT_DOMAIN_ICON = \"mdi:bookmark\";\n\n/** Panel to show when no panel is picked. */\nexport const DEFAULT_PANEL = \"lovelace\";\n\n/** Domains that have a state card. */\nexport const DOMAINS_WITH_CARD = [\n \"climate\",\n \"cover\",\n \"configurator\",\n \"input_select\",\n \"input_number\",\n \"input_text\",\n \"lock\",\n \"media_player\",\n \"scene\",\n \"script\",\n \"timer\",\n \"vacuum\",\n \"water_heater\",\n \"weblink\"\n];\n\n/** Domains with separate more info dialog. */\nexport const DOMAINS_WITH_MORE_INFO = [\n \"alarm_control_panel\",\n \"automation\",\n \"camera\",\n \"climate\",\n \"configurator\",\n \"cover\",\n \"fan\",\n \"group\",\n \"history_graph\",\n \"input_datetime\",\n \"light\",\n \"lock\",\n \"media_player\",\n \"script\",\n \"sun\",\n \"updater\",\n \"vacuum\",\n \"water_heater\",\n \"weather\"\n];\n\n/** Domains that show no more info dialog. */\nexport const DOMAINS_HIDE_MORE_INFO = [\n \"input_number\",\n \"input_select\",\n \"input_text\",\n \"scene\",\n \"weblink\"\n];\n\n/** Domains that should have the history hidden in the more info dialog. */\nexport const DOMAINS_MORE_INFO_NO_HISTORY = [\n \"camera\",\n \"configurator\",\n \"history_graph\",\n \"scene\"\n];\n\n/** States that we consider \"off\". */\nexport const STATES_OFF = [\"closed\", \"locked\", \"off\"];\n\n/** Domains where we allow toggle in Lovelace. */\nexport const DOMAINS_TOGGLE = new Set([\n \"fan\",\n \"input_boolean\",\n \"light\",\n \"switch\",\n \"group\",\n \"automation\"\n]);\n\n/** Temperature units. */\nexport const UNIT_C = \"°C\";\nexport const UNIT_F = \"°F\";\n\n/** Entity ID of the default view. */\nexport const DEFAULT_VIEW_ENTITY_ID = \"group.default_view\";\n","// Polymer legacy event helpers used courtesy of the Polymer project.\n//\n// Copyright (c) 2017 The Polymer Authors. All rights reserved.\n//\n// Redistribution and use in source and binary forms, with or without\n// modification, are permitted provided that the following conditions are\n// met:\n//\n// * Redistributions of source code must retain the above copyright\n// notice, this list of conditions and the following disclaimer.\n// * Redistributions in binary form must reproduce the above\n// copyright notice, this list of conditions and the following disclaimer\n// in the documentation and/or other materials provided with the\n// distribution.\n// * Neither the name of Google Inc. nor the names of its\n// contributors may be used to endorse or promote products derived from\n// this software without specific prior written permission.\n//\n// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n// \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\ndeclare global {\n // tslint:disable-next-line\n interface HASSDomEvents {}\n}\n\nexport type ValidHassDomEvent = keyof HASSDomEvents;\n\nexport interface HASSDomEvent extends Event {\n detail: T;\n}\n\n/**\n * Dispatches a custom event with an optional detail value.\n *\n * @param {string} type Name of event type.\n * @param {*=} detail Detail value containing event-specific\n * payload.\n * @param {{ bubbles: (boolean|undefined),\n * cancelable: (boolean|undefined),\n * composed: (boolean|undefined) }=}\n * options Object specifying options. These may include:\n * `bubbles` (boolean, defaults to `true`),\n * `cancelable` (boolean, defaults to false), and\n * `node` on which to fire the event (HTMLElement, defaults to `this`).\n * @return {Event} The new event that was fired.\n */\nexport const fireEvent = (\n node: HTMLElement | Window,\n type: HassEvent,\n detail?: HASSDomEvents[HassEvent],\n options?: {\n bubbles?: boolean;\n cancelable?: boolean;\n composed?: boolean;\n }\n) => {\n options = options || {};\n // @ts-ignore\n detail = detail === null || detail === undefined ? {} : detail;\n const event = new Event(type, {\n bubbles: options.bubbles === undefined ? true : options.bubbles,\n cancelable: Boolean(options.cancelable),\n composed: options.composed === undefined ? true : options.composed\n });\n (event as any).detail = detail;\n node.dispatchEvent(event);\n return event;\n};\n","import { fireEvent } from \"./fire-event\";\n\nconst SPECIAL_TYPES = new Set([\n \"call-service\",\n \"divider\",\n \"section\",\n \"weblink\",\n \"cast\",\n \"select\"\n]);\nconst DOMAIN_TO_ELEMENT_TYPE = {\n alert: \"toggle\",\n automation: \"toggle\",\n climate: \"climate\",\n cover: \"cover\",\n fan: \"toggle\",\n group: \"group\",\n input_boolean: \"toggle\",\n input_number: \"input-number\",\n input_select: \"input-select\",\n input_text: \"input-text\",\n light: \"toggle\",\n lock: \"lock\",\n media_player: \"media-player\",\n remote: \"toggle\",\n scene: \"scene\",\n script: \"script\",\n sensor: \"sensor\",\n timer: \"timer\",\n switch: \"toggle\",\n vacuum: \"toggle\",\n // Temporary. Once climate is rewritten,\n // water heater should get it's own row.\n water_heater: \"climate\",\n input_datetime: \"input-datetime\"\n};\n\nexport const createThing = (cardConfig, isRow = false) => {\n const _createError = (error, config) => {\n return _createThing(\n \"hui-error-card\",\n {\n type: \"error\",\n error,\n config\n }\n );\n };\n\n const _createThing = (tag, config) => {\n const element = window.document.createElement(tag);\n try {\n // Preventing an error-card infinity loop: https://github.com/custom-cards/custom-card-helpers/issues/54\n if (!element.setConfig) return;\n element.setConfig(config);\n } catch (err) {\n console.error(tag, err);\n return _createError((err as Error).message, config);\n }\n return element;\n };\n\n if (!cardConfig || typeof cardConfig !== \"object\" || (!isRow && !cardConfig.type))\n return _createError(\"No type defined\", cardConfig);\n let tag = cardConfig.type;\n if (tag && tag.startsWith(\"custom:\")) {\n tag = tag.substr(\"custom:\".length);\n } else if (isRow) {\n if (SPECIAL_TYPES.has(tag)) {\n tag = `hui-${tag}-row`;\n } else {\n if (!cardConfig.entity) {\n return _createError(\"Invalid config given.\", cardConfig);\n }\n \n const domain = cardConfig.entity.split(\".\", 1)[0];\n tag = `hui-${DOMAIN_TO_ELEMENT_TYPE[domain] || \"text\"}-entity-row`;\n }\n } else {\n tag = `hui-${tag}-card`;\n }\n\n if (customElements.get(tag)) return _createThing(tag, cardConfig);\n\n // If element doesn't exist (yet) create an error\n const element = _createError(\n `Custom element doesn't exist: ${cardConfig.type}.`,\n cardConfig\n );\n element.style.display = \"None\";\n const timer = setTimeout(() => {\n element.style.display = \"\";\n }, 2000);\n // Remove error if element is defined later\n customElements.whenDefined(cardConfig.type).then(() => {\n clearTimeout(timer);\n fireEvent(element, \"ll-rebuild\", {}, element);\n });\n\n return element;\n};\n","/**\n * Return the icon to be used for a domain.\n *\n * Optionally pass in a state to influence the domain icon.\n */\nimport { DEFAULT_DOMAIN_ICON } from \"./const\";\n\nexport const fixedIcons = {\n alert: \"mdi:alert\",\n automation: \"mdi:playlist-play\",\n calendar: \"mdi:calendar\",\n camera: \"mdi:video\",\n climate: \"mdi:thermostat\",\n configurator: \"mdi:settings\",\n conversation: \"mdi:text-to-speech\",\n device_tracker: \"mdi:account\",\n fan: \"mdi:fan\",\n group: \"mdi:google-circles-communities\",\n history_graph: \"mdi:chart-line\",\n homeassistant: \"mdi:home-assistant\",\n homekit: \"mdi:home-automation\",\n image_processing: \"mdi:image-filter-frames\",\n input_boolean: \"mdi:drawing\",\n input_datetime: \"mdi:calendar-clock\",\n input_number: \"mdi:ray-vertex\",\n input_select: \"mdi:format-list-bulleted\",\n input_text: \"mdi:textbox\",\n light: \"mdi:lightbulb\",\n mailbox: \"mdi:mailbox\",\n notify: \"mdi:comment-alert\",\n person: \"mdi:account\",\n plant: \"mdi:flower\",\n proximity: \"mdi:apple-safari\",\n remote: \"mdi:remote\",\n scene: \"mdi:google-pages\",\n script: \"mdi:file-document\",\n sensor: \"mdi:eye\",\n simple_alarm: \"mdi:bell\",\n sun: \"mdi:white-balance-sunny\",\n switch: \"mdi:flash\",\n timer: \"mdi:timer\",\n updater: \"mdi:cloud-upload\",\n vacuum: \"mdi:robot-vacuum\",\n water_heater: \"mdi:thermometer\",\n weblink: \"mdi:open-in-new\"\n};\n\nexport function domainIcon(domain: string, state?: string): string {\n if (domain in fixedIcons) {\n return fixedIcons[domain];\n }\n\n switch (domain) {\n case \"alarm_control_panel\":\n switch (state) {\n case \"armed_home\":\n return \"mdi:bell-plus\";\n case \"armed_night\":\n return \"mdi:bell-sleep\";\n case \"disarmed\":\n return \"mdi:bell-outline\";\n case \"triggered\":\n return \"mdi:bell-ring\";\n default:\n return \"mdi:bell\";\n }\n\n case \"binary_sensor\":\n return state && state === \"off\"\n ? \"mdi:radiobox-blank\"\n : \"mdi:checkbox-marked-circle\";\n\n case \"cover\":\n return state === \"closed\" ? \"mdi:window-closed\" : \"mdi:window-open\";\n\n case \"lock\":\n return state && state === \"unlocked\" ? \"mdi:lock-open\" : \"mdi:lock\";\n\n case \"media_player\":\n return state && state !== \"off\" && state !== \"idle\"\n ? \"mdi:cast-connected\"\n : \"mdi:cast\";\n\n case \"zwave\":\n switch (state) {\n case \"dead\":\n return \"mdi:emoticon-dead\";\n case \"sleeping\":\n return \"mdi:sleep\";\n case \"initializing\":\n return \"mdi:timer-sand\";\n default:\n return \"mdi:z-wave\";\n }\n\n default:\n // tslint:disable-next-line\n console.warn(\n \"Unable to find icon for domain \" + domain + \" (\" + state + \")\"\n );\n return DEFAULT_DOMAIN_ICON;\n }\n}\n","import { HASSDomEvent, fireEvent } from \"./fire-event\";\n\n/**\n * Broadcast haptic feedback requests\n */\n\n\n// Allowed types are from iOS HIG.\n// https://developer.apple.com/design/human-interface-guidelines/ios/user-interaction/feedback/#haptics\n// Implementors on platforms other than iOS should attempt to match the patterns (shown in HIG) as closely as possible.\nexport type HapticType =\n | \"success\"\n | \"warning\"\n | \"failure\"\n | \"light\"\n | \"medium\"\n | \"heavy\"\n | \"selection\";\n\ndeclare global {\n // for fire event\n interface HASSDomEvents {\n haptic: HapticType;\n }\n\n interface GlobalEventHandlersEventMap {\n haptic: HASSDomEvent;\n }\n}\n\nexport const forwardHaptic = (hapticType: HapticType) => {\n fireEvent(window, \"haptic\", hapticType);\n};\n","import { fireEvent } from \"./fire-event\";\n\ndeclare global {\n // for fire event\n interface HASSDomEvents {\n \"location-changed\": {\n replace: boolean;\n };\n }\n}\n\nexport const navigate = (\n _node: any,\n path: string,\n replace: boolean = false\n) => {\n if (replace) {\n history.replaceState(null, \"\", path);\n } else {\n history.pushState(null, \"\", path);\n }\n fireEvent(window, \"location-changed\", {\n replace\n });\n};\n","import { HomeAssistant } from \"./types\";\nimport { computeDomain } from \"./compute-domain\";\n\nexport const turnOnOffEntity = (\n hass: HomeAssistant,\n entityId: string,\n turnOn = true\n): Promise => {\n const stateDomain = computeDomain(entityId);\n const serviceDomain = stateDomain === \"group\" ? \"homeassistant\" : stateDomain;\n\n let service;\n switch (stateDomain) {\n case \"lock\":\n service = turnOn ? \"unlock\" : \"lock\";\n break;\n case \"cover\":\n service = turnOn ? \"open_cover\" : \"close_cover\";\n break;\n default:\n service = turnOn ? \"turn_on\" : \"turn_off\";\n }\n\n return hass.callService(serviceDomain, service, { entity_id: entityId });\n};\n","import { STATES_OFF } from \"./const\";\nimport { turnOnOffEntity } from \"./turn-on-off-entity\";\nimport { HomeAssistant } from \"./types\";\n\nexport const toggleEntity = (\n hass: HomeAssistant,\n entityId: string\n): Promise => {\n const turnOn = STATES_OFF.includes(hass.states[entityId].state);\n return turnOnOffEntity(hass, entityId, turnOn);\n};\n","import { HomeAssistant, ActionConfig } from \"./types\";\nimport { forwardHaptic } from \"./haptic\";\nimport { fireEvent } from \"./fire-event\";\nimport { navigate } from \"./navigate\";\nimport { toggleEntity } from \"./toggle-entity\";\n\nexport const handleActionConfig = (\n node: HTMLElement,\n hass: HomeAssistant,\n config: {\n entity?: string;\n camera_image?: string;\n hold_action?: ActionConfig;\n tap_action?: ActionConfig;\n double_tap_action?: ActionConfig;\n },\n actionConfig: ActionConfig | undefined\n): void => {\n if (!actionConfig) {\n actionConfig = {\n action: \"more-info\",\n };\n }\n\n if (\n actionConfig.confirmation &&\n (!actionConfig.confirmation.exemptions ||\n !actionConfig.confirmation.exemptions.some(\n (e) => e.user === hass!.user!.id\n ))\n ) {\n forwardHaptic(\"warning\");\n\n if (\n !confirm(\n actionConfig.confirmation.text ||\n `Are you sure you want to ${actionConfig.action}?`\n )\n ) {\n return;\n }\n }\n\n switch (actionConfig.action) {\n case \"more-info\":\n if (config.entity || config.camera_image) {\n fireEvent(node, \"hass-more-info\", {\n entityId: config.entity ? config.entity : config.camera_image!,\n });\n }\n break;\n case \"navigate\":\n if (actionConfig.navigation_path) {\n navigate(node, actionConfig.navigation_path);\n }\n break;\n case \"url\":\n if (actionConfig.url_path) {\n window.open(actionConfig.url_path);\n }\n break;\n case \"toggle\":\n if (config.entity) {\n toggleEntity(hass, config.entity!);\n forwardHaptic(\"success\");\n }\n break;\n case \"call-service\": {\n if (!actionConfig.service) {\n forwardHaptic(\"failure\");\n return;\n }\n const [domain, service] = actionConfig.service.split(\".\", 2);\n hass.callService(domain, service, actionConfig.service_data, actionConfig.target);\n forwardHaptic(\"success\");\n break;\n }\n case \"fire-dom-event\": {\n fireEvent(node, \"ll-custom\", actionConfig);\n }\n }\n};\n\nexport const handleAction = (\n node: HTMLElement,\n hass: HomeAssistant,\n config: {\n entity?: string;\n camera_image?: string;\n hold_action?: ActionConfig;\n tap_action?: ActionConfig;\n double_tap_action?: ActionConfig;\n },\n action: string\n): void => {\n let actionConfig: ActionConfig | undefined;\n\n if (action === \"double_tap\" && config.double_tap_action) {\n actionConfig = config.double_tap_action;\n } else if (action === \"hold\" && config.hold_action) {\n actionConfig = config.hold_action;\n } else if (action === \"tap\" && config.tap_action) {\n actionConfig = config.tap_action;\n }\n\n handleActionConfig(node, hass, config, actionConfig);\n};\n","/** Return an icon representing a sensor state. */\nimport { HassEntity } from \"home-assistant-js-websocket\";\nimport { UNIT_C, UNIT_F } from \"./const\";\nimport { domainIcon } from \"./domain_icons\";\n\nconst fixedDeviceClassIcons = {\n humidity: \"mdi:water-percent\",\n illuminance: \"mdi:brightness-5\",\n temperature: \"mdi:thermometer\",\n pressure: \"mdi:gauge\",\n power: \"mdi:flash\",\n signal_strength: \"mdi:wifi\",\n};\n\nexport const sensorIcon = (state: HassEntity) => {\n const dclass = state.attributes.device_class;\n\n if (dclass && dclass in fixedDeviceClassIcons) {\n return fixedDeviceClassIcons[dclass];\n }\n if (dclass === \"battery\") {\n const battery = Number(state.state);\n if (isNaN(battery)) {\n return \"mdi:battery-unknown\";\n }\n const batteryRound = Math.round(battery / 10) * 10;\n if (batteryRound >= 100) {\n return \"mdi:battery\";\n }\n if (batteryRound <= 0) {\n return \"mdi:battery-alert\";\n }\n // Will return one of the following icons: (listed so extractor picks up)\n // mdi:battery-10\n // mdi:battery-20\n // mdi:battery-30\n // mdi:battery-40\n // mdi:battery-50\n // mdi:battery-60\n // mdi:battery-70\n // mdi:battery-80\n // mdi:battery-90\n // We obscure 'hass' in iconname so this name does not get picked up\n return `${\"hass\"}:battery-${batteryRound}`;\n }\n\n const unit = state.attributes.unit_of_measurement;\n if (unit === UNIT_C || unit === UNIT_F) {\n return \"mdi:thermometer\";\n }\n return domainIcon(\"sensor\");\n};\n","import { HassEntity } from \"home-assistant-js-websocket\";\nimport { computeDomain } from \"./compute-domain\";\nimport { DEFAULT_DOMAIN_ICON } from \"./const\";\nimport { binarySensorIcon } from \"./binary_sensor_icon\";\nimport { coverIcon } from \"./cover_icon\";\nimport { sensorIcon } from \"./sensor_icon\";\nimport { inputDateTimeIcon } from \"./input_datetime_icon\";\nimport { domainIcon } from \"./domain_icons\";\n\nconst domainIcons = {\n binary_sensor: binarySensorIcon,\n cover: coverIcon,\n sensor: sensorIcon,\n input_datetime: inputDateTimeIcon,\n};\n\nexport const stateIcon = (state: HassEntity) => {\n if (!state) {\n return DEFAULT_DOMAIN_ICON;\n }\n if (state.attributes.icon) {\n return state.attributes.icon;\n }\n\n const domain = computeDomain(state.entity_id);\n\n if (domain in domainIcons) {\n return domainIcons[domain](state);\n }\n return domainIcon(domain, state.state);\n};\n","import { HassEntity } from \"home-assistant-js-websocket\";\n\n/** Return an icon representing a binary sensor state. */\n\nexport const binarySensorIcon = (state?: string, stateObj?: HassEntity) => {\n const is_off = state === \"off\";\n switch (stateObj?.attributes.device_class) {\n case \"battery\":\n return is_off ? \"mdi:battery\" : \"mdi:battery-outline\";\n case \"battery_charging\":\n return is_off ? \"mdi:battery\" : \"mdi:battery-charging\";\n case \"cold\":\n return is_off ? \"mdi:thermometer\" : \"mdi:snowflake\";\n case \"connectivity\":\n return is_off ? \"mdi:server-network-off\" : \"mdi:server-network\";\n case \"door\":\n return is_off ? \"mdi:door-closed\" : \"mdi:door-open\";\n case \"garage_door\":\n return is_off ? \"mdi:garage\" : \"mdi:garage-open\";\n case \"power\":\n return is_off ? \"mdi:power-plug-off\" : \"mdi:power-plug\";\n case \"gas\":\n case \"problem\":\n case \"safety\":\n case \"tamper\":\n return is_off ? \"mdi:check-circle\" : \"mdi:alert-circle\";\n case \"smoke\":\n return is_off ? \"mdi:check-circle\" : \"mdi:smoke\";\n case \"heat\":\n return is_off ? \"mdi:thermometer\" : \"mdi:fire\";\n case \"light\":\n return is_off ? \"mdi:brightness-5\" : \"mdi:brightness-7\";\n case \"lock\":\n return is_off ? \"mdi:lock\" : \"mdi:lock-open\";\n case \"moisture\":\n return is_off ? \"mdi:water-off\" : \"mdi:water\";\n case \"motion\":\n return is_off ? \"mdi:walk\" : \"mdi:run\";\n case \"occupancy\":\n return is_off ? \"mdi:home-outline\" : \"mdi:home\";\n case \"opening\":\n return is_off ? \"mdi:square\" : \"mdi:square-outline\";\n case \"plug\":\n return is_off ? \"mdi:power-plug-off\" : \"mdi:power-plug\";\n case \"presence\":\n return is_off ? \"mdi:home-outline\" : \"mdi:home\";\n case \"running\":\n return is_off ? \"mdi:stop\" : \"mdi:play\";\n case \"sound\":\n return is_off ? \"mdi:music-note-off\" : \"mdi:music-note\";\n case \"update\":\n return is_off ? \"mdi:package\" : \"mdi:package-up\";\n case \"vibration\":\n return is_off ? \"mdi:crop-portrait\" : \"mdi:vibrate\";\n case \"window\":\n return is_off ? \"mdi:window-closed\" : \"mdi:window-open\";\n default:\n return is_off ? \"mdi:radiobox-blank\" : \"mdi:checkbox-marked-circle\";\n }\n};\n","/** Return an icon representing a cover state. */\nimport { HassEntity } from \"home-assistant-js-websocket\";\nimport { domainIcon } from \"./domain_icons\";\n\nexport const coverIcon = (state: HassEntity): string => {\n const open = state.state !== \"closed\";\n switch (state.attributes.device_class) {\n case \"garage\":\n return open ? \"mdi:garage-open\" : \"mdi:garage\";\n case \"door\":\n return open ? \"mdi:door-open\" : \"mdi:door-closed\";\n case \"shutter\":\n return open ? \"mdi:window-shutter-open\" : \"mdi:window-shutter\";\n case \"blind\":\n return open ? \"mdi:blinds-open\" : \"mdi:blinds\";\n case \"window\":\n return open ? \"mdi:window-open\" : \"mdi:window-closed\";\n default:\n return domainIcon(\"cover\", state.state);\n }\n};\n","/** Return an icon representing an input datetime state. */\nimport { domainIcon } from \"./domain_icons\";\nimport { HassEntity } from \"home-assistant-js-websocket\";\n\nexport const inputDateTimeIcon = (state: HassEntity): string => {\n if (!state.attributes.has_date) {\n return \"mdi:clock\";\n }\n if (!state.attributes.has_time) {\n return \"mdi:calendar\";\n }\n return domainIcon(\"input_datetime\");\n};\n","/**\n * Apply a theme to an element by setting the CSS variables on it.\n *\n * element: Element to apply theme on.\n * themes: HASS Theme information\n * localTheme: selected theme.\n * updateMeta: boolean if we should update the theme-color meta element.\n */\nexport const applyThemesOnElement = (\n element,\n themes,\n localTheme,\n updateMeta = false\n) => {\n if (!element._themes) {\n element._themes = {};\n }\n let themeName = themes.default_theme;\n if (localTheme === \"default\" || (localTheme && themes.themes[localTheme])) {\n themeName = localTheme;\n }\n const styles = { ...element._themes };\n if (themeName !== \"default\") {\n const theme = themes.themes[themeName];\n Object.keys(theme).forEach((key) => {\n const prefixedKey = \"--\" + key;\n element._themes[prefixedKey] = \"\";\n styles[prefixedKey] = theme[key];\n });\n }\n if (element.updateStyles) {\n element.updateStyles(styles);\n } else if ((window as any).ShadyCSS) {\n // implement updateStyles() method of Polemer elements\n (window as any).ShadyCSS.styleSubtree(/** @type {!HTMLElement} */ (element), styles);\n }\n\n if (!updateMeta) {\n return;\n }\n\n const meta = document.querySelector(\"meta[name=theme-color]\");\n if (meta) {\n if (!meta.hasAttribute(\"default-content\")) {\n meta.setAttribute(\"default-content\", meta.getAttribute(\"content\")!);\n }\n const themeColor =\n styles[\"--primary-color\"] || meta.getAttribute(\"default-content\");\n meta.setAttribute(\"content\", themeColor);\n }\n}\n","import { LovelaceCard } from \"./types\";\n\nexport const computeCardSize = (card: LovelaceCard): number | Promise => {\n return typeof card.getCardSize === \"function\" ? card.getCardSize() : 4;\n};","export function computeEntity(entityId: string): string {\n return entityId.substr(entityId.indexOf(\".\") + 1);\n}\n","import { HassEntity } from \"home-assistant-js-websocket\";\nimport { formatDateTime } from \"./datetime/format_date_time\";\nimport { formatDate } from \"./datetime/format_date\";\nimport { formatTime } from \"./datetime/format_time\";\nimport { LocalizeFunc } from \"./translations/localize\";\nimport { computeStateDomain } from \"./compute-state-domain\";\nimport { FrontendLocaleData } from \"./types\";\nimport { formatNumber, isNumericState } from \"./format-number\";\n\nexport const computeStateDisplay = (\n localize: LocalizeFunc,\n stateObj: HassEntity,\n locale: FrontendLocaleData,\n state?: string\n): string => {\n const compareState = state !== undefined ? state : stateObj.state;\n\n if (compareState === \"unknown\" || compareState === \"unavailable\") {\n return localize(`state.default.${compareState}`);\n }\n\n // Entities with a `unit_of_measurement` or `state_class` are numeric values and should use `formatNumber`\n if (isNumericState(stateObj)) {\n if (stateObj.attributes.device_class === \"monetary\") {\n try {\n return formatNumber(compareState, locale, {\n style: \"currency\",\n currency: stateObj.attributes.unit_of_measurement,\n });\n } catch (_err) {\n // fallback to default\n }\n }\n return `${formatNumber(compareState, locale)}${\n stateObj.attributes.unit_of_measurement\n ? \" \" + stateObj.attributes.unit_of_measurement\n : \"\"\n }`;\n }\n\n const domain = computeStateDomain(stateObj);\n\n if (domain === \"input_datetime\") {\n if (state !== undefined) {\n // If trying to display an explicit state, need to parse the explict state to `Date` then format.\n // Attributes aren't available, we have to use `state`.\n try {\n const components = state.split(\" \");\n if (components.length === 2) {\n // Date and time.\n return formatDateTime(new Date(components.join(\"T\")), locale);\n }\n if (components.length === 1) {\n if (state.includes(\"-\")) {\n // Date only.\n return formatDate(new Date(`${state}T00:00`), locale);\n }\n if (state.includes(\":\")) {\n // Time only.\n const now = new Date();\n return formatTime(\n new Date(`${now.toISOString().split(\"T\")[0]}T${state}`),\n locale\n );\n }\n }\n return state;\n } catch (_e) {\n // Formatting methods may throw error if date parsing doesn't go well,\n // just return the state string in that case.\n return state;\n }\n } else {\n // If not trying to display an explicit state, create `Date` object from `stateObj`'s attributes then format.\n let date: Date;\n if (stateObj.attributes.has_date && stateObj.attributes.has_time) {\n date = new Date(\n stateObj.attributes.year,\n stateObj.attributes.month - 1,\n stateObj.attributes.day,\n stateObj.attributes.hour,\n stateObj.attributes.minute\n );\n return formatDateTime(date, locale);\n }\n if (stateObj.attributes.has_date) {\n date = new Date(\n stateObj.attributes.year,\n stateObj.attributes.month - 1,\n stateObj.attributes.day\n );\n return formatDate(date, locale);\n }\n if (stateObj.attributes.has_time) {\n date = new Date();\n date.setHours(stateObj.attributes.hour, stateObj.attributes.minute);\n return formatTime(date, locale);\n }\n return stateObj.state;\n }\n }\n\n if (domain === \"humidifier\") {\n if (compareState === \"on\" && stateObj.attributes.humidity) {\n return `${stateObj.attributes.humidity} %`;\n }\n }\n\n // `counter` `number` and `input_number` domains do not have a unit of measurement but should still use `formatNumber`\n if (\n domain === \"counter\" ||\n domain === \"number\" ||\n domain === \"input_number\"\n ) {\n return formatNumber(compareState, locale);\n }\n\n return (\n // Return device class translation\n (stateObj.attributes.device_class &&\n localize(\n `component.${domain}.state.${stateObj.attributes.device_class}.${compareState}`\n )) ||\n // Return default translation\n localize(`component.${domain}.state._.${compareState}`) ||\n // We don't know! Return the raw state.\n compareState\n );\n};","/**\r\n * Returns a function, that, as long as it continues to be invoked, will not be triggered. It will be called after it stops being called for `wait` ms.\r\n * This can be usefull for ResizeObservers for example.\r\n * @param func The function you want to debounce\r\n * @param wait Period to wait in ms\r\n * @param immediate Triggering on the leading edge instead of the trailing\r\n * @returns Debounced Function\r\n */\r\n// eslint-disable-next-line: ban-types\r\nexport const debounce = unknown>(\r\n func: T,\r\n wait: number,\r\n immediate = false\r\n): T => {\r\n let timeout;\r\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\r\n // @ts-ignore\r\n return function (...args) {\r\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\r\n // @ts-ignore\r\n // eslint-disable-next-line @typescript-eslint/no-this-alias\r\n const context = this;\r\n const later = () => {\r\n timeout = null;\r\n if (!immediate) {\r\n func.apply(context, args);\r\n }\r\n };\r\n const callNow = immediate && !timeout;\r\n clearTimeout(timeout);\r\n timeout = setTimeout(later, wait);\r\n if (callNow) {\r\n func.apply(context, args);\r\n }\r\n };\r\n};\r\n","import { HassEntity } from \"home-assistant-js-websocket\";\n\nexport const evaluateFilter = (stateObj: HassEntity, filter: any): boolean => {\n const operator = filter.operator || \"==\";\n const value = filter.value || filter;\n const state = filter.attribute\n ? stateObj.attributes[filter.attribute]\n : stateObj.state;\n\n switch (operator) {\n case \"==\":\n return state === value;\n case \"<=\":\n return state <= value;\n case \"<\":\n return state < value;\n case \">=\":\n return state >= value;\n case \">\":\n return state > value;\n case \"!=\":\n return state !== value;\n case \"regex\": {\n return state.match(value);\n }\n default:\n return false;\n }\n};\n","export const getLovelace = () => {\n let root: any = document.querySelector('home-assistant');\n root = root && root.shadowRoot;\n root = root && root.querySelector('home-assistant-main');\n root = root && root.shadowRoot;\n root = root && root.querySelector('app-drawer-layout partial-panel-resolver');\n root = root && root.shadowRoot || root;\n root = root && root.querySelector('ha-panel-lovelace');\n root = root && root.shadowRoot;\n root = root && root.querySelector('hui-root');\n if (root) {\n const ll = root.lovelace;\n ll.current_view = root.___curView;\n return ll;\n }\n return null;\n}\n","import { HomeAssistant, ActionConfig } from \"./types\";\nimport { fireEvent } from \"./fire-event\";\nimport { forwardHaptic } from \"./haptic\";\nimport { navigate } from \"./navigate\";\nimport { toggleEntity } from \"./toggle-entity\";\n\nexport const handleClick = (\n node: HTMLElement,\n hass: HomeAssistant,\n config: {\n entity?: string;\n camera_image?: string;\n hold_action?: ActionConfig;\n tap_action?: ActionConfig;\n double_tap_action?: ActionConfig;\n },\n hold: boolean,\n dblClick: boolean\n): void => {\n let actionConfig: ActionConfig | undefined;\n\n if (dblClick && config.double_tap_action) {\n actionConfig = config.double_tap_action;\n } else if (hold && config.hold_action) {\n actionConfig = config.hold_action;\n } else if (!hold && config.tap_action) {\n actionConfig = config.tap_action;\n }\n\n if (!actionConfig) {\n actionConfig = {\n action: \"more-info\"\n };\n }\n\n if (\n actionConfig.confirmation &&\n (!actionConfig.confirmation.exemptions ||\n !actionConfig.confirmation.exemptions.some(\n e => e.user === hass!.user!.id\n ))\n ) {\n if (\n !confirm(\n actionConfig.confirmation.text ||\n `Are you sure you want to ${actionConfig.action}?`\n )\n ) {\n return;\n }\n }\n\n switch (actionConfig.action) {\n case \"more-info\":\n if (actionConfig.entity || config.entity || config.camera_image) {\n fireEvent(node, \"hass-more-info\", {\n entityId: actionConfig.entity\n ? actionConfig.entity\n : config.entity\n ? config.entity\n : config.camera_image\n });\n if (actionConfig.haptic) forwardHaptic(actionConfig.haptic);\n }\n break;\n case \"navigate\":\n if (actionConfig.navigation_path) {\n navigate(node, actionConfig.navigation_path);\n if (actionConfig.haptic) forwardHaptic(actionConfig.haptic);\n }\n break;\n case \"url\":\n actionConfig.url_path && window.open(actionConfig.url_path);\n if (actionConfig.haptic) forwardHaptic(actionConfig.haptic);\n break;\n case \"toggle\":\n if (config.entity) {\n toggleEntity(hass, config.entity!);\n if (actionConfig.haptic) forwardHaptic(actionConfig.haptic);\n }\n break;\n case \"call-service\": {\n if (!actionConfig.service) {\n return;\n }\n const [domain, service] = actionConfig.service.split(\".\", 2);\n const serviceData = { ...actionConfig.service_data };\n if (serviceData.entity_id === \"entity\") {\n serviceData.entity_id = config.entity;\n }\n hass.callService(domain, service, serviceData, actionConfig.target);\n if (actionConfig.haptic) forwardHaptic(actionConfig.haptic);\n break;\n }\n case \"fire-dom-event\": {\n fireEvent(node, \"ll-custom\", actionConfig);\n if (actionConfig.haptic) forwardHaptic(actionConfig.haptic);\n break;\n }\n }\n};\n","import { ActionConfig } from \"./types\";\n\nexport function hasAction(config?: ActionConfig): boolean {\n return config !== undefined && config.action !== \"none\";\n}\n","import { PropertyValues } from \"lit\";\n\nimport { HomeAssistant } from \"./types\";\n\n// Check if config or Entity changed\nexport function hasConfigOrEntityChanged(\n element: any,\n changedProps: PropertyValues,\n forceUpdate: Boolean,\n): boolean {\n if (changedProps.has('config') || forceUpdate) {\n return true;\n }\n\n if (element.config!.entity) {\n const oldHass = changedProps.get('hass') as HomeAssistant | undefined;\n if (oldHass) {\n return (\n oldHass.states[element.config!.entity]\n !== element.hass!.states[element.config!.entity]\n );\n }\n return true;\n } else {\n return false;\n }\n}","import { ActionConfig } from \"./types\";\n\n// Check if config or Entity changed\nexport function hasDoubleClick(config?: ActionConfig): boolean {\n return config !== undefined && config.action !== \"none\";\n}","//REF: https://github.com/home-assistant/frontend/blob/dev/src/common/datetime/relative_time.ts\n\nimport { selectUnit } from \"@formatjs/intl-utils\";\nimport { FrontendLocaleData } from \"../types\";\n\n const formatRelTimeMem =\n (locale: FrontendLocaleData) =>\n new Intl.RelativeTimeFormat(locale.language, { numeric: \"auto\" });\n\n/**\n * Calculate a string representing a date object as relative time from now.\n *\n * Example output: 5 minutes ago, in 3 days.\n */\n export const relativeTime = (\n from: Date,\n locale: FrontendLocaleData,\n to?: Date,\n includeTense = true\n): string => {\n const diff = selectUnit(from, to);\n if (includeTense) {\n return formatRelTimeMem(locale).format(diff.value, diff.unit);\n }\n return Intl.NumberFormat(locale.language, {\n style: \"unit\",\n unit: diff.unit,\n unitDisplay: \"long\",\n }).format(Math.abs(diff.value));\n};\n","import { HassEntity } from \"home-assistant-js-websocket\";\nimport durationToSeconds from \"../datetime/duration_to_seconds\";\n\nexport function timerTimeRemaining(stateObj: HassEntity) {\n let timeRemaining = durationToSeconds(stateObj.attributes.remaining);\n\n if (stateObj.state === \"active\") {\n const now = new Date().getTime();\n const madeActive = new Date(stateObj.last_changed).getTime();\n timeRemaining = Math.max(timeRemaining - (now - madeActive) / 1000, 0);\n }\n\n return timeRemaining;\n}\n","/**\n * Convert a Duration hh:mm:ss format to seconds\n * @param duration hh:mm:ss formated duration\n * @returns duration in seconds\n */\n export default function durationToSeconds(duration: string): number {\n const parts = duration.split(\":\").map(Number);\n return parts[0] * 3600 + parts[1] * 60 + parts[2];\n}\n","import { HomeAssistant } from \"./types\";\nimport { STATES_OFF } from \"./const\";\nimport { computeDomain } from \"./compute-domain\";\n\nexport const turnOnOffEntities = (\n hass: HomeAssistant,\n entityIds: string[],\n turnOn = true\n): void => {\n const domainsToCall = {};\n entityIds.forEach((entityId) => {\n if (STATES_OFF.includes(hass.states[entityId].state) === turnOn) {\n const stateDomain = computeDomain(entityId);\n const serviceDomain = [\"cover\", \"lock\"].includes(stateDomain)\n ? stateDomain\n : \"homeassistant\";\n\n if (!(serviceDomain in domainsToCall)) {\n domainsToCall[serviceDomain] = [];\n }\n domainsToCall[serviceDomain].push(entityId);\n }\n });\n\n Object.keys(domainsToCall).forEach((domain) => {\n let service;\n switch (domain) {\n case \"lock\":\n service = turnOn ? \"unlock\" : \"lock\";\n break;\n case \"cover\":\n service = turnOn ? \"open_cover\" : \"close_cover\";\n break;\n default:\n service = turnOn ? \"turn_on\" : \"turn_off\";\n }\n\n const entities = domainsToCall[domain];\n hass.callService(domain, service, { entity_id: entities });\n });\n};\n"],"names":["NumberFormat","TimeFormat","formatDate","dateObj","locale","formatDateMem","format","Intl","DateTimeFormat","language","year","month","day","useAmPm","time_format","system","testLanguage","undefined","test","Date","toLocaleString","includes","am_pm","formatDateTime","formatDateTimeMem","hour","minute","hour12","formatTime","formatTimeMem","computeDomain","entityId","substr","indexOf","computeRTL","hass","lang","translationMetadata","translations","isRTL","computeStateDomain","stateObj","entity_id","isNumericState","attributes","unit_of_measurement","state_class","numberFormatToLocale","localeOptions","number_format","comma_decimal","decimal_comma","space_comma","round","value","precision","Math","formatNumber","num","options","Number","isNaN","input","none","getDefaultFormatOptions","err","console","error","maximumFractionDigits","toString","style","currency","defaultOptions","minimumFractionDigits","digits","split","length","DEFAULT_DOMAIN_ICON","STATES_OFF","DOMAINS_TOGGLE","Set","fireEvent","node","type","detail","event","Event","bubbles","cancelable","Boolean","composed","dispatchEvent","SPECIAL_TYPES","DOMAIN_TO_ELEMENT_TYPE","alert","automation","climate","cover","fan","group","input_boolean","input_number","input_select","input_text","light","lock","media_player","remote","scene","script","sensor","timer","switch","vacuum","water_heater","input_datetime","fixedIcons","calendar","camera","configurator","conversation","device_tracker","history_graph","homeassistant","homekit","image_processing","mailbox","notify","person","plant","proximity","simple_alarm","sun","updater","weblink","domainIcon","domain","state","warn","forwardHaptic","hapticType","window","navigate","_node","path","replace","history","replaceState","pushState","turnOnOffEntity","turnOn","service","stateDomain","serviceDomain","callService","toggleEntity","states","handleActionConfig","config","actionConfig","action","confirmation","exemptions","some","e","user","id","confirm","text","entity","camera_image","navigation_path","url_path","open","service_data","target","fixedDeviceClassIcons","humidity","illuminance","temperature","pressure","power","signal_strength","domainIcons","binary_sensor","is_off","device_class","dclass","battery","batteryRound","unit","has_date","has_time","element","themes","localTheme","updateMeta","_themes","themeName","default_theme","styles","theme","Object","keys","forEach","key","prefixedKey","updateStyles","ShadyCSS","styleSubtree","meta","document","querySelector","hasAttribute","setAttribute","getAttribute","themeColor","card","getCardSize","localize","compareState","_err","date","setHours","components","join","now","toISOString","_e","cardConfig","isRow","_createError","_createThing","tag","createElement","setConfig","message","startsWith","has","customElements","get","display","setTimeout","whenDefined","then","clearTimeout","func","wait","immediate","timeout","args","context","this","later","apply","callNow","filter","attribute","operator","match","formatDateMonthMem","formatDateMonthYearMem","formatDateNumericMem","formatDateShortMem","formatDateTimeNumericMem","second","formatDateTimeWithSecondsMem","weekday","formatDateWeekdayMem","formatDateYearMem","formatTimeWeekdayMem","formatTimeWithSecondsMem","root","shadowRoot","ll","lovelace","current_view","___curView","double_tap_action","hold_action","tap_action","hold","dblClick","haptic","serviceData","changedProps","forceUpdate","oldHass","from","to","includeTense","diff","selectUnit","RelativeTimeFormat","numeric","formatRelTimeMem","unitDisplay","abs","icon","parts","timeRemaining","remaining","map","getTime","madeActive","last_changed","max","entityIds","domainsToCall","push"],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"index.umd.js","sources":["../src/types.ts","../src/datetime/format_date.ts","../src/datetime/use_am_pm.ts","../src/datetime/format_date_time.ts","../src/datetime/format_time.ts","../src/compute-domain.ts","../src/compute-rtl.ts","../src/compute-state-domain.ts","../src/format-number.ts","../src/const.ts","../src/fire-event.ts","../src/create-thing.ts","../src/domain_icons.ts","../src/haptic.ts","../src/navigate.ts","../src/turn-on-off-entity.ts","../src/toggle-entity.ts","../src/handle-action.ts","../src/sensor_icon.ts","../src/state_icon.ts","../src/binary_sensor_icon.ts","../src/cover_icon.ts","../src/input_datetime_icon.ts","../src/apply_themes_on_element.ts","../src/compute-card-size.ts","../src/compute-entity.ts","../src/compute-state-display.ts","../src/debounce.ts","../src/evaluate-filter.ts","../src/get-lovelace.ts","../src/handle-click.ts","../src/has-action.ts","../src/has-changed.ts","../src/has-double-click.ts","../src/datetime/relative_time.ts","../src/datetime/timer_time_remaining.ts","../src/datetime/duration_to_seconds.ts","../src/turn-on-off-entities.ts"],"sourcesContent":["import {\n HassEntities,\n HassConfig,\n Auth,\n Connection,\n MessageBase,\n HassServices,\n HassServiceTarget,\n} from \"home-assistant-js-websocket\";\nimport { HapticType } from \"./haptic\";\nimport { HASSDomEvent } from \"./fire-event\";\n\nexport interface ToggleMenuActionConfig extends BaseActionConfig {\n action: \"toggle-menu\";\n}\n\nexport interface ToggleActionConfig extends BaseActionConfig {\n action: \"toggle\";\n}\n\nexport interface CallServiceActionConfig extends BaseActionConfig {\n action: \"call-service\";\n service: string;\n data?: {\n entity_id?: string | [string];\n [key: string]: any;\n };\n\n target?: HassServiceTarget;\n repeat?: number;\n haptic?: HapticType;\n}\n\nexport interface NavigateActionConfig extends BaseActionConfig {\n action: \"navigate\";\n navigation_path: string;\n}\n\nexport interface UrlActionConfig extends BaseActionConfig {\n action: \"url\";\n url_path: string;\n}\n\nexport interface MoreInfoActionConfig extends BaseActionConfig {\n action: \"more-info\";\n entity?: string;\n}\n\nexport interface NoActionConfig extends BaseActionConfig {\n action: \"none\";\n}\n\nexport interface CustomActionConfig extends BaseActionConfig {\n action: \"fire-dom-event\";\n}\n\n/**\n * `repeat` and `haptic` are specifically for use in custom cards like the Button-Card\n */\nexport interface BaseActionConfig {\n confirmation?: ConfirmationRestrictionConfig;\n repeat?: number;\n haptic?: HapticType;\n}\n\nexport interface ConfirmationRestrictionConfig {\n text?: string;\n exemptions?: RestrictionConfig[];\n}\n\nexport interface RestrictionConfig {\n user: string;\n}\n\nexport type ActionConfig =\n | ToggleActionConfig\n | CallServiceActionConfig\n | NavigateActionConfig\n | UrlActionConfig\n | MoreInfoActionConfig\n | NoActionConfig\n | CustomActionConfig\n | ToggleMenuActionConfig;\n\nexport interface Window {\n // Custom panel entry point url\n customPanelJS: string;\n ShadyCSS: {\n nativeCss: boolean;\n nativeShadow: boolean;\n prepareTemplate(templateElement, elementName, elementExtension);\n styleElement(element);\n styleSubtree(element, overrideProperties);\n styleDocument(overrideProperties);\n getComputedStyleValue(element, propertyName);\n };\n}\n\ndeclare global {\n // for fire event\n interface HASSDomEvents {\n \"value-changed\": {\n value: unknown;\n };\n \"config-changed\": {\n config: any;\n };\n \"hass-more-info\": {\n entityId: string | undefined;\n };\n \"ll-rebuild\": {};\n \"ll-custom\": {};\n \"location-changed\": {\n replace: boolean;\n };\n \"show-dialog\": {};\n undefined;\n action: {\n action: string;\n };\n }\n}\n\ntype ValidHassDomEvent = keyof HASSDomEvents;\n\nexport type LocalizeFunc = (key: string, ...args: any[]) => string;\n\nexport interface Credential {\n auth_provider_type: string;\n auth_provider_id: string;\n}\n\nexport interface MFAModule {\n id: string;\n name: string;\n enabled: boolean;\n}\n\nexport interface CurrentUser {\n id: string;\n is_owner: boolean;\n is_admin: boolean;\n name: string;\n credentials: Credential[];\n mfa_modules: MFAModule[];\n}\n\nexport interface Theme {\n // Incomplete\n \"primary-color\": string;\n \"text-primary-color\": string;\n \"accent-color\": string;\n}\n\nexport interface Themes {\n default_theme: string;\n themes: { [key: string]: Theme };\n}\n\nexport interface Panel {\n component_name: string;\n config: { [key: string]: any } | null;\n icon: string | null;\n title: string | null;\n url_path: string;\n}\n\nexport interface Panels {\n [name: string]: Panel;\n}\n\nexport interface Resources {\n [language: string]: { [key: string]: string };\n}\n\nexport interface Translation {\n nativeName: string;\n isRTL: boolean;\n fingerprints: { [fragment: string]: string };\n}\n\nexport interface ServiceCallRequest {\n domain: string;\n service: string;\n serviceData?: Record;\n target?: HassServiceTarget;\n}\n\nexport interface HomeAssistant {\n auth: Auth;\n connection: Connection;\n connected: boolean;\n states: HassEntities;\n services: HassServices;\n config: HassConfig;\n themes: Themes;\n selectedTheme?: string | null;\n panels: Panels;\n panelUrl: string;\n\n // i18n\n // current effective language, in that order:\n // - backend saved user selected lanugage\n // - language in local appstorage\n // - browser language\n // - english (en)\n language: string;\n locale: FrontendLocaleData;\n // local stored language, keep that name for backward compability\n selectedLanguage: string | null;\n resources: Resources;\n localize: LocalizeFunc;\n translationMetadata: {\n fragments: string[];\n translations: {\n [lang: string]: Translation;\n };\n };\n\n dockedSidebar: boolean;\n moreInfoEntityId: string;\n user: CurrentUser;\n callService: (\n domain: ServiceCallRequest[\"domain\"],\n service: ServiceCallRequest[\"service\"],\n serviceData?: ServiceCallRequest[\"serviceData\"],\n target?: ServiceCallRequest[\"target\"]\n ) => Promise;\n callApi: (\n method: \"GET\" | \"POST\" | \"PUT\" | \"DELETE\",\n path: string,\n parameters?: { [key: string]: any }\n ) => Promise;\n fetchWithAuth: (\n path: string,\n init?: { [key: string]: any }\n ) => Promise;\n sendWS: (msg: MessageBase) => Promise;\n callWS: (msg: MessageBase) => Promise;\n}\n\nexport enum NumberFormat {\n language = \"language\",\n system = \"system\",\n comma_decimal = \"comma_decimal\",\n decimal_comma = \"decimal_comma\",\n space_comma = \"space_comma\",\n none = \"none\",\n}\n\nexport enum TimeFormat {\n language = \"language\",\n system = \"system\",\n am_pm = \"12\",\n twenty_four = \"24\",\n}\n\nexport interface FrontendLocaleData {\n language: string;\n number_format: NumberFormat;\n time_format: TimeFormat;\n}\n\nexport interface LovelaceCardConfig {\n index?: number;\n view_index?: number;\n type: string;\n [key: string]: any;\n}\n\nexport interface LovelaceCard extends HTMLElement {\n hass?: HomeAssistant;\n isPanel?: boolean;\n editMode?: boolean;\n getCardSize(): number | Promise;\n setConfig(config: LovelaceCardConfig): void;\n}\n\nexport interface LovelaceCardEditor extends HTMLElement {\n hass?: HomeAssistant;\n lovelace?: LovelaceConfig;\n setConfig(config: LovelaceCardConfig): void;\n}\n\nexport interface LovelaceConfig {\n title?: string;\n views: LovelaceViewConfig[];\n background?: string;\n}\n\nexport interface LovelaceViewConfig {\n index?: number;\n title?: string;\n badges?: Array;\n cards?: LovelaceCardConfig[];\n path?: string;\n icon?: string;\n theme?: string;\n panel?: boolean;\n background?: string;\n visible?: boolean | ShowViewConfig[];\n}\n\nexport interface ShowViewConfig {\n user?: string;\n}\n\nexport interface LovelaceBadgeConfig {\n type?: string;\n [key: string]: any;\n}\n\nexport interface ActionHandlerDetail {\n action: string;\n}\n\nexport type ActionHandlerEvent = HASSDomEvent;\n\nexport interface ActionHandlerOptions {\n hasHold?: boolean;\n hasDoubleClick?: boolean;\n}\n\nexport interface EntitiesCardEntityConfig extends EntityConfig {\n type?: string;\n secondary_info?:\n | \"entity-id\"\n | \"last-changed\"\n | \"last-triggered\"\n | \"last-updated\"\n | \"position\"\n | \"tilt-position\"\n | \"brightness\";\n action_name?: string;\n service?: string;\n data?: Record;\n url?: string;\n tap_action?: ActionConfig;\n hold_action?: ActionConfig;\n double_tap_action?: ActionConfig;\n state_color?: boolean;\n show_name?: boolean;\n show_icon?: boolean;\n}\n\nexport interface EntityConfig {\n entity: string;\n type?: string;\n name?: string;\n icon?: string;\n image?: string;\n}\n\nexport interface LovelaceElementConfigBase {\n type: string;\n style: Record;\n}\n","//REF: https://github.com/home-assistant/frontend/blob/dev/src/common/datetime/format_date.ts\n\nimport { FrontendLocaleData } from \"../types\";\n\n/**\n * Formatting a Date to the dddd, mmmm yy format e.g. Tuesday, August 10\n * @param dateObj The date to convert\n * @param locale The users's locale settings\n * @returns date string like \"Tuesday, August 10\"\n */\nexport const formatDateWeekday = (dateObj: Date, locale: FrontendLocaleData) =>\n formatDateWeekdayMem(locale).format(dateObj);\n\nconst formatDateWeekdayMem =\n (locale: FrontendLocaleData) =>\n new Intl.DateTimeFormat(locale.language, {\n weekday: \"long\",\n month: \"long\",\n day: \"numeric\",\n });\n\n/**\n * Formatting a Date to the mmmm dd, yyyy format e.g. August 10, 2021\n * @param dateObj The date to convert\n * @param locale The users's locale settings\n * @returns date string like \"August 10, 2021\"\n */\nexport const formatDate = (dateObj: Date, locale: FrontendLocaleData) =>\n formatDateMem(locale).format(dateObj);\n\nconst formatDateMem =\n (locale: FrontendLocaleData) =>\n new Intl.DateTimeFormat(locale.language, {\n year: \"numeric\",\n month: \"long\",\n day: \"numeric\",\n });\n\n/**\n * Formatting a Date to the classic date format e.g. 10/08/2021\n * @param dateObj The date to convert\n * @param locale The users's locale settings\n * @returns classic date format \"10/08/2021\"\n */\nexport const formatDateNumeric = (dateObj: Date, locale: FrontendLocaleData) =>\n formatDateNumericMem(locale).format(dateObj);\n\nconst formatDateNumericMem =\n (locale: FrontendLocaleData) =>\n new Intl.DateTimeFormat(locale.language, {\n year: \"numeric\",\n month: \"numeric\",\n day: \"numeric\",\n });\n\n\n/**\n * Formatting a Date to just a month with days e.g. Aug 10\n * @param dateObj The date to convert\n * @param locale The users's locale settings\n * @returns month and day like \"Aug 10\"\n */\nexport const formatDateShort = (dateObj: Date, locale: FrontendLocaleData) =>\nformatDateShortMem(locale).format(dateObj);\n\nconst formatDateShortMem =\n(locale: FrontendLocaleData) =>\n new Intl.DateTimeFormat(locale.language, {\n day: \"numeric\",\n month: \"short\",\n });\n\n\n/**\n * Formatting a Date to just a month with year e.g. August 2021\n * @param dateObj The date to convert\n * @param locale The users's locale settings\n * @returns month and year like \"August 2021\"\n */\nexport const formatDateMonthYear = (\ndateObj: Date,\nlocale: FrontendLocaleData\n) => formatDateMonthYearMem(locale).format(dateObj);\n\nconst formatDateMonthYearMem = (locale: FrontendLocaleData) =>\n new Intl.DateTimeFormat(locale.language, {\n month: \"long\",\n year: \"numeric\",\n });\n\n\n/**\n * Formatting a Date to just a month e.g. August\n * @param dateObj The date to convert\n * @param locale The users's locale settings\n * @returns the written out months of the date\n */\nexport const formatDateMonth = (dateObj: Date, locale: FrontendLocaleData) =>\nformatDateMonthMem(locale).format(dateObj);\n\nconst formatDateMonthMem = (locale: FrontendLocaleData) =>\n new Intl.DateTimeFormat(locale.language, {\n month: \"long\",\n });\n\n\n/**\n * Formatting a Date to just a year e.g. 2021\n * @param dateObj The date to convert\n * @param locale The users's locale settings\n * @returns the year of the date in yyyy\n */\nexport const formatDateYear = (dateObj: Date, locale: FrontendLocaleData) =>\nformatDateYearMem(locale).format(dateObj);\n\nconst formatDateYearMem = (locale: FrontendLocaleData) =>\n new Intl.DateTimeFormat(locale.language, {\n year: \"numeric\",\n });\n","// REF: https://github.com/home-assistant/frontend/blob/dev/src/common/datetime/use_am_pm.ts\r\n\r\nimport { FrontendLocaleData, TimeFormat } from \"../types\"\r\n\r\n/**\r\n * Checking if AM/PM time format is used within the browser.\r\n * @param locale Homeassistant frontend locale data\r\n * @returns \r\n */\r\nexport const useAmPm = (locale: FrontendLocaleData): boolean => {\r\n if (\r\n locale.time_format === TimeFormat.language ||\r\n locale.time_format === TimeFormat.system\r\n ) {\r\n const testLanguage =\r\n locale.time_format === TimeFormat.language ? locale.language : undefined;\r\n const test = new Date().toLocaleString(testLanguage);\r\n return test.includes(\"AM\") || test.includes(\"PM\");\r\n }\r\n\r\n return locale.time_format === TimeFormat.am_pm;\r\n};\r\n","//REF: https://github.com/home-assistant/frontend/blob/dev/src/common/datetime/format_date_time.ts\n\nimport { FrontendLocaleData } from \"../types\";\nimport { useAmPm } from \"./use_am_pm\";\n\n// August 9, 2021, 8:23 AM\n/**\n * Formatting a dateObject to date with time e.g. August 9, 2021, 8:23 AM\n * @param dateObj The date to convert\n * @param locale The users's locale settings\n * @returns month and day like \"August 9, 2021, 8:23 AM\"\n */\nexport const formatDateTime = (dateObj: Date, locale: FrontendLocaleData) =>\n formatDateTimeMem(locale).format(dateObj);\n\nconst formatDateTimeMem = (locale: FrontendLocaleData) =>\n new Intl.DateTimeFormat(locale.language, {\n year: \"numeric\",\n month: \"long\",\n day: \"numeric\",\n hour: useAmPm(locale) ? \"numeric\" : \"2-digit\",\n minute: \"2-digit\",\n hour12: useAmPm(locale),\n });\n\n\n/**\n * Formatting a dateObject to date with time e.g. August 9, 2021, 8:23:15 AM\n * @param dateObj The date to convert\n * @param locale The users's locale settings\n * @returns month and day like \"August 9, 2021, 8:23:15 AM\"\n */\nexport const formatDateTimeWithSeconds = (\n dateObj: Date,\n locale: FrontendLocaleData\n) => formatDateTimeWithSecondsMem(locale).format(dateObj);\n\nconst formatDateTimeWithSecondsMem =\n (locale: FrontendLocaleData) =>\n new Intl.DateTimeFormat(locale.language, {\n year: \"numeric\",\n month: \"long\",\n day: \"numeric\",\n hour: useAmPm(locale) ? \"numeric\" : \"2-digit\",\n minute: \"2-digit\",\n second: \"2-digit\",\n hour12: useAmPm(locale),\n });\n\n/**\n * Formatting a Date to just date with AM/PM time e.g. 9/8/2021, 8:23 AM\n * @param dateObj The date to convert\n * @param locale The users's locale settings\n * @returns month and day like \"9/8/2021, 8:23 AM\"\n */\nexport const formatDateTimeNumeric = (\n dateObj: Date,\n locale: FrontendLocaleData\n) => formatDateTimeNumericMem(locale).format(dateObj);\n\nconst formatDateTimeNumericMem =\n (locale: FrontendLocaleData) =>\n new Intl.DateTimeFormat(locale.language, {\n year: \"numeric\",\n month: \"numeric\",\n day: \"numeric\",\n hour: \"numeric\",\n minute: \"2-digit\",\n hour12: useAmPm(locale),\n });","//REF: https://github.com/home-assistant/frontend/blob/dev/src/common/datetime/format_time.ts\n\nimport { FrontendLocaleData } from \"../types\";\nimport { useAmPm } from \"./use_am_pm\";\n\n/**\n * 9:15 PM or 21:15\n * @param dateObj The time to convert\n * @param locale The users's locale settings\n * @returns Reformated time in hh:mm\n */\n export const formatTime = (dateObj: Date, locale: FrontendLocaleData) =>\n formatTimeMem(locale).format(dateObj);\n\n const formatTimeMem =\n (locale: FrontendLocaleData) =>\n new Intl.DateTimeFormat(locale.language, {\n hour: \"numeric\",\n minute: \"2-digit\",\n hour12: useAmPm(locale),\n });\n\n/**\n* 9:15:24 PM or 21:15:24\n* @param dateObj The time to convert\n* @param locale The users's locale settings\n* @returns Reformated time in hh:mm:ss\n*/\nexport const formatTimeWithSeconds = (\n dateObj: Date,\n locale: FrontendLocaleData\n) => formatTimeWithSecondsMem(locale).format(dateObj);\n\nconst formatTimeWithSecondsMem =\n (locale: FrontendLocaleData) =>\n new Intl.DateTimeFormat(locale.language, {\n hour: useAmPm(locale) ? \"numeric\" : \"2-digit\",\n minute: \"2-digit\",\n second: \"2-digit\",\n hour12: useAmPm(locale),\n });\n\n/**\n* Tuesday 7:00 PM or Tuesday 19:00\n* @param dateObj The datetime to convert\n* @param locale The users's locale settings\n* @returns Reformated weekday/time in dddd hh:mm\n*/\nexport const formatTimeWeekday = (dateObj: Date, locale: FrontendLocaleData) =>\n formatTimeWeekdayMem(locale).format(dateObj);\n\nconst formatTimeWeekdayMem =\n (locale: FrontendLocaleData) =>\n new Intl.DateTimeFormat(locale.language, {\n hour: useAmPm(locale) ? \"numeric\" : \"2-digit\",\n minute: \"2-digit\",\n second: \"2-digit\",\n hour12: useAmPm(locale),\n }); \n","export function computeDomain(entityId: string): string {\n return entityId.substr(0, entityId.indexOf(\".\"));\n}\n","import { HomeAssistant } from \"./types\";\n\nexport function computeRTL(hass: HomeAssistant) {\n const lang = hass?.locale?.language || \"en\";\n if (hass.translationMetadata.translations[lang]) {\n return hass.translationMetadata.translations[lang].isRTL || false;\n }\n return false;\n}\n\nexport function computeRTLDirection(hass: HomeAssistant) {\n return computeRTL(hass) ? \"rtl\" : \"ltr\";\n}\n","import { HassEntity } from \"home-assistant-js-websocket\";\nimport { computeDomain } from \"./compute-domain\";\n\nexport function computeStateDomain(stateObj: HassEntity) {\n return computeDomain(stateObj.entity_id);\n}\n","//REF: https://github.com/home-assistant/frontend/blob/dev/src/common/number/format_number.ts\n\nimport { HassEntity } from \"home-assistant-js-websocket\";\nimport { FrontendLocaleData, NumberFormat } from \"./types\";\n\n/**\n * Returns true if the entity is considered numeric based on the attributes it has\n * @param stateObj The entity state object\n */\n export const isNumericState = (stateObj: HassEntity): boolean =>\n !!stateObj.attributes.unit_of_measurement ||\n !!stateObj.attributes.state_class;\n\nexport const numberFormatToLocale = (\n localeOptions: FrontendLocaleData\n): string | string[] | undefined => {\n switch (localeOptions.number_format) {\n case NumberFormat.comma_decimal:\n return [\"en-US\", \"en\"]; // Use United States with fallback to English formatting 1,234,567.89\n case NumberFormat.decimal_comma:\n return [\"de\", \"es\", \"it\"]; // Use German with fallback to Spanish then Italian formatting 1.234.567,89\n case NumberFormat.space_comma:\n return [\"fr\", \"sv\", \"cs\"]; // Use French with fallback to Swedish and Czech formatting 1 234 567,89\n case NumberFormat.system:\n return undefined;\n default:\n return localeOptions.language;\n }\n};\n\nexport const round = (value: number, precision = 2): number =>\n Math.round(value * 10 ** precision) / 10 ** precision;\n\n/**\n * Formats a number based on the specified language with thousands separator(s) and decimal character for better legibility.\n * @param num The number to format\n * @param locale The user-selected language and number format, from `hass.locale`\n * @param options Intl.NumberFormatOptions to use\n */\nexport const formatNumber = (\n num: string | number,\n localeOptions?: FrontendLocaleData,\n options?: Intl.NumberFormatOptions\n): string => {\n const locale = localeOptions\n ? numberFormatToLocale(localeOptions)\n : undefined;\n\n // Polyfill for Number.isNaN, which is more reliable than the global isNaN()\n Number.isNaN =\n Number.isNaN ||\n function isNaN(input) {\n return typeof input === \"number\" && isNaN(input);\n };\n\n if (\n localeOptions?.number_format !== NumberFormat.none &&\n !Number.isNaN(Number(num)) &&\n Intl\n ) {\n try {\n return new Intl.NumberFormat(\n locale,\n getDefaultFormatOptions(num, options)\n ).format(Number(num));\n } catch (err: any) {\n // Don't fail when using \"TEST\" language\n // eslint-disable-next-line no-console\n console.error(err);\n return new Intl.NumberFormat(\n undefined,\n getDefaultFormatOptions(num, options)\n ).format(Number(num));\n }\n }\n if (typeof num === \"string\") {\n return num;\n }\n return `${round(num, options?.maximumFractionDigits).toString()}${\n options?.style === \"currency\" ? ` ${options.currency}` : \"\"\n }`;\n};\n\n/**\n * Generates default options for Intl.NumberFormat\n * @param num The number to be formatted\n * @param options The Intl.NumberFormatOptions that should be included in the returned options\n */\nconst getDefaultFormatOptions = (\n num: string | number,\n options?: Intl.NumberFormatOptions\n): Intl.NumberFormatOptions => {\n const defaultOptions: Intl.NumberFormatOptions = {\n maximumFractionDigits: 2,\n ...options,\n };\n\n if (typeof num !== \"string\") {\n return defaultOptions;\n }\n\n // Keep decimal trailing zeros if they are present in a string numeric value\n if (\n !options ||\n (!options.minimumFractionDigits && !options.maximumFractionDigits)\n ) {\n const digits = num.indexOf(\".\") > -1 ? num.split(\".\")[1].length : 0;\n defaultOptions.minimumFractionDigits = digits;\n defaultOptions.maximumFractionDigits = digits;\n }\n\n return defaultOptions;\n};\n","/** Constants to be used in the frontend. */\n\n// Constants should be alphabetically sorted by name.\n// Arrays with values should be alphabetically sorted if order doesn't matter.\n// Each constant should have a description what it is supposed to be used for.\n\n/** Icon to use when no icon specified for domain. */\nexport const DEFAULT_DOMAIN_ICON = \"mdi:bookmark\";\n\n/** Panel to show when no panel is picked. */\nexport const DEFAULT_PANEL = \"lovelace\";\n\n/** Domains that have a state card. */\nexport const DOMAINS_WITH_CARD = [\n \"climate\",\n \"cover\",\n \"configurator\",\n \"input_select\",\n \"input_number\",\n \"input_text\",\n \"lock\",\n \"media_player\",\n \"scene\",\n \"script\",\n \"timer\",\n \"vacuum\",\n \"water_heater\",\n \"weblink\"\n];\n\n/** Domains with separate more info dialog. */\nexport const DOMAINS_WITH_MORE_INFO = [\n \"alarm_control_panel\",\n \"automation\",\n \"camera\",\n \"climate\",\n \"configurator\",\n \"cover\",\n \"fan\",\n \"group\",\n \"history_graph\",\n \"input_datetime\",\n \"light\",\n \"lock\",\n \"media_player\",\n \"script\",\n \"sun\",\n \"updater\",\n \"vacuum\",\n \"water_heater\",\n \"weather\"\n];\n\n/** Domains that show no more info dialog. */\nexport const DOMAINS_HIDE_MORE_INFO = [\n \"input_number\",\n \"input_select\",\n \"input_text\",\n \"scene\",\n \"weblink\"\n];\n\n/** Domains that should have the history hidden in the more info dialog. */\nexport const DOMAINS_MORE_INFO_NO_HISTORY = [\n \"camera\",\n \"configurator\",\n \"history_graph\",\n \"scene\"\n];\n\n/** States that we consider \"off\". */\nexport const STATES_OFF = [\"closed\", \"locked\", \"off\"];\n\n/** Domains where we allow toggle in Lovelace. */\nexport const DOMAINS_TOGGLE = new Set([\n \"fan\",\n \"input_boolean\",\n \"light\",\n \"switch\",\n \"group\",\n \"automation\"\n]);\n\n/** Temperature units. */\nexport const UNIT_C = \"°C\";\nexport const UNIT_F = \"°F\";\n\n/** Entity ID of the default view. */\nexport const DEFAULT_VIEW_ENTITY_ID = \"group.default_view\";\n","// Polymer legacy event helpers used courtesy of the Polymer project.\n//\n// Copyright (c) 2017 The Polymer Authors. All rights reserved.\n//\n// Redistribution and use in source and binary forms, with or without\n// modification, are permitted provided that the following conditions are\n// met:\n//\n// * Redistributions of source code must retain the above copyright\n// notice, this list of conditions and the following disclaimer.\n// * Redistributions in binary form must reproduce the above\n// copyright notice, this list of conditions and the following disclaimer\n// in the documentation and/or other materials provided with the\n// distribution.\n// * Neither the name of Google Inc. nor the names of its\n// contributors may be used to endorse or promote products derived from\n// this software without specific prior written permission.\n//\n// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n// \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\ndeclare global {\n // tslint:disable-next-line\n interface HASSDomEvents {}\n}\n\nexport type ValidHassDomEvent = keyof HASSDomEvents;\n\nexport interface HASSDomEvent extends Event {\n detail: T;\n}\n\n/**\n * Dispatches a custom event with an optional detail value.\n *\n * @param {string} type Name of event type.\n * @param {*=} detail Detail value containing event-specific\n * payload.\n * @param {{ bubbles: (boolean|undefined),\n * cancelable: (boolean|undefined),\n * composed: (boolean|undefined) }=}\n * options Object specifying options. These may include:\n * `bubbles` (boolean, defaults to `true`),\n * `cancelable` (boolean, defaults to false), and\n * `node` on which to fire the event (HTMLElement, defaults to `this`).\n * @return {Event} The new event that was fired.\n */\nexport const fireEvent = (\n node: HTMLElement | Window,\n type: HassEvent,\n detail?: HASSDomEvents[HassEvent],\n options?: {\n bubbles?: boolean;\n cancelable?: boolean;\n composed?: boolean;\n }\n) => {\n options = options || {};\n // @ts-ignore\n detail = detail === null || detail === undefined ? {} : detail;\n const event = new Event(type, {\n bubbles: options.bubbles === undefined ? true : options.bubbles,\n cancelable: Boolean(options.cancelable),\n composed: options.composed === undefined ? true : options.composed\n });\n (event as any).detail = detail;\n node.dispatchEvent(event);\n return event;\n};\n","import { fireEvent } from \"./fire-event\";\n\nconst SPECIAL_TYPES = new Set([\n \"call-service\",\n \"divider\",\n \"section\",\n \"weblink\",\n \"cast\",\n \"select\"\n]);\nconst DOMAIN_TO_ELEMENT_TYPE = {\n alert: \"toggle\",\n automation: \"toggle\",\n climate: \"climate\",\n cover: \"cover\",\n fan: \"toggle\",\n group: \"group\",\n input_boolean: \"toggle\",\n input_number: \"input-number\",\n input_select: \"input-select\",\n input_text: \"input-text\",\n light: \"toggle\",\n lock: \"lock\",\n media_player: \"media-player\",\n remote: \"toggle\",\n scene: \"scene\",\n script: \"script\",\n sensor: \"sensor\",\n timer: \"timer\",\n switch: \"toggle\",\n vacuum: \"toggle\",\n // Temporary. Once climate is rewritten,\n // water heater should get it's own row.\n water_heater: \"climate\",\n input_datetime: \"input-datetime\"\n};\n\nexport const createThing = (cardConfig, isRow = false) => {\n const _createError = (error, config) => {\n return _createThing(\n \"hui-error-card\",\n {\n type: \"error\",\n error,\n config\n }\n );\n };\n\n const _createThing = (tag, config) => {\n const element = window.document.createElement(tag);\n try {\n // Preventing an error-card infinity loop: https://github.com/custom-cards/custom-card-helpers/issues/54\n if (!element.setConfig) return;\n element.setConfig(config);\n } catch (err) {\n console.error(tag, err);\n return _createError((err as Error).message, config);\n }\n return element;\n };\n\n if (!cardConfig || typeof cardConfig !== \"object\" || (!isRow && !cardConfig.type))\n return _createError(\"No type defined\", cardConfig);\n let tag = cardConfig.type;\n if (tag && tag.startsWith(\"custom:\")) {\n tag = tag.substr(\"custom:\".length);\n } else if (isRow) {\n if (SPECIAL_TYPES.has(tag)) {\n tag = `hui-${tag}-row`;\n } else {\n if (!cardConfig.entity) {\n return _createError(\"Invalid config given.\", cardConfig);\n }\n \n const domain = cardConfig.entity.split(\".\", 1)[0];\n tag = `hui-${DOMAIN_TO_ELEMENT_TYPE[domain] || \"text\"}-entity-row`;\n }\n } else {\n tag = `hui-${tag}-card`;\n }\n\n if (customElements.get(tag)) return _createThing(tag, cardConfig);\n\n // If element doesn't exist (yet) create an error\n const element = _createError(\n `Custom element doesn't exist: ${cardConfig.type}.`,\n cardConfig\n );\n element.style.display = \"None\";\n const timer = setTimeout(() => {\n element.style.display = \"\";\n }, 2000);\n // Remove error if element is defined later\n customElements.whenDefined(cardConfig.type).then(() => {\n clearTimeout(timer);\n fireEvent(element, \"ll-rebuild\", {}, element);\n });\n\n return element;\n};\n","/**\n * Return the icon to be used for a domain.\n *\n * Optionally pass in a state to influence the domain icon.\n */\nimport { DEFAULT_DOMAIN_ICON } from \"./const\";\n\nexport const fixedIcons = {\n alert: \"mdi:alert\",\n automation: \"mdi:playlist-play\",\n calendar: \"mdi:calendar\",\n camera: \"mdi:video\",\n climate: \"mdi:thermostat\",\n configurator: \"mdi:settings\",\n conversation: \"mdi:text-to-speech\",\n device_tracker: \"mdi:account\",\n fan: \"mdi:fan\",\n group: \"mdi:google-circles-communities\",\n history_graph: \"mdi:chart-line\",\n homeassistant: \"mdi:home-assistant\",\n homekit: \"mdi:home-automation\",\n image_processing: \"mdi:image-filter-frames\",\n input_boolean: \"mdi:drawing\",\n input_datetime: \"mdi:calendar-clock\",\n input_number: \"mdi:ray-vertex\",\n input_select: \"mdi:format-list-bulleted\",\n input_text: \"mdi:textbox\",\n light: \"mdi:lightbulb\",\n mailbox: \"mdi:mailbox\",\n notify: \"mdi:comment-alert\",\n person: \"mdi:account\",\n plant: \"mdi:flower\",\n proximity: \"mdi:apple-safari\",\n remote: \"mdi:remote\",\n scene: \"mdi:google-pages\",\n script: \"mdi:file-document\",\n sensor: \"mdi:eye\",\n simple_alarm: \"mdi:bell\",\n sun: \"mdi:white-balance-sunny\",\n switch: \"mdi:flash\",\n timer: \"mdi:timer\",\n updater: \"mdi:cloud-upload\",\n vacuum: \"mdi:robot-vacuum\",\n water_heater: \"mdi:thermometer\",\n weblink: \"mdi:open-in-new\"\n};\n\nexport function domainIcon(domain: string, state?: string): string {\n if (domain in fixedIcons) {\n return fixedIcons[domain];\n }\n\n switch (domain) {\n case \"alarm_control_panel\":\n switch (state) {\n case \"armed_home\":\n return \"mdi:bell-plus\";\n case \"armed_night\":\n return \"mdi:bell-sleep\";\n case \"disarmed\":\n return \"mdi:bell-outline\";\n case \"triggered\":\n return \"mdi:bell-ring\";\n default:\n return \"mdi:bell\";\n }\n\n case \"binary_sensor\":\n return state && state === \"off\"\n ? \"mdi:radiobox-blank\"\n : \"mdi:checkbox-marked-circle\";\n\n case \"cover\":\n return state === \"closed\" ? \"mdi:window-closed\" : \"mdi:window-open\";\n\n case \"lock\":\n return state && state === \"unlocked\" ? \"mdi:lock-open\" : \"mdi:lock\";\n\n case \"media_player\":\n return state && state !== \"off\" && state !== \"idle\"\n ? \"mdi:cast-connected\"\n : \"mdi:cast\";\n\n case \"zwave\":\n switch (state) {\n case \"dead\":\n return \"mdi:emoticon-dead\";\n case \"sleeping\":\n return \"mdi:sleep\";\n case \"initializing\":\n return \"mdi:timer-sand\";\n default:\n return \"mdi:z-wave\";\n }\n\n default:\n // tslint:disable-next-line\n console.warn(\n \"Unable to find icon for domain \" + domain + \" (\" + state + \")\"\n );\n return DEFAULT_DOMAIN_ICON;\n }\n}\n","import { HASSDomEvent, fireEvent } from \"./fire-event\";\n\n/**\n * Broadcast haptic feedback requests\n */\n\n\n// Allowed types are from iOS HIG.\n// https://developer.apple.com/design/human-interface-guidelines/ios/user-interaction/feedback/#haptics\n// Implementors on platforms other than iOS should attempt to match the patterns (shown in HIG) as closely as possible.\nexport type HapticType =\n | \"success\"\n | \"warning\"\n | \"failure\"\n | \"light\"\n | \"medium\"\n | \"heavy\"\n | \"selection\";\n\ndeclare global {\n // for fire event\n interface HASSDomEvents {\n haptic: HapticType;\n }\n\n interface GlobalEventHandlersEventMap {\n haptic: HASSDomEvent;\n }\n}\n\nexport const forwardHaptic = (hapticType: HapticType) => {\n fireEvent(window, \"haptic\", hapticType);\n};\n","import { fireEvent } from \"./fire-event\";\n\ndeclare global {\n // for fire event\n interface HASSDomEvents {\n \"location-changed\": {\n replace: boolean;\n };\n }\n}\n\nexport const navigate = (\n _node: any,\n path: string,\n replace: boolean = false\n) => {\n if (replace) {\n history.replaceState(null, \"\", path);\n } else {\n history.pushState(null, \"\", path);\n }\n fireEvent(window, \"location-changed\", {\n replace\n });\n};\n","import { HomeAssistant } from \"./types\";\nimport { computeDomain } from \"./compute-domain\";\n\nexport const turnOnOffEntity = (\n hass: HomeAssistant,\n entityId: string,\n turnOn = true\n): Promise => {\n const stateDomain = computeDomain(entityId);\n const serviceDomain = stateDomain === \"group\" ? \"homeassistant\" : stateDomain;\n\n let service;\n switch (stateDomain) {\n case \"lock\":\n service = turnOn ? \"unlock\" : \"lock\";\n break;\n case \"cover\":\n service = turnOn ? \"open_cover\" : \"close_cover\";\n break;\n default:\n service = turnOn ? \"turn_on\" : \"turn_off\";\n }\n\n return hass.callService(serviceDomain, service, { entity_id: entityId });\n};\n","import { STATES_OFF } from \"./const\";\nimport { turnOnOffEntity } from \"./turn-on-off-entity\";\nimport { HomeAssistant } from \"./types\";\n\nexport const toggleEntity = (\n hass: HomeAssistant,\n entityId: string\n): Promise => {\n const turnOn = STATES_OFF.includes(hass.states[entityId].state);\n return turnOnOffEntity(hass, entityId, turnOn);\n};\n","import { HomeAssistant, ActionConfig } from \"./types\";\nimport { forwardHaptic } from \"./haptic\";\nimport { fireEvent } from \"./fire-event\";\nimport { navigate } from \"./navigate\";\nimport { toggleEntity } from \"./toggle-entity\";\n\nexport const handleActionConfig = (\n node: HTMLElement,\n hass: HomeAssistant,\n config: {\n entity?: string;\n camera_image?: string;\n hold_action?: ActionConfig;\n tap_action?: ActionConfig;\n double_tap_action?: ActionConfig;\n },\n actionConfig: ActionConfig | undefined\n): void => {\n if (!actionConfig) {\n actionConfig = {\n action: \"more-info\",\n };\n }\n\n if (\n actionConfig.confirmation &&\n (!actionConfig.confirmation.exemptions ||\n !actionConfig.confirmation.exemptions.some(\n (e) => e.user === hass!.user!.id\n ))\n ) {\n forwardHaptic(\"warning\");\n\n if (\n !confirm(\n actionConfig.confirmation.text ||\n `Are you sure you want to ${actionConfig.action}?`\n )\n ) {\n return;\n }\n }\n\n switch (actionConfig.action) {\n case \"more-info\":\n if (config.entity || config.camera_image) {\n fireEvent(node, \"hass-more-info\", {\n entityId: config.entity ? config.entity : config.camera_image!,\n });\n }\n break;\n case \"navigate\":\n if (actionConfig.navigation_path) {\n navigate(node, actionConfig.navigation_path);\n }\n break;\n case \"url\":\n if (actionConfig.url_path) {\n window.open(actionConfig.url_path);\n }\n break;\n case \"toggle\":\n if (config.entity) {\n toggleEntity(hass, config.entity!);\n forwardHaptic(\"success\");\n }\n break;\n case \"call-service\": {\n if (!actionConfig.service) {\n forwardHaptic(\"failure\");\n return;\n }\n const [domain, service] = actionConfig.service.split(\".\", 2);\n hass.callService(domain, service, actionConfig.data, actionConfig.target);\n forwardHaptic(\"success\");\n break;\n }\n case \"fire-dom-event\": {\n fireEvent(node, \"ll-custom\", actionConfig);\n }\n }\n};\n\nexport const handleAction = (\n node: HTMLElement,\n hass: HomeAssistant,\n config: {\n entity?: string;\n camera_image?: string;\n hold_action?: ActionConfig;\n tap_action?: ActionConfig;\n double_tap_action?: ActionConfig;\n },\n action: string\n): void => {\n let actionConfig: ActionConfig | undefined;\n\n if (action === \"double_tap\" && config.double_tap_action) {\n actionConfig = config.double_tap_action;\n } else if (action === \"hold\" && config.hold_action) {\n actionConfig = config.hold_action;\n } else if (action === \"tap\" && config.tap_action) {\n actionConfig = config.tap_action;\n }\n\n handleActionConfig(node, hass, config, actionConfig);\n};\n","/** Return an icon representing a sensor state. */\nimport { HassEntity } from \"home-assistant-js-websocket\";\nimport { UNIT_C, UNIT_F } from \"./const\";\nimport { domainIcon } from \"./domain_icons\";\n\nconst fixedDeviceClassIcons = {\n humidity: \"mdi:water-percent\",\n illuminance: \"mdi:brightness-5\",\n temperature: \"mdi:thermometer\",\n pressure: \"mdi:gauge\",\n power: \"mdi:flash\",\n signal_strength: \"mdi:wifi\",\n};\n\nexport const sensorIcon = (state: HassEntity) => {\n const dclass = state.attributes.device_class;\n\n if (dclass && dclass in fixedDeviceClassIcons) {\n return fixedDeviceClassIcons[dclass];\n }\n if (dclass === \"battery\") {\n const battery = Number(state.state);\n if (isNaN(battery)) {\n return \"mdi:battery-unknown\";\n }\n const batteryRound = Math.round(battery / 10) * 10;\n if (batteryRound >= 100) {\n return \"mdi:battery\";\n }\n if (batteryRound <= 0) {\n return \"mdi:battery-alert\";\n }\n // Will return one of the following icons: (listed so extractor picks up)\n // mdi:battery-10\n // mdi:battery-20\n // mdi:battery-30\n // mdi:battery-40\n // mdi:battery-50\n // mdi:battery-60\n // mdi:battery-70\n // mdi:battery-80\n // mdi:battery-90\n // We obscure 'hass' in iconname so this name does not get picked up\n return `${\"hass\"}:battery-${batteryRound}`;\n }\n\n const unit = state.attributes.unit_of_measurement;\n if (unit === UNIT_C || unit === UNIT_F) {\n return \"mdi:thermometer\";\n }\n return domainIcon(\"sensor\");\n};\n","import { HassEntity } from \"home-assistant-js-websocket\";\nimport { computeDomain } from \"./compute-domain\";\nimport { DEFAULT_DOMAIN_ICON } from \"./const\";\nimport { binarySensorIcon } from \"./binary_sensor_icon\";\nimport { coverIcon } from \"./cover_icon\";\nimport { sensorIcon } from \"./sensor_icon\";\nimport { inputDateTimeIcon } from \"./input_datetime_icon\";\nimport { domainIcon } from \"./domain_icons\";\n\nconst domainIcons = {\n binary_sensor: binarySensorIcon,\n cover: coverIcon,\n sensor: sensorIcon,\n input_datetime: inputDateTimeIcon,\n};\n\nexport const stateIcon = (state: HassEntity) => {\n if (!state) {\n return DEFAULT_DOMAIN_ICON;\n }\n if (state.attributes.icon) {\n return state.attributes.icon;\n }\n\n const domain = computeDomain(state.entity_id);\n\n if (domain in domainIcons) {\n return domainIcons[domain](state);\n }\n return domainIcon(domain, state.state);\n};\n","import { HassEntity } from \"home-assistant-js-websocket\";\n\n/** Return an icon representing a binary sensor state. */\n\nexport const binarySensorIcon = (state?: string, stateObj?: HassEntity) => {\n const is_off = state === \"off\";\n switch (stateObj?.attributes.device_class) {\n case \"battery\":\n return is_off ? \"mdi:battery\" : \"mdi:battery-outline\";\n case \"battery_charging\":\n return is_off ? \"mdi:battery\" : \"mdi:battery-charging\";\n case \"cold\":\n return is_off ? \"mdi:thermometer\" : \"mdi:snowflake\";\n case \"connectivity\":\n return is_off ? \"mdi:server-network-off\" : \"mdi:server-network\";\n case \"door\":\n return is_off ? \"mdi:door-closed\" : \"mdi:door-open\";\n case \"garage_door\":\n return is_off ? \"mdi:garage\" : \"mdi:garage-open\";\n case \"power\":\n return is_off ? \"mdi:power-plug-off\" : \"mdi:power-plug\";\n case \"gas\":\n case \"problem\":\n case \"safety\":\n case \"tamper\":\n return is_off ? \"mdi:check-circle\" : \"mdi:alert-circle\";\n case \"smoke\":\n return is_off ? \"mdi:check-circle\" : \"mdi:smoke\";\n case \"heat\":\n return is_off ? \"mdi:thermometer\" : \"mdi:fire\";\n case \"light\":\n return is_off ? \"mdi:brightness-5\" : \"mdi:brightness-7\";\n case \"lock\":\n return is_off ? \"mdi:lock\" : \"mdi:lock-open\";\n case \"moisture\":\n return is_off ? \"mdi:water-off\" : \"mdi:water\";\n case \"motion\":\n return is_off ? \"mdi:walk\" : \"mdi:run\";\n case \"occupancy\":\n return is_off ? \"mdi:home-outline\" : \"mdi:home\";\n case \"opening\":\n return is_off ? \"mdi:square\" : \"mdi:square-outline\";\n case \"plug\":\n return is_off ? \"mdi:power-plug-off\" : \"mdi:power-plug\";\n case \"presence\":\n return is_off ? \"mdi:home-outline\" : \"mdi:home\";\n case \"running\":\n return is_off ? \"mdi:stop\" : \"mdi:play\";\n case \"sound\":\n return is_off ? \"mdi:music-note-off\" : \"mdi:music-note\";\n case \"update\":\n return is_off ? \"mdi:package\" : \"mdi:package-up\";\n case \"vibration\":\n return is_off ? \"mdi:crop-portrait\" : \"mdi:vibrate\";\n case \"window\":\n return is_off ? \"mdi:window-closed\" : \"mdi:window-open\";\n default:\n return is_off ? \"mdi:radiobox-blank\" : \"mdi:checkbox-marked-circle\";\n }\n};\n","/** Return an icon representing a cover state. */\nimport { HassEntity } from \"home-assistant-js-websocket\";\nimport { domainIcon } from \"./domain_icons\";\n\nexport const coverIcon = (state: HassEntity): string => {\n const open = state.state !== \"closed\";\n switch (state.attributes.device_class) {\n case \"garage\":\n return open ? \"mdi:garage-open\" : \"mdi:garage\";\n case \"door\":\n return open ? \"mdi:door-open\" : \"mdi:door-closed\";\n case \"shutter\":\n return open ? \"mdi:window-shutter-open\" : \"mdi:window-shutter\";\n case \"blind\":\n return open ? \"mdi:blinds-open\" : \"mdi:blinds\";\n case \"window\":\n return open ? \"mdi:window-open\" : \"mdi:window-closed\";\n default:\n return domainIcon(\"cover\", state.state);\n }\n};\n","/** Return an icon representing an input datetime state. */\nimport { domainIcon } from \"./domain_icons\";\nimport { HassEntity } from \"home-assistant-js-websocket\";\n\nexport const inputDateTimeIcon = (state: HassEntity): string => {\n if (!state.attributes.has_date) {\n return \"mdi:clock\";\n }\n if (!state.attributes.has_time) {\n return \"mdi:calendar\";\n }\n return domainIcon(\"input_datetime\");\n};\n","/**\n * Apply a theme to an element by setting the CSS variables on it.\n *\n * element: Element to apply theme on.\n * themes: HASS Theme information\n * localTheme: selected theme.\n * updateMeta: boolean if we should update the theme-color meta element.\n */\nexport const applyThemesOnElement = (\n element,\n themes,\n localTheme,\n updateMeta = false\n) => {\n if (!element._themes) {\n element._themes = {};\n }\n let themeName = themes.default_theme;\n if (localTheme === \"default\" || (localTheme && themes.themes[localTheme])) {\n themeName = localTheme;\n }\n const styles = { ...element._themes };\n if (themeName !== \"default\") {\n const theme = themes.themes[themeName];\n Object.keys(theme).forEach((key) => {\n const prefixedKey = \"--\" + key;\n element._themes[prefixedKey] = \"\";\n styles[prefixedKey] = theme[key];\n });\n }\n if (element.updateStyles) {\n element.updateStyles(styles);\n } else if ((window as any).ShadyCSS) {\n // implement updateStyles() method of Polemer elements\n (window as any).ShadyCSS.styleSubtree(/** @type {!HTMLElement} */ (element), styles);\n }\n\n if (!updateMeta) {\n return;\n }\n\n const meta = document.querySelector(\"meta[name=theme-color]\");\n if (meta) {\n if (!meta.hasAttribute(\"default-content\")) {\n meta.setAttribute(\"default-content\", meta.getAttribute(\"content\")!);\n }\n const themeColor =\n styles[\"--primary-color\"] || meta.getAttribute(\"default-content\");\n meta.setAttribute(\"content\", themeColor);\n }\n}\n","import { LovelaceCard } from \"./types\";\n\nexport const computeCardSize = (card: LovelaceCard): number | Promise => {\n return typeof card.getCardSize === \"function\" ? card.getCardSize() : 4;\n};","export function computeEntity(entityId: string): string {\n return entityId.substr(entityId.indexOf(\".\") + 1);\n}\n","import { HassEntity } from \"home-assistant-js-websocket\";\nimport { formatDateTime } from \"./datetime/format_date_time\";\nimport { formatDate } from \"./datetime/format_date\";\nimport { formatTime } from \"./datetime/format_time\";\nimport { LocalizeFunc } from \"./translations/localize\";\nimport { computeStateDomain } from \"./compute-state-domain\";\nimport { FrontendLocaleData } from \"./types\";\nimport { formatNumber, isNumericState } from \"./format-number\";\n\nexport const computeStateDisplay = (\n localize: LocalizeFunc,\n stateObj: HassEntity,\n locale: FrontendLocaleData,\n state?: string\n): string => {\n const compareState = state !== undefined ? state : stateObj.state;\n\n if (compareState === \"unknown\" || compareState === \"unavailable\") {\n return localize(`state.default.${compareState}`);\n }\n\n // Entities with a `unit_of_measurement` or `state_class` are numeric values and should use `formatNumber`\n if (isNumericState(stateObj)) {\n if (stateObj.attributes.device_class === \"monetary\") {\n try {\n return formatNumber(compareState, locale, {\n style: \"currency\",\n currency: stateObj.attributes.unit_of_measurement,\n });\n } catch (_err) {\n // fallback to default\n }\n }\n return `${formatNumber(compareState, locale)}${\n stateObj.attributes.unit_of_measurement\n ? \" \" + stateObj.attributes.unit_of_measurement\n : \"\"\n }`;\n }\n\n const domain = computeStateDomain(stateObj);\n\n if (domain === \"input_datetime\") {\n if (state !== undefined) {\n // If trying to display an explicit state, need to parse the explict state to `Date` then format.\n // Attributes aren't available, we have to use `state`.\n try {\n const components = state.split(\" \");\n if (components.length === 2) {\n // Date and time.\n return formatDateTime(new Date(components.join(\"T\")), locale);\n }\n if (components.length === 1) {\n if (state.includes(\"-\")) {\n // Date only.\n return formatDate(new Date(`${state}T00:00`), locale);\n }\n if (state.includes(\":\")) {\n // Time only.\n const now = new Date();\n return formatTime(\n new Date(`${now.toISOString().split(\"T\")[0]}T${state}`),\n locale\n );\n }\n }\n return state;\n } catch (_e) {\n // Formatting methods may throw error if date parsing doesn't go well,\n // just return the state string in that case.\n return state;\n }\n } else {\n // If not trying to display an explicit state, create `Date` object from `stateObj`'s attributes then format.\n let date: Date;\n if (stateObj.attributes.has_date && stateObj.attributes.has_time) {\n date = new Date(\n stateObj.attributes.year,\n stateObj.attributes.month - 1,\n stateObj.attributes.day,\n stateObj.attributes.hour,\n stateObj.attributes.minute\n );\n return formatDateTime(date, locale);\n }\n if (stateObj.attributes.has_date) {\n date = new Date(\n stateObj.attributes.year,\n stateObj.attributes.month - 1,\n stateObj.attributes.day\n );\n return formatDate(date, locale);\n }\n if (stateObj.attributes.has_time) {\n date = new Date();\n date.setHours(stateObj.attributes.hour, stateObj.attributes.minute);\n return formatTime(date, locale);\n }\n return stateObj.state;\n }\n }\n\n if (domain === \"humidifier\") {\n if (compareState === \"on\" && stateObj.attributes.humidity) {\n return `${stateObj.attributes.humidity} %`;\n }\n }\n\n // `counter` `number` and `input_number` domains do not have a unit of measurement but should still use `formatNumber`\n if (\n domain === \"counter\" ||\n domain === \"number\" ||\n domain === \"input_number\"\n ) {\n return formatNumber(compareState, locale);\n }\n\n return (\n // Return device class translation\n (stateObj.attributes.device_class &&\n localize(\n `component.${domain}.state.${stateObj.attributes.device_class}.${compareState}`\n )) ||\n // Return default translation\n localize(`component.${domain}.state._.${compareState}`) ||\n // We don't know! Return the raw state.\n compareState\n );\n};","/**\r\n * Returns a function, that, as long as it continues to be invoked, will not be triggered. It will be called after it stops being called for `wait` ms.\r\n * This can be usefull for ResizeObservers for example.\r\n * @param func The function you want to debounce\r\n * @param wait Period to wait in ms\r\n * @param immediate Triggering on the leading edge instead of the trailing\r\n * @returns Debounced Function\r\n */\r\n// eslint-disable-next-line: ban-types\r\nexport const debounce = unknown>(\r\n func: T,\r\n wait: number,\r\n immediate = false\r\n): T => {\r\n let timeout;\r\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\r\n // @ts-ignore\r\n return function (...args) {\r\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\r\n // @ts-ignore\r\n // eslint-disable-next-line @typescript-eslint/no-this-alias\r\n const context = this;\r\n const later = () => {\r\n timeout = null;\r\n if (!immediate) {\r\n func.apply(context, args);\r\n }\r\n };\r\n const callNow = immediate && !timeout;\r\n clearTimeout(timeout);\r\n timeout = setTimeout(later, wait);\r\n if (callNow) {\r\n func.apply(context, args);\r\n }\r\n };\r\n};\r\n","import { HassEntity } from \"home-assistant-js-websocket\";\n\nexport const evaluateFilter = (stateObj: HassEntity, filter: any): boolean => {\n const operator = filter.operator || \"==\";\n const value = filter.value || filter;\n const state = filter.attribute\n ? stateObj.attributes[filter.attribute]\n : stateObj.state;\n\n switch (operator) {\n case \"==\":\n return state === value;\n case \"<=\":\n return state <= value;\n case \"<\":\n return state < value;\n case \">=\":\n return state >= value;\n case \">\":\n return state > value;\n case \"!=\":\n return state !== value;\n case \"regex\": {\n return state.match(value);\n }\n default:\n return false;\n }\n};\n","export const getLovelace = () => {\n let root: any = document.querySelector('home-assistant');\n root = root && root.shadowRoot;\n root = root && root.querySelector('home-assistant-main');\n root = root && root.shadowRoot;\n root = root && root.querySelector('app-drawer-layout partial-panel-resolver');\n root = root && root.shadowRoot || root;\n root = root && root.querySelector('ha-panel-lovelace');\n root = root && root.shadowRoot;\n root = root && root.querySelector('hui-root');\n if (root) {\n const ll = root.lovelace;\n ll.current_view = root.___curView;\n return ll;\n }\n return null;\n}\n","import { HomeAssistant, ActionConfig } from \"./types\";\nimport { fireEvent } from \"./fire-event\";\nimport { forwardHaptic } from \"./haptic\";\nimport { navigate } from \"./navigate\";\nimport { toggleEntity } from \"./toggle-entity\";\n\nexport const handleClick = (\n node: HTMLElement,\n hass: HomeAssistant,\n config: {\n entity?: string;\n camera_image?: string;\n hold_action?: ActionConfig;\n tap_action?: ActionConfig;\n double_tap_action?: ActionConfig;\n },\n hold: boolean,\n dblClick: boolean\n): void => {\n let actionConfig: ActionConfig | undefined;\n\n if (dblClick && config.double_tap_action) {\n actionConfig = config.double_tap_action;\n } else if (hold && config.hold_action) {\n actionConfig = config.hold_action;\n } else if (!hold && config.tap_action) {\n actionConfig = config.tap_action;\n }\n\n if (!actionConfig) {\n actionConfig = {\n action: \"more-info\"\n };\n }\n\n if (\n actionConfig.confirmation &&\n (!actionConfig.confirmation.exemptions ||\n !actionConfig.confirmation.exemptions.some(\n e => e.user === hass!.user!.id\n ))\n ) {\n if (\n !confirm(\n actionConfig.confirmation.text ||\n `Are you sure you want to ${actionConfig.action}?`\n )\n ) {\n return;\n }\n }\n\n switch (actionConfig.action) {\n case \"more-info\":\n if (actionConfig.entity || config.entity || config.camera_image) {\n fireEvent(node, \"hass-more-info\", {\n entityId: actionConfig.entity\n ? actionConfig.entity\n : config.entity\n ? config.entity\n : config.camera_image\n });\n if (actionConfig.haptic) forwardHaptic(actionConfig.haptic);\n }\n break;\n case \"navigate\":\n if (actionConfig.navigation_path) {\n navigate(node, actionConfig.navigation_path);\n if (actionConfig.haptic) forwardHaptic(actionConfig.haptic);\n }\n break;\n case \"url\":\n actionConfig.url_path && window.open(actionConfig.url_path);\n if (actionConfig.haptic) forwardHaptic(actionConfig.haptic);\n break;\n case \"toggle\":\n if (config.entity) {\n toggleEntity(hass, config.entity!);\n if (actionConfig.haptic) forwardHaptic(actionConfig.haptic);\n }\n break;\n case \"call-service\": {\n if (!actionConfig.service) {\n return;\n }\n const [domain, service] = actionConfig.service.split(\".\", 2);\n const serviceData = { ...actionConfig.data };\n if (serviceData.entity_id === \"entity\") {\n serviceData.entity_id = config.entity;\n }\n hass.callService(domain, service, serviceData, actionConfig.target);\n if (actionConfig.haptic) forwardHaptic(actionConfig.haptic);\n break;\n }\n case \"fire-dom-event\": {\n fireEvent(node, \"ll-custom\", actionConfig);\n if (actionConfig.haptic) forwardHaptic(actionConfig.haptic);\n break;\n }\n }\n};\n","import { ActionConfig } from \"./types\";\n\nexport function hasAction(config?: ActionConfig): boolean {\n return config !== undefined && config.action !== \"none\";\n}\n","import { PropertyValues } from \"lit\";\n\nimport { HomeAssistant } from \"./types\";\n\n// Check if config or Entity changed\nexport function hasConfigOrEntityChanged(\n element: any,\n changedProps: PropertyValues,\n forceUpdate: Boolean,\n): boolean {\n if (changedProps.has('config') || forceUpdate) {\n return true;\n }\n\n if (element.config!.entity) {\n const oldHass = changedProps.get('hass') as HomeAssistant | undefined;\n if (oldHass) {\n return (\n oldHass.states[element.config!.entity]\n !== element.hass!.states[element.config!.entity]\n );\n }\n return true;\n } else {\n return false;\n }\n}","import { ActionConfig } from \"./types\";\n\n// Check if config or Entity changed\nexport function hasDoubleClick(config?: ActionConfig): boolean {\n return config !== undefined && config.action !== \"none\";\n}","//REF: https://github.com/home-assistant/frontend/blob/dev/src/common/datetime/relative_time.ts\n\nimport { selectUnit } from \"@formatjs/intl-utils\";\nimport { FrontendLocaleData } from \"../types\";\n\n const formatRelTimeMem =\n (locale: FrontendLocaleData) =>\n new Intl.RelativeTimeFormat(locale.language, { numeric: \"auto\" });\n\n/**\n * Calculate a string representing a date object as relative time from now.\n *\n * Example output: 5 minutes ago, in 3 days.\n */\n export const relativeTime = (\n from: Date,\n locale: FrontendLocaleData,\n to?: Date,\n includeTense = true\n): string => {\n const diff = selectUnit(from, to);\n if (includeTense) {\n return formatRelTimeMem(locale).format(diff.value, diff.unit);\n }\n return Intl.NumberFormat(locale.language, {\n style: \"unit\",\n unit: diff.unit,\n unitDisplay: \"long\",\n }).format(Math.abs(diff.value));\n};\n","import { HassEntity } from \"home-assistant-js-websocket\";\nimport durationToSeconds from \"../datetime/duration_to_seconds\";\n\nexport function timerTimeRemaining(stateObj: HassEntity) {\n let timeRemaining = durationToSeconds(stateObj.attributes.remaining);\n\n if (stateObj.state === \"active\") {\n const now = new Date().getTime();\n const madeActive = new Date(stateObj.last_changed).getTime();\n timeRemaining = Math.max(timeRemaining - (now - madeActive) / 1000, 0);\n }\n\n return timeRemaining;\n}\n","/**\n * Convert a Duration hh:mm:ss format to seconds\n * @param duration hh:mm:ss formated duration\n * @returns duration in seconds\n */\n export default function durationToSeconds(duration: string): number {\n const parts = duration.split(\":\").map(Number);\n return parts[0] * 3600 + parts[1] * 60 + parts[2];\n}\n","import { HomeAssistant } from \"./types\";\nimport { STATES_OFF } from \"./const\";\nimport { computeDomain } from \"./compute-domain\";\n\nexport const turnOnOffEntities = (\n hass: HomeAssistant,\n entityIds: string[],\n turnOn = true\n): void => {\n const domainsToCall = {};\n entityIds.forEach((entityId) => {\n if (STATES_OFF.includes(hass.states[entityId].state) === turnOn) {\n const stateDomain = computeDomain(entityId);\n const serviceDomain = [\"cover\", \"lock\"].includes(stateDomain)\n ? stateDomain\n : \"homeassistant\";\n\n if (!(serviceDomain in domainsToCall)) {\n domainsToCall[serviceDomain] = [];\n }\n domainsToCall[serviceDomain].push(entityId);\n }\n });\n\n Object.keys(domainsToCall).forEach((domain) => {\n let service;\n switch (domain) {\n case \"lock\":\n service = turnOn ? \"unlock\" : \"lock\";\n break;\n case \"cover\":\n service = turnOn ? \"open_cover\" : \"close_cover\";\n break;\n default:\n service = turnOn ? \"turn_on\" : \"turn_off\";\n }\n\n const entities = domainsToCall[domain];\n hass.callService(domain, service, { entity_id: entities });\n });\n};\n"],"names":["NumberFormat","TimeFormat","formatDate","dateObj","locale","formatDateMem","format","Intl","DateTimeFormat","language","year","month","day","useAmPm","time_format","system","testLanguage","undefined","test","Date","toLocaleString","includes","am_pm","formatDateTime","formatDateTimeMem","hour","minute","hour12","formatTime","formatTimeMem","computeDomain","entityId","substr","indexOf","computeRTL","hass","lang","translationMetadata","translations","isRTL","computeStateDomain","stateObj","entity_id","isNumericState","attributes","unit_of_measurement","state_class","numberFormatToLocale","localeOptions","number_format","comma_decimal","decimal_comma","space_comma","round","value","precision","Math","formatNumber","num","options","Number","isNaN","input","none","getDefaultFormatOptions","err","console","error","maximumFractionDigits","toString","style","currency","defaultOptions","minimumFractionDigits","digits","split","length","DEFAULT_DOMAIN_ICON","STATES_OFF","DOMAINS_TOGGLE","Set","fireEvent","node","type","detail","event","Event","bubbles","cancelable","Boolean","composed","dispatchEvent","SPECIAL_TYPES","DOMAIN_TO_ELEMENT_TYPE","alert","automation","climate","cover","fan","group","input_boolean","input_number","input_select","input_text","light","lock","media_player","remote","scene","script","sensor","timer","switch","vacuum","water_heater","input_datetime","fixedIcons","calendar","camera","configurator","conversation","device_tracker","history_graph","homeassistant","homekit","image_processing","mailbox","notify","person","plant","proximity","simple_alarm","sun","updater","weblink","domainIcon","domain","state","warn","forwardHaptic","hapticType","window","navigate","_node","path","replace","history","replaceState","pushState","turnOnOffEntity","turnOn","service","stateDomain","serviceDomain","callService","toggleEntity","states","handleActionConfig","config","actionConfig","action","confirmation","exemptions","some","e","user","id","confirm","text","entity","camera_image","navigation_path","url_path","open","data","target","fixedDeviceClassIcons","humidity","illuminance","temperature","pressure","power","signal_strength","domainIcons","binary_sensor","is_off","device_class","dclass","battery","batteryRound","unit","has_date","has_time","element","themes","localTheme","updateMeta","_themes","themeName","default_theme","styles","theme","Object","keys","forEach","key","prefixedKey","updateStyles","ShadyCSS","styleSubtree","meta","document","querySelector","hasAttribute","setAttribute","getAttribute","themeColor","card","getCardSize","localize","compareState","_err","date","setHours","components","join","now","toISOString","_e","cardConfig","isRow","_createError","_createThing","tag","createElement","setConfig","message","startsWith","has","customElements","get","display","setTimeout","whenDefined","then","clearTimeout","func","wait","immediate","timeout","args","context","this","later","apply","callNow","filter","attribute","operator","match","formatDateMonthMem","formatDateMonthYearMem","formatDateNumericMem","formatDateShortMem","formatDateTimeNumericMem","second","formatDateTimeWithSecondsMem","weekday","formatDateWeekdayMem","formatDateYearMem","formatTimeWeekdayMem","formatTimeWithSecondsMem","root","shadowRoot","ll","lovelace","current_view","___curView","double_tap_action","hold_action","tap_action","hold","dblClick","haptic","serviceData","changedProps","forceUpdate","oldHass","from","to","includeTense","diff","selectUnit","RelativeTimeFormat","numeric","formatRelTimeMem","unitDisplay","abs","icon","parts","timeRemaining","remaining","map","getTime","madeActive","last_changed","max","entityIds","domainsToCall","push"],"mappings":"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"} \ No newline at end of file diff --git a/dist/types.d.ts b/dist/types.d.ts index 5d0fbb1..c83de95 100644 --- a/dist/types.d.ts +++ b/dist/types.d.ts @@ -10,7 +10,7 @@ export interface ToggleActionConfig extends BaseActionConfig { export interface CallServiceActionConfig extends BaseActionConfig { action: "call-service"; service: string; - service_data?: { + data?: { entity_id?: string | [string]; [key: string]: any; }; @@ -255,7 +255,7 @@ export interface EntitiesCardEntityConfig extends EntityConfig { secondary_info?: "entity-id" | "last-changed" | "last-triggered" | "last-updated" | "position" | "tilt-position" | "brightness"; action_name?: string; service?: string; - service_data?: Record; + data?: Record; url?: string; tap_action?: ActionConfig; hold_action?: ActionConfig; diff --git a/src/handle-action.ts b/src/handle-action.ts index ac01cfe..2d4536c 100644 --- a/src/handle-action.ts +++ b/src/handle-action.ts @@ -71,7 +71,7 @@ export const handleActionConfig = ( return; } const [domain, service] = actionConfig.service.split(".", 2); - hass.callService(domain, service, actionConfig.service_data, actionConfig.target); + hass.callService(domain, service, actionConfig.data, actionConfig.target); forwardHaptic("success"); break; } diff --git a/src/handle-click.ts b/src/handle-click.ts index ac8e63f..d250c26 100644 --- a/src/handle-click.ts +++ b/src/handle-click.ts @@ -84,7 +84,7 @@ export const handleClick = ( return; } const [domain, service] = actionConfig.service.split(".", 2); - const serviceData = { ...actionConfig.service_data }; + const serviceData = { ...actionConfig.data }; if (serviceData.entity_id === "entity") { serviceData.entity_id = config.entity; } diff --git a/src/types.ts b/src/types.ts index d69e821..c741075 100644 --- a/src/types.ts +++ b/src/types.ts @@ -21,7 +21,7 @@ export interface ToggleActionConfig extends BaseActionConfig { export interface CallServiceActionConfig extends BaseActionConfig { action: "call-service"; service: string; - service_data?: { + data?: { entity_id?: string | [string]; [key: string]: any; }; @@ -333,7 +333,7 @@ export interface EntitiesCardEntityConfig extends EntityConfig { | "brightness"; action_name?: string; service?: string; - service_data?: Record; + data?: Record; url?: string; tap_action?: ActionConfig; hold_action?: ActionConfig;