diff --git a/dist/slider-button-card.js b/dist/slider-button-card.js index 5ebcf3f..50216e5 100644 --- a/dist/slider-button-card.js +++ b/dist/slider-button-card.js @@ -1,18 +1,762 @@ -/*! ***************************************************************************** -Copyright (c) Microsoft Corporation. - -Permission to use, copy, modify, and/or distribute this software for any -purpose with or without fee is hereby granted. - -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH -REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, -INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR -OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -PERFORMANCE OF THIS SOFTWARE. -***************************************************************************** */ -function t(t,e,i,s){var r,o=arguments.length,n=o<3?e:null===s?s=Object.getOwnPropertyDescriptor(e,i):s;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)n=Reflect.decorate(t,e,i,s);else for(var a=t.length-1;a>=0;a--)(r=t[a])&&(n=(o<3?r(n):o>3?r(e,i,n):r(e,i))||n);return o>3&&n&&Object.defineProperty(e,i,n),n}var e=/d{1,4}|M{1,4}|YY(?:YY)?|S{1,3}|Do|ZZ|Z|([HhMsDm])\1?|[aA]|"[^"]*"|'[^']*'/g,i="[^\\s]+",s=/\[([^]*?)\]/gm;function r(t,e){for(var i=[],s=0,r=t.length;s-1?s:null}};function n(t){for(var e=[],i=1;i3?0:(t-t%10!=10?1:0)*t%10]}},d=n({},h),u=function(t,e){for(void 0===e&&(e=2),t=String(t);t.length0?"-":"+")+u(100*Math.floor(Math.abs(e)/60)+Math.abs(e)%60,4)},Z:function(t){var e=t.getTimezoneOffset();return(e>0?"-":"+")+u(Math.floor(Math.abs(e)/60),2)+":"+u(Math.abs(e)%60,2)}},g=function(t){return+t-1},f=[null,"[1-9]\\d?"],b=[null,i],m=["isPm",i,function(t,e){var i=t.toLowerCase();return i===e.amPm[0]?0:i===e.amPm[1]?1:null}],_=["timezoneOffset","[^\\s]*?[\\+\\-]\\d\\d:?\\d\\d|[^\\s]*?Z?",function(t){var e=(t+"").match(/([+-]|\d\d)/gi);if(e){var i=60*+e[1]+parseInt(e[2],10);return"+"===e[0]?i:-i}return 0}],v=(o("monthNamesShort"),o("monthNames"),{default:"ddd MMM DD YYYY HH:mm:ss",shortDate:"M/D/YY",mediumDate:"MMM D, YYYY",longDate:"MMMM D, YYYY",fullDate:"dddd, MMMM D, YYYY",isoDate:"YYYY-MM-DD",isoDateTime:"YYYY-MM-DDTHH:mm:ssZ",shortTime:"HH:mm",mediumTime:"HH:mm:ss",longTime:"HH:mm:ss.SSS"});var y=function(t,i,r){if(void 0===i&&(i=v.default),void 0===r&&(r={}),"number"==typeof t&&(t=new Date(t)),"[object Date]"!==Object.prototype.toString.call(t)||isNaN(t.getTime()))throw new Error("Invalid Date pass to format");var o=[];i=(i=v[i]||i).replace(s,(function(t,e){return o.push(e),"@@@"}));var a=n(n({},d),r);return(i=i.replace(e,(function(e){return p[e](t,a)}))).replace(/@@@/g,(function(){return o.shift()}))};(function(){try{(new Date).toLocaleDateString("i")}catch(t){return"RangeError"===t.name}})(),function(){try{(new Date).toLocaleString("i")}catch(t){return"RangeError"===t.name}}(),function(){try{(new Date).toLocaleTimeString("i")}catch(t){return"RangeError"===t.name}}();function w(t){return t.substr(0,t.indexOf("."))}function S(t){return w(t.entity_id)}var k="hass:bookmark",x=["closed","locked","off"],O=function(t,e,i,s){s=s||{},i=null==i?{}:i;var r=new Event(e,{bubbles:void 0===s.bubbles||s.bubbles,cancelable:Boolean(s.cancelable),composed:void 0===s.composed||s.composed});return r.detail=i,t.dispatchEvent(r),r},T={alert:"hass:alert",automation:"hass:playlist-play",calendar:"hass:calendar",camera:"hass:video",climate:"hass:thermostat",configurator:"hass:settings",conversation:"hass:text-to-speech",device_tracker:"hass:account",fan:"hass:fan",group:"hass:google-circles-communities",history_graph:"hass:chart-line",homeassistant:"hass:home-assistant",homekit:"hass:home-automation",image_processing:"hass:image-filter-frames",input_boolean:"hass:drawing",input_datetime:"hass:calendar-clock",input_number:"hass:ray-vertex",input_select:"hass:format-list-bulleted",input_text:"hass:textbox",light:"hass:lightbulb",mailbox:"hass:mailbox",notify:"hass:comment-alert",person:"hass:account",plant:"hass:flower",proximity:"hass:apple-safari",remote:"hass:remote",scene:"hass:google-pages",script:"hass:file-document",sensor:"hass:eye",simple_alarm:"hass:bell",sun:"hass:white-balance-sunny",switch:"hass:flash",timer:"hass:timer",updater:"hass:cloud-upload",vacuum:"hass:robot-vacuum",water_heater:"hass:thermometer",weblink:"hass:open-in-new"};function C(t,e){if(t in T)return T[t];switch(t){case"alarm_control_panel":switch(e){case"armed_home":return"hass:bell-plus";case"armed_night":return"hass:bell-sleep";case"disarmed":return"hass:bell-outline";case"triggered":return"hass:bell-ring";default:return"hass:bell"}case"binary_sensor":return e&&"off"===e?"hass:radiobox-blank":"hass:checkbox-marked-circle";case"cover":return"closed"===e?"hass:window-closed":"hass:window-open";case"lock":return e&&"unlocked"===e?"hass:lock-open":"hass:lock";case"media_player":return e&&"off"!==e&&"idle"!==e?"hass:cast-connected":"hass:cast";case"zwave":switch(e){case"dead":return"hass:emoticon-dead";case"sleeping":return"hass:sleep";case"initializing":return"hass:timer-sand";default:return"hass:z-wave"}default:return console.warn("Unable to find icon for domain "+t+" ("+e+")"),k}}var M=function(t){O(window,"haptic",t)},P=function(t,e){return function(t,e,i){void 0===i&&(i=!0);var s,r=w(e),o="group"===r?"homeassistant":r;switch(r){case"lock":s=i?"unlock":"lock";break;case"cover":s=i?"open_cover":"close_cover";break;default:s=i?"turn_on":"turn_off"}return t.callService(o,s,{entity_id:e})}(t,e,x.includes(t.states[e].state))},E=function(t,e,i,s){if(s||(s={action:"more-info"}),!s.confirmation||s.confirmation.exemptions&&s.confirmation.exemptions.some((function(t){return t.user===e.user.id}))||(M("warning"),confirm(s.confirmation.text||"Are you sure you want to "+s.action+"?")))switch(s.action){case"more-info":(i.entity||i.camera_image)&&O(t,"hass-more-info",{entityId:i.entity?i.entity:i.camera_image});break;case"navigate":s.navigation_path&&function(t,e,i){void 0===i&&(i=!1),i?history.replaceState(null,"",e):history.pushState(null,"",e),O(window,"location-changed",{replace:i})}(0,s.navigation_path);break;case"url":s.url_path&&window.open(s.url_path);break;case"toggle":i.entity&&(P(e,i.entity),M("success"));break;case"call-service":if(!s.service)return void M("failure");var r=s.service.split(".",2);e.callService(r[0],r[1],s.service_data),M("success");break;case"fire-dom-event":O(t,"ll-custom",s)}},A=function(t,e,i,s){var r;"double_tap"===s&&i.double_tap_action?r=i.double_tap_action:"hold"===s&&i.hold_action?r=i.hold_action:"tap"===s&&i.tap_action&&(r=i.tap_action),E(t,e,i,r)};var $={humidity:"hass:water-percent",illuminance:"hass:brightness-5",temperature:"hass:thermometer",pressure:"hass:gauge",power:"hass:flash",signal_strength:"hass:wifi"},N={binary_sensor:function(t){var e=t.state&&"off"===t.state;switch(t.attributes.device_class){case"battery":return e?"hass:battery":"hass:battery-outline";case"cold":return e?"hass:thermometer":"hass:snowflake";case"connectivity":return e?"hass:server-network-off":"hass:server-network";case"door":return e?"hass:door-closed":"hass:door-open";case"garage_door":return e?"hass:garage":"hass:garage-open";case"gas":case"power":case"problem":case"safety":case"smoke":return e?"hass:shield-check":"hass:alert";case"heat":return e?"hass:thermometer":"hass:fire";case"light":return e?"hass:brightness-5":"hass:brightness-7";case"lock":return e?"hass:lock":"hass:lock-open";case"moisture":return e?"hass:water-off":"hass:water";case"motion":return e?"hass:walk":"hass:run";case"occupancy":return e?"hass:home-outline":"hass:home";case"opening":return e?"hass:square":"hass:square-outline";case"plug":return e?"hass:power-plug-off":"hass:power-plug";case"presence":return e?"hass:home-outline":"hass:home";case"sound":return e?"hass:music-note-off":"hass:music-note";case"vibration":return e?"hass:crop-portrait":"hass:vibrate";case"window":return e?"hass:window-closed":"hass:window-open";default:return e?"hass:radiobox-blank":"hass:checkbox-marked-circle"}},cover:function(t){var e="closed"!==t.state;switch(t.attributes.device_class){case"garage":return e?"hass:garage-open":"hass:garage";case"door":return e?"hass:door-open":"hass:door-closed";case"shutter":return e?"hass:window-shutter-open":"hass:window-shutter";case"blind":return e?"hass:blinds-open":"hass:blinds";case"window":return e?"hass:window-open":"hass:window-closed";default:return C("cover",t.state)}},sensor:function(t){var e=t.attributes.device_class;if(e&&e in $)return $[e];if("battery"===e){var i=Number(t.state);if(isNaN(i))return"hass:battery-unknown";var s=10*Math.round(i/10);return s>=100?"hass:battery":s<=0?"hass:battery-alert":"hass:battery-"+s}var r=t.attributes.unit_of_measurement;return"°C"===r||"°F"===r?"hass:thermometer":C("sensor")},input_datetime:function(t){return t.attributes.has_date?t.attributes.has_time?C("input_datetime"):"hass:calendar":"hass:clock"}},j=function(t){if(!t)return k;if(t.attributes.icon)return t.attributes.icon;var e=w(t.entity_id);return e in N?N[e](t):C(e,t.state)},R=Function.prototype.toString,I=Object.create,V=Object.defineProperty,H=Object.getOwnPropertyDescriptor,L=Object.getOwnPropertyNames,U=Object.getOwnPropertySymbols,z=Object.getPrototypeOf,D=Object.prototype,F=D.hasOwnProperty,B=D.propertyIsEnumerable,q="function"==typeof U,G="function"==typeof WeakMap,Y=function(t,e){if(!t.constructor)return I(null);var i=t.constructor,s=t.__proto__||z(t);if(i===e.Object)return s===e.Object.prototype?{}:I(s);if(~R.call(i).indexOf("[native code]"))try{return new i}catch(t){}return I(s)},W=function(t,e,i,s){var r=Y(t,e);for(var o in s.set(t,r),t)F.call(t,o)&&(r[o]=i(t[o],s));if(q){var n=U(t),a=n.length;if(a)for(var l=0,c=void 0;l= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +} + +var token = /d{1,4}|M{1,4}|YY(?:YY)?|S{1,3}|Do|ZZ|Z|([HhMsDm])\1?|[aA]|"[^"]*"|'[^']*'/g; +var twoDigitsOptional = "[1-9]\\d?"; +var twoDigits = "\\d\\d"; +var threeDigits = "\\d{3}"; +var fourDigits = "\\d{4}"; +var word = "[^\\s]+"; +var literal = /\[([^]*?)\]/gm; +function shorten(arr, sLen) { + var newArr = []; + for (var i = 0, len = arr.length; i < len; i++) { + newArr.push(arr[i].substr(0, sLen)); + } + return newArr; +} +var monthUpdate = function (arrName) { return function (v, i18n) { + var lowerCaseArr = i18n[arrName].map(function (v) { return v.toLowerCase(); }); + var index = lowerCaseArr.indexOf(v.toLowerCase()); + if (index > -1) { + return index; + } + return null; +}; }; +function assign(origObj) { + var args = []; + for (var _i = 1; _i < arguments.length; _i++) { + args[_i - 1] = arguments[_i]; + } + for (var _a = 0, args_1 = args; _a < args_1.length; _a++) { + var obj = args_1[_a]; + for (var key in obj) { + // @ts-ignore ex + origObj[key] = obj[key]; + } + } + return origObj; +} +var dayNames = [ + "Sunday", + "Monday", + "Tuesday", + "Wednesday", + "Thursday", + "Friday", + "Saturday" +]; +var monthNames = [ + "January", + "February", + "March", + "April", + "May", + "June", + "July", + "August", + "September", + "October", + "November", + "December" +]; +var monthNamesShort = shorten(monthNames, 3); +var dayNamesShort = shorten(dayNames, 3); +var defaultI18n = { + dayNamesShort: dayNamesShort, + dayNames: dayNames, + monthNamesShort: monthNamesShort, + monthNames: monthNames, + amPm: ["am", "pm"], + DoFn: function (dayOfMonth) { + return (dayOfMonth + + ["th", "st", "nd", "rd"][dayOfMonth % 10 > 3 + ? 0 + : ((dayOfMonth - (dayOfMonth % 10) !== 10 ? 1 : 0) * dayOfMonth) % 10]); + } +}; +var globalI18n = assign({}, defaultI18n); +var setGlobalDateI18n = function (i18n) { + return (globalI18n = assign(globalI18n, i18n)); +}; +var regexEscape = function (str) { + return str.replace(/[|\\{()[^$+*?.-]/g, "\\$&"); +}; +var pad = function (val, len) { + if (len === void 0) { len = 2; } + val = String(val); + while (val.length < len) { + val = "0" + val; + } + return val; +}; +var formatFlags = { + D: function (dateObj) { return String(dateObj.getDate()); }, + DD: function (dateObj) { return pad(dateObj.getDate()); }, + Do: function (dateObj, i18n) { + return i18n.DoFn(dateObj.getDate()); + }, + d: function (dateObj) { return String(dateObj.getDay()); }, + dd: function (dateObj) { return pad(dateObj.getDay()); }, + ddd: function (dateObj, i18n) { + return i18n.dayNamesShort[dateObj.getDay()]; + }, + dddd: function (dateObj, i18n) { + return i18n.dayNames[dateObj.getDay()]; + }, + M: function (dateObj) { return String(dateObj.getMonth() + 1); }, + MM: function (dateObj) { return pad(dateObj.getMonth() + 1); }, + MMM: function (dateObj, i18n) { + return i18n.monthNamesShort[dateObj.getMonth()]; + }, + MMMM: function (dateObj, i18n) { + return i18n.monthNames[dateObj.getMonth()]; + }, + YY: function (dateObj) { + return pad(String(dateObj.getFullYear()), 4).substr(2); + }, + YYYY: function (dateObj) { return pad(dateObj.getFullYear(), 4); }, + h: function (dateObj) { return String(dateObj.getHours() % 12 || 12); }, + hh: function (dateObj) { return pad(dateObj.getHours() % 12 || 12); }, + H: function (dateObj) { return String(dateObj.getHours()); }, + HH: function (dateObj) { return pad(dateObj.getHours()); }, + m: function (dateObj) { return String(dateObj.getMinutes()); }, + mm: function (dateObj) { return pad(dateObj.getMinutes()); }, + s: function (dateObj) { return String(dateObj.getSeconds()); }, + ss: function (dateObj) { return pad(dateObj.getSeconds()); }, + S: function (dateObj) { + return String(Math.round(dateObj.getMilliseconds() / 100)); + }, + SS: function (dateObj) { + return pad(Math.round(dateObj.getMilliseconds() / 10), 2); + }, + SSS: function (dateObj) { return pad(dateObj.getMilliseconds(), 3); }, + a: function (dateObj, i18n) { + return dateObj.getHours() < 12 ? i18n.amPm[0] : i18n.amPm[1]; + }, + A: function (dateObj, i18n) { + return dateObj.getHours() < 12 + ? i18n.amPm[0].toUpperCase() + : i18n.amPm[1].toUpperCase(); + }, + ZZ: function (dateObj) { + var offset = dateObj.getTimezoneOffset(); + return ((offset > 0 ? "-" : "+") + + pad(Math.floor(Math.abs(offset) / 60) * 100 + (Math.abs(offset) % 60), 4)); + }, + Z: function (dateObj) { + var offset = dateObj.getTimezoneOffset(); + return ((offset > 0 ? "-" : "+") + + pad(Math.floor(Math.abs(offset) / 60), 2) + + ":" + + pad(Math.abs(offset) % 60, 2)); + } +}; +var monthParse = function (v) { return +v - 1; }; +var emptyDigits = [null, twoDigitsOptional]; +var emptyWord = [null, word]; +var amPm = [ + "isPm", + word, + function (v, i18n) { + var val = v.toLowerCase(); + if (val === i18n.amPm[0]) { + return 0; + } + else if (val === i18n.amPm[1]) { + return 1; + } + return null; + } +]; +var timezoneOffset = [ + "timezoneOffset", + "[^\\s]*?[\\+\\-]\\d\\d:?\\d\\d|[^\\s]*?Z?", + function (v) { + var parts = (v + "").match(/([+-]|\d\d)/gi); + if (parts) { + var minutes = +parts[1] * 60 + parseInt(parts[2], 10); + return parts[0] === "+" ? minutes : -minutes; + } + return 0; + } +]; +var parseFlags = { + D: ["day", twoDigitsOptional], + DD: ["day", twoDigits], + Do: ["day", twoDigitsOptional + word, function (v) { return parseInt(v, 10); }], + M: ["month", twoDigitsOptional, monthParse], + MM: ["month", twoDigits, monthParse], + YY: [ + "year", + twoDigits, + function (v) { + var now = new Date(); + var cent = +("" + now.getFullYear()).substr(0, 2); + return +("" + (+v > 68 ? cent - 1 : cent) + v); + } + ], + h: ["hour", twoDigitsOptional, undefined, "isPm"], + hh: ["hour", twoDigits, undefined, "isPm"], + H: ["hour", twoDigitsOptional], + HH: ["hour", twoDigits], + m: ["minute", twoDigitsOptional], + mm: ["minute", twoDigits], + s: ["second", twoDigitsOptional], + ss: ["second", twoDigits], + YYYY: ["year", fourDigits], + S: ["millisecond", "\\d", function (v) { return +v * 100; }], + SS: ["millisecond", twoDigits, function (v) { return +v * 10; }], + SSS: ["millisecond", threeDigits], + d: emptyDigits, + dd: emptyDigits, + ddd: emptyWord, + dddd: emptyWord, + MMM: ["month", word, monthUpdate("monthNamesShort")], + MMMM: ["month", word, monthUpdate("monthNames")], + a: amPm, + A: amPm, + ZZ: timezoneOffset, + Z: timezoneOffset +}; +// Some common format strings +var globalMasks = { + default: "ddd MMM DD YYYY HH:mm:ss", + shortDate: "M/D/YY", + mediumDate: "MMM D, YYYY", + longDate: "MMMM D, YYYY", + fullDate: "dddd, MMMM D, YYYY", + isoDate: "YYYY-MM-DD", + isoDateTime: "YYYY-MM-DDTHH:mm:ssZ", + shortTime: "HH:mm", + mediumTime: "HH:mm:ss", + longTime: "HH:mm:ss.SSS" +}; +var setGlobalDateMasks = function (masks) { return assign(globalMasks, masks); }; +/*** + * Format a date + * @method format + * @param {Date|number} dateObj + * @param {string} mask Format of the date, i.e. 'mm-dd-yy' or 'shortDate' + * @returns {string} Formatted date string + */ +var format = function (dateObj, mask, i18n) { + if (mask === void 0) { mask = globalMasks["default"]; } + if (i18n === void 0) { i18n = {}; } + if (typeof dateObj === "number") { + dateObj = new Date(dateObj); + } + if (Object.prototype.toString.call(dateObj) !== "[object Date]" || + isNaN(dateObj.getTime())) { + throw new Error("Invalid Date pass to format"); + } + mask = globalMasks[mask] || mask; + var literals = []; + // Make literals inactive by replacing them with @@@ + mask = mask.replace(literal, function ($0, $1) { + literals.push($1); + return "@@@"; + }); + var combinedI18nSettings = assign(assign({}, globalI18n), i18n); + // Apply formatting rules + mask = mask.replace(token, function ($0) { + return formatFlags[$0](dateObj, combinedI18nSettings); + }); + // Inline literal values back into the formatted value + return mask.replace(/@@@/g, function () { return literals.shift(); }); +}; +/** + * Parse a date string into a Javascript Date object / + * @method parse + * @param {string} dateStr Date string + * @param {string} format Date parse format + * @param {i18n} I18nSettingsOptional Full or subset of I18N settings + * @returns {Date|null} Returns Date object. Returns null what date string is invalid or doesn't match format + */ +function parse(dateStr, format, i18n) { + if (i18n === void 0) { i18n = {}; } + if (typeof format !== "string") { + throw new Error("Invalid format in fecha parse"); + } + // Check to see if the format is actually a mask + format = globalMasks[format] || format; + // Avoid regular expression denial of service, fail early for really long strings + // https://www.owasp.org/index.php/Regular_expression_Denial_of_Service_-_ReDoS + if (dateStr.length > 1000) { + return null; + } + // Default to the beginning of the year. + var today = new Date(); + var dateInfo = { + year: today.getFullYear(), + month: 0, + day: 1, + hour: 0, + minute: 0, + second: 0, + millisecond: 0, + isPm: null, + timezoneOffset: null + }; + var parseInfo = []; + var literals = []; + // Replace all the literals with @@@. Hopefully a string that won't exist in the format + var newFormat = format.replace(literal, function ($0, $1) { + literals.push(regexEscape($1)); + return "@@@"; + }); + var specifiedFields = {}; + var requiredFields = {}; + // Change every token that we find into the correct regex + newFormat = regexEscape(newFormat).replace(token, function ($0) { + var info = parseFlags[$0]; + var field = info[0], regex = info[1], requiredField = info[3]; + // Check if the person has specified the same field twice. This will lead to confusing results. + if (specifiedFields[field]) { + throw new Error("Invalid format. " + field + " specified twice in format"); + } + specifiedFields[field] = true; + // Check if there are any required fields. For instance, 12 hour time requires AM/PM specified + if (requiredField) { + requiredFields[requiredField] = true; + } + parseInfo.push(info); + return "(" + regex + ")"; + }); + // Check all the required fields are present + Object.keys(requiredFields).forEach(function (field) { + if (!specifiedFields[field]) { + throw new Error("Invalid format. " + field + " is required in specified format"); + } + }); + // Add back all the literals after + newFormat = newFormat.replace(/@@@/g, function () { return literals.shift(); }); + // Check if the date string matches the format. If it doesn't return null + var matches = dateStr.match(new RegExp(newFormat, "i")); + if (!matches) { + return null; + } + var combinedI18nSettings = assign(assign({}, globalI18n), i18n); + // For each match, call the parser function for that date part + for (var i = 1; i < matches.length; i++) { + var _a = parseInfo[i - 1], field = _a[0], parser = _a[2]; + var value = parser + ? parser(matches[i], combinedI18nSettings) + : +matches[i]; + // If the parser can't make sense of the value, return null + if (value == null) { + return null; + } + dateInfo[field] = value; + } + if (dateInfo.isPm === 1 && dateInfo.hour != null && +dateInfo.hour !== 12) { + dateInfo.hour = +dateInfo.hour + 12; + } + else if (dateInfo.isPm === 0 && +dateInfo.hour === 12) { + dateInfo.hour = 0; + } + var dateWithoutTZ = new Date(dateInfo.year, dateInfo.month, dateInfo.day, dateInfo.hour, dateInfo.minute, dateInfo.second, dateInfo.millisecond); + var validateFields = [ + ["month", "getMonth"], + ["day", "getDate"], + ["hour", "getHours"], + ["minute", "getMinutes"], + ["second", "getSeconds"] + ]; + for (var i = 0, len = validateFields.length; i < len; i++) { + // Check to make sure the date field is within the allowed range. Javascript dates allows values + // outside the allowed range. If the values don't match the value was invalid + if (specifiedFields[validateFields[i][0]] && + dateInfo[validateFields[i][0]] !== dateWithoutTZ[validateFields[i][1]]()) { + return null; + } + } + if (dateInfo.timezoneOffset == null) { + return dateWithoutTZ; + } + return new Date(Date.UTC(dateInfo.year, dateInfo.month, dateInfo.day, dateInfo.hour, dateInfo.minute - dateInfo.timezoneOffset, dateInfo.second, dateInfo.millisecond)); +} +var fecha = { + format: format, + parse: parse, + defaultI18n: defaultI18n, + setGlobalDateI18n: setGlobalDateI18n, + setGlobalDateMasks: setGlobalDateMasks +}; + +(function(){try{(new Date).toLocaleDateString("i");}catch(e){return "RangeError"===e.name}return !1})()?function(e,t){return e.toLocaleDateString(t,{year:"numeric",month:"long",day:"numeric"})}:function(t){return fecha.format(t,"mediumDate")};(function(){try{(new Date).toLocaleString("i");}catch(e){return "RangeError"===e.name}return !1})()?function(e,t){return e.toLocaleString(t,{year:"numeric",month:"long",day:"numeric",hour:"numeric",minute:"2-digit"})}:function(t){return fecha.format(t,"haDateTime")};(function(){try{(new Date).toLocaleTimeString("i");}catch(e){return "RangeError"===e.name}return !1})()?function(e,t){return e.toLocaleTimeString(t,{hour:"numeric",minute:"2-digit"})}:function(t){return fecha.format(t,"shortTime")};var h=function(e,t,a,r){void 0===r&&(r=!1),e._themes||(e._themes={});var n=t.default_theme;("default"===a||a&&t.themes[a])&&(n=a);var s=Object.assign({},e._themes);if("default"!==n){var i=t.themes[n];Object.keys(i).forEach(function(t){var a="--"+t;e._themes[a]="",s[a]=i[t];});}if(e.updateStyles?e.updateStyles(s):window.ShadyCSS&&window.ShadyCSS.styleSubtree(e,s),r){var o=document.querySelector("meta[name=theme-color]");if(o){o.hasAttribute("default-content")||o.setAttribute("default-content",o.getAttribute("content"));var c=s["--primary-color"]||o.getAttribute("default-content");o.setAttribute("content",c);}}};function f(e){return e.substr(0,e.indexOf("."))}function v(e){return f(e.entity_id)}var _="hass:bookmark",D=["closed","locked","off"],q=function(e,t,a,r){r=r||{},a=null==a?{}:a;var 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=a,e.dispatchEvent(n),n},L={alert:"hass:alert",automation:"hass:playlist-play",calendar:"hass:calendar",camera:"hass:video",climate:"hass:thermostat",configurator:"hass:settings",conversation:"hass:text-to-speech",device_tracker:"hass:account",fan:"hass:fan",group:"hass:google-circles-communities",history_graph:"hass:chart-line",homeassistant:"hass:home-assistant",homekit:"hass:home-automation",image_processing:"hass:image-filter-frames",input_boolean:"hass:drawing",input_datetime:"hass:calendar-clock",input_number:"hass:ray-vertex",input_select:"hass:format-list-bulleted",input_text:"hass:textbox",light:"hass:lightbulb",mailbox:"hass:mailbox",notify:"hass:comment-alert",person:"hass:account",plant:"hass:flower",proximity:"hass:apple-safari",remote:"hass:remote",scene:"hass:google-pages",script:"hass:file-document",sensor:"hass:eye",simple_alarm:"hass:bell",sun:"hass:white-balance-sunny",switch:"hass:flash",timer:"hass:timer",updater:"hass:cloud-upload",vacuum:"hass:robot-vacuum",water_heater:"hass:thermometer",weblink:"hass:open-in-new"};function O(e,t){if(e in L)return L[e];switch(e){case"alarm_control_panel":switch(t){case"armed_home":return "hass:bell-plus";case"armed_night":return "hass:bell-sleep";case"disarmed":return "hass:bell-outline";case"triggered":return "hass:bell-ring";default:return "hass:bell"}case"binary_sensor":return t&&"off"===t?"hass:radiobox-blank":"hass:checkbox-marked-circle";case"cover":return "closed"===t?"hass:window-closed":"hass:window-open";case"lock":return t&&"unlocked"===t?"hass:lock-open":"hass:lock";case"media_player":return t&&"off"!==t&&"idle"!==t?"hass:cast-connected":"hass:cast";case"zwave":switch(t){case"dead":return "hass:emoticon-dead";case"sleeping":return "hass:sleep";case"initializing":return "hass:timer-sand";default:return "hass:z-wave"}default:return console.warn("Unable to find icon for domain "+e+" ("+t+")"),_}}var B=function(e){q(window,"haptic",e);},U=function(e,t,a){void 0===a&&(a=!1),a?history.replaceState(null,"",t):history.pushState(null,"",t),q(window,"location-changed",{replace:a});},V=function(e,t,a){void 0===a&&(a=!0);var r,n=f(t),s="group"===n?"homeassistant":n;switch(n){case"lock":r=a?"unlock":"lock";break;case"cover":r=a?"open_cover":"close_cover";break;default:r=a?"turn_on":"turn_off";}return e.callService(s,r,{entity_id:t})},W=function(e,t){var a=D.includes(e.states[t].state);return V(e,t,a)},Y=function(e,t,a,r){if(r||(r={action:"more-info"}),!r.confirmation||r.confirmation.exemptions&&r.confirmation.exemptions.some(function(e){return e.user===t.user.id})||(B("warning"),confirm(r.confirmation.text||"Are you sure you want to "+r.action+"?")))switch(r.action){case"more-info":(a.entity||a.camera_image)&&q(e,"hass-more-info",{entityId:a.entity?a.entity:a.camera_image});break;case"navigate":r.navigation_path&&U(0,r.navigation_path);break;case"url":r.url_path&&window.open(r.url_path);break;case"toggle":a.entity&&(W(t,a.entity),B("success"));break;case"call-service":if(!r.service)return void B("failure");var n=r.service.split(".",2);t.callService(n[0],n[1],r.service_data),B("success");break;case"fire-dom-event":q(e,"ll-custom",r);}},G=function(e,t,a,r){var n;"double_tap"===r&&a.double_tap_action?n=a.double_tap_action:"hold"===r&&a.hold_action?n=a.hold_action:"tap"===r&&a.tap_action&&(n=a.tap_action),Y(e,t,a,n);};function K(e,t,a){if(t.has("config")||a)return !0;if(e.config.entity){var r=t.get("hass");return !r||r.states[e.config.entity]!==e.hass.states[e.config.entity]}return !1}var Z={humidity:"hass:water-percent",illuminance:"hass:brightness-5",temperature:"hass:thermometer",pressure:"hass:gauge",power:"hass:flash",signal_strength:"hass:wifi"},$={binary_sensor:function(e){var t=e.state&&"off"===e.state;switch(e.attributes.device_class){case"battery":return t?"hass:battery":"hass:battery-outline";case"cold":return t?"hass:thermometer":"hass:snowflake";case"connectivity":return t?"hass:server-network-off":"hass:server-network";case"door":return t?"hass:door-closed":"hass:door-open";case"garage_door":return t?"hass:garage":"hass:garage-open";case"gas":case"power":case"problem":case"safety":case"smoke":return t?"hass:shield-check":"hass:alert";case"heat":return t?"hass:thermometer":"hass:fire";case"light":return t?"hass:brightness-5":"hass:brightness-7";case"lock":return t?"hass:lock":"hass:lock-open";case"moisture":return t?"hass:water-off":"hass:water";case"motion":return t?"hass:walk":"hass:run";case"occupancy":return t?"hass:home-outline":"hass:home";case"opening":return t?"hass:square":"hass:square-outline";case"plug":return t?"hass:power-plug-off":"hass:power-plug";case"presence":return t?"hass:home-outline":"hass:home";case"sound":return t?"hass:music-note-off":"hass:music-note";case"vibration":return t?"hass:crop-portrait":"hass:vibrate";case"window":return t?"hass:window-closed":"hass:window-open";default:return t?"hass:radiobox-blank":"hass:checkbox-marked-circle"}},cover:function(e){var t="closed"!==e.state;switch(e.attributes.device_class){case"garage":return t?"hass:garage-open":"hass:garage";case"door":return t?"hass:door-open":"hass:door-closed";case"shutter":return t?"hass:window-shutter-open":"hass:window-shutter";case"blind":return t?"hass:blinds-open":"hass:blinds";case"window":return t?"hass:window-open":"hass:window-closed";default:return O("cover",e.state)}},sensor:function(e){var t=e.attributes.device_class;if(t&&t in Z)return Z[t];if("battery"===t){var a=Number(e.state);if(isNaN(a))return "hass:battery-unknown";var r=10*Math.round(a/10);return r>=100?"hass:battery":r<=0?"hass:battery-alert":"hass:battery-"+r}var n=e.attributes.unit_of_measurement;return "°C"===n||"°F"===n?"hass:thermometer":O("sensor")},input_datetime:function(e){return e.attributes.has_date?e.attributes.has_time?O("input_datetime"):"hass:calendar":"hass:clock"}},ee=function(e){if(!e)return _;if(e.attributes.icon)return e.attributes.icon;var t=f(e.entity_id);return t in $?$[t](e):O(t,e.state)}; + +var toStringFunction = Function.prototype.toString; +var create = Object.create, defineProperty = Object.defineProperty, getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor, getOwnPropertyNames = Object.getOwnPropertyNames, getOwnPropertySymbols = Object.getOwnPropertySymbols, getPrototypeOf = Object.getPrototypeOf; +var _a$1 = Object.prototype, hasOwnProperty = _a$1.hasOwnProperty, propertyIsEnumerable = _a$1.propertyIsEnumerable; +/** + * @enum + * + * @const {Object} SUPPORTS + * + * @property {boolean} SYMBOL_PROPERTIES are symbol properties supported + * @property {boolean} WEAKMAP is WeakMap supported + */ +var SUPPORTS = { + SYMBOL_PROPERTIES: typeof getOwnPropertySymbols === 'function', + WEAKMAP: typeof WeakMap === 'function', +}; +/** + * @function createCache + * + * @description + * get a new cache object to prevent circular references + * + * @returns the new cache object + */ +var createCache = function () { + if (SUPPORTS.WEAKMAP) { + return new WeakMap(); + } + // tiny implementation of WeakMap + var object = create({ + has: function (key) { return !!~object._keys.indexOf(key); }, + set: function (key, value) { + object._keys.push(key); + object._values.push(value); + }, + get: function (key) { return object._values[object._keys.indexOf(key)]; }, + }); + object._keys = []; + object._values = []; + return object; +}; +/** + * @function getCleanClone + * + * @description + * get an empty version of the object with the same prototype it has + * + * @param object the object to build a clean clone from + * @param realm the realm the object resides in + * @returns the empty cloned object + */ +var getCleanClone = function (object, realm) { + if (!object.constructor) { + return create(null); + } + var Constructor = object.constructor; + var prototype = object.__proto__ || getPrototypeOf(object); + if (Constructor === realm.Object) { + return prototype === realm.Object.prototype ? {} : create(prototype); + } + if (~toStringFunction.call(Constructor).indexOf('[native code]')) { + try { + return new Constructor(); + } + catch (_a) { } + } + return create(prototype); +}; +/** + * @function getObjectCloneLoose + * + * @description + * get a copy of the object based on loose rules, meaning all enumerable keys + * and symbols are copied, but property descriptors are not considered + * + * @param object the object to clone + * @param realm the realm the object resides in + * @param handleCopy the function that handles copying the object + * @returns the copied object + */ +var getObjectCloneLoose = function (object, realm, handleCopy, cache) { + var clone = getCleanClone(object, realm); + // set in the cache immediately to be able to reuse the object recursively + cache.set(object, clone); + for (var key in object) { + if (hasOwnProperty.call(object, key)) { + clone[key] = handleCopy(object[key], cache); + } + } + if (SUPPORTS.SYMBOL_PROPERTIES) { + var symbols = getOwnPropertySymbols(object); + var length_1 = symbols.length; + if (length_1) { + for (var index = 0, symbol = void 0; index < length_1; index++) { + symbol = symbols[index]; + if (propertyIsEnumerable.call(object, symbol)) { + clone[symbol] = handleCopy(object[symbol], cache); + } + } + } + } + return clone; +}; +/** + * @function getObjectCloneStrict + * + * @description + * get a copy of the object based on strict rules, meaning all keys and symbols + * are copied based on the original property descriptors + * + * @param object the object to clone + * @param realm the realm the object resides in + * @param handleCopy the function that handles copying the object + * @returns the copied object + */ +var getObjectCloneStrict = function (object, realm, handleCopy, cache) { + var clone = getCleanClone(object, realm); + // set in the cache immediately to be able to reuse the object recursively + cache.set(object, clone); + var properties = SUPPORTS.SYMBOL_PROPERTIES + ? getOwnPropertyNames(object).concat(getOwnPropertySymbols(object)) + : getOwnPropertyNames(object); + var length = properties.length; + if (length) { + for (var index = 0, property = void 0, descriptor = void 0; index < length; index++) { + property = properties[index]; + if (property !== 'callee' && property !== 'caller') { + descriptor = getOwnPropertyDescriptor(object, property); + if (descriptor) { + // Only clone the value if actually a value, not a getter / setter. + if (!descriptor.get && !descriptor.set) { + descriptor.value = handleCopy(object[property], cache); + } + try { + defineProperty(clone, property, descriptor); + } + catch (error) { + // Tee above can fail on node in edge cases, so fall back to the loose assignment. + clone[property] = descriptor.value; + } + } + else { + // In extra edge cases where the property descriptor cannot be retrived, fall back to + // the loose assignment. + clone[property] = handleCopy(object[property], cache); + } + } + } + } + return clone; +}; +/** + * @function getRegExpFlags + * + * @description + * get the flags to apply to the copied regexp + * + * @param regExp the regexp to get the flags of + * @returns the flags for the regexp + */ +var getRegExpFlags = function (regExp) { + var flags = ''; + if (regExp.global) { + flags += 'g'; + } + if (regExp.ignoreCase) { + flags += 'i'; + } + if (regExp.multiline) { + flags += 'm'; + } + if (regExp.unicode) { + flags += 'u'; + } + if (regExp.sticky) { + flags += 'y'; + } + return flags; +}; + +// utils +var isArray = Array.isArray; +var GLOBAL_THIS = (function () { + if (typeof self !== 'undefined') { + return self; + } + if (typeof window !== 'undefined') { + return window; + } + if (typeof global !== 'undefined') { + return global; + } + if (console && console.error) { + console.error('Unable to locate global object, returning "this".'); + } +})(); +/** + * @function copy + * + * @description + * copy an object deeply as much as possible + * + * If `strict` is applied, then all properties (including non-enumerable ones) + * are copied with their original property descriptors on both objects and arrays. + * + * The object is compared to the global constructors in the `realm` provided, + * and the native constructor is always used to ensure that extensions of native + * objects (allows in ES2015+) are maintained. + * + * @param object the object to copy + * @param [options] the options for copying with + * @param [options.isStrict] should the copy be strict + * @param [options.realm] the realm (this) object the object is copied from + * @returns the copied object + */ +function copy(object, options) { + // manually coalesced instead of default parameters for performance + var isStrict = !!(options && options.isStrict); + var realm = (options && options.realm) || GLOBAL_THIS; + var getObjectClone = isStrict + ? getObjectCloneStrict + : getObjectCloneLoose; + /** + * @function handleCopy + * + * @description + * copy the object recursively based on its type + * + * @param object the object to copy + * @returns the copied object + */ + var handleCopy = function (object, cache) { + if (!object || typeof object !== 'object') { + return object; + } + if (cache.has(object)) { + return cache.get(object); + } + var Constructor = object.constructor; + // plain objects + if (Constructor === realm.Object) { + return getObjectClone(object, realm, handleCopy, cache); + } + var clone; + // arrays + if (isArray(object)) { + // if strict, include non-standard properties + if (isStrict) { + return getObjectCloneStrict(object, realm, handleCopy, cache); + } + var length_1 = object.length; + clone = new Constructor(); + cache.set(object, clone); + for (var index = 0; index < length_1; index++) { + clone[index] = handleCopy(object[index], cache); + } + return clone; + } + // dates + if (object instanceof realm.Date) { + return new Constructor(object.getTime()); + } + // regexps + if (object instanceof realm.RegExp) { + clone = new Constructor(object.source, object.flags || getRegExpFlags(object)); + clone.lastIndex = object.lastIndex; + return clone; + } + // maps + if (realm.Map && object instanceof realm.Map) { + clone = new Constructor(); + cache.set(object, clone); + object.forEach(function (value, key) { + clone.set(key, handleCopy(value, cache)); + }); + return clone; + } + // sets + if (realm.Set && object instanceof realm.Set) { + clone = new Constructor(); + cache.set(object, clone); + object.forEach(function (value) { + clone.add(handleCopy(value, cache)); + }); + return clone; + } + // blobs + if (realm.Blob && object instanceof realm.Blob) { + return object.slice(0, object.size, object.type); + } + // buffers (node-only) + if (realm.Buffer && realm.Buffer.isBuffer(object)) { + clone = realm.Buffer.allocUnsafe + ? realm.Buffer.allocUnsafe(object.length) + : new Constructor(object.length); + cache.set(object, clone); + object.copy(clone); + return clone; + } + // arraybuffers / dataviews + if (realm.ArrayBuffer) { + // dataviews + if (realm.ArrayBuffer.isView(object)) { + clone = new Constructor(object.buffer.slice(0)); + cache.set(object, clone); + return clone; + } + // arraybuffers + if (object instanceof realm.ArrayBuffer) { + clone = object.slice(0); + cache.set(object, clone); + return clone; + } + } + // if the object cannot / should not be cloned, don't + if ( + // promise-like + typeof object.then === 'function' || + // errors + object instanceof Error || + // weakmaps + (realm.WeakMap && object instanceof realm.WeakMap) || + // weaksets + (realm.WeakSet && object instanceof realm.WeakSet)) { + return object; + } + // assume anything left is a custom constructor + return getObjectClone(object, realm, handleCopy, cache); + }; + return handleCopy(object, createCache()); +} +// Adding reference to allow usage in CommonJS libraries compiled using TSC, which +// expects there to be a default property on the exported object. See +// [#37](https://github.com/planttheidea/fast-copy/issues/37) for details. +copy.default = copy; +/** + * @function strictCopy + * + * @description + * copy the object with `strict` option pre-applied + * + * @param object the object to copy + * @param [options] the options for copying with + * @param [options.realm] the realm (this) object the object is copied from + * @returns the copied object + */ +copy.strict = function strictCopy(object, options) { + return copy(object, { + isStrict: true, + realm: options ? options.realm : void 0, + }); +}; + /** * @license * Copyright (c) 2017 The Polymer Project Authors. All rights reserved. @@ -26,7 +770,25 @@ function t(t,e,i,s){var r,o=arguments.length,n=o<3?e:null===s?s=Object.getOwnPro * subject to an additional IP rights grant found at * http://polymer.github.io/PATENTS.txt */ -const Q="undefined"!=typeof window&&null!=window.customElements&&void 0!==window.customElements.polyfillWrapFlushCallback,tt=(t,e,i=null)=>{for(;e!==i;){const i=e.nextSibling;t.removeChild(e),e=i}},et=`{{lit-${String(Math.random()).slice(2)}}}`,it=`\x3c!--${et}--\x3e`,st=new RegExp(`${et}|${it}`);class rt{constructor(t,e){this.parts=[],this.element=e;const i=[],s=[],r=document.createTreeWalker(e.content,133,null,!1);let o=0,n=-1,a=0;const{strings:l,values:{length:c}}=t;for(;a0;){const e=l[a],i=lt.exec(e)[2],s=i.toLowerCase()+"$lit$",r=t.getAttribute(s);t.removeAttribute(s);const o=r.split(st);this.parts.push({type:"attribute",index:n,name:i,strings:o}),a+=o.length-1}}"TEMPLATE"===t.tagName&&(s.push(t),r.currentNode=t.content)}else if(3===t.nodeType){const e=t.data;if(e.indexOf(et)>=0){const s=t.parentNode,r=e.split(st),o=r.length-1;for(let e=0;e{const i=t.length-e.length;return i>=0&&t.slice(i)===e},nt=t=>-1!==t.index,at=()=>document.createComment(""),lt=/([ \x09\x0a\x0c\x0d])([^\0-\x1F\x7F-\x9F "'>=/]+)([ \x09\x0a\x0c\x0d]*=[ \x09\x0a\x0c\x0d]*(?:[^ \x09\x0a\x0c\x0d"'`<>=]*|"[^"]*|'[^']*))$/;function ct(t,e){const{element:{content:i},parts:s}=t,r=document.createTreeWalker(i,133,null,!1);let o=dt(s),n=s[o],a=-1,l=0;const c=[];let h=null;for(;r.nextNode();){a++;const t=r.currentNode;for(t.previousSibling===h&&(h=null),e.has(t)&&(c.push(t),null===h&&(h=t)),null!==h&&l++;void 0!==n&&n.index===a;)n.index=null!==h?-1:n.index-l,o=dt(s,o),n=s[o]}c.forEach(t=>t.parentNode.removeChild(t))}const ht=t=>{let e=11===t.nodeType?0:1;const i=document.createTreeWalker(t,133,null,!1);for(;i.nextNode();)e++;return e},dt=(t,e=-1)=>{for(let i=e+1;i { + while (start !== end) { + const n = start.nextSibling; + container.removeChild(start); + start = n; + } +}; + /** * @license * Copyright (c) 2017 The Polymer Project Authors. All rights reserved. @@ -40,7 +802,208 @@ const Q="undefined"!=typeof window&&null!=window.customElements&&void 0!==window * subject to an additional IP rights grant found at * http://polymer.github.io/PATENTS.txt */ -const ut=new WeakMap,pt=t=>(...e)=>{const i=t(...e);return ut.set(i,!0),i},gt=t=>"function"==typeof t&&ut.has(t),ft={},bt={}; +/** + * An expression marker with embedded unique key to avoid collision with + * possible text in templates. + */ +const marker = `{{lit-${String(Math.random()).slice(2)}}}`; +/** + * An expression marker used text-positions, multi-binding attributes, and + * attributes with markup-like text values. + */ +const nodeMarker = ``; +const markerRegex = new RegExp(`${marker}|${nodeMarker}`); +/** + * Suffix appended to all bound attribute names. + */ +const boundAttributeSuffix = '$lit$'; +/** + * An updatable Template that tracks the location of dynamic parts. + */ +class Template { + constructor(result, element) { + this.parts = []; + this.element = element; + const nodesToRemove = []; + const stack = []; + // Edge needs all 4 parameters present; IE11 needs 3rd parameter to be null + const walker = document.createTreeWalker(element.content, 133 /* NodeFilter.SHOW_{ELEMENT|COMMENT|TEXT} */, null, false); + // Keeps track of the last index associated with a part. We try to delete + // unnecessary nodes, but we never want to associate two different parts + // to the same index. They must have a constant node between. + let lastPartIndex = 0; + let index = -1; + let partIndex = 0; + const { strings, values: { length } } = result; + while (partIndex < length) { + const node = walker.nextNode(); + if (node === null) { + // We've exhausted the content inside a nested template element. + // Because we still have parts (the outer for-loop), we know: + // - There is a template in the stack + // - The walker will find a nextNode outside the template + walker.currentNode = stack.pop(); + continue; + } + index++; + if (node.nodeType === 1 /* Node.ELEMENT_NODE */) { + if (node.hasAttributes()) { + const attributes = node.attributes; + const { length } = attributes; + // Per + // https://developer.mozilla.org/en-US/docs/Web/API/NamedNodeMap, + // attributes are not guaranteed to be returned in document order. + // In particular, Edge/IE can return them out of order, so we cannot + // assume a correspondence between part index and attribute index. + let count = 0; + for (let i = 0; i < length; i++) { + if (endsWith(attributes[i].name, boundAttributeSuffix)) { + count++; + } + } + while (count-- > 0) { + // Get the template literal section leading up to the first + // expression in this attribute + const stringForPart = strings[partIndex]; + // Find the attribute name + const name = lastAttributeNameRegex.exec(stringForPart)[2]; + // Find the corresponding attribute + // All bound attributes have had a suffix added in + // TemplateResult#getHTML to opt out of special attribute + // handling. To look up the attribute value we also need to add + // the suffix. + const attributeLookupName = name.toLowerCase() + boundAttributeSuffix; + const attributeValue = node.getAttribute(attributeLookupName); + node.removeAttribute(attributeLookupName); + const statics = attributeValue.split(markerRegex); + this.parts.push({ type: 'attribute', index, name, strings: statics }); + partIndex += statics.length - 1; + } + } + if (node.tagName === 'TEMPLATE') { + stack.push(node); + walker.currentNode = node.content; + } + } + else if (node.nodeType === 3 /* Node.TEXT_NODE */) { + const data = node.data; + if (data.indexOf(marker) >= 0) { + const parent = node.parentNode; + const strings = data.split(markerRegex); + const lastIndex = strings.length - 1; + // Generate a new text node for each literal section + // These nodes are also used as the markers for node parts + for (let i = 0; i < lastIndex; i++) { + let insert; + let s = strings[i]; + if (s === '') { + insert = createMarker(); + } + else { + const match = lastAttributeNameRegex.exec(s); + if (match !== null && endsWith(match[2], boundAttributeSuffix)) { + s = s.slice(0, match.index) + match[1] + + match[2].slice(0, -boundAttributeSuffix.length) + match[3]; + } + insert = document.createTextNode(s); + } + parent.insertBefore(insert, node); + this.parts.push({ type: 'node', index: ++index }); + } + // If there's no text, we must insert a comment to mark our place. + // Else, we can trust it will stick around after cloning. + if (strings[lastIndex] === '') { + parent.insertBefore(createMarker(), node); + nodesToRemove.push(node); + } + else { + node.data = strings[lastIndex]; + } + // We have a part for each match found + partIndex += lastIndex; + } + } + else if (node.nodeType === 8 /* Node.COMMENT_NODE */) { + if (node.data === marker) { + const parent = node.parentNode; + // Add a new marker node to be the startNode of the Part if any of + // the following are true: + // * We don't have a previousSibling + // * The previousSibling is already the start of a previous part + if (node.previousSibling === null || index === lastPartIndex) { + index++; + parent.insertBefore(createMarker(), node); + } + lastPartIndex = index; + this.parts.push({ type: 'node', index }); + // If we don't have a nextSibling, keep this node so we have an end. + // Else, we can remove it to save future costs. + if (node.nextSibling === null) { + node.data = ''; + } + else { + nodesToRemove.push(node); + index--; + } + partIndex++; + } + else { + let i = -1; + while ((i = node.data.indexOf(marker, i + 1)) !== -1) { + // Comment node has a binding marker inside, make an inactive part + // The binding won't work, but subsequent bindings will + // TODO (justinfagnani): consider whether it's even worth it to + // make bindings in comments work + this.parts.push({ type: 'node', index: -1 }); + partIndex++; + } + } + } + } + // Remove text binding nodes after the walk to not disturb the TreeWalker + for (const n of nodesToRemove) { + n.parentNode.removeChild(n); + } + } +} +const endsWith = (str, suffix) => { + const index = str.length - suffix.length; + return index >= 0 && str.slice(index) === suffix; +}; +const isTemplatePartActive = (part) => part.index !== -1; +// Allows `document.createComment('')` to be renamed for a +// small manual size-savings. +const createMarker = () => document.createComment(''); +/** + * This regex extracts the attribute name preceding an attribute-position + * expression. It does this by matching the syntax allowed for attributes + * against the string literal directly preceding the expression, assuming that + * the expression is in an attribute-value position. + * + * See attributes in the HTML spec: + * https://www.w3.org/TR/html5/syntax.html#elements-attributes + * + * " \x09\x0a\x0c\x0d" are HTML space characters: + * https://www.w3.org/TR/html5/infrastructure.html#space-characters + * + * "\0-\x1F\x7F-\x9F" are Unicode control characters, which includes every + * space character except " ". + * + * So an attribute is: + * * The name: any character except a control character, space character, ('), + * ("), ">", "=", or "/" + * * Followed by zero or more space characters + * * Followed by "=" + * * Followed by zero or more space characters + * * Followed by: + * * Any character except space, ('), ("), "<", ">", "=", (`), or + * * (") then any non-("), or + * * (') then any non-(') + */ +const lastAttributeNameRegex = +// eslint-disable-next-line no-control-regex +/([ \x09\x0a\x0c\x0d])([^\0-\x1F\x7F-\x9F "'>=/]+)([ \x09\x0a\x0c\x0d]*=[ \x09\x0a\x0c\x0d]*(?:[^ \x09\x0a\x0c\x0d"'`<>=]*|"[^"]*|'[^']*))$/; + /** * @license * Copyright (c) 2017 The Polymer Project Authors. All rights reserved. @@ -54,7 +1017,117 @@ const ut=new WeakMap,pt=t=>(...e)=>{const i=t(...e);return ut.set(i,!0),i},gt=t= * subject to an additional IP rights grant found at * http://polymer.github.io/PATENTS.txt */ -class mt{constructor(t,e,i){this.__parts=[],this.template=t,this.processor=e,this.options=i}update(t){let e=0;for(const i of this.__parts)void 0!==i&&i.setValue(t[e]),e++;for(const t of this.__parts)void 0!==t&&t.commit()}_clone(){const t=Q?this.template.element.content.cloneNode(!0):document.importNode(this.template.element.content,!0),e=[],i=this.template.parts,s=document.createTreeWalker(t,133,null,!1);let r,o=0,n=0,a=s.nextNode();for(;o n.parentNode.removeChild(n)); +} +const countNodes = (node) => { + let count = (node.nodeType === 11 /* Node.DOCUMENT_FRAGMENT_NODE */) ? 0 : 1; + const walker = document.createTreeWalker(node, walkerNodeFilter, null, false); + while (walker.nextNode()) { + count++; + } + return count; +}; +const nextActiveIndexInTemplateParts = (parts, startIndex = -1) => { + for (let i = startIndex + 1; i < parts.length; i++) { + const part = parts[i]; + if (isTemplatePartActive(part)) { + return i; + } + } + return -1; +}; +/** + * Inserts the given node into the Template, optionally before the given + * refNode. In addition to inserting the node into the Template, the Template + * part indices are updated to match the mutated Template DOM. + */ +function insertNodeIntoTemplate(template, node, refNode = null) { + const { element: { content }, parts } = template; + // If there's no refNode, then put node at end of template. + // No part indices need to be shifted in this case. + if (refNode === null || refNode === undefined) { + content.appendChild(node); + return; + } + const walker = document.createTreeWalker(content, walkerNodeFilter, null, false); + let partIndex = nextActiveIndexInTemplateParts(parts); + let insertCount = 0; + let walkerIndex = -1; + while (walker.nextNode()) { + walkerIndex++; + const walkerNode = walker.currentNode; + if (walkerNode === refNode) { + insertCount = countNodes(node); + refNode.parentNode.insertBefore(node, refNode); + } + while (partIndex !== -1 && parts[partIndex].index === walkerIndex) { + // If we've inserted the node, simply adjust all subsequent parts + if (insertCount > 0) { + while (partIndex !== -1) { + parts[partIndex].index += insertCount; + partIndex = nextActiveIndexInTemplateParts(parts, partIndex); + } + return; + } + partIndex = nextActiveIndexInTemplateParts(parts, partIndex); + } + } +} + /** * @license * Copyright (c) 2017 The Polymer Project Authors. All rights reserved. @@ -67,7 +1140,80 @@ class mt{constructor(t,e,i){this.__parts=[],this.template=t,this.processor=e,thi * Code distributed by Google as part of the polymer project is also * subject to an additional IP rights grant found at * http://polymer.github.io/PATENTS.txt - */const _t=window.trustedTypes&&trustedTypes.createPolicy("lit-html",{createHTML:t=>t}),vt=` ${et} `;class yt{constructor(t,e,i,s){this.strings=t,this.values=e,this.type=i,this.processor=s}getHTML(){const t=this.strings.length-1;let e="",i=!1;for(let s=0;s-1||i)&&-1===t.indexOf("--\x3e",r+1);const o=lt.exec(t);e+=null===o?t+(i?vt:it):t.substr(0,o.index)+o[1]+o[2]+"$lit$"+o[3]+et}return e+=this.strings[t],e}getTemplateElement(){const t=document.createElement("template");let e=this.getHTML();return void 0!==_t&&(e=_t.createHTML(e)),t.innerHTML=e,t}} + */ +const directives = new WeakMap(); +/** + * Brands a function as a directive factory function so that lit-html will call + * the function during template rendering, rather than passing as a value. + * + * A _directive_ is a function that takes a Part as an argument. It has the + * signature: `(part: Part) => void`. + * + * A directive _factory_ is a function that takes arguments for data and + * configuration and returns a directive. Users of directive usually refer to + * the directive factory as the directive. For example, "The repeat directive". + * + * Usually a template author will invoke a directive factory in their template + * with relevant arguments, which will then return a directive function. + * + * Here's an example of using the `repeat()` directive factory that takes an + * array and a function to render an item: + * + * ```js + * html`
    <${repeat(items, (item) => html`
  • ${item}
  • `)}
` + * ``` + * + * When `repeat` is invoked, it returns a directive function that closes over + * `items` and the template function. When the outer template is rendered, the + * return directive function is called with the Part for the expression. + * `repeat` then performs it's custom logic to render multiple items. + * + * @param f The directive factory function. Must be a function that returns a + * function of the signature `(part: Part) => void`. The returned function will + * be called with the part object. + * + * @example + * + * import {directive, html} from 'lit-html'; + * + * const immutable = directive((v) => (part) => { + * if (part.value !== v) { + * part.setValue(v) + * } + * }); + */ +const directive = (f) => ((...args) => { + const d = f(...args); + directives.set(d, true); + return d; +}); +const isDirective = (o) => { + return typeof o === 'function' && directives.has(o); +}; + +/** + * @license + * Copyright (c) 2018 The Polymer Project Authors. All rights reserved. + * This code may only be used under the BSD style license found at + * http://polymer.github.io/LICENSE.txt + * The complete set of authors may be found at + * http://polymer.github.io/AUTHORS.txt + * The complete set of contributors may be found at + * http://polymer.github.io/CONTRIBUTORS.txt + * Code distributed by Google as part of the polymer project is also + * subject to an additional IP rights grant found at + * http://polymer.github.io/PATENTS.txt + */ +/** + * A sentinel value that signals that a value was handled by a directive and + * should not be written to the DOM. + */ +const noChange = {}; +/** + * A sentinel value that signals a NodePart to fully clear its content. + */ +const nothing = {}; + /** * @license * Copyright (c) 2017 The Polymer Project Authors. All rights reserved. @@ -80,7 +1226,126 @@ class mt{constructor(t,e,i){this.__parts=[],this.template=t,this.processor=e,thi * Code distributed by Google as part of the polymer project is also * subject to an additional IP rights grant found at * http://polymer.github.io/PATENTS.txt - */const wt=t=>null===t||!("object"==typeof t||"function"==typeof t),St=t=>Array.isArray(t)||!(!t||!t[Symbol.iterator]);class kt{constructor(t,e,i){this.dirty=!0,this.element=t,this.name=e,this.strings=i,this.parts=[];for(let t=0;t{try{const t={get capture(){return Pt=!0,!1}};window.addEventListener("test",t,t),window.removeEventListener("test",t,t)}catch(t){}})();class Et{constructor(t,e,i){this.value=void 0,this.__pendingValue=void 0,this.element=t,this.eventName=e,this.eventContext=i,this.__boundHandleEvent=t=>this.handleEvent(t)}setValue(t){this.__pendingValue=t}commit(){for(;gt(this.__pendingValue);){const t=this.__pendingValue;this.__pendingValue=ft,t(this)}if(this.__pendingValue===ft)return;const t=this.__pendingValue,e=this.value,i=null==t||null!=e&&(t.capture!==e.capture||t.once!==e.once||t.passive!==e.passive),s=null!=t&&(null==e||i);i&&this.element.removeEventListener(this.eventName,this.__boundHandleEvent,this.__options),s&&(this.__options=At(t),this.element.addEventListener(this.eventName,this.__boundHandleEvent,this.__options)),this.value=t,this.__pendingValue=ft}handleEvent(t){"function"==typeof this.value?this.value.call(this.eventContext||this.element,t):this.value.handleEvent(t)}}const At=t=>t&&(Pt?{capture:t.capture,passive:t.passive,once:t.once}:t.capture) + */ +/** + * An instance of a `Template` that can be attached to the DOM and updated + * with new values. + */ +class TemplateInstance { + constructor(template, processor, options) { + this.__parts = []; + this.template = template; + this.processor = processor; + this.options = options; + } + update(values) { + let i = 0; + for (const part of this.__parts) { + if (part !== undefined) { + part.setValue(values[i]); + } + i++; + } + for (const part of this.__parts) { + if (part !== undefined) { + part.commit(); + } + } + } + _clone() { + // There are a number of steps in the lifecycle of a template instance's + // DOM fragment: + // 1. Clone - create the instance fragment + // 2. Adopt - adopt into the main document + // 3. Process - find part markers and create parts + // 4. Upgrade - upgrade custom elements + // 5. Update - set node, attribute, property, etc., values + // 6. Connect - connect to the document. Optional and outside of this + // method. + // + // We have a few constraints on the ordering of these steps: + // * We need to upgrade before updating, so that property values will pass + // through any property setters. + // * We would like to process before upgrading so that we're sure that the + // cloned fragment is inert and not disturbed by self-modifying DOM. + // * We want custom elements to upgrade even in disconnected fragments. + // + // Given these constraints, with full custom elements support we would + // prefer the order: Clone, Process, Adopt, Upgrade, Update, Connect + // + // But Safari does not implement CustomElementRegistry#upgrade, so we + // can not implement that order and still have upgrade-before-update and + // upgrade disconnected fragments. So we instead sacrifice the + // process-before-upgrade constraint, since in Custom Elements v1 elements + // must not modify their light DOM in the constructor. We still have issues + // when co-existing with CEv0 elements like Polymer 1, and with polyfills + // that don't strictly adhere to the no-modification rule because shadow + // DOM, which may be created in the constructor, is emulated by being placed + // in the light DOM. + // + // The resulting order is on native is: Clone, Adopt, Upgrade, Process, + // Update, Connect. document.importNode() performs Clone, Adopt, and Upgrade + // in one step. + // + // The Custom Elements v1 polyfill supports upgrade(), so the order when + // polyfilled is the more ideal: Clone, Process, Adopt, Upgrade, Update, + // Connect. + const fragment = isCEPolyfill ? + this.template.element.content.cloneNode(true) : + document.importNode(this.template.element.content, true); + const stack = []; + const parts = this.template.parts; + // Edge needs all 4 parameters present; IE11 needs 3rd parameter to be null + const walker = document.createTreeWalker(fragment, 133 /* NodeFilter.SHOW_{ELEMENT|COMMENT|TEXT} */, null, false); + let partIndex = 0; + let nodeIndex = 0; + let part; + let node = walker.nextNode(); + // Loop through all the nodes and parts of a template + while (partIndex < parts.length) { + part = parts[partIndex]; + if (!isTemplatePartActive(part)) { + this.__parts.push(undefined); + partIndex++; + continue; + } + // Progress the tree walker until we find our next part's node. + // Note that multiple parts may share the same node (attribute parts + // on a single element), so this loop may not run at all. + while (nodeIndex < part.index) { + nodeIndex++; + if (node.nodeName === 'TEMPLATE') { + stack.push(node); + walker.currentNode = node.content; + } + if ((node = walker.nextNode()) === null) { + // We've exhausted the content inside a nested template element. + // Because we still have parts (the outer for-loop), we know: + // - There is a template in the stack + // - The walker will find a nextNode outside the template + walker.currentNode = stack.pop(); + node = walker.nextNode(); + } + } + // We've arrived at our part's node. + if (part.type === 'node') { + const part = this.processor.handleTextExpression(this.options); + part.insertAfterNode(node.previousSibling); + this.__parts.push(part); + } + else { + this.__parts.push(...this.processor.handleAttributeExpressions(node, part.name, part.strings, this.options)); + } + partIndex++; + } + if (isCEPolyfill) { + document.adoptNode(fragment); + customElements.upgrade(fragment); + } + return fragment; + } +} + /** * @license * Copyright (c) 2017 The Polymer Project Authors. All rights reserved. @@ -93,7 +1358,100 @@ class mt{constructor(t,e,i){this.__parts=[],this.template=t,this.processor=e,thi * Code distributed by Google as part of the polymer project is also * subject to an additional IP rights grant found at * http://polymer.github.io/PATENTS.txt - */;function $t(t){let e=Nt.get(t.type);void 0===e&&(e={stringsArray:new WeakMap,keyString:new Map},Nt.set(t.type,e));let i=e.stringsArray.get(t.strings);if(void 0!==i)return i;const s=t.strings.join(et);return i=e.keyString.get(s),void 0===i&&(i=new rt(t,t.getTemplateElement()),e.keyString.set(s,i)),e.stringsArray.set(t.strings,i),i}const Nt=new Map,jt=new WeakMap; + */ +/** + * Our TrustedTypePolicy for HTML which is declared using the html template + * tag function. + * + * That HTML is a developer-authored constant, and is parsed with innerHTML + * before any untrusted expressions have been mixed in. Therefor it is + * considered safe by construction. + */ +const policy = window.trustedTypes && + trustedTypes.createPolicy('lit-html', { createHTML: (s) => s }); +const commentMarker = ` ${marker} `; +/** + * The return type of `html`, which holds a Template and the values from + * interpolated expressions. + */ +class TemplateResult { + constructor(strings, values, type, processor) { + this.strings = strings; + this.values = values; + this.type = type; + this.processor = processor; + } + /** + * Returns a string of HTML used to create a `