@everymatrix/lottery-game-page 0.1.27 → 1.13.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (180) hide show
  1. package/dist/cjs/helper-accordion.cjs.entry.js +10 -2
  2. package/dist/cjs/helper-accordion.cjs.entry.js.map +1 -0
  3. package/dist/cjs/helper-filters_2.cjs.entry.js +1716 -1002
  4. package/dist/cjs/helper-filters_2.cjs.entry.js.map +1 -0
  5. package/dist/cjs/helper-modal.cjs.entry.js +2 -0
  6. package/dist/cjs/helper-modal.cjs.entry.js.map +1 -0
  7. package/dist/cjs/helper-pagination.cjs.entry.js +14 -0
  8. package/dist/cjs/helper-pagination.cjs.entry.js.map +1 -0
  9. package/dist/cjs/helper-tab.cjs.entry.js +2 -0
  10. package/dist/cjs/helper-tab.cjs.entry.js.map +1 -0
  11. package/dist/cjs/helper-tabs.cjs.entry.js +2 -0
  12. package/dist/cjs/helper-tabs.cjs.entry.js.map +1 -0
  13. package/dist/cjs/index-cd44e726.js +2 -0
  14. package/dist/cjs/index-cd44e726.js.map +1 -0
  15. package/dist/cjs/index.cjs.js +2 -0
  16. package/dist/cjs/index.cjs.js.map +1 -0
  17. package/dist/cjs/loader.cjs.js +3 -1
  18. package/dist/cjs/loader.cjs.js.map +1 -0
  19. package/dist/cjs/lottery-bullet_2.cjs.entry.js +13 -2
  20. package/dist/cjs/lottery-bullet_2.cjs.entry.js.map +1 -0
  21. package/dist/cjs/lottery-draw-results-history.cjs.entry.js +45 -16
  22. package/dist/cjs/lottery-draw-results-history.cjs.entry.js.map +1 -0
  23. package/dist/cjs/lottery-game-details.cjs.entry.js +2 -0
  24. package/dist/cjs/lottery-game-details.cjs.entry.js.map +1 -0
  25. package/dist/cjs/lottery-game-page.cjs.entry.js +34 -28
  26. package/dist/cjs/lottery-game-page.cjs.entry.js.map +1 -0
  27. package/dist/cjs/lottery-game-page.cjs.js +3 -1
  28. package/dist/cjs/lottery-game-page.cjs.js.map +1 -0
  29. package/dist/cjs/lottery-ticket-controller.cjs.entry.js +15 -2
  30. package/dist/cjs/lottery-ticket-controller.cjs.entry.js.map +1 -0
  31. package/dist/cjs/lottery-ticket.cjs.entry.js +29 -7
  32. package/dist/cjs/lottery-ticket.cjs.entry.js.map +1 -0
  33. package/dist/collection/components/lottery-game-page/lottery-game-page.css +10 -1
  34. package/dist/collection/components/lottery-game-page/lottery-game-page.js +84 -33
  35. package/dist/collection/components/lottery-game-page/lottery-game-page.js.map +1 -0
  36. package/dist/collection/index.js +1 -0
  37. package/dist/collection/index.js.map +1 -0
  38. package/dist/collection/utils/locale.utils.js +1 -0
  39. package/dist/collection/utils/locale.utils.js.map +1 -0
  40. package/dist/collection/utils/utils.js +1 -0
  41. package/dist/collection/utils/utils.js.map +1 -0
  42. package/dist/components/helper-accordion.js +2 -0
  43. package/dist/components/helper-accordion.js.map +1 -0
  44. package/dist/components/helper-accordion2.js +10 -2
  45. package/dist/components/helper-accordion2.js.map +1 -0
  46. package/dist/components/helper-filters.js +2 -0
  47. package/dist/components/helper-filters.js.map +1 -0
  48. package/dist/components/helper-filters2.js +1696 -974
  49. package/dist/components/helper-filters2.js.map +1 -0
  50. package/dist/components/helper-modal.js +2 -0
  51. package/dist/components/helper-modal.js.map +1 -0
  52. package/dist/components/helper-modal2.js +2 -0
  53. package/dist/components/helper-modal2.js.map +1 -0
  54. package/dist/components/helper-pagination.js +14 -0
  55. package/dist/components/helper-pagination.js.map +1 -0
  56. package/dist/components/helper-tab.js +2 -0
  57. package/dist/components/helper-tab.js.map +1 -0
  58. package/dist/components/helper-tab2.js +2 -0
  59. package/dist/components/helper-tab2.js.map +1 -0
  60. package/dist/components/helper-tabs.js +2 -0
  61. package/dist/components/helper-tabs.js.map +1 -0
  62. package/dist/components/helper-tabs2.js +2 -0
  63. package/dist/components/helper-tabs2.js.map +1 -0
  64. package/dist/components/index.js +2 -0
  65. package/dist/components/index.js.map +1 -0
  66. package/dist/components/lottery-bullet.js +2 -0
  67. package/dist/components/lottery-bullet.js.map +1 -0
  68. package/dist/components/lottery-bullet2.js +2 -0
  69. package/dist/components/lottery-bullet2.js.map +1 -0
  70. package/dist/components/lottery-draw-results-history.js +2 -0
  71. package/dist/components/lottery-draw-results-history.js.map +1 -0
  72. package/dist/components/lottery-draw-results-history2.js +46 -17
  73. package/dist/components/lottery-draw-results-history2.js.map +1 -0
  74. package/dist/components/lottery-draw-results.js +2 -0
  75. package/dist/components/lottery-draw-results.js.map +1 -0
  76. package/dist/components/lottery-draw-results2.js +95 -101
  77. package/dist/components/lottery-draw-results2.js.map +1 -0
  78. package/dist/components/lottery-game-details.js +2 -0
  79. package/dist/components/lottery-game-details.js.map +1 -0
  80. package/dist/components/lottery-game-details2.js +2 -0
  81. package/dist/components/lottery-game-details2.js.map +1 -0
  82. package/dist/components/lottery-game-page.js +36 -29
  83. package/dist/components/lottery-game-page.js.map +1 -0
  84. package/dist/components/lottery-grid.js +2 -0
  85. package/dist/components/lottery-grid.js.map +1 -0
  86. package/dist/components/lottery-grid2.js +13 -2
  87. package/dist/components/lottery-grid2.js.map +1 -0
  88. package/dist/components/lottery-ticket-controller.js +2 -0
  89. package/dist/components/lottery-ticket-controller.js.map +1 -0
  90. package/dist/components/lottery-ticket-controller2.js +30 -16
  91. package/dist/components/lottery-ticket-controller2.js.map +1 -0
  92. package/dist/components/lottery-ticket.js +2 -0
  93. package/dist/components/lottery-ticket.js.map +1 -0
  94. package/dist/components/lottery-ticket2.js +29 -7
  95. package/dist/components/lottery-ticket2.js.map +1 -0
  96. package/dist/esm/helper-accordion.entry.js +10 -2
  97. package/dist/esm/helper-accordion.entry.js.map +1 -0
  98. package/dist/esm/helper-filters_2.entry.js +1716 -1002
  99. package/dist/esm/helper-filters_2.entry.js.map +1 -0
  100. package/dist/esm/helper-modal.entry.js +2 -0
  101. package/dist/esm/helper-modal.entry.js.map +1 -0
  102. package/dist/esm/helper-pagination.entry.js +14 -0
  103. package/dist/esm/helper-pagination.entry.js.map +1 -0
  104. package/dist/esm/helper-tab.entry.js +2 -0
  105. package/dist/esm/helper-tab.entry.js.map +1 -0
  106. package/dist/esm/helper-tabs.entry.js +2 -0
  107. package/dist/esm/helper-tabs.entry.js.map +1 -0
  108. package/dist/esm/index-d1baacd4.js +2 -0
  109. package/dist/esm/index-d1baacd4.js.map +1 -0
  110. package/dist/esm/index.js +2 -0
  111. package/dist/esm/index.js.map +1 -0
  112. package/dist/esm/loader.js +3 -1
  113. package/dist/esm/loader.js.map +1 -0
  114. package/dist/esm/lottery-bullet_2.entry.js +13 -2
  115. package/dist/esm/lottery-bullet_2.entry.js.map +1 -0
  116. package/dist/esm/lottery-draw-results-history.entry.js +45 -16
  117. package/dist/esm/lottery-draw-results-history.entry.js.map +1 -0
  118. package/dist/esm/lottery-game-details.entry.js +2 -0
  119. package/dist/esm/lottery-game-details.entry.js.map +1 -0
  120. package/dist/esm/lottery-game-page.entry.js +35 -29
  121. package/dist/esm/lottery-game-page.entry.js.map +1 -0
  122. package/dist/esm/lottery-game-page.js +3 -1
  123. package/dist/esm/lottery-game-page.js.map +1 -0
  124. package/dist/esm/lottery-ticket-controller.entry.js +15 -2
  125. package/dist/esm/lottery-ticket-controller.entry.js.map +1 -0
  126. package/dist/esm/lottery-ticket.entry.js +29 -7
  127. package/dist/esm/lottery-ticket.entry.js.map +1 -0
  128. package/dist/lottery-game-page/index.esm.js +2 -0
  129. package/dist/lottery-game-page/index.esm.js.map +1 -0
  130. package/dist/lottery-game-page/lottery-game-page.esm.js +2 -1
  131. package/dist/lottery-game-page/lottery-game-page.esm.js.map +1 -0
  132. package/dist/lottery-game-page/p-042065c6.entry.js +2 -0
  133. package/dist/lottery-game-page/p-042065c6.entry.js.map +1 -0
  134. package/dist/lottery-game-page/p-15309f9a.entry.js +2 -0
  135. package/dist/lottery-game-page/p-15309f9a.entry.js.map +1 -0
  136. package/dist/lottery-game-page/p-167c9dbe.entry.js +2 -0
  137. package/dist/lottery-game-page/p-167c9dbe.entry.js.map +1 -0
  138. package/dist/lottery-game-page/p-2e78ed7b.entry.js +2 -0
  139. package/dist/lottery-game-page/p-2e78ed7b.entry.js.map +1 -0
  140. package/dist/lottery-game-page/p-5b49ab69.entry.js +2 -0
  141. package/dist/lottery-game-page/p-5b49ab69.entry.js.map +1 -0
  142. package/dist/lottery-game-page/p-606c0b0f.entry.js +2 -0
  143. package/dist/lottery-game-page/p-606c0b0f.entry.js.map +1 -0
  144. package/dist/lottery-game-page/p-662d9dac.entry.js +2 -0
  145. package/dist/lottery-game-page/p-662d9dac.entry.js.map +1 -0
  146. package/dist/lottery-game-page/p-66729e9c.entry.js +2 -0
  147. package/dist/lottery-game-page/p-66729e9c.entry.js.map +1 -0
  148. package/dist/lottery-game-page/p-76c280ec.entry.js +2 -0
  149. package/dist/lottery-game-page/p-76c280ec.entry.js.map +1 -0
  150. package/dist/lottery-game-page/p-a9ef5b8c.entry.js +2 -0
  151. package/dist/lottery-game-page/p-a9ef5b8c.entry.js.map +1 -0
  152. package/dist/lottery-game-page/p-aa68559a.entry.js +2 -0
  153. package/dist/lottery-game-page/p-aa68559a.entry.js.map +1 -0
  154. package/dist/lottery-game-page/p-d9e7b5da.entry.js +2899 -0
  155. package/dist/lottery-game-page/p-d9e7b5da.entry.js.map +1 -0
  156. package/dist/lottery-game-page/p-e765c7d9.js +2 -1
  157. package/dist/lottery-game-page/p-e765c7d9.js.map +1 -0
  158. package/dist/stencil.config.js +16 -11
  159. package/dist/stencil.config.js.map +1 -0
  160. package/dist/types/Users/adrian.pripon/Documents/Work/stencil/widgets-stencil/packages/lottery-game-page/.stencil/packages/lottery-game-page/stencil.config.d.ts +2 -0
  161. package/dist/types/components/lottery-game-page/lottery-game-page.d.ts +10 -1
  162. package/dist/types/components.d.ts +12 -2
  163. package/package.json +1 -1
  164. package/dist/lottery-game-page/assets/chrono_desktop.png +0 -0
  165. package/dist/lottery-game-page/assets/chrono_lottery_mobile.png +0 -0
  166. package/dist/lottery-game-page/p-023325a2.entry.js +0 -1
  167. package/dist/lottery-game-page/p-04fbc8fd.entry.js +0 -1
  168. package/dist/lottery-game-page/p-256b151c.entry.js +0 -1
  169. package/dist/lottery-game-page/p-381b5507.entry.js +0 -1
  170. package/dist/lottery-game-page/p-3f8b6ad9.entry.js +0 -1
  171. package/dist/lottery-game-page/p-4274053c.entry.js +0 -1
  172. package/dist/lottery-game-page/p-4f81cd37.entry.js +0 -1
  173. package/dist/lottery-game-page/p-5c389034.entry.js +0 -1
  174. package/dist/lottery-game-page/p-ca8430a0.entry.js +0 -2849
  175. package/dist/lottery-game-page/p-d6f76e8d.entry.js +0 -1
  176. package/dist/lottery-game-page/p-ea251208.entry.js +0 -1
  177. package/dist/lottery-game-page/p-f6fcc22c.entry.js +0 -1
  178. package/dist/types/Users/user/workspace/everymatrix/widgets-stencil/packages/lottery-game-page/.stencil/packages/lottery-game-page/stencil.config.d.ts +0 -2
  179. /package/dist/{collection/components/lottery-game-page/assets → assets}/chrono_desktop.png +0 -0
  180. /package/dist/{collection/components/lottery-game-page/assets → assets}/chrono_lottery_mobile.png +0 -0
@@ -31,6 +31,32 @@ const TRANSLATIONS$1 = {
31
31
  filterModalButton: 'Cauta',
32
32
  filterOrDate: 'sau cauta dupa data'
33
33
  },
34
+ fr: {
35
+ filterOpen: 'Filter',
36
+ filterClear: 'Clear',
37
+ filterModalTicketTitle: 'Ticket Results',
38
+ filterModalDrawTitle: 'Draws Results History',
39
+ filterTicketPlaceholder: 'Search for a ticket ID',
40
+ filterDrawPlaceholder: 'Search for a draw ID',
41
+ filterDateRangePlaceholder: 'Date Range',
42
+ filterModalButton: 'Search',
43
+ filterFromCalendar: 'From',
44
+ filterToCalendar: 'To',
45
+ filterOrDate: 'or search by date'
46
+ },
47
+ ar: {
48
+ filterOpen: 'Filter',
49
+ filterClear: 'Clear',
50
+ filterModalTicketTitle: 'Ticket Results',
51
+ filterModalDrawTitle: 'Draws Results History',
52
+ filterTicketPlaceholder: 'Search for a ticket ID',
53
+ filterDrawPlaceholder: 'Search for a draw ID',
54
+ filterDateRangePlaceholder: 'Date Range',
55
+ filterModalButton: 'Search',
56
+ filterFromCalendar: 'From',
57
+ filterToCalendar: 'To',
58
+ filterOrDate: 'or search by date'
59
+ }
34
60
  };
35
61
  const translate$2 = (key, customLang) => {
36
62
  const lang = customLang;
@@ -42,9 +68,16 @@ const translate$2 = (key, customLang) => {
42
68
  * Copyright (c) 2017 - 2022 Vaadin Ltd.
43
69
  * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
44
70
  */
71
+
72
+ /**
73
+ * Dummy custom element used for collecting
74
+ * development time usage statistics.
75
+ *
76
+ * @private
77
+ */
45
78
  class Lumo extends HTMLElement {
46
79
  static get version() {
47
- return '23.1.5';
80
+ return '23.3.14';
48
81
  }
49
82
  }
50
83
 
@@ -61,20 +94,20 @@ const t$1=window,e$2=t$1.ShadowRoot&&(void 0===t$1.ShadyCSS||t$1.ShadyCSS.native
61
94
  * @license
62
95
  * Copyright 2017 Google LLC
63
96
  * SPDX-License-Identifier: BSD-3-Clause
64
- */var s$2;const e$1=window,r$1=e$1.trustedTypes,h$1=r$1?r$1.emptyScript:"",o$2=e$1.reactiveElementPolyfillSupport,n$2={toAttribute(t,i){switch(i){case Boolean:t=t?h$1:null;break;case Object:case Array:t=null==t?t:JSON.stringify(t);}return t},fromAttribute(t,i){let s=t;switch(i){case Boolean:s=null!==t;break;case Number:s=null===t?null:Number(t);break;case Object:case Array:try{s=JSON.parse(t);}catch(t){s=null;}}return s}},a$1=(t,i)=>i!==t&&(i==i||t==t),l$2={attribute:!0,type:String,converter:n$2,reflect:!1,hasChanged:a$1};class d$1 extends HTMLElement{constructor(){super(),this._$Ei=new Map,this.isUpdatePending=!1,this.hasUpdated=!1,this._$El=null,this.u();}static addInitializer(t){var i;null!==(i=this.h)&&void 0!==i||(this.h=[]),this.h.push(t);}static get observedAttributes(){this.finalize();const t=[];return this.elementProperties.forEach(((i,s)=>{const e=this._$Ep(s,i);void 0!==e&&(this._$Ev.set(e,s),t.push(e));})),t}static createProperty(t,i=l$2){if(i.state&&(i.attribute=!1),this.finalize(),this.elementProperties.set(t,i),!i.noAccessor&&!this.prototype.hasOwnProperty(t)){const s="symbol"==typeof t?Symbol():"__"+t,e=this.getPropertyDescriptor(t,s,i);void 0!==e&&Object.defineProperty(this.prototype,t,e);}}static getPropertyDescriptor(t,i,s){return {get(){return this[i]},set(e){const r=this[t];this[i]=e,this.requestUpdate(t,r,s);},configurable:!0,enumerable:!0}}static getPropertyOptions(t){return this.elementProperties.get(t)||l$2}static finalize(){if(this.hasOwnProperty("finalized"))return !1;this.finalized=!0;const t=Object.getPrototypeOf(this);if(t.finalize(),this.elementProperties=new Map(t.elementProperties),this._$Ev=new Map,this.hasOwnProperty("properties")){const t=this.properties,i=[...Object.getOwnPropertyNames(t),...Object.getOwnPropertySymbols(t)];for(const s of i)this.createProperty(s,t[s]);}return this.elementStyles=this.finalizeStyles(this.styles),!0}static finalizeStyles(i){const s=[];if(Array.isArray(i)){const e=new Set(i.flat(1/0).reverse());for(const i of e)s.unshift(c$1(i));}else void 0!==i&&s.push(c$1(i));return s}static _$Ep(t,i){const s=i.attribute;return !1===s?void 0:"string"==typeof s?s:"string"==typeof t?t.toLowerCase():void 0}u(){var t;this._$E_=new Promise((t=>this.enableUpdating=t)),this._$AL=new Map,this._$Eg(),this.requestUpdate(),null===(t=this.constructor.h)||void 0===t||t.forEach((t=>t(this)));}addController(t){var i,s;(null!==(i=this._$ES)&&void 0!==i?i:this._$ES=[]).push(t),void 0!==this.renderRoot&&this.isConnected&&(null===(s=t.hostConnected)||void 0===s||s.call(t));}removeController(t){var i;null===(i=this._$ES)||void 0===i||i.splice(this._$ES.indexOf(t)>>>0,1);}_$Eg(){this.constructor.elementProperties.forEach(((t,i)=>{this.hasOwnProperty(i)&&(this._$Ei.set(i,this[i]),delete this[i]);}));}createRenderRoot(){var t;const s=null!==(t=this.shadowRoot)&&void 0!==t?t:this.attachShadow(this.constructor.shadowRootOptions);return S$1(s,this.constructor.elementStyles),s}connectedCallback(){var t;void 0===this.renderRoot&&(this.renderRoot=this.createRenderRoot()),this.enableUpdating(!0),null===(t=this._$ES)||void 0===t||t.forEach((t=>{var i;return null===(i=t.hostConnected)||void 0===i?void 0:i.call(t)}));}enableUpdating(t){}disconnectedCallback(){var t;null===(t=this._$ES)||void 0===t||t.forEach((t=>{var i;return null===(i=t.hostDisconnected)||void 0===i?void 0:i.call(t)}));}attributeChangedCallback(t,i,s){this._$AK(t,s);}_$EO(t,i,s=l$2){var e;const r=this.constructor._$Ep(t,s);if(void 0!==r&&!0===s.reflect){const h=(void 0!==(null===(e=s.converter)||void 0===e?void 0:e.toAttribute)?s.converter:n$2).toAttribute(i,s.type);this._$El=t,null==h?this.removeAttribute(r):this.setAttribute(r,h),this._$El=null;}}_$AK(t,i){var s;const e=this.constructor,r=e._$Ev.get(t);if(void 0!==r&&this._$El!==r){const t=e.getPropertyOptions(r),h="function"==typeof t.converter?{fromAttribute:t.converter}:void 0!==(null===(s=t.converter)||void 0===s?void 0:s.fromAttribute)?t.converter:n$2;this._$El=r,this[r]=h.fromAttribute(i,t.type),this._$El=null;}}requestUpdate(t,i,s){let e=!0;void 0!==t&&(((s=s||this.constructor.getPropertyOptions(t)).hasChanged||a$1)(this[t],i)?(this._$AL.has(t)||this._$AL.set(t,i),!0===s.reflect&&this._$El!==t&&(void 0===this._$EC&&(this._$EC=new Map),this._$EC.set(t,s))):e=!1),!this.isUpdatePending&&e&&(this._$E_=this._$Ej());}async _$Ej(){this.isUpdatePending=!0;try{await this._$E_;}catch(t){Promise.reject(t);}const t=this.scheduleUpdate();return null!=t&&await t,!this.isUpdatePending}scheduleUpdate(){return this.performUpdate()}performUpdate(){var t;if(!this.isUpdatePending)return;this._$Ei&&(this._$Ei.forEach(((t,i)=>this[i]=t)),this._$Ei=void 0);let i=!1;const s=this._$AL;try{i=this.shouldUpdate(s),i?(this.willUpdate(s),null===(t=this._$ES)||void 0===t||t.forEach((t=>{var i;return null===(i=t.hostUpdate)||void 0===i?void 0:i.call(t)})),this.update(s)):this._$Ek();}catch(t){throw i=!1,this._$Ek(),t}i&&this._$AE(s);}willUpdate(t){}_$AE(t){var i;null===(i=this._$ES)||void 0===i||i.forEach((t=>{var i;return null===(i=t.hostUpdated)||void 0===i?void 0:i.call(t)})),this.hasUpdated||(this.hasUpdated=!0,this.firstUpdated(t)),this.updated(t);}_$Ek(){this._$AL=new Map,this.isUpdatePending=!1;}get updateComplete(){return this.getUpdateComplete()}getUpdateComplete(){return this._$E_}shouldUpdate(t){return !0}update(t){void 0!==this._$EC&&(this._$EC.forEach(((t,i)=>this._$EO(i,this[i],t))),this._$EC=void 0),this._$Ek();}updated(t){}firstUpdated(t){}}d$1.finalized=!0,d$1.elementProperties=new Map,d$1.elementStyles=[],d$1.shadowRootOptions={mode:"open"},null==o$2||o$2({ReactiveElement:d$1}),(null!==(s$2=e$1.reactiveElementVersions)&&void 0!==s$2?s$2:e$1.reactiveElementVersions=[]).push("1.4.1");
97
+ */var s$2;const e$1=window,r$1=e$1.trustedTypes,h$1=r$1?r$1.emptyScript:"",o$2=e$1.reactiveElementPolyfillSupport,n$2={toAttribute(t,i){switch(i){case Boolean:t=t?h$1:null;break;case Object:case Array:t=null==t?t:JSON.stringify(t);}return t},fromAttribute(t,i){let s=t;switch(i){case Boolean:s=null!==t;break;case Number:s=null===t?null:Number(t);break;case Object:case Array:try{s=JSON.parse(t);}catch(t){s=null;}}return s}},a$1=(t,i)=>i!==t&&(i==i||t==t),l$2={attribute:!0,type:String,converter:n$2,reflect:!1,hasChanged:a$1};class d$1 extends HTMLElement{constructor(){super(),this._$Ei=new Map,this.isUpdatePending=!1,this.hasUpdated=!1,this._$El=null,this.u();}static addInitializer(t){var i;this.finalize(),(null!==(i=this.h)&&void 0!==i?i:this.h=[]).push(t);}static get observedAttributes(){this.finalize();const t=[];return this.elementProperties.forEach(((i,s)=>{const e=this._$Ep(s,i);void 0!==e&&(this._$Ev.set(e,s),t.push(e));})),t}static createProperty(t,i=l$2){if(i.state&&(i.attribute=!1),this.finalize(),this.elementProperties.set(t,i),!i.noAccessor&&!this.prototype.hasOwnProperty(t)){const s="symbol"==typeof t?Symbol():"__"+t,e=this.getPropertyDescriptor(t,s,i);void 0!==e&&Object.defineProperty(this.prototype,t,e);}}static getPropertyDescriptor(t,i,s){return {get(){return this[i]},set(e){const r=this[t];this[i]=e,this.requestUpdate(t,r,s);},configurable:!0,enumerable:!0}}static getPropertyOptions(t){return this.elementProperties.get(t)||l$2}static finalize(){if(this.hasOwnProperty("finalized"))return !1;this.finalized=!0;const t=Object.getPrototypeOf(this);if(t.finalize(),void 0!==t.h&&(this.h=[...t.h]),this.elementProperties=new Map(t.elementProperties),this._$Ev=new Map,this.hasOwnProperty("properties")){const t=this.properties,i=[...Object.getOwnPropertyNames(t),...Object.getOwnPropertySymbols(t)];for(const s of i)this.createProperty(s,t[s]);}return this.elementStyles=this.finalizeStyles(this.styles),!0}static finalizeStyles(i){const s=[];if(Array.isArray(i)){const e=new Set(i.flat(1/0).reverse());for(const i of e)s.unshift(c$1(i));}else void 0!==i&&s.push(c$1(i));return s}static _$Ep(t,i){const s=i.attribute;return !1===s?void 0:"string"==typeof s?s:"string"==typeof t?t.toLowerCase():void 0}u(){var t;this._$E_=new Promise((t=>this.enableUpdating=t)),this._$AL=new Map,this._$Eg(),this.requestUpdate(),null===(t=this.constructor.h)||void 0===t||t.forEach((t=>t(this)));}addController(t){var i,s;(null!==(i=this._$ES)&&void 0!==i?i:this._$ES=[]).push(t),void 0!==this.renderRoot&&this.isConnected&&(null===(s=t.hostConnected)||void 0===s||s.call(t));}removeController(t){var i;null===(i=this._$ES)||void 0===i||i.splice(this._$ES.indexOf(t)>>>0,1);}_$Eg(){this.constructor.elementProperties.forEach(((t,i)=>{this.hasOwnProperty(i)&&(this._$Ei.set(i,this[i]),delete this[i]);}));}createRenderRoot(){var t;const s=null!==(t=this.shadowRoot)&&void 0!==t?t:this.attachShadow(this.constructor.shadowRootOptions);return S$1(s,this.constructor.elementStyles),s}connectedCallback(){var t;void 0===this.renderRoot&&(this.renderRoot=this.createRenderRoot()),this.enableUpdating(!0),null===(t=this._$ES)||void 0===t||t.forEach((t=>{var i;return null===(i=t.hostConnected)||void 0===i?void 0:i.call(t)}));}enableUpdating(t){}disconnectedCallback(){var t;null===(t=this._$ES)||void 0===t||t.forEach((t=>{var i;return null===(i=t.hostDisconnected)||void 0===i?void 0:i.call(t)}));}attributeChangedCallback(t,i,s){this._$AK(t,s);}_$EO(t,i,s=l$2){var e;const r=this.constructor._$Ep(t,s);if(void 0!==r&&!0===s.reflect){const h=(void 0!==(null===(e=s.converter)||void 0===e?void 0:e.toAttribute)?s.converter:n$2).toAttribute(i,s.type);this._$El=t,null==h?this.removeAttribute(r):this.setAttribute(r,h),this._$El=null;}}_$AK(t,i){var s;const e=this.constructor,r=e._$Ev.get(t);if(void 0!==r&&this._$El!==r){const t=e.getPropertyOptions(r),h="function"==typeof t.converter?{fromAttribute:t.converter}:void 0!==(null===(s=t.converter)||void 0===s?void 0:s.fromAttribute)?t.converter:n$2;this._$El=r,this[r]=h.fromAttribute(i,t.type),this._$El=null;}}requestUpdate(t,i,s){let e=!0;void 0!==t&&(((s=s||this.constructor.getPropertyOptions(t)).hasChanged||a$1)(this[t],i)?(this._$AL.has(t)||this._$AL.set(t,i),!0===s.reflect&&this._$El!==t&&(void 0===this._$EC&&(this._$EC=new Map),this._$EC.set(t,s))):e=!1),!this.isUpdatePending&&e&&(this._$E_=this._$Ej());}async _$Ej(){this.isUpdatePending=!0;try{await this._$E_;}catch(t){Promise.reject(t);}const t=this.scheduleUpdate();return null!=t&&await t,!this.isUpdatePending}scheduleUpdate(){return this.performUpdate()}performUpdate(){var t;if(!this.isUpdatePending)return;this._$Ei&&(this._$Ei.forEach(((t,i)=>this[i]=t)),this._$Ei=void 0);let i=!1;const s=this._$AL;try{i=this.shouldUpdate(s),i?(this.willUpdate(s),null===(t=this._$ES)||void 0===t||t.forEach((t=>{var i;return null===(i=t.hostUpdate)||void 0===i?void 0:i.call(t)})),this.update(s)):this._$Ek();}catch(t){throw i=!1,this._$Ek(),t}i&&this._$AE(s);}willUpdate(t){}_$AE(t){var i;null===(i=this._$ES)||void 0===i||i.forEach((t=>{var i;return null===(i=t.hostUpdated)||void 0===i?void 0:i.call(t)})),this.hasUpdated||(this.hasUpdated=!0,this.firstUpdated(t)),this.updated(t);}_$Ek(){this._$AL=new Map,this.isUpdatePending=!1;}get updateComplete(){return this.getUpdateComplete()}getUpdateComplete(){return this._$E_}shouldUpdate(t){return !0}update(t){void 0!==this._$EC&&(this._$EC.forEach(((t,i)=>this._$EO(i,this[i],t))),this._$EC=void 0),this._$Ek();}updated(t){}firstUpdated(t){}}d$1.finalized=!0,d$1.elementProperties=new Map,d$1.elementStyles=[],d$1.shadowRootOptions={mode:"open"},null==o$2||o$2({ReactiveElement:d$1}),(null!==(s$2=e$1.reactiveElementVersions)&&void 0!==s$2?s$2:e$1.reactiveElementVersions=[]).push("1.6.1");
65
98
 
66
99
  /**
67
100
  * @license
68
101
  * Copyright 2017 Google LLC
69
102
  * SPDX-License-Identifier: BSD-3-Clause
70
103
  */
71
- var t;const i=window,s$1=i.trustedTypes,e=s$1?s$1.createPolicy("lit-html",{createHTML:t=>t}):void 0,o$1=`lit$${(Math.random()+"").slice(9)}$`,n$1="?"+o$1,l$1=`<${n$1}>`,h=document,r=(t="")=>h.createComment(t),d=t=>null===t||"object"!=typeof t&&"function"!=typeof t,u=Array.isArray,c=t=>u(t)||"function"==typeof(null==t?void 0:t[Symbol.iterator]),v=/<(?:(!--|\/[^a-zA-Z])|(\/?[a-zA-Z][^>\s]*)|(\/?$))/g,a=/-->/g,f=/>/g,_=RegExp(">|[ \t\n\f\r](?:([^\\s\"'>=/]+)([ \t\n\f\r]*=[ \t\n\f\r]*(?:[^ \t\n\f\r\"'`<>=]|(\"|')|))|$)","g"),m=/'/g,p=/"/g,$=/^(?:script|style|textarea|title)$/i,x=Symbol.for("lit-noChange"),b=Symbol.for("lit-nothing"),T=new WeakMap,A=(t,i,s)=>{var e,o;const n=null!==(e=null==s?void 0:s.renderBefore)&&void 0!==e?e:i;let l=n._$litPart$;if(void 0===l){const t=null!==(o=null==s?void 0:s.renderBefore)&&void 0!==o?o:null;n._$litPart$=l=new S(i.insertBefore(r(),t),t,void 0,null!=s?s:{});}return l._$AI(t),l},E=h.createTreeWalker(h,129,null,!1),C=(t,i)=>{const s=t.length-1,n=[];let h,r=2===i?"<svg>":"",d=v;for(let i=0;i<s;i++){const s=t[i];let e,u,c=-1,g=0;for(;g<s.length&&(d.lastIndex=g,u=d.exec(s),null!==u);)g=d.lastIndex,d===v?"!--"===u[1]?d=a:void 0!==u[1]?d=f:void 0!==u[2]?($.test(u[2])&&(h=RegExp("</"+u[2],"g")),d=_):void 0!==u[3]&&(d=_):d===_?">"===u[0]?(d=null!=h?h:v,c=-1):void 0===u[1]?c=-2:(c=d.lastIndex-u[2].length,e=u[1],d=void 0===u[3]?_:'"'===u[3]?p:m):d===p||d===m?d=_:d===a||d===f?d=v:(d=_,h=void 0);const y=d===_&&t[i+1].startsWith("/>")?" ":"";r+=d===v?s+l$1:c>=0?(n.push(e),s.slice(0,c)+"$lit$"+s.slice(c)+o$1+y):s+o$1+(-2===c?(n.push(void 0),i):y);}const u=r+(t[s]||"<?>")+(2===i?"</svg>":"");if(!Array.isArray(t)||!t.hasOwnProperty("raw"))throw Error("invalid template strings array");return [void 0!==e?e.createHTML(u):u,n]};class P{constructor({strings:t,_$litType$:i},e){let l;this.parts=[];let h=0,d=0;const u=t.length-1,c=this.parts,[v,a]=C(t,i);if(this.el=P.createElement(v,e),E.currentNode=this.el.content,2===i){const t=this.el.content,i=t.firstChild;i.remove(),t.append(...i.childNodes);}for(;null!==(l=E.nextNode())&&c.length<u;){if(1===l.nodeType){if(l.hasAttributes()){const t=[];for(const i of l.getAttributeNames())if(i.endsWith("$lit$")||i.startsWith(o$1)){const s=a[d++];if(t.push(i),void 0!==s){const t=l.getAttribute(s.toLowerCase()+"$lit$").split(o$1),i=/([.?@])?(.*)/.exec(s);c.push({type:1,index:h,name:i[2],strings:t,ctor:"."===i[1]?R:"?"===i[1]?H:"@"===i[1]?I:M});}else c.push({type:6,index:h});}for(const i of t)l.removeAttribute(i);}if($.test(l.tagName)){const t=l.textContent.split(o$1),i=t.length-1;if(i>0){l.textContent=s$1?s$1.emptyScript:"";for(let s=0;s<i;s++)l.append(t[s],r()),E.nextNode(),c.push({type:2,index:++h});l.append(t[i],r());}}}else if(8===l.nodeType)if(l.data===n$1)c.push({type:2,index:h});else {let t=-1;for(;-1!==(t=l.data.indexOf(o$1,t+1));)c.push({type:7,index:h}),t+=o$1.length-1;}h++;}}static createElement(t,i){const s=h.createElement("template");return s.innerHTML=t,s}}function V(t,i,s=t,e){var o,n,l,h;if(i===x)return i;let r=void 0!==e?null===(o=s._$Cl)||void 0===o?void 0:o[e]:s._$Cu;const u=d(i)?void 0:i._$litDirective$;return (null==r?void 0:r.constructor)!==u&&(null===(n=null==r?void 0:r._$AO)||void 0===n||n.call(r,!1),void 0===u?r=void 0:(r=new u(t),r._$AT(t,s,e)),void 0!==e?(null!==(l=(h=s)._$Cl)&&void 0!==l?l:h._$Cl=[])[e]=r:s._$Cu=r),void 0!==r&&(i=V(t,r._$AS(t,i.values),r,e)),i}class N{constructor(t,i){this.v=[],this._$AN=void 0,this._$AD=t,this._$AM=i;}get parentNode(){return this._$AM.parentNode}get _$AU(){return this._$AM._$AU}p(t){var i;const{el:{content:s},parts:e}=this._$AD,o=(null!==(i=null==t?void 0:t.creationScope)&&void 0!==i?i:h).importNode(s,!0);E.currentNode=o;let n=E.nextNode(),l=0,r=0,d=e[0];for(;void 0!==d;){if(l===d.index){let i;2===d.type?i=new S(n,n.nextSibling,this,t):1===d.type?i=new d.ctor(n,d.name,d.strings,this,t):6===d.type&&(i=new L(n,this,t)),this.v.push(i),d=e[++r];}l!==(null==d?void 0:d.index)&&(n=E.nextNode(),l++);}return o}m(t){let i=0;for(const s of this.v)void 0!==s&&(void 0!==s.strings?(s._$AI(t,s,i),i+=s.strings.length-2):s._$AI(t[i])),i++;}}class S{constructor(t,i,s,e){var o;this.type=2,this._$AH=b,this._$AN=void 0,this._$AA=t,this._$AB=i,this._$AM=s,this.options=e,this._$C_=null===(o=null==e?void 0:e.isConnected)||void 0===o||o;}get _$AU(){var t,i;return null!==(i=null===(t=this._$AM)||void 0===t?void 0:t._$AU)&&void 0!==i?i:this._$C_}get parentNode(){let t=this._$AA.parentNode;const i=this._$AM;return void 0!==i&&11===t.nodeType&&(t=i.parentNode),t}get startNode(){return this._$AA}get endNode(){return this._$AB}_$AI(t,i=this){t=V(this,t,i),d(t)?t===b||null==t||""===t?(this._$AH!==b&&this._$AR(),this._$AH=b):t!==this._$AH&&t!==x&&this.$(t):void 0!==t._$litType$?this.T(t):void 0!==t.nodeType?this.k(t):c(t)?this.O(t):this.$(t);}S(t,i=this._$AB){return this._$AA.parentNode.insertBefore(t,i)}k(t){this._$AH!==t&&(this._$AR(),this._$AH=this.S(t));}$(t){this._$AH!==b&&d(this._$AH)?this._$AA.nextSibling.data=t:this.k(h.createTextNode(t)),this._$AH=t;}T(t){var i;const{values:s,_$litType$:e}=t,o="number"==typeof e?this._$AC(t):(void 0===e.el&&(e.el=P.createElement(e.h,this.options)),e);if((null===(i=this._$AH)||void 0===i?void 0:i._$AD)===o)this._$AH.m(s);else {const t=new N(o,this),i=t.p(this.options);t.m(s),this.k(i),this._$AH=t;}}_$AC(t){let i=T.get(t.strings);return void 0===i&&T.set(t.strings,i=new P(t)),i}O(t){u(this._$AH)||(this._$AH=[],this._$AR());const i=this._$AH;let s,e=0;for(const o of t)e===i.length?i.push(s=new S(this.S(r()),this.S(r()),this,this.options)):s=i[e],s._$AI(o),e++;e<i.length&&(this._$AR(s&&s._$AB.nextSibling,e),i.length=e);}_$AR(t=this._$AA.nextSibling,i){var s;for(null===(s=this._$AP)||void 0===s||s.call(this,!1,!0,i);t&&t!==this._$AB;){const i=t.nextSibling;t.remove(),t=i;}}setConnected(t){var i;void 0===this._$AM&&(this._$C_=t,null===(i=this._$AP)||void 0===i||i.call(this,t));}}class M{constructor(t,i,s,e,o){this.type=1,this._$AH=b,this._$AN=void 0,this.element=t,this.name=i,this._$AM=e,this.options=o,s.length>2||""!==s[0]||""!==s[1]?(this._$AH=Array(s.length-1).fill(new String),this.strings=s):this._$AH=b;}get tagName(){return this.element.tagName}get _$AU(){return this._$AM._$AU}_$AI(t,i=this,s,e){const o=this.strings;let n=!1;if(void 0===o)t=V(this,t,i,0),n=!d(t)||t!==this._$AH&&t!==x,n&&(this._$AH=t);else {const e=t;let l,h;for(t=o[0],l=0;l<o.length-1;l++)h=V(this,e[s+l],i,l),h===x&&(h=this._$AH[l]),n||(n=!d(h)||h!==this._$AH[l]),h===b?t=b:t!==b&&(t+=(null!=h?h:"")+o[l+1]),this._$AH[l]=h;}n&&!e&&this.P(t);}P(t){t===b?this.element.removeAttribute(this.name):this.element.setAttribute(this.name,null!=t?t:"");}}class R extends M{constructor(){super(...arguments),this.type=3;}P(t){this.element[this.name]=t===b?void 0:t;}}const k=s$1?s$1.emptyScript:"";class H extends M{constructor(){super(...arguments),this.type=4;}P(t){t&&t!==b?this.element.setAttribute(this.name,k):this.element.removeAttribute(this.name);}}class I extends M{constructor(t,i,s,e,o){super(t,i,s,e,o),this.type=5;}_$AI(t,i=this){var s;if((t=null!==(s=V(this,t,i,0))&&void 0!==s?s:b)===x)return;const e=this._$AH,o=t===b&&e!==b||t.capture!==e.capture||t.once!==e.once||t.passive!==e.passive,n=t!==b&&(e===b||o);o&&this.element.removeEventListener(this.name,this,e),n&&this.element.addEventListener(this.name,this,t),this._$AH=t;}handleEvent(t){var i,s;"function"==typeof this._$AH?this._$AH.call(null!==(s=null===(i=this.options)||void 0===i?void 0:i.host)&&void 0!==s?s:this.element,t):this._$AH.handleEvent(t);}}class L{constructor(t,i,s){this.element=t,this.type=6,this._$AN=void 0,this._$AM=i,this.options=s;}get _$AU(){return this._$AM._$AU}_$AI(t){V(this,t);}}const Z=i.litHtmlPolyfillSupport;null==Z||Z(P,S),(null!==(t=i.litHtmlVersions)&&void 0!==t?t:i.litHtmlVersions=[]).push("2.3.1");
104
+ var t;const i=window,s$1=i.trustedTypes,e=s$1?s$1.createPolicy("lit-html",{createHTML:t=>t}):void 0,o$1="$lit$",n$1=`lit$${(Math.random()+"").slice(9)}$`,l$1="?"+n$1,h=`<${l$1}>`,r=document,d=()=>r.createComment(""),u=t=>null===t||"object"!=typeof t&&"function"!=typeof t,c=Array.isArray,v=t=>c(t)||"function"==typeof(null==t?void 0:t[Symbol.iterator]),a="[ \t\n\f\r]",f=/<(?:(!--|\/[^a-zA-Z])|(\/?[a-zA-Z][^>\s]*)|(\/?$))/g,_=/-->/g,m=/>/g,p=RegExp(`>|${a}(?:([^\\s"'>=/]+)(${a}*=${a}*(?:[^ \t\n\f\r"'\`<>=]|("|')|))|$)`,"g"),g=/'/g,$=/"/g,y=/^(?:script|style|textarea|title)$/i,T=Symbol.for("lit-noChange"),A=Symbol.for("lit-nothing"),E=new WeakMap,C=r.createTreeWalker(r,129,null,!1),P=(t,i)=>{const s=t.length-1,l=[];let r,d=2===i?"<svg>":"",u=f;for(let i=0;i<s;i++){const s=t[i];let e,c,v=-1,a=0;for(;a<s.length&&(u.lastIndex=a,c=u.exec(s),null!==c);)a=u.lastIndex,u===f?"!--"===c[1]?u=_:void 0!==c[1]?u=m:void 0!==c[2]?(y.test(c[2])&&(r=RegExp("</"+c[2],"g")),u=p):void 0!==c[3]&&(u=p):u===p?">"===c[0]?(u=null!=r?r:f,v=-1):void 0===c[1]?v=-2:(v=u.lastIndex-c[2].length,e=c[1],u=void 0===c[3]?p:'"'===c[3]?$:g):u===$||u===g?u=p:u===_||u===m?u=f:(u=p,r=void 0);const w=u===p&&t[i+1].startsWith("/>")?" ":"";d+=u===f?s+h:v>=0?(l.push(e),s.slice(0,v)+o$1+s.slice(v)+n$1+w):s+n$1+(-2===v?(l.push(void 0),i):w);}const c=d+(t[s]||"<?>")+(2===i?"</svg>":"");if(!Array.isArray(t)||!t.hasOwnProperty("raw"))throw Error("invalid template strings array");return [void 0!==e?e.createHTML(c):c,l]};class V{constructor({strings:t,_$litType$:i},e){let h;this.parts=[];let r=0,u=0;const c=t.length-1,v=this.parts,[a,f]=P(t,i);if(this.el=V.createElement(a,e),C.currentNode=this.el.content,2===i){const t=this.el.content,i=t.firstChild;i.remove(),t.append(...i.childNodes);}for(;null!==(h=C.nextNode())&&v.length<c;){if(1===h.nodeType){if(h.hasAttributes()){const t=[];for(const i of h.getAttributeNames())if(i.endsWith(o$1)||i.startsWith(n$1)){const s=f[u++];if(t.push(i),void 0!==s){const t=h.getAttribute(s.toLowerCase()+o$1).split(n$1),i=/([.?@])?(.*)/.exec(s);v.push({type:1,index:r,name:i[2],strings:t,ctor:"."===i[1]?k:"?"===i[1]?I:"@"===i[1]?L:R});}else v.push({type:6,index:r});}for(const i of t)h.removeAttribute(i);}if(y.test(h.tagName)){const t=h.textContent.split(n$1),i=t.length-1;if(i>0){h.textContent=s$1?s$1.emptyScript:"";for(let s=0;s<i;s++)h.append(t[s],d()),C.nextNode(),v.push({type:2,index:++r});h.append(t[i],d());}}}else if(8===h.nodeType)if(h.data===l$1)v.push({type:2,index:r});else {let t=-1;for(;-1!==(t=h.data.indexOf(n$1,t+1));)v.push({type:7,index:r}),t+=n$1.length-1;}r++;}}static createElement(t,i){const s=r.createElement("template");return s.innerHTML=t,s}}function N(t,i,s=t,e){var o,n,l,h;if(i===T)return i;let r=void 0!==e?null===(o=s._$Co)||void 0===o?void 0:o[e]:s._$Cl;const d=u(i)?void 0:i._$litDirective$;return (null==r?void 0:r.constructor)!==d&&(null===(n=null==r?void 0:r._$AO)||void 0===n||n.call(r,!1),void 0===d?r=void 0:(r=new d(t),r._$AT(t,s,e)),void 0!==e?(null!==(l=(h=s)._$Co)&&void 0!==l?l:h._$Co=[])[e]=r:s._$Cl=r),void 0!==r&&(i=N(t,r._$AS(t,i.values),r,e)),i}class S{constructor(t,i){this._$AV=[],this._$AN=void 0,this._$AD=t,this._$AM=i;}get parentNode(){return this._$AM.parentNode}get _$AU(){return this._$AM._$AU}u(t){var i;const{el:{content:s},parts:e}=this._$AD,o=(null!==(i=null==t?void 0:t.creationScope)&&void 0!==i?i:r).importNode(s,!0);C.currentNode=o;let n=C.nextNode(),l=0,h=0,d=e[0];for(;void 0!==d;){if(l===d.index){let i;2===d.type?i=new M(n,n.nextSibling,this,t):1===d.type?i=new d.ctor(n,d.name,d.strings,this,t):6===d.type&&(i=new z(n,this,t)),this._$AV.push(i),d=e[++h];}l!==(null==d?void 0:d.index)&&(n=C.nextNode(),l++);}return C.currentNode=r,o}v(t){let i=0;for(const s of this._$AV)void 0!==s&&(void 0!==s.strings?(s._$AI(t,s,i),i+=s.strings.length-2):s._$AI(t[i])),i++;}}class M{constructor(t,i,s,e){var o;this.type=2,this._$AH=A,this._$AN=void 0,this._$AA=t,this._$AB=i,this._$AM=s,this.options=e,this._$Cp=null===(o=null==e?void 0:e.isConnected)||void 0===o||o;}get _$AU(){var t,i;return null!==(i=null===(t=this._$AM)||void 0===t?void 0:t._$AU)&&void 0!==i?i:this._$Cp}get parentNode(){let t=this._$AA.parentNode;const i=this._$AM;return void 0!==i&&11===(null==t?void 0:t.nodeType)&&(t=i.parentNode),t}get startNode(){return this._$AA}get endNode(){return this._$AB}_$AI(t,i=this){t=N(this,t,i),u(t)?t===A||null==t||""===t?(this._$AH!==A&&this._$AR(),this._$AH=A):t!==this._$AH&&t!==T&&this._(t):void 0!==t._$litType$?this.g(t):void 0!==t.nodeType?this.$(t):v(t)?this.T(t):this._(t);}k(t){return this._$AA.parentNode.insertBefore(t,this._$AB)}$(t){this._$AH!==t&&(this._$AR(),this._$AH=this.k(t));}_(t){this._$AH!==A&&u(this._$AH)?this._$AA.nextSibling.data=t:this.$(r.createTextNode(t)),this._$AH=t;}g(t){var i;const{values:s,_$litType$:e}=t,o="number"==typeof e?this._$AC(t):(void 0===e.el&&(e.el=V.createElement(e.h,this.options)),e);if((null===(i=this._$AH)||void 0===i?void 0:i._$AD)===o)this._$AH.v(s);else {const t=new S(o,this),i=t.u(this.options);t.v(s),this.$(i),this._$AH=t;}}_$AC(t){let i=E.get(t.strings);return void 0===i&&E.set(t.strings,i=new V(t)),i}T(t){c(this._$AH)||(this._$AH=[],this._$AR());const i=this._$AH;let s,e=0;for(const o of t)e===i.length?i.push(s=new M(this.k(d()),this.k(d()),this,this.options)):s=i[e],s._$AI(o),e++;e<i.length&&(this._$AR(s&&s._$AB.nextSibling,e),i.length=e);}_$AR(t=this._$AA.nextSibling,i){var s;for(null===(s=this._$AP)||void 0===s||s.call(this,!1,!0,i);t&&t!==this._$AB;){const i=t.nextSibling;t.remove(),t=i;}}setConnected(t){var i;void 0===this._$AM&&(this._$Cp=t,null===(i=this._$AP)||void 0===i||i.call(this,t));}}class R{constructor(t,i,s,e,o){this.type=1,this._$AH=A,this._$AN=void 0,this.element=t,this.name=i,this._$AM=e,this.options=o,s.length>2||""!==s[0]||""!==s[1]?(this._$AH=Array(s.length-1).fill(new String),this.strings=s):this._$AH=A;}get tagName(){return this.element.tagName}get _$AU(){return this._$AM._$AU}_$AI(t,i=this,s,e){const o=this.strings;let n=!1;if(void 0===o)t=N(this,t,i,0),n=!u(t)||t!==this._$AH&&t!==T,n&&(this._$AH=t);else {const e=t;let l,h;for(t=o[0],l=0;l<o.length-1;l++)h=N(this,e[s+l],i,l),h===T&&(h=this._$AH[l]),n||(n=!u(h)||h!==this._$AH[l]),h===A?t=A:t!==A&&(t+=(null!=h?h:"")+o[l+1]),this._$AH[l]=h;}n&&!e&&this.j(t);}j(t){t===A?this.element.removeAttribute(this.name):this.element.setAttribute(this.name,null!=t?t:"");}}class k extends R{constructor(){super(...arguments),this.type=3;}j(t){this.element[this.name]=t===A?void 0:t;}}const H=s$1?s$1.emptyScript:"";class I extends R{constructor(){super(...arguments),this.type=4;}j(t){t&&t!==A?this.element.setAttribute(this.name,H):this.element.removeAttribute(this.name);}}class L extends R{constructor(t,i,s,e,o){super(t,i,s,e,o),this.type=5;}_$AI(t,i=this){var s;if((t=null!==(s=N(this,t,i,0))&&void 0!==s?s:A)===T)return;const e=this._$AH,o=t===A&&e!==A||t.capture!==e.capture||t.once!==e.once||t.passive!==e.passive,n=t!==A&&(e===A||o);o&&this.element.removeEventListener(this.name,this,e),n&&this.element.addEventListener(this.name,this,t),this._$AH=t;}handleEvent(t){var i,s;"function"==typeof this._$AH?this._$AH.call(null!==(s=null===(i=this.options)||void 0===i?void 0:i.host)&&void 0!==s?s:this.element,t):this._$AH.handleEvent(t);}}class z{constructor(t,i,s){this.element=t,this.type=6,this._$AN=void 0,this._$AM=i,this.options=s;}get _$AU(){return this._$AM._$AU}_$AI(t){N(this,t);}}const j=i.litHtmlPolyfillSupport;null==j||j(V,M),(null!==(t=i.litHtmlVersions)&&void 0!==t?t:i.litHtmlVersions=[]).push("2.7.4");const B=(t,i,s)=>{var e,o;const n=null!==(e=null==s?void 0:s.renderBefore)&&void 0!==e?e:i;let l=n._$litPart$;if(void 0===l){const t=null!==(o=null==s?void 0:s.renderBefore)&&void 0!==o?o:null;n._$litPart$=l=new M(i.insertBefore(d(),t),t,void 0,null!=s?s:{});}return l._$AI(t),l};
72
105
 
73
106
  /**
74
107
  * @license
75
108
  * Copyright 2017 Google LLC
76
109
  * SPDX-License-Identifier: BSD-3-Clause
77
- */var l,o;class s extends d$1{constructor(){super(...arguments),this.renderOptions={host:this},this._$Do=void 0;}createRenderRoot(){var t,e;const i=super.createRenderRoot();return null!==(t=(e=this.renderOptions).renderBefore)&&void 0!==t||(e.renderBefore=i.firstChild),i}update(t){const i=this.render();this.hasUpdated||(this.renderOptions.isConnected=this.isConnected),super.update(t),this._$Do=A(i,this.renderRoot,this.renderOptions);}connectedCallback(){var t;super.connectedCallback(),null===(t=this._$Do)||void 0===t||t.setConnected(!0);}disconnectedCallback(){var t;super.disconnectedCallback(),null===(t=this._$Do)||void 0===t||t.setConnected(!1);}render(){return x}}s.finalized=!0,s._$litElement$=!0,null===(l=globalThis.litElementHydrateSupport)||void 0===l||l.call(globalThis,{LitElement:s});const n=globalThis.litElementPolyfillSupport;null==n||n({LitElement:s});(null!==(o=globalThis.litElementVersions)&&void 0!==o?o:globalThis.litElementVersions=[]).push("3.2.2");
110
+ */var l,o;class s extends d$1{constructor(){super(...arguments),this.renderOptions={host:this},this._$Do=void 0;}createRenderRoot(){var t,e;const i=super.createRenderRoot();return null!==(t=(e=this.renderOptions).renderBefore)&&void 0!==t||(e.renderBefore=i.firstChild),i}update(t){const i=this.render();this.hasUpdated||(this.renderOptions.isConnected=this.isConnected),super.update(t),this._$Do=B(i,this.renderRoot,this.renderOptions);}connectedCallback(){var t;super.connectedCallback(),null===(t=this._$Do)||void 0===t||t.setConnected(!0);}disconnectedCallback(){var t;super.disconnectedCallback(),null===(t=this._$Do)||void 0===t||t.setConnected(!1);}render(){return T}}s.finalized=!0,s._$litElement$=!0,null===(l=globalThis.litElementHydrateSupport)||void 0===l||l.call(globalThis,{LitElement:s});const n=globalThis.litElementPolyfillSupport;null==n||n({LitElement:s});(null!==(o=globalThis.litElementVersions)&&void 0!==o?o:globalThis.litElementVersions=[]).push("3.3.2");
78
111
 
79
112
  /**
80
113
  * @license
@@ -100,7 +133,7 @@ const ThemePropertyMixin = (superClass) =>
100
133
  * **NOTE:** Extending the mixin only provides the property for binding,
101
134
  * and does not make the propagation alone.
102
135
  *
103
- * See [Styling Components: Sub-components](https://vaadin.com/docs/latest/ds/customization/styling-components/#sub-components).
136
+ * See [Styling Components: Sub-components](https://vaadin.com/docs/latest/styling/custom-theme/styling-components/#sub-components).
104
137
  * page for more information.
105
138
  *
106
139
  * @deprecated The `theme` property is not supposed for public use and will be dropped in Vaadin 24.
@@ -125,7 +158,7 @@ const ThemePropertyMixin = (superClass) =>
125
158
  * **NOTE:** Extending the mixin only provides the property for binding,
126
159
  * and does not make the propagation alone.
127
160
  *
128
- * See [Styling Components: Sub-components](https://vaadin.com/docs/latest/ds/customization/styling-components/#sub-components).
161
+ * See [Styling Components: Sub-components](https://vaadin.com/docs/latest/styling/custom-theme/styling-components/#sub-components).
129
162
  * page for more information.
130
163
  *
131
164
  * @protected
@@ -230,9 +263,9 @@ function matchesThemeFor(themeFor, tagName) {
230
263
  */
231
264
  function getIncludePriority(moduleName = '') {
232
265
  let includePriority = 0;
233
- if (moduleName.indexOf('lumo-') === 0 || moduleName.indexOf('material-') === 0) {
266
+ if (moduleName.startsWith('lumo-') || moduleName.startsWith('material-')) {
234
267
  includePriority = 1;
235
- } else if (moduleName.indexOf('vaadin-') === 0) {
268
+ } else if (moduleName.startsWith('vaadin-')) {
236
269
  includePriority = 2;
237
270
  }
238
271
  return includePriority;
@@ -466,9 +499,9 @@ const colorBase = i$1`
466
499
  }
467
500
  `;
468
501
 
469
- const $tpl$5 = document.createElement('template');
470
- $tpl$5.innerHTML = `<style>${colorBase.toString().replace(':host', 'html')}</style>`;
471
- document.head.appendChild($tpl$5.content);
502
+ const $tpl$4 = document.createElement('template');
503
+ $tpl$4.innerHTML = `<style>${colorBase.toString().replace(':host', 'html')}</style>`;
504
+ document.head.appendChild($tpl$4.content);
472
505
 
473
506
  const color = i$1`
474
507
  [theme~='dark'] {
@@ -615,9 +648,9 @@ const sizing = i$1`
615
648
  }
616
649
  `;
617
650
 
618
- const $tpl$4 = document.createElement('template');
619
- $tpl$4.innerHTML = `<style>${sizing.toString().replace(':host', 'html')}</style>`;
620
- document.head.appendChild($tpl$4.content);
651
+ const $tpl$3 = document.createElement('template');
652
+ $tpl$3.innerHTML = `<style>${sizing.toString().replace(':host', 'html')}</style>`;
653
+ document.head.appendChild($tpl$3.content);
621
654
 
622
655
  /**
623
656
  * @license
@@ -645,9 +678,19 @@ const style = i$1`
645
678
  }
646
679
  `;
647
680
 
648
- const $tpl$3 = document.createElement('template');
649
- $tpl$3.innerHTML = `<style>${style.toString().replace(':host', 'html')}</style>`;
650
- document.head.appendChild($tpl$3.content);
681
+ /**
682
+ * Default values for component-specific custom properties.
683
+ */
684
+ i$1`
685
+ html {
686
+ --vaadin-checkbox-size: calc(var(--lumo-size-m) / 2);
687
+ --vaadin-radio-button-size: calc(var(--lumo-size-m) / 2);
688
+ }
689
+ `;
690
+
691
+ const $tpl$2 = document.createElement('template');
692
+ $tpl$2.innerHTML = `<style>${style.toString().replace(':host', 'html')}$</style>`;
693
+ document.head.appendChild($tpl$2.content);
651
694
 
652
695
  /**
653
696
  * @license
@@ -784,9 +827,9 @@ const typography = i$1`
784
827
 
785
828
  registerStyles('', typography, { moduleId: 'lumo-typography' });
786
829
 
787
- const $tpl$2 = document.createElement('template');
788
- $tpl$2.innerHTML = `<style>${font.toString().replace(':host', 'html')}</style>`;
789
- document.head.appendChild($tpl$2.content);
830
+ const $tpl$1 = document.createElement('template');
831
+ $tpl$1.innerHTML = `<style>${font.toString().replace(':host', 'html')}</style>`;
832
+ document.head.appendChild($tpl$1.content);
790
833
 
791
834
  registerStyles(
792
835
  'vaadin-input-container',
@@ -8078,6 +8121,7 @@ class DirHelper {
8078
8121
  * Array of Vaadin custom element classes that have been subscribed to the dir changes.
8079
8122
  */
8080
8123
  const directionSubscribers = [];
8124
+
8081
8125
  function directionUpdater() {
8082
8126
  const documentDir = getDocumentDir();
8083
8127
  directionSubscribers.forEach((element) => {
@@ -8143,7 +8187,7 @@ const DirMixin = (superClass) =>
8143
8187
  connectedCallback() {
8144
8188
  super.connectedCallback();
8145
8189
 
8146
- if (!this.hasAttribute('dir')) {
8190
+ if (!this.hasAttribute('dir') || this.__restoreSubscription) {
8147
8191
  this.__subscribe();
8148
8192
  alignDirs(this, getDocumentDir(), null);
8149
8193
  }
@@ -8169,15 +8213,15 @@ const DirMixin = (superClass) =>
8169
8213
  this.__subscribe();
8170
8214
  alignDirs(this, documentDir, newValue);
8171
8215
  } else if (newDiffValue) {
8172
- this.__subscribe(false);
8216
+ this.__unsubscribe();
8173
8217
  }
8174
8218
  }
8175
8219
 
8176
8220
  /** @protected */
8177
8221
  disconnectedCallback() {
8178
8222
  super.disconnectedCallback();
8179
- this.__subscribe(false);
8180
- this.removeAttribute('dir');
8223
+ this.__restoreSubscription = directionSubscribers.includes(this);
8224
+ this.__unsubscribe();
8181
8225
  }
8182
8226
 
8183
8227
  /** @protected */
@@ -8202,12 +8246,15 @@ const DirMixin = (superClass) =>
8202
8246
  }
8203
8247
 
8204
8248
  /** @private */
8205
- __subscribe(push = true) {
8206
- if (push) {
8207
- if (!directionSubscribers.includes(this)) {
8208
- directionSubscribers.push(this);
8209
- }
8210
- } else if (directionSubscribers.includes(this)) {
8249
+ __subscribe() {
8250
+ if (!directionSubscribers.includes(this)) {
8251
+ directionSubscribers.push(this);
8252
+ }
8253
+ }
8254
+
8255
+ /** @private */
8256
+ __unsubscribe() {
8257
+ if (directionSubscribers.includes(this)) {
8211
8258
  directionSubscribers.splice(directionSubscribers.indexOf(this), 1);
8212
8259
  }
8213
8260
  }
@@ -8285,7 +8332,6 @@ class InputContainer extends ThemableMixin(DirMixin(PolymerElement)) {
8285
8332
  ::slotted(:is(input, textarea))::placeholder {
8286
8333
  /* Use ::slotted(input:placeholder-shown) in themes to style the placeholder. */
8287
8334
  /* because ::slotted(...)::placeholder does not work in Safari. */
8288
- /* See the workaround at the end of this file. */
8289
8335
  font: inherit;
8290
8336
  color: inherit;
8291
8337
  /* Override default opacity in Firefox */
@@ -8352,18 +8398,6 @@ class InputContainer extends ThemableMixin(DirMixin(PolymerElement)) {
8352
8398
 
8353
8399
  customElements.define(InputContainer.is, InputContainer);
8354
8400
 
8355
- const placeholderStyleWorkaround = i$1`
8356
- /* Needed for Safari, where ::slotted(...)::placeholder does not work */
8357
- :is(input[slot='input'], textarea[slot='textarea'])::placeholder {
8358
- font: inherit;
8359
- color: inherit;
8360
- }
8361
- `;
8362
-
8363
- const $tpl$1 = document.createElement('template');
8364
- $tpl$1.innerHTML = `<style>${placeholderStyleWorkaround.toString()}</style>`;
8365
- document.head.appendChild($tpl$1.content);
8366
-
8367
8401
  /**
8368
8402
  * @license
8369
8403
  * Copyright (c) 2017 - 2022 Vaadin Ltd.
@@ -10117,6 +10151,38 @@ const ControllerMixin = dedupingMixin(
10117
10151
  * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
10118
10152
  */
10119
10153
 
10154
+ // We consider the keyboard to be active if the window has received a keydown
10155
+ // event since the last mousedown event.
10156
+ let keyboardActive = false;
10157
+
10158
+ // Listen for top-level keydown and mousedown events.
10159
+ // Use capture phase so we detect events even if they're handled.
10160
+ window.addEventListener(
10161
+ 'keydown',
10162
+ () => {
10163
+ keyboardActive = true;
10164
+ },
10165
+ { capture: true },
10166
+ );
10167
+
10168
+ window.addEventListener(
10169
+ 'mousedown',
10170
+ () => {
10171
+ keyboardActive = false;
10172
+ },
10173
+ { capture: true },
10174
+ );
10175
+
10176
+ /**
10177
+ * Returns true if the window has received a keydown
10178
+ * event since the last mousedown event.
10179
+ *
10180
+ * @return {boolean}
10181
+ */
10182
+ function isKeyboardActive() {
10183
+ return keyboardActive;
10184
+ }
10185
+
10120
10186
  /**
10121
10187
  * Returns true if the element is hidden directly with `display: none` or `visibility: hidden`,
10122
10188
  * false otherwise.
@@ -10557,7 +10623,7 @@ class FocusTrapController {
10557
10623
  * ---|---|---
10558
10624
  * `--vaadin-overlay-viewport-bottom` | Bottom offset of the visible viewport area | `0` or detected offset
10559
10625
  *
10560
- * See [Styling Components](https://vaadin.com/docs/latest/ds/customization/styling-components) documentation.
10626
+ * See [Styling Components](https://vaadin.com/docs/latest/styling/custom-theme/styling-components) documentation.
10561
10627
  *
10562
10628
  * @fires {CustomEvent} opened-changed - Fired when the `opened` property changes.
10563
10629
  * @fires {CustomEvent} vaadin-overlay-open - Fired after the overlay is opened.
@@ -10571,7 +10637,7 @@ class FocusTrapController {
10571
10637
  * @mixes DirMixin
10572
10638
  * @mixes ControllerMixin
10573
10639
  */
10574
- class OverlayElement extends ThemableMixin(DirMixin(ControllerMixin(PolymerElement))) {
10640
+ class Overlay extends ThemableMixin(DirMixin(ControllerMixin(PolymerElement))) {
10575
10641
  static get template() {
10576
10642
  return html`
10577
10643
  <style>
@@ -10871,7 +10937,7 @@ class OverlayElement extends ThemableMixin(DirMixin(ControllerMixin(PolymerEleme
10871
10937
  * @protected
10872
10938
  */
10873
10939
  _setTemplateFromNodes(nodes) {
10874
- this.template = nodes.filter((node) => node.localName && node.localName === 'template')[0] || this.template;
10940
+ this.template = nodes.find((node) => node.localName && node.localName === 'template') || this.template;
10875
10941
  }
10876
10942
 
10877
10943
  /**
@@ -11198,7 +11264,7 @@ class OverlayElement extends ThemableMixin(DirMixin(ControllerMixin(PolymerEleme
11198
11264
  */
11199
11265
  static get __attachedInstances() {
11200
11266
  return Array.from(document.body.children)
11201
- .filter((el) => el instanceof OverlayElement && !el.hasAttribute('closing'))
11267
+ .filter((el) => el instanceof Overlay && !el.hasAttribute('closing'))
11202
11268
  .sort((a, b) => a.__zIndex - b.__zIndex || 0);
11203
11269
  }
11204
11270
 
@@ -11208,7 +11274,7 @@ class OverlayElement extends ThemableMixin(DirMixin(ControllerMixin(PolymerEleme
11208
11274
  * @protected
11209
11275
  */
11210
11276
  get _last() {
11211
- return this === OverlayElement.__attachedInstances.pop();
11277
+ return this === Overlay.__attachedInstances.pop();
11212
11278
  }
11213
11279
 
11214
11280
  /** @private */
@@ -11243,7 +11309,7 @@ class OverlayElement extends ThemableMixin(DirMixin(ControllerMixin(PolymerEleme
11243
11309
  }
11244
11310
 
11245
11311
  // Disable pointer events in other attached overlays
11246
- OverlayElement.__attachedInstances.forEach((el) => {
11312
+ Overlay.__attachedInstances.forEach((el) => {
11247
11313
  if (el !== this) {
11248
11314
  el.shadowRoot.querySelector('[part="overlay"]').style.pointerEvents = 'none';
11249
11315
  }
@@ -11266,7 +11332,7 @@ class OverlayElement extends ThemableMixin(DirMixin(ControllerMixin(PolymerEleme
11266
11332
  }
11267
11333
 
11268
11334
  // Restore pointer events in the previous overlay(s)
11269
- const instances = OverlayElement.__attachedInstances;
11335
+ const instances = Overlay.__attachedInstances;
11270
11336
  let el;
11271
11337
  // Use instances.pop() to ensure the reverse order
11272
11338
  while ((el = instances.pop())) {
@@ -11445,7 +11511,7 @@ class OverlayElement extends ThemableMixin(DirMixin(ControllerMixin(PolymerEleme
11445
11511
  */
11446
11512
  bringToFront() {
11447
11513
  let zIndex = '';
11448
- const frontmost = OverlayElement.__attachedInstances.filter((o) => o !== this).pop();
11514
+ const frontmost = Overlay.__attachedInstances.filter((o) => o !== this).pop();
11449
11515
  if (frontmost) {
11450
11516
  const frontmostZIndex = frontmost.__zIndex;
11451
11517
  zIndex = frontmostZIndex + 1;
@@ -11455,7 +11521,7 @@ class OverlayElement extends ThemableMixin(DirMixin(ControllerMixin(PolymerEleme
11455
11521
  }
11456
11522
  }
11457
11523
 
11458
- customElements.define(OverlayElement.is, OverlayElement);
11524
+ customElements.define(Overlay.is, Overlay);
11459
11525
 
11460
11526
  /**
11461
11527
  * @license
@@ -11641,7 +11707,7 @@ const button = i$1`
11641
11707
  -moz-osx-font-smoothing: grayscale;
11642
11708
  }
11643
11709
 
11644
- /* Set only for the internal parts so we dont affect the host vertical alignment */
11710
+ /* Set only for the internal parts so we don't affect the host vertical alignment */
11645
11711
  [part='label'],
11646
11712
  [part='prefix'],
11647
11713
  [part='suffix'] {
@@ -11877,7 +11943,7 @@ const button = i$1`
11877
11943
  registerStyles('vaadin-button', button, { moduleId: 'lumo-button' });
11878
11944
 
11879
11945
  const DEV_MODE_CODE_REGEXP =
11880
- /\/\*\*\s+vaadin-dev-mode:start([\s\S]*)vaadin-dev-mode:end\s+\*\*\//i;
11946
+ /\/\*[\*!]\s+vaadin-dev-mode:start([\s\S]*)vaadin-dev-mode:end\s+\*\*\//i;
11881
11947
 
11882
11948
  const FlowClients = window.Vaadin && window.Vaadin.Flow && window.Vaadin.Flow.clients;
11883
11949
 
@@ -12827,7 +12893,7 @@ const registered = new Set();
12827
12893
  const ElementMixin = (superClass) =>
12828
12894
  class VaadinElementMixin extends DirMixin(superClass) {
12829
12895
  static get version() {
12830
- return '23.1.5';
12896
+ return '23.3.14';
12831
12897
  }
12832
12898
 
12833
12899
  /** @protected */
@@ -12862,159 +12928,538 @@ const ElementMixin = (superClass) =>
12862
12928
  };
12863
12929
 
12864
12930
  /**
12865
- @license
12866
- Copyright (c) 2017 The Polymer Project Authors. All rights reserved.
12867
- This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
12868
- The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
12869
- The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
12870
- Code distributed by Google as part of the polymer project is also
12871
- subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
12872
- */
12873
-
12874
- const passiveTouchGestures = false;
12875
- const wrap = (node) => node;
12876
-
12877
- // Detect native touch action support
12878
- const HAS_NATIVE_TA = typeof document.head.style.touchAction === 'string';
12879
- const GESTURE_KEY = '__polymerGestures';
12880
- const HANDLED_OBJ = '__polymerGesturesHandled';
12881
- const TOUCH_ACTION = '__polymerGesturesTouchAction';
12882
- // Radius for tap and track
12883
- const TAP_DISTANCE = 25;
12884
- const TRACK_DISTANCE = 5;
12885
- // Number of last N track positions to keep
12886
- const TRACK_LENGTH = 2;
12931
+ * @license
12932
+ * Copyright (c) 2021 - 2022 Vaadin Ltd.
12933
+ * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
12934
+ */
12887
12935
 
12888
- const MOUSE_EVENTS = ['mousedown', 'mousemove', 'mouseup', 'click'];
12889
- // An array of bitmask values for mapping MouseEvent.which to MouseEvent.buttons
12890
- const MOUSE_WHICH_TO_BUTTONS = [0, 1, 4, 2];
12891
- const MOUSE_HAS_BUTTONS = (function () {
12892
- try {
12893
- return new MouseEvent('test', { buttons: 1 }).buttons === 1;
12894
- } catch (e) {
12895
- return false;
12896
- }
12897
- })();
12936
+ let uniqueId = 0;
12898
12937
 
12899
12938
  /**
12900
- * @param {string} name Possible mouse event name
12901
- * @return {boolean} true if mouse event, false if not
12939
+ * Returns a unique integer id.
12940
+ *
12941
+ * @return {number}
12902
12942
  */
12903
- function isMouseEvent(name) {
12904
- return MOUSE_EVENTS.indexOf(name) > -1;
12943
+ function generateUniqueId() {
12944
+ // eslint-disable-next-line no-plusplus
12945
+ return uniqueId++;
12905
12946
  }
12906
12947
 
12907
- /* eslint no-empty: ["error", { "allowEmptyCatch": true }] */
12908
- // check for passive event listeners
12909
- let supportsPassive = false;
12910
- (function () {
12911
- try {
12912
- const opts = Object.defineProperty({}, 'passive', {
12913
- // eslint-disable-next-line getter-return
12914
- get() {
12915
- supportsPassive = true;
12916
- },
12917
- });
12918
- window.addEventListener('test', null, opts);
12919
- window.removeEventListener('test', null, opts);
12920
- } catch (e) {}
12921
- })();
12948
+ /**
12949
+ * @license
12950
+ * Copyright (c) 2021 - 2022 Vaadin Ltd.
12951
+ * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
12952
+ */
12922
12953
 
12923
12954
  /**
12924
- * Generate settings for event listeners, dependant on `passiveTouchGestures`
12925
- *
12926
- * @param {string} eventName Event name to determine if `{passive}` option is
12927
- * needed
12928
- * @return {{passive: boolean} | undefined} Options to use for addEventListener
12929
- * and removeEventListener
12955
+ * A controller for providing content to slot element and observing changes.
12930
12956
  */
12931
- function PASSIVE_TOUCH(eventName) {
12932
- if (isMouseEvent(eventName) || eventName === 'touchend') {
12933
- return;
12934
- }
12935
- if (HAS_NATIVE_TA && supportsPassive && passiveTouchGestures) {
12936
- return { passive: true };
12957
+ class SlotController extends EventTarget {
12958
+ /**
12959
+ * Ensure that every instance has unique ID.
12960
+ *
12961
+ * @param {string} slotName
12962
+ * @param {HTMLElement} host
12963
+ * @return {string}
12964
+ * @protected
12965
+ */
12966
+ static generateId(slotName, host) {
12967
+ const prefix = slotName || 'default';
12968
+ return `${prefix}-${host.localName}-${generateUniqueId()}`;
12937
12969
  }
12938
- }
12939
12970
 
12940
- // Check for touch-only devices
12941
- const IS_TOUCH_ONLY = navigator.userAgent.match(/iP(?:[oa]d|hone)|Android/);
12971
+ constructor(host, slotName, slotFactory, slotInitializer, useUniqueId) {
12972
+ super();
12942
12973
 
12943
- // Defined at https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#enabling-and-disabling-form-controls:-the-disabled-attribute
12944
- /** @type {!Object<boolean>} */
12945
- const canBeDisabled = {
12946
- button: true,
12947
- command: true,
12948
- fieldset: true,
12949
- input: true,
12950
- keygen: true,
12951
- optgroup: true,
12952
- option: true,
12953
- select: true,
12954
- textarea: true,
12955
- };
12974
+ this.host = host;
12975
+ this.slotName = slotName;
12976
+ this.slotFactory = slotFactory;
12977
+ this.slotInitializer = slotInitializer;
12956
12978
 
12957
- /**
12958
- * @param {MouseEvent} ev event to test for left mouse button down
12959
- * @return {boolean} has left mouse button down
12960
- */
12961
- function hasLeftMouseButton(ev) {
12962
- const type = ev.type;
12963
- // Exit early if the event is not a mouse event
12964
- if (!isMouseEvent(type)) {
12965
- return false;
12966
- }
12967
- // Ev.button is not reliable for mousemove (0 is overloaded as both left button and no buttons)
12968
- // instead we use ev.buttons (bitmask of buttons) or fall back to ev.which (deprecated, 0 for no buttons, 1 for left button)
12969
- if (type === 'mousemove') {
12970
- // Allow undefined for testing events
12971
- let buttons = ev.buttons === undefined ? 1 : ev.buttons;
12972
- if (ev instanceof window.MouseEvent && !MOUSE_HAS_BUTTONS) {
12973
- buttons = MOUSE_WHICH_TO_BUTTONS[ev.which] || 0;
12979
+ // Only generate the default ID if requested by the controller.
12980
+ if (useUniqueId) {
12981
+ this.defaultId = SlotController.generateId(slotName, host);
12974
12982
  }
12975
- // Buttons is a bitmask, check that the left button bit is set (1)
12976
- return Boolean(buttons & 1);
12977
12983
  }
12978
- // Allow undefined for testing events
12979
- const button = ev.button === undefined ? 0 : ev.button;
12980
- // Ev.button is 0 in mousedown/mouseup/click for left button activation
12981
- return button === 0;
12982
- }
12983
12984
 
12984
- function isSyntheticClick(ev) {
12985
- if (ev.type === 'click') {
12986
- // Ev.detail is 0 for HTMLElement.click in most browsers
12987
- if (ev.detail === 0) {
12988
- return true;
12989
- }
12990
- // In the worst case, check that the x/y position of the click is within
12991
- // the bounding box of the target of the event
12992
- // Thanks IE 10 >:(
12993
- const t = _findOriginalTarget(ev);
12994
- // Make sure the target of the event is an element so we can use getBoundingClientRect,
12995
- // if not, just assume it is a synthetic click
12996
- if (!t.nodeType || /** @type {Element} */ (t).nodeType !== Node.ELEMENT_NODE) {
12997
- return true;
12998
- }
12999
- const bcr = /** @type {Element} */ (t).getBoundingClientRect();
13000
- // Use page x/y to account for scrolling
13001
- const x = ev.pageX,
13002
- y = ev.pageY;
13003
- // Ev is a synthetic click if the position is outside the bounding box of the target
13004
- return !(x >= bcr.left && x <= bcr.right && y >= bcr.top && y <= bcr.bottom);
13005
- }
13006
- return false;
13007
- }
12985
+ hostConnected() {
12986
+ if (!this.initialized) {
12987
+ let node = this.getSlotChild();
13008
12988
 
13009
- const POINTERSTATE = {
13010
- mouse: {
13011
- target: null,
13012
- mouseIgnoreJob: null,
13013
- },
13014
- touch: {
13015
- x: 0,
13016
- y: 0,
13017
- id: -1,
12989
+ if (!node) {
12990
+ node = this.attachDefaultNode();
12991
+ } else {
12992
+ this.node = node;
12993
+ this.initCustomNode(node);
12994
+ }
12995
+
12996
+ this.initNode(node);
12997
+
12998
+ // TODO: Consider making this behavior opt-in to improve performance.
12999
+ this.observe();
13000
+
13001
+ this.initialized = true;
13002
+ }
13003
+ }
13004
+
13005
+ /**
13006
+ * Create and attach default node using the slot factory.
13007
+ * @return {Node | undefined}
13008
+ * @protected
13009
+ */
13010
+ attachDefaultNode() {
13011
+ const { host, slotName, slotFactory } = this;
13012
+
13013
+ // Check if the node was created previously and if so, reuse it.
13014
+ let node = this.defaultNode;
13015
+
13016
+ // Slot factory is optional, some slots don't have default content.
13017
+ if (!node && slotFactory) {
13018
+ node = slotFactory(host);
13019
+ if (node instanceof Element) {
13020
+ if (slotName !== '') {
13021
+ node.setAttribute('slot', slotName);
13022
+ }
13023
+ this.node = node;
13024
+ this.defaultNode = node;
13025
+ }
13026
+ }
13027
+
13028
+ if (node) {
13029
+ host.appendChild(node);
13030
+ }
13031
+
13032
+ return node;
13033
+ }
13034
+
13035
+ /**
13036
+ * Return a reference to the node managed by the controller.
13037
+ * @return {Node}
13038
+ */
13039
+ getSlotChild() {
13040
+ const { slotName } = this;
13041
+ return Array.from(this.host.childNodes).find((node) => {
13042
+ // Either an element (any slot) or a text node (only un-named slot).
13043
+ return (
13044
+ (node.nodeType === Node.ELEMENT_NODE && node.slot === slotName) ||
13045
+ (node.nodeType === Node.TEXT_NODE && node.textContent.trim() && slotName === '')
13046
+ );
13047
+ });
13048
+ }
13049
+
13050
+ /**
13051
+ * @param {Node} node
13052
+ * @protected
13053
+ */
13054
+ initNode(node) {
13055
+ const { slotInitializer } = this;
13056
+ // Don't try to bind `this` to initializer (normally it's arrow function).
13057
+ // Instead, pass the host as a first argument to access component's state.
13058
+ if (slotInitializer) {
13059
+ slotInitializer(this.host, node);
13060
+ }
13061
+ }
13062
+
13063
+ /**
13064
+ * Override to initialize the newly added custom node.
13065
+ *
13066
+ * @param {Node} _node
13067
+ * @protected
13068
+ */
13069
+ initCustomNode(_node) {}
13070
+
13071
+ /**
13072
+ * Override to teardown slotted node when it's removed.
13073
+ *
13074
+ * @param {Node} _node
13075
+ * @protected
13076
+ */
13077
+ teardownNode(_node) {}
13078
+
13079
+ /**
13080
+ * Setup the observer to manage slot content changes.
13081
+ * @protected
13082
+ */
13083
+ observe() {
13084
+ const { slotName } = this;
13085
+ const selector = slotName === '' ? 'slot:not([name])' : `slot[name=${slotName}]`;
13086
+ const slot = this.host.shadowRoot.querySelector(selector);
13087
+
13088
+ this.__slotObserver = new FlattenedNodesObserver(slot, (info) => {
13089
+ // TODO: support default slot with multiple nodes (e.g. confirm-dialog)
13090
+ const current = this.node;
13091
+ const newNode = info.addedNodes.find((node) => node !== current);
13092
+
13093
+ if (info.removedNodes.length) {
13094
+ info.removedNodes.forEach((node) => {
13095
+ this.teardownNode(node);
13096
+ });
13097
+ }
13098
+
13099
+ if (newNode) {
13100
+ // Custom node is added, remove the current one.
13101
+ if (current && current.isConnected) {
13102
+ this.host.removeChild(current);
13103
+ }
13104
+
13105
+ this.node = newNode;
13106
+
13107
+ if (newNode !== this.defaultNode) {
13108
+ this.initCustomNode(newNode);
13109
+
13110
+ this.initNode(newNode);
13111
+ }
13112
+ }
13113
+ });
13114
+ }
13115
+ }
13116
+
13117
+ /**
13118
+ * @license
13119
+ * Copyright (c) 2022 Vaadin Ltd.
13120
+ * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
13121
+ */
13122
+
13123
+ /**
13124
+ * A controller that manages the slotted tooltip element.
13125
+ */
13126
+ class TooltipController extends SlotController {
13127
+ constructor(host) {
13128
+ // Do not provide slot factory to create tooltip lazily.
13129
+ super(host, 'tooltip');
13130
+
13131
+ this.setTarget(host);
13132
+ }
13133
+
13134
+ /**
13135
+ * Override to initialize the newly added custom tooltip.
13136
+ *
13137
+ * @param {Node} tooltipNode
13138
+ * @protected
13139
+ * @override
13140
+ */
13141
+ initCustomNode(tooltipNode) {
13142
+ tooltipNode.target = this.target;
13143
+
13144
+ if (this.context !== undefined) {
13145
+ tooltipNode.context = this.context;
13146
+ }
13147
+
13148
+ if (this.manual !== undefined) {
13149
+ tooltipNode.manual = this.manual;
13150
+ }
13151
+
13152
+ if (this.opened !== undefined) {
13153
+ tooltipNode.opened = this.opened;
13154
+ }
13155
+
13156
+ if (this.position !== undefined) {
13157
+ tooltipNode._position = this.position;
13158
+ }
13159
+
13160
+ if (this.shouldShow !== undefined) {
13161
+ tooltipNode.shouldShow = this.shouldShow;
13162
+ }
13163
+ }
13164
+
13165
+ /**
13166
+ * Set a context object to be used by generator.
13167
+ * @param {object} context
13168
+ */
13169
+ setContext(context) {
13170
+ this.context = context;
13171
+
13172
+ const tooltipNode = this.node;
13173
+ if (tooltipNode) {
13174
+ tooltipNode.context = context;
13175
+ }
13176
+ }
13177
+
13178
+ /**
13179
+ * Toggle manual state on the slotted tooltip.
13180
+ * @param {boolean} manual
13181
+ */
13182
+ setManual(manual) {
13183
+ this.manual = manual;
13184
+
13185
+ const tooltipNode = this.node;
13186
+ if (tooltipNode) {
13187
+ tooltipNode.manual = manual;
13188
+ }
13189
+ }
13190
+
13191
+ /**
13192
+ * Toggle opened state on the slotted tooltip.
13193
+ * @param {boolean} opened
13194
+ */
13195
+ setOpened(opened) {
13196
+ this.opened = opened;
13197
+
13198
+ const tooltipNode = this.node;
13199
+ if (tooltipNode) {
13200
+ tooltipNode.opened = opened;
13201
+ }
13202
+ }
13203
+
13204
+ /**
13205
+ * Set default position for the slotted tooltip.
13206
+ * This can be overridden by setting the position
13207
+ * using corresponding property or attribute.
13208
+ * @param {string} position
13209
+ */
13210
+ setPosition(position) {
13211
+ this.position = position;
13212
+
13213
+ const tooltipNode = this.node;
13214
+ if (tooltipNode) {
13215
+ tooltipNode._position = position;
13216
+ }
13217
+ }
13218
+
13219
+ /**
13220
+ * Set function used to detect whether to show
13221
+ * the tooltip based on a condition.
13222
+ * @param {Function} shouldShow
13223
+ */
13224
+ setShouldShow(shouldShow) {
13225
+ this.shouldShow = shouldShow;
13226
+
13227
+ const tooltipNode = this.node;
13228
+ if (tooltipNode) {
13229
+ tooltipNode.shouldShow = shouldShow;
13230
+ }
13231
+ }
13232
+
13233
+ /**
13234
+ * Set an HTML element to attach the tooltip to.
13235
+ * @param {HTMLElement} target
13236
+ */
13237
+ setTarget(target) {
13238
+ this.target = target;
13239
+
13240
+ const tooltipNode = this.node;
13241
+ if (tooltipNode) {
13242
+ tooltipNode.target = target;
13243
+ }
13244
+ }
13245
+ }
13246
+
13247
+ /**
13248
+ * @license
13249
+ * Copyright (c) 2021 - 2022 Vaadin Ltd.
13250
+ * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
13251
+ */
13252
+
13253
+ /**
13254
+ * A mixin to provide disabled property for field components.
13255
+ *
13256
+ * @polymerMixin
13257
+ */
13258
+ const DisabledMixin = dedupingMixin(
13259
+ (superclass) =>
13260
+ class DisabledMixinClass extends superclass {
13261
+ static get properties() {
13262
+ return {
13263
+ /**
13264
+ * If true, the user cannot interact with this element.
13265
+ */
13266
+ disabled: {
13267
+ type: Boolean,
13268
+ value: false,
13269
+ observer: '_disabledChanged',
13270
+ reflectToAttribute: true,
13271
+ },
13272
+ };
13273
+ }
13274
+
13275
+ /**
13276
+ * @param {boolean} disabled
13277
+ * @protected
13278
+ */
13279
+ _disabledChanged(disabled) {
13280
+ this._setAriaDisabled(disabled);
13281
+ }
13282
+
13283
+ /**
13284
+ * @param {boolean} disabled
13285
+ * @protected
13286
+ */
13287
+ _setAriaDisabled(disabled) {
13288
+ if (disabled) {
13289
+ this.setAttribute('aria-disabled', 'true');
13290
+ } else {
13291
+ this.removeAttribute('aria-disabled');
13292
+ }
13293
+ }
13294
+
13295
+ /**
13296
+ * Overrides the default element `click` method in order to prevent
13297
+ * firing the `click` event when the element is disabled.
13298
+ * @protected
13299
+ * @override
13300
+ */
13301
+ click() {
13302
+ if (!this.disabled) {
13303
+ super.click();
13304
+ }
13305
+ }
13306
+ },
13307
+ );
13308
+
13309
+ /**
13310
+ @license
13311
+ Copyright (c) 2017 The Polymer Project Authors. All rights reserved.
13312
+ This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
13313
+ The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
13314
+ The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
13315
+ Code distributed by Google as part of the polymer project is also
13316
+ subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
13317
+ */
13318
+
13319
+ const passiveTouchGestures = false;
13320
+ const wrap = (node) => node;
13321
+
13322
+ // Detect native touch action support
13323
+ const HAS_NATIVE_TA = typeof document.head.style.touchAction === 'string';
13324
+ const GESTURE_KEY = '__polymerGestures';
13325
+ const HANDLED_OBJ = '__polymerGesturesHandled';
13326
+ const TOUCH_ACTION = '__polymerGesturesTouchAction';
13327
+ // Radius for tap and track
13328
+ const TAP_DISTANCE = 25;
13329
+ const TRACK_DISTANCE = 5;
13330
+ // Number of last N track positions to keep
13331
+ const TRACK_LENGTH = 2;
13332
+
13333
+ const MOUSE_EVENTS = ['mousedown', 'mousemove', 'mouseup', 'click'];
13334
+ // An array of bitmask values for mapping MouseEvent.which to MouseEvent.buttons
13335
+ const MOUSE_WHICH_TO_BUTTONS = [0, 1, 4, 2];
13336
+ const MOUSE_HAS_BUTTONS = (function () {
13337
+ try {
13338
+ return new MouseEvent('test', { buttons: 1 }).buttons === 1;
13339
+ } catch (e) {
13340
+ return false;
13341
+ }
13342
+ })();
13343
+
13344
+ /**
13345
+ * @param {string} name Possible mouse event name
13346
+ * @return {boolean} true if mouse event, false if not
13347
+ */
13348
+ function isMouseEvent(name) {
13349
+ return MOUSE_EVENTS.indexOf(name) > -1;
13350
+ }
13351
+
13352
+ /* eslint no-empty: ["error", { "allowEmptyCatch": true }] */
13353
+ // check for passive event listeners
13354
+ let supportsPassive = false;
13355
+ (function () {
13356
+ try {
13357
+ const opts = Object.defineProperty({}, 'passive', {
13358
+ // eslint-disable-next-line getter-return
13359
+ get() {
13360
+ supportsPassive = true;
13361
+ },
13362
+ });
13363
+ window.addEventListener('test', null, opts);
13364
+ window.removeEventListener('test', null, opts);
13365
+ } catch (e) {}
13366
+ })();
13367
+
13368
+ /**
13369
+ * Generate settings for event listeners, dependant on `passiveTouchGestures`
13370
+ *
13371
+ * @param {string} eventName Event name to determine if `{passive}` option is
13372
+ * needed
13373
+ * @return {{passive: boolean} | undefined} Options to use for addEventListener
13374
+ * and removeEventListener
13375
+ */
13376
+ function PASSIVE_TOUCH(eventName) {
13377
+ if (isMouseEvent(eventName) || eventName === 'touchend') {
13378
+ return;
13379
+ }
13380
+ if (HAS_NATIVE_TA && supportsPassive && passiveTouchGestures) {
13381
+ return { passive: true };
13382
+ }
13383
+ }
13384
+
13385
+ // Check for touch-only devices
13386
+ const IS_TOUCH_ONLY = navigator.userAgent.match(/iP(?:[oa]d|hone)|Android/);
13387
+
13388
+ // Defined at https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#enabling-and-disabling-form-controls:-the-disabled-attribute
13389
+ /** @type {!Object<boolean>} */
13390
+ const canBeDisabled = {
13391
+ button: true,
13392
+ command: true,
13393
+ fieldset: true,
13394
+ input: true,
13395
+ keygen: true,
13396
+ optgroup: true,
13397
+ option: true,
13398
+ select: true,
13399
+ textarea: true,
13400
+ };
13401
+
13402
+ /**
13403
+ * @param {MouseEvent} ev event to test for left mouse button down
13404
+ * @return {boolean} has left mouse button down
13405
+ */
13406
+ function hasLeftMouseButton(ev) {
13407
+ const type = ev.type;
13408
+ // Exit early if the event is not a mouse event
13409
+ if (!isMouseEvent(type)) {
13410
+ return false;
13411
+ }
13412
+ // Ev.button is not reliable for mousemove (0 is overloaded as both left button and no buttons)
13413
+ // instead we use ev.buttons (bitmask of buttons) or fall back to ev.which (deprecated, 0 for no buttons, 1 for left button)
13414
+ if (type === 'mousemove') {
13415
+ // Allow undefined for testing events
13416
+ let buttons = ev.buttons === undefined ? 1 : ev.buttons;
13417
+ if (ev instanceof window.MouseEvent && !MOUSE_HAS_BUTTONS) {
13418
+ buttons = MOUSE_WHICH_TO_BUTTONS[ev.which] || 0;
13419
+ }
13420
+ // Buttons is a bitmask, check that the left button bit is set (1)
13421
+ return Boolean(buttons & 1);
13422
+ }
13423
+ // Allow undefined for testing events
13424
+ const button = ev.button === undefined ? 0 : ev.button;
13425
+ // Ev.button is 0 in mousedown/mouseup/click for left button activation
13426
+ return button === 0;
13427
+ }
13428
+
13429
+ function isSyntheticClick(ev) {
13430
+ if (ev.type === 'click') {
13431
+ // Ev.detail is 0 for HTMLElement.click in most browsers
13432
+ if (ev.detail === 0) {
13433
+ return true;
13434
+ }
13435
+ // In the worst case, check that the x/y position of the click is within
13436
+ // the bounding box of the target of the event
13437
+ // Thanks IE 10 >:(
13438
+ const t = _findOriginalTarget(ev);
13439
+ // Make sure the target of the event is an element so we can use getBoundingClientRect,
13440
+ // if not, just assume it is a synthetic click
13441
+ if (!t.nodeType || /** @type {Element} */ (t).nodeType !== Node.ELEMENT_NODE) {
13442
+ return true;
13443
+ }
13444
+ const bcr = /** @type {Element} */ (t).getBoundingClientRect();
13445
+ // Use page x/y to account for scrolling
13446
+ const x = ev.pageX,
13447
+ y = ev.pageY;
13448
+ // Ev is a synthetic click if the position is outside the bounding box of the target
13449
+ return !(x >= bcr.left && x <= bcr.right && y >= bcr.top && y <= bcr.bottom);
13450
+ }
13451
+ return false;
13452
+ }
13453
+
13454
+ const POINTERSTATE = {
13455
+ mouse: {
13456
+ target: null,
13457
+ mouseIgnoreJob: null,
13458
+ },
13459
+ touch: {
13460
+ x: 0,
13461
+ y: 0,
13462
+ id: -1,
13018
13463
  scrollDecided: false,
13019
13464
  },
13020
13465
  };
@@ -13125,7 +13570,7 @@ function _handleNative(ev) {
13125
13570
  }
13126
13571
  if (!ev[HANDLED_OBJ]) {
13127
13572
  ev[HANDLED_OBJ] = {};
13128
- if (type.slice(0, 5) === 'touch') {
13573
+ if (type.startsWith('touch')) {
13129
13574
  const t = ev.changedTouches[0];
13130
13575
  if (type === 'touchstart') {
13131
13576
  // Only handle the first finger
@@ -13729,68 +14174,6 @@ function trackForward(info, e, preventer) {
13729
14174
  }
13730
14175
  }
13731
14176
 
13732
- /**
13733
- * @license
13734
- * Copyright (c) 2021 - 2022 Vaadin Ltd.
13735
- * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
13736
- */
13737
-
13738
- /**
13739
- * A mixin to provide disabled property for field components.
13740
- *
13741
- * @polymerMixin
13742
- */
13743
- const DisabledMixin = dedupingMixin(
13744
- (superclass) =>
13745
- class DisabledMixinClass extends superclass {
13746
- static get properties() {
13747
- return {
13748
- /**
13749
- * If true, the user cannot interact with this element.
13750
- */
13751
- disabled: {
13752
- type: Boolean,
13753
- value: false,
13754
- observer: '_disabledChanged',
13755
- reflectToAttribute: true,
13756
- },
13757
- };
13758
- }
13759
-
13760
- /**
13761
- * @param {boolean} disabled
13762
- * @protected
13763
- */
13764
- _disabledChanged(disabled) {
13765
- this._setAriaDisabled(disabled);
13766
- }
13767
-
13768
- /**
13769
- * @param {boolean} disabled
13770
- * @protected
13771
- */
13772
- _setAriaDisabled(disabled) {
13773
- if (disabled) {
13774
- this.setAttribute('aria-disabled', 'true');
13775
- } else {
13776
- this.removeAttribute('aria-disabled');
13777
- }
13778
- }
13779
-
13780
- /**
13781
- * Overrides the default element `click` method in order to prevent
13782
- * firing the `click` event when the element is disabled.
13783
- * @protected
13784
- * @override
13785
- */
13786
- click() {
13787
- if (!this.disabled) {
13788
- super.click();
13789
- }
13790
- }
13791
- },
13792
- );
13793
-
13794
14177
  /**
13795
14178
  * @license
13796
14179
  * Copyright (c) 2021 - 2022 Vaadin Ltd.
@@ -13984,28 +14367,6 @@ const ActiveMixin = (superclass) =>
13984
14367
  * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
13985
14368
  */
13986
14369
 
13987
- // We consider the keyboard to be active if the window has received a keydown
13988
- // event since the last mousedown event.
13989
- let keyboardActive = false;
13990
-
13991
- // Listen for top-level keydown and mousedown events.
13992
- // Use capture phase so we detect events even if they're handled.
13993
- window.addEventListener(
13994
- 'keydown',
13995
- () => {
13996
- keyboardActive = true;
13997
- },
13998
- { capture: true },
13999
- );
14000
-
14001
- window.addEventListener(
14002
- 'mousedown',
14003
- () => {
14004
- keyboardActive = false;
14005
- },
14006
- { capture: true },
14007
- );
14008
-
14009
14370
  /**
14010
14371
  * A mixin to handle `focused` and `focus-ring` attributes based on focus.
14011
14372
  *
@@ -14019,7 +14380,7 @@ const FocusMixin = dedupingMixin(
14019
14380
  * @return {boolean}
14020
14381
  */
14021
14382
  get _keyboardActive() {
14022
- return keyboardActive;
14383
+ return isKeyboardActive();
14023
14384
  }
14024
14385
 
14025
14386
  /** @protected */
@@ -14283,14 +14644,15 @@ const ButtonMixin = (superClass) =>
14283
14644
  * `focus-ring` | Set when the button is focused using the keyboard.
14284
14645
  * `focused` | Set when the button is focused.
14285
14646
  *
14286
- * See [Styling Components](https://vaadin.com/docs/latest/ds/customization/styling-components) documentation.
14647
+ * See [Styling Components](https://vaadin.com/docs/latest/styling/custom-theme/styling-components) documentation.
14287
14648
  *
14288
14649
  * @extends HTMLElement
14289
14650
  * @mixes ButtonMixin
14651
+ * @mixes ControllerMixin
14290
14652
  * @mixes ElementMixin
14291
14653
  * @mixes ThemableMixin
14292
14654
  */
14293
- class Button extends ButtonMixin(ElementMixin(ThemableMixin(PolymerElement))) {
14655
+ class Button extends ButtonMixin(ElementMixin(ThemableMixin(ControllerMixin(PolymerElement)))) {
14294
14656
  static get is() {
14295
14657
  return 'vaadin-button';
14296
14658
  }
@@ -14344,18 +14706,27 @@ class Button extends ButtonMixin(ElementMixin(ThemableMixin(PolymerElement))) {
14344
14706
  }
14345
14707
  </style>
14346
14708
  <div class="vaadin-button-container">
14347
- <span part="prefix">
14709
+ <span part="prefix" aria-hidden="true">
14348
14710
  <slot name="prefix"></slot>
14349
14711
  </span>
14350
14712
  <span part="label">
14351
14713
  <slot></slot>
14352
14714
  </span>
14353
- <span part="suffix">
14715
+ <span part="suffix" aria-hidden="true">
14354
14716
  <slot name="suffix"></slot>
14355
14717
  </span>
14356
14718
  </div>
14719
+ <slot name="tooltip"></slot>
14357
14720
  `;
14358
14721
  }
14722
+
14723
+ /** @protected */
14724
+ ready() {
14725
+ super.ready();
14726
+
14727
+ this._tooltipController = new TooltipController(this);
14728
+ this.addController(this._tooltipController);
14729
+ }
14359
14730
  }
14360
14731
 
14361
14732
  customElements.define(Button.is, Button);
@@ -14365,7 +14736,6 @@ registerStyles(
14365
14736
  i$1`
14366
14737
  :host {
14367
14738
  position: relative;
14368
- background-color: transparent;
14369
14739
  /* Background for the year scroller, placed here as we are using a mask image on the actual years part */
14370
14740
  background-image: linear-gradient(var(--lumo-shade-5pct), var(--lumo-shade-5pct));
14371
14741
  background-size: 57px 100%;
@@ -14391,7 +14761,7 @@ registerStyles(
14391
14761
  + var(--lumo-size-m) * 6
14392
14762
  + var(--lumo-space-s)
14393
14763
  );
14394
- --vaadin-infinite-scroller-buffer-offset: 20%;
14764
+ --vaadin-infinite-scroller-buffer-offset: 10%;
14395
14765
  -webkit-mask-image: linear-gradient(transparent, #000 10%, #000 85%, transparent);
14396
14766
  mask-image: linear-gradient(transparent, #000 10%, #000 85%, transparent);
14397
14767
  position: relative;
@@ -14473,17 +14843,10 @@ registerStyles(
14473
14843
 
14474
14844
  [part='toolbar'] {
14475
14845
  padding: var(--lumo-space-s);
14476
- box-shadow: 0 -1px 0 0 var(--lumo-contrast-10pct);
14477
14846
  border-bottom-left-radius: var(--lumo-border-radius-l);
14478
14847
  margin-right: 57px;
14479
14848
  }
14480
14849
 
14481
- @supports (mask-image: linear-gradient(#000, #000)) or (-webkit-mask-image: linear-gradient(#000, #000)) {
14482
- [part='toolbar'] {
14483
- box-shadow: none;
14484
- }
14485
- }
14486
-
14487
14850
  /* Today and Cancel buttons */
14488
14851
 
14489
14852
  [part='toolbar'] [part\$='button'] {
@@ -14516,8 +14879,6 @@ registerStyles(
14516
14879
  /* Very narrow screen (year scroller initially hidden) */
14517
14880
 
14518
14881
  [part='years-toggle-button'] {
14519
- position: relative;
14520
- right: auto;
14521
14882
  display: flex;
14522
14883
  align-items: center;
14523
14884
  height: var(--lumo-size-s);
@@ -14535,11 +14896,7 @@ registerStyles(
14535
14896
  color: var(--lumo-primary-contrast-color);
14536
14897
  }
14537
14898
 
14538
- [part='years-toggle-button']::before {
14539
- content: none;
14540
- }
14541
-
14542
- /* TODO magic number (same as used for iron-media-query in vaadin-date-picker-overlay-content) */
14899
+ /* TODO magic number (same as used for media-query in vaadin-date-picker-overlay-content) */
14543
14900
  @media screen and (max-width: 374px) {
14544
14901
  :host {
14545
14902
  background-image: none;
@@ -14714,9 +15071,9 @@ registerStyles(
14714
15071
  { moduleId: 'lumo-month-calendar' },
14715
15072
  );
14716
15073
 
14717
- const $_documentContainer$1 = document.createElement('template');
15074
+ const template$1 = document.createElement('template');
14718
15075
 
14719
- $_documentContainer$1.innerHTML = `
15076
+ template$1.innerHTML = `
14720
15077
  <style>
14721
15078
  @keyframes vaadin-date-picker-month-calendar-focus-date {
14722
15079
  50% {
@@ -14726,7 +15083,7 @@ $_documentContainer$1.innerHTML = `
14726
15083
  </style>
14727
15084
  `;
14728
15085
 
14729
- document.head.appendChild($_documentContainer$1.content);
15086
+ document.head.appendChild(template$1.content);
14730
15087
 
14731
15088
  /**
14732
15089
  * @license
@@ -14734,9 +15091,9 @@ document.head.appendChild($_documentContainer$1.content);
14734
15091
  * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
14735
15092
  */
14736
15093
 
14737
- const $_documentContainer = document.createElement('template');
15094
+ const template = document.createElement('template');
14738
15095
 
14739
- $_documentContainer.innerHTML = `
15096
+ template.innerHTML = `
14740
15097
  <style>
14741
15098
  @font-face {
14742
15099
  font-family: 'lumo-icons';
@@ -14792,7 +15149,7 @@ $_documentContainer.innerHTML = `
14792
15149
  </style>
14793
15150
  `;
14794
15151
 
14795
- document.head.appendChild($_documentContainer.content);
15152
+ document.head.appendChild(template.content);
14796
15153
 
14797
15154
  /**
14798
15155
  * @license
@@ -14906,6 +15263,10 @@ const requiredField = i$1`
14906
15263
  line-height: 1;
14907
15264
  padding-right: 1em;
14908
15265
  padding-bottom: 0.5em;
15266
+ /* As a workaround for diacritics being cut off, add a top padding and a
15267
+ negative margin to compensate */
15268
+ padding-top: 0.25em;
15269
+ margin-top: -0.25em;
14909
15270
  overflow: hidden;
14910
15271
  white-space: nowrap;
14911
15272
  text-overflow: ellipsis;
@@ -14926,6 +15287,10 @@ const requiredField = i$1`
14926
15287
  padding-top: var(--lumo-space-m);
14927
15288
  }
14928
15289
 
15290
+ :host([has-label]) ::slotted([slot='tooltip']) {
15291
+ --vaadin-tooltip-offset-bottom: calc((var(--lumo-space-m) - var(--lumo-space-xs)) * -1);
15292
+ }
15293
+
14929
15294
  :host([required]) [part='required-indicator']::after {
14930
15295
  content: var(--lumo-required-field-indicator, '•');
14931
15296
  transition: opacity 0.2s;
@@ -15359,6 +15724,57 @@ function getAncestorRootNodes(node) {
15359
15724
  return result;
15360
15725
  }
15361
15726
 
15727
+ /**
15728
+ * @param {string} value
15729
+ * @return {Set<string>}
15730
+ */
15731
+ function deserializeAttributeValue(value) {
15732
+ if (!value) {
15733
+ return new Set();
15734
+ }
15735
+
15736
+ return new Set(value.split(' '));
15737
+ }
15738
+
15739
+ /**
15740
+ * @param {Set<string>} values
15741
+ * @return {string}
15742
+ */
15743
+ function serializeAttributeValue(values) {
15744
+ return [...values].join(' ');
15745
+ }
15746
+
15747
+ /**
15748
+ * Adds a value to an attribute containing space-delimited values.
15749
+ *
15750
+ * @param {HTMLElement} element
15751
+ * @param {string} attr
15752
+ * @param {string} value
15753
+ */
15754
+ function addValueToAttribute(element, attr, value) {
15755
+ const values = deserializeAttributeValue(element.getAttribute(attr));
15756
+ values.add(value);
15757
+ element.setAttribute(attr, serializeAttributeValue(values));
15758
+ }
15759
+
15760
+ /**
15761
+ * Removes a value from an attribute containing space-delimited values.
15762
+ * If the value is the last one, the whole attribute is removed.
15763
+ *
15764
+ * @param {HTMLElement} element
15765
+ * @param {string} attr
15766
+ * @param {string} value
15767
+ */
15768
+ function removeValueFromAttribute(element, attr, value) {
15769
+ const values = deserializeAttributeValue(element.getAttribute(attr));
15770
+ values.delete(value);
15771
+ if (values.size === 0) {
15772
+ element.removeAttribute(attr);
15773
+ return;
15774
+ }
15775
+ element.setAttribute(attr, serializeAttributeValue(values));
15776
+ }
15777
+
15362
15778
  /**
15363
15779
  * @license
15364
15780
  * Copyright (c) 2017 - 2022 Vaadin Ltd.
@@ -15375,6 +15791,16 @@ const PROP_NAMES_HORIZONTAL = {
15375
15791
  end: 'right',
15376
15792
  };
15377
15793
 
15794
+ const targetResizeObserver = new ResizeObserver((entries) => {
15795
+ setTimeout(() => {
15796
+ entries.forEach((entry) => {
15797
+ if (entry.target.__overlay) {
15798
+ entry.target.__overlay._updatePosition();
15799
+ }
15800
+ });
15801
+ });
15802
+ });
15803
+
15378
15804
  /**
15379
15805
  * @polymerMixin
15380
15806
  */
@@ -15400,6 +15826,8 @@ const PositionMixin = (superClass) =>
15400
15826
  * RTL is taken into account when interpreting the value.
15401
15827
  * The overlay is automatically flipped to the opposite side when it doesn't fit into
15402
15828
  * the default side defined by this property.
15829
+ *
15830
+ * @attr {start|end} horizontal-align
15403
15831
  */
15404
15832
  horizontalAlign: {
15405
15833
  type: String,
@@ -15412,6 +15840,8 @@ const PositionMixin = (superClass) =>
15412
15840
  * Possible values are `top` and `bottom`.
15413
15841
  * The overlay is automatically flipped to the opposite side when it doesn't fit into
15414
15842
  * the default side defined by this property.
15843
+ *
15844
+ * @attr {top|bottom} vertical-align
15415
15845
  */
15416
15846
  verticalAlign: {
15417
15847
  type: String,
@@ -15421,6 +15851,8 @@ const PositionMixin = (superClass) =>
15421
15851
  /**
15422
15852
  * When `positionTarget` is set, this property defines whether the overlay should overlap
15423
15853
  * the target element in the x-axis, or be positioned right next to it.
15854
+ *
15855
+ * @attr {boolean} no-horizontal-overlap
15424
15856
  */
15425
15857
  noHorizontalOverlap: {
15426
15858
  type: Boolean,
@@ -15430,17 +15862,32 @@ const PositionMixin = (superClass) =>
15430
15862
  /**
15431
15863
  * When `positionTarget` is set, this property defines whether the overlay should overlap
15432
15864
  * the target element in the y-axis, or be positioned right above/below it.
15865
+ *
15866
+ * @attr {boolean} no-vertical-overlap
15433
15867
  */
15434
15868
  noVerticalOverlap: {
15435
15869
  type: Boolean,
15436
15870
  value: false,
15437
15871
  },
15872
+
15873
+ /**
15874
+ * If the overlay content has no intrinsic height, this property can be used to set
15875
+ * the minimum vertical space (in pixels) required by the overlay. Setting a value to
15876
+ * the property effectively disables the content measurement in favor of using this
15877
+ * fixed value for determining the open direction.
15878
+ *
15879
+ * @attr {number} required-vertical-space
15880
+ */
15881
+ requiredVerticalSpace: {
15882
+ type: Number,
15883
+ value: 0,
15884
+ },
15438
15885
  };
15439
15886
  }
15440
15887
 
15441
15888
  static get observers() {
15442
15889
  return [
15443
- '__positionSettingsChanged(horizontalAlign, verticalAlign, noHorizontalOverlap, noVerticalOverlap)',
15890
+ '__positionSettingsChanged(horizontalAlign, verticalAlign, noHorizontalOverlap, noVerticalOverlap, requiredVerticalSpace)',
15444
15891
  '__overlayOpenedChanged(opened, positionTarget)',
15445
15892
  ];
15446
15893
  }
@@ -15448,6 +15895,7 @@ const PositionMixin = (superClass) =>
15448
15895
  constructor() {
15449
15896
  super();
15450
15897
 
15898
+ this.__onScroll = this.__onScroll.bind(this);
15451
15899
  this._updatePosition = this._updatePosition.bind(this);
15452
15900
  }
15453
15901
 
@@ -15472,7 +15920,7 @@ const PositionMixin = (superClass) =>
15472
15920
 
15473
15921
  this.__positionTargetAncestorRootNodes = getAncestorRootNodes(this.positionTarget);
15474
15922
  this.__positionTargetAncestorRootNodes.forEach((node) => {
15475
- node.addEventListener('scroll', this._updatePosition, true);
15923
+ node.addEventListener('scroll', this.__onScroll, true);
15476
15924
  });
15477
15925
  }
15478
15926
 
@@ -15482,7 +15930,7 @@ const PositionMixin = (superClass) =>
15482
15930
 
15483
15931
  if (this.__positionTargetAncestorRootNodes) {
15484
15932
  this.__positionTargetAncestorRootNodes.forEach((node) => {
15485
- node.removeEventListener('scroll', this._updatePosition, true);
15933
+ node.removeEventListener('scroll', this.__onScroll, true);
15486
15934
  });
15487
15935
  this.__positionTargetAncestorRootNodes = null;
15488
15936
  }
@@ -15492,8 +15940,15 @@ const PositionMixin = (superClass) =>
15492
15940
  __overlayOpenedChanged(opened, positionTarget) {
15493
15941
  this.__removeUpdatePositionEventListeners();
15494
15942
 
15495
- if (opened && positionTarget) {
15496
- this.__addUpdatePositionEventListeners();
15943
+ if (positionTarget) {
15944
+ positionTarget.__overlay = null;
15945
+ targetResizeObserver.unobserve(positionTarget);
15946
+
15947
+ if (opened) {
15948
+ this.__addUpdatePositionEventListeners();
15949
+ positionTarget.__overlay = this;
15950
+ targetResizeObserver.observe(positionTarget);
15951
+ }
15497
15952
  }
15498
15953
 
15499
15954
  if (opened) {
@@ -15520,6 +15975,14 @@ const PositionMixin = (superClass) =>
15520
15975
  this._updatePosition();
15521
15976
  }
15522
15977
 
15978
+ /** @private */
15979
+ __onScroll(e) {
15980
+ // If the scroll event occurred inside the overlay, ignore it.
15981
+ if (!this.contains(e.target)) {
15982
+ this._updatePosition();
15983
+ }
15984
+ }
15985
+
15523
15986
  _updatePosition() {
15524
15987
  if (!this.positionTarget || !this.opened) {
15525
15988
  return;
@@ -15592,7 +16055,8 @@ const PositionMixin = (superClass) =>
15592
16055
  __shouldAlignStartVertically(targetRect) {
15593
16056
  // Using previous size to fix a case where window resize may cause the overlay to be squeezed
15594
16057
  // smaller than its current space before the fit-calculations.
15595
- const contentHeight = Math.max(this.__oldContentHeight || 0, this.$.overlay.offsetHeight);
16058
+ const contentHeight =
16059
+ this.requiredVerticalSpace || Math.max(this.__oldContentHeight || 0, this.$.overlay.offsetHeight);
15596
16060
  this.__oldContentHeight = this.$.overlay.offsetHeight;
15597
16061
 
15598
16062
  const viewportHeight = Math.min(window.innerHeight, document.documentElement.clientHeight);
@@ -15624,9 +16088,47 @@ const PositionMixin = (superClass) =>
15624
16088
  return defaultAlignStart === shouldGoToDefaultSide;
15625
16089
  }
15626
16090
 
16091
+ /**
16092
+ * Returns an adjusted value after resizing the browser window,
16093
+ * to avoid wrong calculations when e.g. previously set `bottom`
16094
+ * CSS property value is larger than the updated viewport height.
16095
+ * See https://github.com/vaadin/web-components/issues/4604
16096
+ */
16097
+ __adjustBottomProperty(cssPropNameToSet, propNames, currentValue) {
16098
+ let adjustedProp;
16099
+
16100
+ if (cssPropNameToSet === propNames.end) {
16101
+ // Adjust horizontally
16102
+ if (propNames.end === PROP_NAMES_VERTICAL.end) {
16103
+ const viewportHeight = Math.min(window.innerHeight, document.documentElement.clientHeight);
16104
+
16105
+ if (currentValue > viewportHeight && this.__oldViewportHeight) {
16106
+ const heightDiff = this.__oldViewportHeight - viewportHeight;
16107
+ adjustedProp = currentValue - heightDiff;
16108
+ }
16109
+
16110
+ this.__oldViewportHeight = viewportHeight;
16111
+ }
16112
+
16113
+ // Adjust vertically
16114
+ if (propNames.end === PROP_NAMES_HORIZONTAL.end) {
16115
+ const viewportWidth = Math.min(window.innerWidth, document.documentElement.clientWidth);
16116
+
16117
+ if (currentValue > viewportWidth && this.__oldViewportWidth) {
16118
+ const widthDiff = this.__oldViewportWidth - viewportWidth;
16119
+ adjustedProp = currentValue - widthDiff;
16120
+ }
16121
+
16122
+ this.__oldViewportWidth = viewportWidth;
16123
+ }
16124
+ }
16125
+
16126
+ return adjustedProp;
16127
+ }
16128
+
15627
16129
  /**
15628
16130
  * Returns an object with CSS position properties to set,
15629
- * e.g. { top: "100px", bottom: "" }
16131
+ * e.g. { top: "100px" }
15630
16132
  */
15631
16133
  // eslint-disable-next-line max-params
15632
16134
  __calculatePositionInOneDimension(targetRect, overlayRect, noOverlap, propNames, overlay, shouldAlignStart) {
@@ -15634,13 +16136,18 @@ const PositionMixin = (superClass) =>
15634
16136
  const cssPropNameToClear = shouldAlignStart ? propNames.end : propNames.start;
15635
16137
 
15636
16138
  const currentValue = parseFloat(overlay.style[cssPropNameToSet] || getComputedStyle(overlay)[cssPropNameToSet]);
16139
+ const adjustedValue = this.__adjustBottomProperty(cssPropNameToSet, propNames, currentValue);
15637
16140
 
15638
16141
  const diff =
15639
16142
  overlayRect[shouldAlignStart ? propNames.start : propNames.end] -
15640
16143
  targetRect[noOverlap === shouldAlignStart ? propNames.end : propNames.start];
15641
16144
 
16145
+ const valueToSet = adjustedValue
16146
+ ? `${adjustedValue}px`
16147
+ : `${currentValue + diff * (shouldAlignStart ? -1 : 1)}px`;
16148
+
15642
16149
  return {
15643
- [cssPropNameToSet]: `${currentValue + diff * (shouldAlignStart ? -1 : 1)}px`,
16150
+ [cssPropNameToSet]: valueToSet,
15644
16151
  [cssPropNameToClear]: '',
15645
16152
  };
15646
16153
  }
@@ -15657,11 +16164,6 @@ const datePickerStyles = i$1`
15657
16164
  direction: ltr;
15658
16165
  }
15659
16166
 
15660
- :host([dir='rtl']) [part='value']::placeholder {
15661
- direction: rtl;
15662
- text-align: left;
15663
- }
15664
-
15665
16167
  :host([dir='rtl']) [part='input-field'] ::slotted(input)::placeholder {
15666
16168
  direction: rtl;
15667
16169
  text-align: left;
@@ -15694,10 +16196,10 @@ let memoizedTemplate;
15694
16196
  /**
15695
16197
  * An element used internally by `<vaadin-date-picker>`. Not intended to be used separately.
15696
16198
  *
15697
- * @extends OverlayElement
16199
+ * @extends Overlay
15698
16200
  * @private
15699
16201
  */
15700
- class DatePickerOverlay extends DisableUpgradeMixin(PositionMixin(OverlayElement)) {
16202
+ class DatePickerOverlay extends DisableUpgradeMixin(PositionMixin(Overlay)) {
15701
16203
  static get is() {
15702
16204
  return 'vaadin-date-picker-overlay';
15703
16205
  }
@@ -16837,6 +17339,53 @@ function extractDateParts(date) {
16837
17339
  };
16838
17340
  }
16839
17341
 
17342
+ /**
17343
+ * Calculate the year of the date based on the provided reference date.
17344
+ * Gets a two-digit year and returns a full year.
17345
+ * @param {!Date} referenceDate The date to act as basis in the calculation
17346
+ * @param {!number} year Should be in the range of [0, 99]
17347
+ * @param {number} month
17348
+ * @param {number} day
17349
+ * @return {!number} Adjusted year value
17350
+ */
17351
+ function getAdjustedYear(referenceDate, year, month = 0, day = 1) {
17352
+ if (year > 99) {
17353
+ throw new Error('The provided year cannot have more than 2 digits.');
17354
+ }
17355
+ if (year < 0) {
17356
+ throw new Error('The provided year cannot be negative.');
17357
+ }
17358
+ // Year values up to 2 digits are parsed based on the reference date.
17359
+ let adjustedYear = year + Math.floor(referenceDate.getFullYear() / 100) * 100;
17360
+ if (referenceDate < new Date(adjustedYear - 50, month, day)) {
17361
+ adjustedYear -= 100;
17362
+ } else if (referenceDate > new Date(adjustedYear + 50, month, day)) {
17363
+ adjustedYear += 100;
17364
+ }
17365
+ return adjustedYear;
17366
+ }
17367
+
17368
+ /**
17369
+ * Parse date string of one of the following date formats:
17370
+ * - ISO 8601 `"YYYY-MM-DD"`
17371
+ * - 6-digit extended ISO 8601 `"+YYYYYY-MM-DD"`, `"-YYYYYY-MM-DD"`
17372
+ * @param {!string} str Date string to parse
17373
+ * @return {Date} Parsed date
17374
+ */
17375
+ function parseDate(str) {
17376
+ // Parsing with RegExp to ensure correct format
17377
+ const parts = /^([-+]\d{1}|\d{2,4}|[-+]\d{6})-(\d{1,2})-(\d{1,2})$/.exec(str);
17378
+ if (!parts) {
17379
+ return undefined;
17380
+ }
17381
+
17382
+ const date = new Date(0, 0); // Wrong date (1900-01-01), but with midnight in local time
17383
+ date.setFullYear(parseInt(parts[1], 10));
17384
+ date.setMonth(parseInt(parts[2], 10) - 1);
17385
+ date.setDate(parseInt(parts[3], 10));
17386
+ return date;
17387
+ }
17388
+
16840
17389
  /**
16841
17390
  * @license
16842
17391
  * Copyright (c) 2016 - 2022 Vaadin Ltd.
@@ -16913,7 +17462,9 @@ class MonthCalendar extends FocusMixin(ThemableMixin(PolymerElement)) {
16913
17462
  is="dom-repeat"
16914
17463
  items="[[_getWeekDayNames(i18n.weekdays, i18n.weekdaysShort, showWeekNumbers, i18n.firstDayOfWeek)]]"
16915
17464
  >
16916
- <th role="columnheader" part="weekday" scope="col" abbr$="[[item.weekDay]]">[[item.weekDayShort]]</th>
17465
+ <th role="columnheader" part="weekday" scope="col" abbr$="[[item.weekDay]]" aria-hidden="true">
17466
+ [[item.weekDayShort]]
17467
+ </th>
16917
17468
  </template>
16918
17469
  </tr>
16919
17470
  </thead>
@@ -17083,7 +17634,9 @@ class MonthCalendar extends FocusMixin(ThemableMixin(PolymerElement)) {
17083
17634
 
17084
17635
  _onMonthGridTouchStart() {
17085
17636
  this._notTapping = false;
17086
- setTimeout(() => (this._notTapping = true), 300);
17637
+ setTimeout(() => {
17638
+ this._notTapping = true;
17639
+ }, 300);
17087
17640
  }
17088
17641
 
17089
17642
  _dateAdd(date, delta) {
@@ -17257,12 +17810,6 @@ class MonthCalendar extends FocusMixin(ThemableMixin(PolymerElement)) {
17257
17810
 
17258
17811
  return '-1';
17259
17812
  }
17260
-
17261
- __getWeekNumbers(dates) {
17262
- return dates
17263
- .map((date) => this.__getWeekNumber(date, dates))
17264
- .filter((week, index, arr) => arr.indexOf(week) === index);
17265
- }
17266
17813
  }
17267
17814
 
17268
17815
  customElements.define(MonthCalendar.is, MonthCalendar);
@@ -17352,6 +17899,7 @@ class InfiniteScroller extends PolymerElement {
17352
17899
  /**
17353
17900
  * The amount of initial scroll top. Needed in order for the
17354
17901
  * user to be able to scroll backwards.
17902
+ * @private
17355
17903
  */
17356
17904
  _initialScroll: {
17357
17905
  value: 500000,
@@ -17359,17 +17907,22 @@ class InfiniteScroller extends PolymerElement {
17359
17907
 
17360
17908
  /**
17361
17909
  * The index/position mapped at _initialScroll point.
17910
+ * @private
17362
17911
  */
17363
17912
  _initialIndex: {
17364
17913
  value: 0,
17365
17914
  },
17366
17915
 
17916
+ /** @private */
17367
17917
  _buffers: Array,
17368
17918
 
17919
+ /** @private */
17369
17920
  _preventScrollEvent: Boolean,
17370
17921
 
17922
+ /** @private */
17371
17923
  _mayHaveMomentum: Boolean,
17372
17924
 
17925
+ /** @private */
17373
17926
  _initialized: Boolean,
17374
17927
 
17375
17928
  active: {
@@ -17379,10 +17932,11 @@ class InfiniteScroller extends PolymerElement {
17379
17932
  };
17380
17933
  }
17381
17934
 
17935
+ /** @protected */
17382
17936
  ready() {
17383
17937
  super.ready();
17384
17938
 
17385
- this._buffers = Array.prototype.slice.call(this.root.querySelectorAll('.buffer'));
17939
+ this._buffers = [...this.shadowRoot.querySelectorAll('.buffer')];
17386
17940
 
17387
17941
  this.$.fullHeight.style.height = `${this._initialScroll * 2}px`;
17388
17942
 
@@ -17391,8 +17945,8 @@ class InfiniteScroller extends PolymerElement {
17391
17945
  forwardHostProp(prop, value) {
17392
17946
  if (prop !== 'index') {
17393
17947
  this._buffers.forEach((buffer) => {
17394
- [].forEach.call(buffer.children, (insertionPoint) => {
17395
- insertionPoint._itemWrapper.instance[prop] = value;
17948
+ [...buffer.children].forEach((slot) => {
17949
+ slot._itemWrapper.instance[prop] = value;
17396
17950
  });
17397
17951
  });
17398
17952
  }
@@ -17406,6 +17960,19 @@ class InfiniteScroller extends PolymerElement {
17406
17960
  }
17407
17961
  }
17408
17962
 
17963
+ /**
17964
+ * Force the scroller to update clones after a reset, without
17965
+ * waiting for the debouncer to resolve.
17966
+ */
17967
+ forceUpdate() {
17968
+ if (this._debouncerUpdateClones) {
17969
+ this._buffers[0].updated = this._buffers[1].updated = false;
17970
+ this._updateClones();
17971
+ this._debouncerUpdateClones.cancel();
17972
+ }
17973
+ }
17974
+
17975
+ /** @private */
17409
17976
  _activated(active) {
17410
17977
  if (active && !this._initialized) {
17411
17978
  this._createPool();
@@ -17413,12 +17980,15 @@ class InfiniteScroller extends PolymerElement {
17413
17980
  }
17414
17981
  }
17415
17982
 
17983
+ /** @private */
17416
17984
  _finishInit() {
17417
17985
  if (!this._initDone) {
17418
17986
  // Once the first set of items start fading in, stamp the rest
17419
17987
  this._buffers.forEach((buffer) => {
17420
- [].forEach.call(buffer.children, (insertionPoint) => this._ensureStampedInstance(insertionPoint._itemWrapper));
17421
- }, this);
17988
+ [...buffer.children].forEach((slot) => {
17989
+ this._ensureStampedInstance(slot._itemWrapper);
17990
+ });
17991
+ });
17422
17992
 
17423
17993
  if (!this._buffers[0].translateY) {
17424
17994
  this._reset();
@@ -17428,6 +17998,7 @@ class InfiniteScroller extends PolymerElement {
17428
17998
  }
17429
17999
  }
17430
18000
 
18001
+ /** @private */
17431
18002
  _translateBuffer(up) {
17432
18003
  const index = up ? 1 : 0;
17433
18004
  this._buffers[index].translateY = this._buffers[index ? 0 : 1].translateY + this._bufferHeight * (index ? -1 : 1);
@@ -17436,6 +18007,7 @@ class InfiniteScroller extends PolymerElement {
17436
18007
  this._buffers.reverse();
17437
18008
  }
17438
18009
 
18010
+ /** @private */
17439
18011
  _scroll() {
17440
18012
  if (this._scrollDisabled) {
17441
18013
  return;
@@ -17532,10 +18104,12 @@ class InfiniteScroller extends PolymerElement {
17532
18104
  return this._itemHeightVal;
17533
18105
  }
17534
18106
 
18107
+ /** @private */
17535
18108
  get _bufferHeight() {
17536
18109
  return this.itemHeight * this.bufferSize;
17537
18110
  }
17538
18111
 
18112
+ /** @private */
17539
18113
  _reset() {
17540
18114
  this._scrollDisabled = true;
17541
18115
  this.$.scroller.scrollTop = this._initialScroll;
@@ -17555,6 +18129,7 @@ class InfiniteScroller extends PolymerElement {
17555
18129
  this._scrollDisabled = false;
17556
18130
  }
17557
18131
 
18132
+ /** @private */
17558
18133
  _createPool() {
17559
18134
  const container = this.getBoundingClientRect();
17560
18135
  this._buffers.forEach((buffer) => {
@@ -17566,10 +18141,10 @@ class InfiniteScroller extends PolymerElement {
17566
18141
  const contentId = (InfiniteScroller._contentIndex = InfiniteScroller._contentIndex + 1 || 0);
17567
18142
  const slotName = `vaadin-infinite-scroller-item-content-${contentId}`;
17568
18143
 
17569
- const insertionPoint = document.createElement('slot');
17570
- insertionPoint.setAttribute('name', slotName);
17571
- insertionPoint._itemWrapper = itemWrapper;
17572
- buffer.appendChild(insertionPoint);
18144
+ const slot = document.createElement('slot');
18145
+ slot.setAttribute('name', slotName);
18146
+ slot._itemWrapper = itemWrapper;
18147
+ buffer.appendChild(slot);
17573
18148
 
17574
18149
  itemWrapper.setAttribute('slot', slotName);
17575
18150
  this.appendChild(itemWrapper);
@@ -17581,13 +18156,14 @@ class InfiniteScroller extends PolymerElement {
17581
18156
  }
17582
18157
  }, 1); // Wait for first reset
17583
18158
  }
17584
- }, this);
18159
+ });
17585
18160
 
17586
18161
  setTimeout(() => {
17587
18162
  afterNextRender(this, this._finishInit.bind(this));
17588
18163
  }, 1);
17589
18164
  }
17590
18165
 
18166
+ /** @private */
17591
18167
  _ensureStampedInstance(itemWrapper) {
17592
18168
  if (itemWrapper.firstElementChild) {
17593
18169
  return;
@@ -17603,6 +18179,7 @@ class InfiniteScroller extends PolymerElement {
17603
18179
  });
17604
18180
  }
17605
18181
 
18182
+ /** @private */
17606
18183
  _updateClones(viewPortOnly) {
17607
18184
  this._firstIndex = ~~((this._buffers[0].translateY - this._initialScroll) / this.itemHeight) + this._initialIndex;
17608
18185
 
@@ -17611,17 +18188,18 @@ class InfiniteScroller extends PolymerElement {
17611
18188
  if (!buffer.updated) {
17612
18189
  const firstIndex = this._firstIndex + this.bufferSize * bufferIndex;
17613
18190
 
17614
- [].forEach.call(buffer.children, (insertionPoint, index) => {
17615
- const itemWrapper = insertionPoint._itemWrapper;
18191
+ [...buffer.children].forEach((slot, index) => {
18192
+ const itemWrapper = slot._itemWrapper;
17616
18193
  if (!viewPortOnly || this._isVisible(itemWrapper, scrollerRect)) {
17617
18194
  itemWrapper.instance.index = firstIndex + index;
17618
18195
  }
17619
18196
  });
17620
18197
  buffer.updated = true;
17621
18198
  }
17622
- }, this);
18199
+ });
17623
18200
  }
17624
18201
 
18202
+ /** @private */
17625
18203
  _isVisible(element, container) {
17626
18204
  const rect = element.getBoundingClientRect();
17627
18205
  return rect.bottom > container.top && rect.top < container.bottom;
@@ -17718,7 +18296,6 @@ class DatePickerOverlayContent extends ControllerMixin(ThemableMixin(DirMixin(Po
17718
18296
  height: 100%;
17719
18297
  width: 100%;
17720
18298
  outline: none;
17721
- background: #fff;
17722
18299
  }
17723
18300
 
17724
18301
  [part='overlay-header'] {
@@ -17736,22 +18313,14 @@ class DatePickerOverlayContent extends ControllerMixin(ThemableMixin(DirMixin(Po
17736
18313
  flex-grow: 1;
17737
18314
  }
17738
18315
 
17739
- [part='clear-button']:not([showclear]) {
17740
- display: none;
18316
+ [hidden] {
18317
+ display: none !important;
17741
18318
  }
17742
18319
 
17743
18320
  [part='years-toggle-button'] {
17744
18321
  display: flex;
17745
18322
  }
17746
18323
 
17747
- [part='years-toggle-button'][desktop] {
17748
- display: none;
17749
- }
17750
-
17751
- :host(:not([years-visible])) [part='years-toggle-button']::before {
17752
- transform: rotate(180deg);
17753
- }
17754
-
17755
18324
  #scrollers {
17756
18325
  display: flex;
17757
18326
  height: 100%;
@@ -17825,27 +18394,14 @@ class DatePickerOverlayContent extends ControllerMixin(ThemableMixin(DirMixin(Po
17825
18394
  z-index: 2;
17826
18395
  flex-shrink: 0;
17827
18396
  }
17828
-
17829
- [part~='overlay-header']:not([desktop]) {
17830
- padding-bottom: 40px;
17831
- }
17832
-
17833
- [part~='years-toggle-button'] {
17834
- position: absolute;
17835
- top: auto;
17836
- right: 8px;
17837
- bottom: 0;
17838
- z-index: 1;
17839
- padding: 8px;
17840
- }
17841
18397
  </style>
17842
18398
 
17843
18399
  <div part="overlay-header" on-touchend="_preventDefault" desktop$="[[_desktopMode]]" aria-hidden="true">
17844
18400
  <div part="label">[[_formatDisplayed(selectedDate, i18n.formatDate, label)]]</div>
17845
- <div part="clear-button" showclear$="[[_showClear(selectedDate)]]"></div>
18401
+ <div part="clear-button" hidden$="[[!selectedDate]]"></div>
17846
18402
  <div part="toggle-button"></div>
17847
18403
 
17848
- <div part="years-toggle-button" desktop$="[[_desktopMode]]" aria-hidden="true">
18404
+ <div part="years-toggle-button" hidden$="[[_desktopMode]]" aria-hidden="true">
17849
18405
  [[_yearAfterXMonths(_visibleMonthIndex)]]
17850
18406
  </div>
17851
18407
  </div>
@@ -17931,6 +18487,7 @@ class DatePickerOverlayContent extends ControllerMixin(ThemableMixin(DirMixin(Po
17931
18487
  */
17932
18488
  selectedDate: {
17933
18489
  type: Date,
18490
+ value: null,
17934
18491
  },
17935
18492
 
17936
18493
  /**
@@ -18006,10 +18563,24 @@ class DatePickerOverlayContent extends ControllerMixin(ThemableMixin(DirMixin(Po
18006
18563
  return this.getAttribute('dir') === 'rtl';
18007
18564
  }
18008
18565
 
18566
+ /**
18567
+ * Whether to scroll to a sub-month position when scrolling to a date.
18568
+ * This is active if the month scroller is not large enough to fit a
18569
+ * full month. In that case we want to scroll to a position between
18570
+ * two months in order to have the focused date in the visible area.
18571
+ * @returns {boolean} whether to use sub-month scrolling
18572
+ * @private
18573
+ */
18574
+ get __useSubMonthScrolling() {
18575
+ return this.$.monthScroller.clientHeight < this.$.monthScroller.itemHeight + this.$.monthScroller.bufferOffset;
18576
+ }
18577
+
18578
+ get calendars() {
18579
+ return [...this.shadowRoot.querySelectorAll('vaadin-month-calendar')];
18580
+ }
18581
+
18009
18582
  get focusableDateElement() {
18010
- return [...this.shadowRoot.querySelectorAll('vaadin-month-calendar')]
18011
- .map((calendar) => calendar.focusableDateElement)
18012
- .find(Boolean);
18583
+ return this.calendars.map((calendar) => calendar.focusableDateElement).find(Boolean);
18013
18584
  }
18014
18585
 
18015
18586
  ready() {
@@ -18017,7 +18588,6 @@ class DatePickerOverlayContent extends ControllerMixin(ThemableMixin(DirMixin(Po
18017
18588
 
18018
18589
  this.setAttribute('role', 'dialog');
18019
18590
 
18020
- addListener(this, 'tap', this._stopPropagation);
18021
18591
  addListener(this.$.scrollers, 'track', this._track.bind(this));
18022
18592
  addListener(this.shadowRoot.querySelector('[part="clear-button"]'), 'tap', this._clear.bind(this));
18023
18593
  addListener(this.shadowRoot.querySelector('[part="today-button"]'), 'tap', this._onTodayTap.bind(this));
@@ -18062,7 +18632,9 @@ class DatePickerOverlayContent extends ControllerMixin(ThemableMixin(DirMixin(Po
18062
18632
  * Scrolls the list to the given Date.
18063
18633
  */
18064
18634
  scrollToDate(date, animate) {
18065
- this._scrollToPosition(this._differenceInMonths(date, this._originDate), animate);
18635
+ const offset = this.__useSubMonthScrolling ? this._calculateWeekScrollOffset(date) : 0;
18636
+ this._scrollToPosition(this._differenceInMonths(date, this._originDate) + offset, animate);
18637
+ this.$.monthScroller.forceUpdate();
18066
18638
  }
18067
18639
 
18068
18640
  /**
@@ -18094,23 +18666,63 @@ class DatePickerOverlayContent extends ControllerMixin(ThemableMixin(DirMixin(Po
18094
18666
  * Scrolls the month and year scrollers enough to reveal the given date.
18095
18667
  */
18096
18668
  revealDate(date, animate = true) {
18097
- if (date) {
18098
- const diff = this._differenceInMonths(date, this._originDate);
18099
- const scrolledAboveViewport = this.$.monthScroller.position > diff;
18669
+ if (!date) {
18670
+ return;
18671
+ }
18672
+ const diff = this._differenceInMonths(date, this._originDate);
18673
+ // If scroll area does not fit the full month, then always scroll with an offset to
18674
+ // approximately display the week of the date
18675
+ if (this.__useSubMonthScrolling) {
18676
+ const offset = this._calculateWeekScrollOffset(date);
18677
+ this._scrollToPosition(diff + offset, animate);
18678
+ return;
18679
+ }
18100
18680
 
18101
- const visibleArea = Math.max(
18102
- this.$.monthScroller.itemHeight,
18103
- this.$.monthScroller.clientHeight - this.$.monthScroller.bufferOffset * 2,
18104
- );
18105
- const visibleItems = visibleArea / this.$.monthScroller.itemHeight;
18106
- const scrolledBelowViewport = this.$.monthScroller.position + visibleItems - 1 < diff;
18681
+ // Otherwise determine if we need to scroll to make the month of the date visible
18682
+ const scrolledAboveViewport = this.$.monthScroller.position > diff;
18683
+
18684
+ const visibleArea = Math.max(
18685
+ this.$.monthScroller.itemHeight,
18686
+ this.$.monthScroller.clientHeight - this.$.monthScroller.bufferOffset * 2,
18687
+ );
18688
+ const visibleItems = visibleArea / this.$.monthScroller.itemHeight;
18689
+ const scrolledBelowViewport = this.$.monthScroller.position + visibleItems - 1 < diff;
18690
+
18691
+ if (scrolledAboveViewport) {
18692
+ this._scrollToPosition(diff, animate);
18693
+ } else if (scrolledBelowViewport) {
18694
+ this._scrollToPosition(diff - visibleItems + 1, animate);
18695
+ }
18696
+ }
18107
18697
 
18108
- if (scrolledAboveViewport) {
18109
- this._scrollToPosition(diff, animate);
18110
- } else if (scrolledBelowViewport) {
18111
- this._scrollToPosition(diff - visibleItems + 1, animate);
18698
+ /**
18699
+ * Calculates an offset to be added to the month scroll position
18700
+ * when using sub-month scrolling, in order ensure that the week
18701
+ * that the date is in is visible even for small scroll areas.
18702
+ * As the month scroller uses a month as minimal scroll unit
18703
+ * (a value of `1` equals one month), we can not exactly identify
18704
+ * the position of a specific week. This is a best effort
18705
+ * implementation based on manual testing.
18706
+ * @param date the date for which to calculate the offset
18707
+ * @returns {number} the offset
18708
+ * @private
18709
+ */
18710
+ _calculateWeekScrollOffset(date) {
18711
+ // Get first day of month
18712
+ const temp = new Date(0, 0);
18713
+ temp.setFullYear(date.getFullYear());
18714
+ temp.setMonth(date.getMonth());
18715
+ temp.setDate(1);
18716
+ // Determine week (=row index) of date within the month
18717
+ let week = 0;
18718
+ while (temp.getDate() < date.getDate()) {
18719
+ temp.setDate(temp.getDate() + 1);
18720
+ if (temp.getDay() === this.i18n.firstDayOfWeek) {
18721
+ week += 1;
18112
18722
  }
18113
18723
  }
18724
+ // Calculate magic number that approximately keeps the week visible
18725
+ return week / 6;
18114
18726
  }
18115
18727
 
18116
18728
  _initialPositionChanged(initialPosition) {
@@ -18139,7 +18751,9 @@ class DatePickerOverlayContent extends ControllerMixin(ThemableMixin(DirMixin(Po
18139
18751
 
18140
18752
  _onYearScrollTouchStart() {
18141
18753
  this._notTapping = false;
18142
- setTimeout(() => (this._notTapping = true), 300);
18754
+ setTimeout(() => {
18755
+ this._notTapping = true;
18756
+ }, 300);
18143
18757
 
18144
18758
  this._repositionMonthScroller();
18145
18759
  }
@@ -18150,7 +18764,9 @@ class DatePickerOverlayContent extends ControllerMixin(ThemableMixin(DirMixin(Po
18150
18764
 
18151
18765
  _doIgnoreTaps() {
18152
18766
  this._ignoreTaps = true;
18153
- this._debouncer = Debouncer$1.debounce(this._debouncer, timeOut.after(300), () => (this._ignoreTaps = false));
18767
+ this._debouncer = Debouncer$1.debounce(this._debouncer, timeOut.after(300), () => {
18768
+ this._ignoreTaps = false;
18769
+ });
18154
18770
  }
18155
18771
 
18156
18772
  _formatDisplayed(date, formatDate, label) {
@@ -18181,10 +18797,6 @@ class DatePickerOverlayContent extends ControllerMixin(ThemableMixin(DirMixin(Po
18181
18797
  this.scrollToDate(new Date(), true);
18182
18798
  }
18183
18799
 
18184
- _showClear(selectedDate) {
18185
- return !!selectedDate;
18186
- }
18187
-
18188
18800
  _onYearTap(e) {
18189
18801
  if (!this._ignoreTaps && !this._notTapping) {
18190
18802
  const scrollDelta =
@@ -18210,6 +18822,11 @@ class DatePickerOverlayContent extends ControllerMixin(ThemableMixin(DirMixin(Po
18210
18822
 
18211
18823
  this._targetPosition = targetPosition;
18212
18824
 
18825
+ let revealResolve;
18826
+ this._revealPromise = new Promise((resolve) => {
18827
+ revealResolve = resolve;
18828
+ });
18829
+
18213
18830
  // http://gizma.com/easing/
18214
18831
  const easingFunction = (t, b, c, d) => {
18215
18832
  t /= d / 2;
@@ -18250,7 +18867,9 @@ class DatePickerOverlayContent extends ControllerMixin(ThemableMixin(DirMixin(Po
18250
18867
 
18251
18868
  this.$.monthScroller.position = this._targetPosition;
18252
18869
  this._targetPosition = undefined;
18253
- this.__tryFocusDate();
18870
+
18871
+ revealResolve();
18872
+ this._revealPromise = undefined;
18254
18873
  }
18255
18874
 
18256
18875
  setTimeout(this._repositionYearScroller.bind(this), 1);
@@ -18366,10 +18985,6 @@ class DatePickerOverlayContent extends ControllerMixin(ThemableMixin(DirMixin(Po
18366
18985
  return months - date2.getMonth() + date1.getMonth();
18367
18986
  }
18368
18987
 
18369
- _differenceInYears(date1, date2) {
18370
- return this._differenceInMonths(date1, date2) / 12;
18371
- }
18372
-
18373
18988
  _clear() {
18374
18989
  this._selectDate('');
18375
18990
  }
@@ -18460,51 +19075,44 @@ class DatePickerOverlayContent extends ControllerMixin(ThemableMixin(DirMixin(Po
18460
19075
  switch (section) {
18461
19076
  case 'calendar':
18462
19077
  if (event.shiftKey) {
18463
- // Return focus back to the input field.
18464
19078
  event.preventDefault();
18465
- this.__focusInput();
19079
+
19080
+ if (this.hasAttribute('fullscreen')) {
19081
+ // Trap focus in the overlay
19082
+ this.$.cancelButton.focus();
19083
+ } else {
19084
+ this.__focusInput();
19085
+ }
18466
19086
  }
18467
19087
  break;
18468
19088
  case 'today':
18469
19089
  if (event.shiftKey) {
18470
- // Browser returns focus back to the calendar.
18471
- // We need to move the scroll to focused date.
18472
- setTimeout(() => this.revealDate(this.focusedDate), 1);
19090
+ event.preventDefault();
19091
+ this.focusDateElement();
18473
19092
  }
18474
19093
  break;
18475
19094
  case 'cancel':
18476
19095
  if (!event.shiftKey) {
18477
- // Return focus back to the input field.
18478
19096
  event.preventDefault();
18479
- this.__focusInput();
19097
+
19098
+ if (this.hasAttribute('fullscreen')) {
19099
+ // Trap focus in the overlay
19100
+ this.focusDateElement();
19101
+ } else {
19102
+ this.__focusInput();
19103
+ }
18480
19104
  }
18481
19105
  break;
18482
19106
  }
18483
19107
  }
18484
19108
 
18485
19109
  __onTodayButtonKeyDown(event) {
18486
- if (this.hasAttribute('fullscreen')) {
18487
- // Do not prevent closing on Esc
18488
- if (event.key !== 'Escape') {
18489
- event.stopPropagation();
18490
- }
18491
- return;
18492
- }
18493
-
18494
19110
  if (event.key === 'Tab') {
18495
19111
  this._onTabKeyDown(event, 'today');
18496
19112
  }
18497
19113
  }
18498
19114
 
18499
19115
  __onCancelButtonKeyDown(event) {
18500
- if (this.hasAttribute('fullscreen')) {
18501
- // Do not prevent closing on Esc
18502
- if (event.key !== 'Escape') {
18503
- event.stopPropagation();
18504
- }
18505
- return;
18506
- }
18507
-
18508
19116
  if (event.key === 'Tab') {
18509
19117
  this._onTabKeyDown(event, 'cancel');
18510
19118
  }
@@ -18533,15 +19141,29 @@ class DatePickerOverlayContent extends ControllerMixin(ThemableMixin(DirMixin(Po
18533
19141
  if (!keepMonth) {
18534
19142
  this._focusedMonthDate = dateToFocus.getDate();
18535
19143
  }
18536
- await this.focusDateElement();
19144
+ await this.focusDateElement(false);
18537
19145
  }
18538
19146
 
18539
- async focusDateElement() {
19147
+ async focusDateElement(reveal = true) {
18540
19148
  this.__pendingDateFocus = this.focusedDate;
18541
19149
 
18542
- await new Promise((resolve) => {
18543
- requestAnimationFrame(resolve);
18544
- });
19150
+ // Wait for `vaadin-month-calendar` elements to be rendered
19151
+ if (!this.calendars.length) {
19152
+ await new Promise((resolve) => {
19153
+ setTimeout(resolve);
19154
+ });
19155
+ }
19156
+
19157
+ // Reveal focused date unless it has been just set,
19158
+ // which triggers `revealDate()` in the observer.
19159
+ if (reveal) {
19160
+ this.revealDate(this.focusedDate);
19161
+ }
19162
+
19163
+ if (this._revealPromise) {
19164
+ // Wait for focused date to be scrolled into view.
19165
+ await this._revealPromise;
19166
+ }
18545
19167
 
18546
19168
  this.__tryFocusDate();
18547
19169
  }
@@ -18639,10 +19261,6 @@ class DatePickerOverlayContent extends ControllerMixin(ThemableMixin(DirMixin(Po
18639
19261
  todayMidnight.setDate(today.getDate());
18640
19262
  return this._dateAllowed(todayMidnight, min, max);
18641
19263
  }
18642
-
18643
- _stopPropagation(e) {
18644
- e.stopPropagation();
18645
- }
18646
19264
  }
18647
19265
 
18648
19266
  customElements.define(DatePickerOverlayContent.is, DatePickerOverlayContent);
@@ -18817,233 +19435,61 @@ const DelegateFocusMixin = dedupingMixin(
18817
19435
  * @protected
18818
19436
  * @override
18819
19437
  */
18820
- _shouldSetFocus(event) {
18821
- return event.target === this.focusElement;
18822
- }
18823
-
18824
- /**
18825
- * @param {boolean} disabled
18826
- * @param {boolean} oldDisabled
18827
- * @protected
18828
- * @override
18829
- */
18830
- _disabledChanged(disabled, oldDisabled) {
18831
- super._disabledChanged(disabled, oldDisabled);
18832
-
18833
- if (this.focusElement) {
18834
- this.focusElement.disabled = disabled;
18835
- }
18836
-
18837
- if (disabled) {
18838
- this.blur();
18839
- }
18840
- }
18841
-
18842
- /**
18843
- * Override an observer from `TabindexMixin`.
18844
- * Do not call super to remove tabindex attribute
18845
- * from the host after it has been forwarded.
18846
- * @param {string} tabindex
18847
- * @protected
18848
- * @override
18849
- */
18850
- _tabindexChanged(tabindex) {
18851
- this.__forwardTabIndex(tabindex);
18852
- }
18853
-
18854
- /** @private */
18855
- __forwardTabIndex(tabindex) {
18856
- if (tabindex !== undefined && this.focusElement) {
18857
- this.focusElement.tabIndex = tabindex;
18858
-
18859
- // Preserve tabindex="-1" on the host element
18860
- if (tabindex !== -1) {
18861
- this.tabindex = undefined;
18862
- }
18863
- }
18864
-
18865
- if (this.disabled && tabindex) {
18866
- // If tabindex attribute was changed while component was disabled
18867
- if (tabindex !== -1) {
18868
- this._lastTabIndex = tabindex;
18869
- }
18870
- this.tabindex = undefined;
18871
- }
18872
- }
18873
- },
18874
- );
18875
-
18876
- /**
18877
- * @license
18878
- * Copyright (c) 2021 - 2022 Vaadin Ltd.
18879
- * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
18880
- */
18881
-
18882
- /**
18883
- * A controller for providing content to slot element and observing changes.
18884
- */
18885
- class SlotController extends EventTarget {
18886
- /**
18887
- * Ensure that every instance has unique ID.
18888
- *
18889
- * @param {string} slotName
18890
- * @param {HTMLElement} host
18891
- * @return {string}
18892
- * @protected
18893
- */
18894
- static generateId(slotName, host) {
18895
- const prefix = slotName || 'default';
18896
-
18897
- // Support dash-case slot names e.g. "error-message"
18898
- const field = `${dashToCamelCase(prefix)}Id`;
18899
-
18900
- // Maintain the unique ID counter for a given prefix.
18901
- this[field] = 1 + this[field] || 0;
18902
-
18903
- return `${prefix}-${host.localName}-${this[field]}`;
18904
- }
18905
-
18906
- constructor(host, slotName, slotFactory, slotInitializer) {
18907
- super();
18908
-
18909
- this.host = host;
18910
- this.slotName = slotName;
18911
- this.slotFactory = slotFactory;
18912
- this.slotInitializer = slotInitializer;
18913
- this.defaultId = SlotController.generateId(slotName, host);
18914
- }
18915
-
18916
- hostConnected() {
18917
- if (!this.initialized) {
18918
- let node = this.getSlotChild();
18919
-
18920
- if (!node) {
18921
- node = this.attachDefaultNode();
18922
- } else {
18923
- this.node = node;
18924
- this.initCustomNode(node);
18925
- }
18926
-
18927
- this.initNode(node);
18928
-
18929
- // TODO: Consider making this behavior opt-in to improve performance.
18930
- this.observe();
18931
-
18932
- this.initialized = true;
18933
- }
18934
- }
18935
-
18936
- /**
18937
- * Create and attach default node using the slot factory.
18938
- * @return {Node | undefined}
18939
- * @protected
18940
- */
18941
- attachDefaultNode() {
18942
- const { host, slotName, slotFactory } = this;
18943
-
18944
- // Check if the node was created previously and if so, reuse it.
18945
- let node = this.defaultNode;
18946
-
18947
- // Slot factory is optional, some slots don't have default content.
18948
- if (!node && slotFactory) {
18949
- node = slotFactory(host);
18950
- if (node instanceof Element) {
18951
- if (slotName !== '') {
18952
- node.setAttribute('slot', slotName);
18953
- }
18954
- this.node = node;
18955
- this.defaultNode = node;
18956
- }
18957
- }
18958
-
18959
- if (node) {
18960
- host.appendChild(node);
18961
- }
18962
-
18963
- return node;
18964
- }
18965
-
18966
- /**
18967
- * Return a reference to the node managed by the controller.
18968
- * @return {Node}
18969
- */
18970
- getSlotChild() {
18971
- const { slotName } = this;
18972
- return Array.from(this.host.childNodes).find((node) => {
18973
- // Either an element (any slot) or a text node (only un-named slot).
18974
- return (
18975
- (node.nodeType === Node.ELEMENT_NODE && node.slot === slotName) ||
18976
- (node.nodeType === Node.TEXT_NODE && node.textContent.trim() && slotName === '')
18977
- );
18978
- });
18979
- }
18980
-
18981
- /**
18982
- * @param {Node} node
18983
- * @protected
18984
- */
18985
- initNode(node) {
18986
- const { slotInitializer } = this;
18987
- // Don't try to bind `this` to initializer (normally it's arrow function).
18988
- // Instead, pass the host as a first argument to access component's state.
18989
- if (slotInitializer) {
18990
- slotInitializer(this.host, node);
18991
- }
18992
- }
18993
-
18994
- /**
18995
- * Override to initialize the newly added custom node.
18996
- *
18997
- * @param {Node} _node
18998
- * @protected
18999
- */
19000
- initCustomNode(_node) {}
19001
-
19002
- /**
19003
- * Override to teardown slotted node when it's removed.
19004
- *
19005
- * @param {Node} _node
19006
- * @protected
19007
- */
19008
- teardownNode(_node) {}
19009
-
19010
- /**
19011
- * Setup the observer to manage slot content changes.
19012
- * @protected
19013
- */
19014
- observe() {
19015
- const { slotName } = this;
19016
- const selector = slotName === '' ? 'slot:not([name])' : `slot[name=${slotName}]`;
19017
- const slot = this.host.shadowRoot.querySelector(selector);
19438
+ _shouldSetFocus(event) {
19439
+ return event.target === this.focusElement;
19440
+ }
19018
19441
 
19019
- this.__slotObserver = new FlattenedNodesObserver(slot, (info) => {
19020
- // TODO: support default slot with multiple nodes (e.g. confirm-dialog)
19021
- const current = this.node;
19022
- const newNode = info.addedNodes.find((node) => node !== current);
19442
+ /**
19443
+ * @param {boolean} disabled
19444
+ * @param {boolean} oldDisabled
19445
+ * @protected
19446
+ * @override
19447
+ */
19448
+ _disabledChanged(disabled, oldDisabled) {
19449
+ super._disabledChanged(disabled, oldDisabled);
19023
19450
 
19024
- if (info.removedNodes.length) {
19025
- info.removedNodes.forEach((node) => {
19026
- this.teardownNode(node);
19027
- });
19028
- }
19451
+ if (this.focusElement) {
19452
+ this.focusElement.disabled = disabled;
19453
+ }
19029
19454
 
19030
- if (newNode) {
19031
- // Custom node is added, remove the current one.
19032
- if (current && current.isConnected) {
19033
- this.host.removeChild(current);
19455
+ if (disabled) {
19456
+ this.blur();
19034
19457
  }
19458
+ }
19035
19459
 
19036
- this.node = newNode;
19460
+ /**
19461
+ * Override an observer from `TabindexMixin`.
19462
+ * Do not call super to remove tabindex attribute
19463
+ * from the host after it has been forwarded.
19464
+ * @param {string} tabindex
19465
+ * @protected
19466
+ * @override
19467
+ */
19468
+ _tabindexChanged(tabindex) {
19469
+ this.__forwardTabIndex(tabindex);
19470
+ }
19037
19471
 
19038
- if (newNode !== this.defaultNode) {
19039
- this.initCustomNode(newNode);
19472
+ /** @private */
19473
+ __forwardTabIndex(tabindex) {
19474
+ if (tabindex !== undefined && this.focusElement) {
19475
+ this.focusElement.tabIndex = tabindex;
19040
19476
 
19041
- this.initNode(newNode);
19477
+ // Preserve tabindex="-1" on the host element
19478
+ if (tabindex !== -1) {
19479
+ this.tabindex = undefined;
19480
+ }
19481
+ }
19482
+
19483
+ if (this.disabled && tabindex) {
19484
+ // If tabindex attribute was changed while component was disabled
19485
+ if (tabindex !== -1) {
19486
+ this._lastTabIndex = tabindex;
19487
+ }
19488
+ this.tabindex = undefined;
19042
19489
  }
19043
19490
  }
19044
- });
19045
- }
19046
- }
19491
+ },
19492
+ );
19047
19493
 
19048
19494
  /**
19049
19495
  * @license
@@ -19065,6 +19511,7 @@ class ErrorController extends SlotController {
19065
19511
 
19066
19512
  this.__updateHasError();
19067
19513
  },
19514
+ true,
19068
19515
  );
19069
19516
  }
19070
19517
 
@@ -19100,7 +19547,7 @@ class ErrorController extends SlotController {
19100
19547
  }
19101
19548
 
19102
19549
  /**
19103
- * Override to initialize the newly added custom label.
19550
+ * Override to initialize the newly added custom error message.
19104
19551
  *
19105
19552
  * @param {Node} errorNode
19106
19553
  * @protected
@@ -19118,7 +19565,7 @@ class ErrorController extends SlotController {
19118
19565
  }
19119
19566
 
19120
19567
  /**
19121
- * Override to cleanup label node when it's removed.
19568
+ * Override to cleanup error message node when it's removed.
19122
19569
  *
19123
19570
  * @param {Node} node
19124
19571
  * @protected
@@ -19131,7 +19578,7 @@ class ErrorController extends SlotController {
19131
19578
  if (!errorNode && node !== this.defaultNode) {
19132
19579
  errorNode = this.attachDefaultNode();
19133
19580
 
19134
- // Run initializer to update default label and ID.
19581
+ // Run initializer to update default error message ID.
19135
19582
  this.initNode(errorNode);
19136
19583
  }
19137
19584
 
@@ -19179,63 +19626,6 @@ class ErrorController extends SlotController {
19179
19626
  }
19180
19627
  }
19181
19628
 
19182
- /**
19183
- * @license
19184
- * Copyright (c) 2021 - 2022 Vaadin Ltd.
19185
- * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
19186
- */
19187
-
19188
- /**
19189
- * @param {string} value
19190
- * @return {Set<string>}
19191
- */
19192
- function deserializeAttributeValue(value) {
19193
- if (!value) {
19194
- return new Set();
19195
- }
19196
-
19197
- return new Set(value.split(' '));
19198
- }
19199
-
19200
- /**
19201
- * @param {Set<string>} values
19202
- * @return {string}
19203
- */
19204
- function serializeAttributeValue(values) {
19205
- return [...values].join(' ');
19206
- }
19207
-
19208
- /**
19209
- * Adds a value to an attribute containing space-delimited values.
19210
- *
19211
- * @param {HTMLElement} element
19212
- * @param {string} attr
19213
- * @param {string} value
19214
- */
19215
- function addValueToAttribute(element, attr, value) {
19216
- const values = deserializeAttributeValue(element.getAttribute(attr));
19217
- values.add(value);
19218
- element.setAttribute(attr, serializeAttributeValue(values));
19219
- }
19220
-
19221
- /**
19222
- * Removes a value from an attribute containing space-delimited values.
19223
- * If the value is the last one, the whole attribute is removed.
19224
- *
19225
- * @param {HTMLElement} element
19226
- * @param {string} attr
19227
- * @param {string} value
19228
- */
19229
- function removeValueFromAttribute(element, attr, value) {
19230
- const values = deserializeAttributeValue(element.getAttribute(attr));
19231
- values.delete(value);
19232
- if (values.size === 0) {
19233
- element.removeAttribute(attr);
19234
- return;
19235
- }
19236
- element.setAttribute(attr, serializeAttributeValue(values));
19237
- }
19238
-
19239
19629
  /**
19240
19630
  * @license
19241
19631
  * Copyright (c) 2021 - 2022 Vaadin Ltd.
@@ -19410,7 +19800,7 @@ class FieldAriaController {
19410
19800
 
19411
19801
  /**
19412
19802
  * @license
19413
- * Copyright (c) 2021 Vaadin Ltd.
19803
+ * Copyright (c) 2021 - 2022 Vaadin Ltd.
19414
19804
  * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
19415
19805
  */
19416
19806
 
@@ -19420,7 +19810,7 @@ class FieldAriaController {
19420
19810
  class HelperController extends SlotController {
19421
19811
  constructor(host) {
19422
19812
  // Do not provide slot factory, as only create helper lazily.
19423
- super(host, 'helper');
19813
+ super(host, 'helper', null, null, true);
19424
19814
  }
19425
19815
 
19426
19816
  get helperId() {
@@ -19491,7 +19881,11 @@ class HelperController extends SlotController {
19491
19881
  return false;
19492
19882
  }
19493
19883
 
19494
- return helperNode.children.length > 0 || this.__isNotEmpty(helperNode.textContent);
19884
+ return (
19885
+ helperNode.children.length > 0 ||
19886
+ (helperNode.nodeType === Node.ELEMENT_NODE && customElements.get(helperNode.localName)) ||
19887
+ this.__isNotEmpty(helperNode.textContent)
19888
+ );
19495
19889
  }
19496
19890
 
19497
19891
  /**
@@ -19617,6 +20011,7 @@ class LabelController extends SlotController {
19617
20011
 
19618
20012
  this.__observeLabel(node);
19619
20013
  },
20014
+ true,
19620
20015
  );
19621
20016
  }
19622
20017
 
@@ -19791,7 +20186,7 @@ class LabelController extends SlotController {
19791
20186
  * A mixin to provide label via corresponding property or named slot.
19792
20187
  *
19793
20188
  * @polymerMixin
19794
- * @mixes SlotMixin
20189
+ * @mixes ControllerMixin
19795
20190
  */
19796
20191
  const LabelMixin = dedupingMixin(
19797
20192
  (superclass) =>
@@ -19823,6 +20218,12 @@ const LabelMixin = dedupingMixin(
19823
20218
  super();
19824
20219
 
19825
20220
  this._labelController = new LabelController(this);
20221
+ }
20222
+
20223
+ /** @protected */
20224
+ ready() {
20225
+ super.ready();
20226
+
19826
20227
  this.addController(this._labelController);
19827
20228
  }
19828
20229
 
@@ -19870,12 +20271,17 @@ const ValidateMixin = dedupingMixin(
19870
20271
  }
19871
20272
 
19872
20273
  /**
19873
- * Returns true if field is valid, and sets `invalid` based on the field validity.
20274
+ * Validates the field and sets the `invalid` property based on the result.
20275
+ *
20276
+ * The method fires a `validated` event with the result of the validation.
19874
20277
  *
19875
20278
  * @return {boolean} True if the value is valid.
19876
20279
  */
19877
20280
  validate() {
19878
- return !(this.invalid = !this.checkValidity());
20281
+ const isValid = this.checkValidity();
20282
+ this._setInvalid(!isValid);
20283
+ this.dispatchEvent(new CustomEvent('validated', { detail: { valid: isValid } }));
20284
+ return isValid;
19879
20285
  }
19880
20286
 
19881
20287
  /**
@@ -19886,6 +20292,35 @@ const ValidateMixin = dedupingMixin(
19886
20292
  checkValidity() {
19887
20293
  return !this.required || !!this.value;
19888
20294
  }
20295
+
20296
+ /**
20297
+ * @param {boolean} invalid
20298
+ * @protected
20299
+ */
20300
+ _setInvalid(invalid) {
20301
+ if (this._shouldSetInvalid(invalid)) {
20302
+ this.invalid = invalid;
20303
+ }
20304
+ }
20305
+
20306
+ /**
20307
+ * Override this method to define whether the given `invalid` state should be set.
20308
+ *
20309
+ * @param {boolean} _invalid
20310
+ * @return {boolean}
20311
+ * @protected
20312
+ */
20313
+ _shouldSetInvalid(_invalid) {
20314
+ return true;
20315
+ }
20316
+
20317
+ /**
20318
+ * Fired whenever the field is validated.
20319
+ *
20320
+ * @event validated
20321
+ * @param {Object} detail
20322
+ * @param {boolean} detail.valid the result of the validation.
20323
+ */
19889
20324
  },
19890
20325
  );
19891
20326
 
@@ -19974,10 +20409,6 @@ const FieldMixin = (superclass) =>
19974
20409
  this._helperController = new HelperController(this);
19975
20410
  this._errorController = new ErrorController(this);
19976
20411
 
19977
- this.addController(this._fieldAriaController);
19978
- this.addController(this._helperController);
19979
- this.addController(this._errorController);
19980
-
19981
20412
  this._labelController.addEventListener('label-changed', (event) => {
19982
20413
  const { hasLabel, node } = event.detail;
19983
20414
  this.__labelChanged(hasLabel, node);
@@ -19989,6 +20420,15 @@ const FieldMixin = (superclass) =>
19989
20420
  });
19990
20421
  }
19991
20422
 
20423
+ /** @protected */
20424
+ ready() {
20425
+ super.ready();
20426
+
20427
+ this.addController(this._fieldAriaController);
20428
+ this.addController(this._helperController);
20429
+ this.addController(this._errorController);
20430
+ }
20431
+
19992
20432
  /** @private */
19993
20433
  __helperChanged(hasHelper, helperNode) {
19994
20434
  if (hasHelper) {
@@ -20044,7 +20484,7 @@ const FieldMixin = (superclass) =>
20044
20484
  }
20045
20485
 
20046
20486
  /**
20047
- * @param {boolean} required
20487
+ * @param {boolean} invalid
20048
20488
  * @protected
20049
20489
  */
20050
20490
  _invalidChanged(invalid) {
@@ -20244,13 +20684,23 @@ const InputMixin = dedupingMixin(
20244
20684
  observer: '_valueChanged',
20245
20685
  notify: true,
20246
20686
  },
20687
+
20688
+ /**
20689
+ * When true, the input element has a non-empty value entered by the user.
20690
+ * @protected
20691
+ */
20692
+ _hasInputValue: {
20693
+ type: Boolean,
20694
+ value: false,
20695
+ observer: '_hasInputValueChanged',
20696
+ },
20247
20697
  };
20248
20698
  }
20249
20699
 
20250
20700
  constructor() {
20251
20701
  super();
20252
20702
 
20253
- this._boundOnInput = this._onInput.bind(this);
20703
+ this._boundOnInput = this.__onInput.bind(this);
20254
20704
  this._boundOnChange = this._onChange.bind(this);
20255
20705
  }
20256
20706
 
@@ -20265,6 +20715,7 @@ const InputMixin = dedupingMixin(
20265
20715
  * Add event listeners to the input element instance.
20266
20716
  * Override this method to add custom listeners.
20267
20717
  * @param {!HTMLElement} input
20718
+ * @protected
20268
20719
  */
20269
20720
  _addInputListeners(input) {
20270
20721
  input.addEventListener('input', this._boundOnInput);
@@ -20274,6 +20725,7 @@ const InputMixin = dedupingMixin(
20274
20725
  /**
20275
20726
  * Remove event listeners from the input element instance.
20276
20727
  * @param {!HTMLElement} input
20728
+ * @protected
20277
20729
  */
20278
20730
  _removeInputListeners(input) {
20279
20731
  input.removeEventListener('input', this._boundOnInput);
@@ -20287,7 +20739,6 @@ const InputMixin = dedupingMixin(
20287
20739
  * for example to skip this in certain conditions.
20288
20740
  * @param {string} value
20289
20741
  * @protected
20290
- * @override
20291
20742
  */
20292
20743
  _forwardInputValue(value) {
20293
20744
  // Value might be set before an input element is initialized.
@@ -20304,7 +20755,11 @@ const InputMixin = dedupingMixin(
20304
20755
  }
20305
20756
  }
20306
20757
 
20307
- /** @protected */
20758
+ /**
20759
+ * @param {HTMLElement | undefined} input
20760
+ * @param {HTMLElement | undefined} oldInput
20761
+ * @protected
20762
+ */
20308
20763
  _inputElementChanged(input, oldInput) {
20309
20764
  if (input) {
20310
20765
  this._addInputListeners(input);
@@ -20313,17 +20768,43 @@ const InputMixin = dedupingMixin(
20313
20768
  }
20314
20769
  }
20315
20770
 
20771
+ /**
20772
+ * Observer to notify about the change of private property.
20773
+ *
20774
+ * @private
20775
+ */
20776
+ _hasInputValueChanged(hasValue, oldHasValue) {
20777
+ if (hasValue || oldHasValue) {
20778
+ this.dispatchEvent(new CustomEvent('has-input-value-changed'));
20779
+ }
20780
+ }
20781
+
20782
+ /**
20783
+ * An input event listener used to update `_hasInputValue` property.
20784
+ * Do not override this method.
20785
+ *
20786
+ * @param {Event} event
20787
+ * @private
20788
+ */
20789
+ __onInput(event) {
20790
+ this._setHasInputValue(event);
20791
+ this._onInput(event);
20792
+ }
20793
+
20316
20794
  /**
20317
20795
  * An input event listener used to update the field value.
20318
- * Override this method with an actual implementation.
20319
- * @param {Event} _event
20796
+ *
20797
+ * @param {Event} event
20320
20798
  * @protected
20321
- * @override
20322
20799
  */
20323
20800
  _onInput(event) {
20801
+ // In the case a custom web component is passed as `inputElement`,
20802
+ // the actual native input element, on which the event occurred,
20803
+ // can be inside shadow trees.
20804
+ const target = event.composedPath()[0];
20324
20805
  // Ignore fake input events e.g. used by clear button.
20325
20806
  this.__userInput = event.isTrusted;
20326
- this.value = event.target.value;
20807
+ this.value = target.value;
20327
20808
  this.__userInput = false;
20328
20809
  }
20329
20810
 
@@ -20332,12 +20813,12 @@ const InputMixin = dedupingMixin(
20332
20813
  * Override this method with an actual implementation.
20333
20814
  * @param {Event} _event
20334
20815
  * @protected
20335
- * @override
20336
20816
  */
20337
20817
  _onChange(_event) {}
20338
20818
 
20339
20819
  /**
20340
20820
  * Toggle the has-value attribute based on the value property.
20821
+ *
20341
20822
  * @param {boolean} hasValue
20342
20823
  * @protected
20343
20824
  */
@@ -20350,10 +20831,9 @@ const InputMixin = dedupingMixin(
20350
20831
  * @param {string | undefined} newVal
20351
20832
  * @param {string | undefined} oldVal
20352
20833
  * @protected
20353
- * @override
20354
20834
  */
20355
20835
  _valueChanged(newVal, oldVal) {
20356
- this._toggleHasValue(newVal !== '' && newVal != null);
20836
+ this._toggleHasValue(this._hasValue);
20357
20837
 
20358
20838
  // Setting initial value to empty string, do nothing.
20359
20839
  if (newVal === '' && oldVal === undefined) {
@@ -20368,6 +20848,30 @@ const InputMixin = dedupingMixin(
20368
20848
  // Setting a value programmatically, sync it to input element.
20369
20849
  this._forwardInputValue(newVal);
20370
20850
  }
20851
+
20852
+ /**
20853
+ * Indicates whether the value is different from the default one.
20854
+ * Override if the `value` property has a type other than `string`.
20855
+ *
20856
+ * @protected
20857
+ */
20858
+ get _hasValue() {
20859
+ return this.value != null && this.value !== '';
20860
+ }
20861
+
20862
+ /**
20863
+ * Sets the `_hasInputValue` property based on the `input` event.
20864
+ *
20865
+ * @param {InputEvent} event
20866
+ * @protected
20867
+ */
20868
+ _setHasInputValue(event) {
20869
+ // In the case a custom web component is passed as `inputElement`,
20870
+ // the actual native input element, on which the event occurred,
20871
+ // can be inside shadow trees.
20872
+ const target = event.composedPath()[0];
20873
+ this._hasInputValue = target.value.length > 0;
20874
+ }
20371
20875
  },
20372
20876
  );
20373
20877
 
@@ -20439,26 +20943,32 @@ const InputConstraintsMixin = dedupingMixin(
20439
20943
  _createConstraintsObserver() {
20440
20944
  // This complex observer needs to be added dynamically instead of using `static get observers()`
20441
20945
  // to make it possible to tweak this behavior in classes that apply this mixin.
20442
- this._createMethodObserver(`_constraintsChanged(${this.constructor.constraints.join(', ')})`);
20946
+ this._createMethodObserver(`_constraintsChanged(stateTarget, ${this.constructor.constraints.join(', ')})`);
20443
20947
  }
20444
20948
 
20445
20949
  /**
20446
20950
  * Override this method to implement custom validation constraints.
20951
+ * @param {HTMLElement | undefined} stateTarget
20447
20952
  * @param {unknown[]} constraints
20448
20953
  * @protected
20449
20954
  */
20450
- _constraintsChanged(...constraints) {
20451
- // Prevent marking field as invalid when setting required state
20452
- // or any other constraint before a user has entered the value.
20453
- if (!this.invalid) {
20955
+ _constraintsChanged(stateTarget, ...constraints) {
20956
+ // The input element's validity cannot be determined until
20957
+ // all the necessary constraint attributes aren't set on it.
20958
+ if (!stateTarget) {
20454
20959
  return;
20455
20960
  }
20456
20961
 
20457
- if (this._hasValidConstraints(constraints)) {
20962
+ const hasConstraints = this._hasValidConstraints(constraints);
20963
+ const isLastConstraintRemoved = this.__previousHasConstraints && !hasConstraints;
20964
+
20965
+ if ((this._hasValue || this.invalid) && hasConstraints) {
20458
20966
  this.validate();
20459
- } else {
20460
- this.invalid = false;
20967
+ } else if (isLastConstraintRemoved) {
20968
+ this._setInvalid(false);
20461
20969
  }
20970
+
20971
+ this.__previousHasConstraints = hasConstraints;
20462
20972
  }
20463
20973
 
20464
20974
  /**
@@ -20486,9 +20996,85 @@ const InputConstraintsMixin = dedupingMixin(
20486
20996
  }
20487
20997
 
20488
20998
  /** @private */
20489
- __isValidConstraint(constraint) {
20490
- // 0 is valid for `minlength` and `maxlength`
20491
- return Boolean(constraint) || constraint === 0;
20999
+ __isValidConstraint(constraint) {
21000
+ // 0 is valid for `minlength` and `maxlength`
21001
+ return Boolean(constraint) || constraint === 0;
21002
+ }
21003
+ },
21004
+ );
21005
+
21006
+ /**
21007
+ * @license
21008
+ * Copyright (c) 2021 - 2022 Vaadin Ltd.
21009
+ * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
21010
+ */
21011
+
21012
+ const stylesMap = new WeakMap();
21013
+
21014
+ /**
21015
+ * Get all the styles inserted into root.
21016
+ * @param {DocumentOrShadowRoot} root
21017
+ * @return {Set<string>}
21018
+ */
21019
+ function getRootStyles(root) {
21020
+ if (!stylesMap.has(root)) {
21021
+ stylesMap.set(root, new Set());
21022
+ }
21023
+
21024
+ return stylesMap.get(root);
21025
+ }
21026
+
21027
+ /**
21028
+ * Insert styles into the root.
21029
+ * @param {string} styles
21030
+ * @param {DocumentOrShadowRoot} root
21031
+ */
21032
+ function insertStyles(styles, root) {
21033
+ const style = document.createElement('style');
21034
+ style.textContent = styles;
21035
+
21036
+ if (root === document) {
21037
+ document.head.appendChild(style);
21038
+ } else {
21039
+ root.insertBefore(style, root.firstChild);
21040
+ }
21041
+ }
21042
+
21043
+ /**
21044
+ * Mixin to insert styles into the outer scope to handle slotted components.
21045
+ * This is useful e.g. to hide native `<input type="number">` controls.
21046
+ *
21047
+ * @polymerMixin
21048
+ */
21049
+ const SlotStylesMixin = dedupingMixin(
21050
+ (superclass) =>
21051
+ class SlotStylesMixinClass extends superclass {
21052
+ /**
21053
+ * List of styles to insert into root.
21054
+ * @protected
21055
+ */
21056
+ get slotStyles() {
21057
+ return {};
21058
+ }
21059
+
21060
+ /** @protected */
21061
+ connectedCallback() {
21062
+ super.connectedCallback();
21063
+
21064
+ this.__applySlotStyles();
21065
+ }
21066
+
21067
+ /** @private */
21068
+ __applySlotStyles() {
21069
+ const root = this.getRootNode();
21070
+ const rootStyles = getRootStyles(root);
21071
+
21072
+ this.slotStyles.forEach((styles) => {
21073
+ if (!rootStyles.has(styles)) {
21074
+ insertStyles(styles, root);
21075
+ rootStyles.add(styles);
21076
+ }
21077
+ });
20492
21078
  }
20493
21079
  },
20494
21080
  );
@@ -20507,13 +21093,31 @@ const InputConstraintsMixin = dedupingMixin(
20507
21093
  * @mixes FieldMixin
20508
21094
  * @mixes InputConstraintsMixin
20509
21095
  * @mixes KeyboardMixin
21096
+ * @mixes SlotStylesMixin
20510
21097
  */
20511
21098
  const InputControlMixin = (superclass) =>
20512
- class InputControlMixinClass extends DelegateFocusMixin(
20513
- InputConstraintsMixin(FieldMixin(KeyboardMixin(superclass))),
21099
+ class InputControlMixinClass extends SlotStylesMixin(
21100
+ DelegateFocusMixin(InputConstraintsMixin(FieldMixin(KeyboardMixin(superclass)))),
20514
21101
  ) {
20515
21102
  static get properties() {
20516
21103
  return {
21104
+ /**
21105
+ * A pattern matched against individual characters the user inputs.
21106
+ *
21107
+ * When set, the field will prevent:
21108
+ * - `keydown` events if the entered key doesn't match `/^allowedCharPattern$/`
21109
+ * - `paste` events if the pasted text doesn't match `/^allowedCharPattern*$/`
21110
+ * - `drop` events if the dropped text doesn't match `/^allowedCharPattern*$/`
21111
+ *
21112
+ * For example, to allow entering only numbers and minus signs, use:
21113
+ * `allowedCharPattern = "[\\d-]"`
21114
+ * @attr {string} allowed-char-pattern
21115
+ */
21116
+ allowedCharPattern: {
21117
+ type: String,
21118
+ observer: '_allowedCharPatternChanged',
21119
+ },
21120
+
20517
21121
  /**
20518
21122
  * If true, the input text gets fully selected when the field is focused using click or touch / tap.
20519
21123
  */
@@ -20571,6 +21175,14 @@ const InputControlMixin = (superclass) =>
20571
21175
  return [...super.delegateAttrs, 'name', 'type', 'placeholder', 'readonly', 'invalid', 'title'];
20572
21176
  }
20573
21177
 
21178
+ constructor() {
21179
+ super();
21180
+
21181
+ this._boundOnPaste = this._onPaste.bind(this);
21182
+ this._boundOnDrop = this._onDrop.bind(this);
21183
+ this._boundOnBeforeInput = this._onBeforeInput.bind(this);
21184
+ }
21185
+
20574
21186
  /**
20575
21187
  * Any element extending this mixin is required to implement this getter.
20576
21188
  * It returns the reference to the clear button element.
@@ -20582,6 +21194,19 @@ const InputControlMixin = (superclass) =>
20582
21194
  return null;
20583
21195
  }
20584
21196
 
21197
+ /** @protected */
21198
+ get slotStyles() {
21199
+ // Needed for Safari, where ::slotted(...)::placeholder does not work
21200
+ return [
21201
+ `
21202
+ :is(input[slot='input'], textarea[slot='textarea'])::placeholder {
21203
+ font: inherit;
21204
+ color: inherit;
21205
+ }
21206
+ `,
21207
+ ];
21208
+ }
21209
+
20585
21210
  /** @protected */
20586
21211
  ready() {
20587
21212
  super.ready();
@@ -20663,6 +21288,115 @@ const InputControlMixin = (superclass) =>
20663
21288
  this.inputElement.dispatchEvent(new Event('change', { bubbles: true }));
20664
21289
  }
20665
21290
 
21291
+ /**
21292
+ * Override a method from `InputMixin`.
21293
+ * @param {!HTMLElement} input
21294
+ * @protected
21295
+ * @override
21296
+ */
21297
+ _addInputListeners(input) {
21298
+ super._addInputListeners(input);
21299
+
21300
+ input.addEventListener('paste', this._boundOnPaste);
21301
+ input.addEventListener('drop', this._boundOnDrop);
21302
+ input.addEventListener('beforeinput', this._boundOnBeforeInput);
21303
+ }
21304
+
21305
+ /**
21306
+ * Override a method from `InputMixin`.
21307
+ * @param {!HTMLElement} input
21308
+ * @protected
21309
+ * @override
21310
+ */
21311
+ _removeInputListeners(input) {
21312
+ super._removeInputListeners(input);
21313
+
21314
+ input.removeEventListener('paste', this._boundOnPaste);
21315
+ input.removeEventListener('drop', this._boundOnDrop);
21316
+ input.removeEventListener('beforeinput', this._boundOnBeforeInput);
21317
+ }
21318
+
21319
+ /**
21320
+ * Override an event listener from `KeyboardMixin`.
21321
+ * @param {!KeyboardEvent} event
21322
+ * @protected
21323
+ * @override
21324
+ */
21325
+ _onKeyDown(event) {
21326
+ super._onKeyDown(event);
21327
+
21328
+ if (this.allowedCharPattern && !this.__shouldAcceptKey(event)) {
21329
+ event.preventDefault();
21330
+ this._markInputPrevented();
21331
+ }
21332
+ }
21333
+
21334
+ /** @protected */
21335
+ _markInputPrevented() {
21336
+ // Add input-prevented attribute for 200ms
21337
+ this.setAttribute('input-prevented', '');
21338
+ this._preventInputDebouncer = Debouncer$1.debounce(this._preventInputDebouncer, timeOut.after(200), () => {
21339
+ this.removeAttribute('input-prevented');
21340
+ });
21341
+ }
21342
+
21343
+ /** @private */
21344
+ __shouldAcceptKey(event) {
21345
+ return (
21346
+ event.metaKey ||
21347
+ event.ctrlKey ||
21348
+ !event.key || // Allow typing anything if event.key is not supported
21349
+ event.key.length !== 1 || // Allow "Backspace", "ArrowLeft" etc.
21350
+ this.__allowedCharRegExp.test(event.key)
21351
+ );
21352
+ }
21353
+
21354
+ /** @private */
21355
+ _onPaste(e) {
21356
+ if (this.allowedCharPattern) {
21357
+ const pastedText = e.clipboardData.getData('text');
21358
+ if (!this.__allowedTextRegExp.test(pastedText)) {
21359
+ e.preventDefault();
21360
+ this._markInputPrevented();
21361
+ }
21362
+ }
21363
+ }
21364
+
21365
+ /** @private */
21366
+ _onDrop(e) {
21367
+ if (this.allowedCharPattern) {
21368
+ const draggedText = e.dataTransfer.getData('text');
21369
+ if (!this.__allowedTextRegExp.test(draggedText)) {
21370
+ e.preventDefault();
21371
+ this._markInputPrevented();
21372
+ }
21373
+ }
21374
+ }
21375
+
21376
+ /** @private */
21377
+ _onBeforeInput(e) {
21378
+ // The `beforeinput` event covers all the cases for `allowedCharPattern`: keyboard, pasting and dropping,
21379
+ // but it is still experimental technology so we can't rely on it. It's used here just as an additional check,
21380
+ // because it seems to be the only way to detect and prevent specific keys on mobile devices.
21381
+ // See https://github.com/vaadin/vaadin-text-field/issues/429
21382
+ if (this.allowedCharPattern && e.data && !this.__allowedTextRegExp.test(e.data)) {
21383
+ e.preventDefault();
21384
+ this._markInputPrevented();
21385
+ }
21386
+ }
21387
+
21388
+ /** @private */
21389
+ _allowedCharPatternChanged(charPattern) {
21390
+ if (charPattern) {
21391
+ try {
21392
+ this.__allowedCharRegExp = new RegExp(`^${charPattern}$`);
21393
+ this.__allowedTextRegExp = new RegExp(`^${charPattern}*$`);
21394
+ } catch (e) {
21395
+ console.error(e);
21396
+ }
21397
+ }
21398
+ }
21399
+
20666
21400
  /**
20667
21401
  * Fired when the user commits a value change.
20668
21402
  *
@@ -20701,14 +21435,13 @@ class InputController extends SlotController {
20701
21435
  }
20702
21436
 
20703
21437
  // Ensure every instance has unique ID
20704
- const uniqueId = (InputController._uniqueInputId = 1 + InputController._uniqueInputId || 0);
20705
- host._inputId = `${host.localName}-${uniqueId}`;
20706
- node.id = host._inputId;
21438
+ node.id = this.defaultId;
20707
21439
 
20708
21440
  if (typeof callback === 'function') {
20709
21441
  callback(node);
20710
21442
  }
20711
21443
  },
21444
+ true,
20712
21445
  );
20713
21446
  }
20714
21447
  }
@@ -20890,7 +21623,9 @@ class VirtualKeyboardController {
20890
21623
  * @param {function(new:HTMLElement)} subclass
20891
21624
  */
20892
21625
  const DatePickerMixin = (subclass) =>
20893
- class VaadinDatePickerMixin extends ControllerMixin(DelegateFocusMixin(InputMixin(KeyboardMixin(subclass)))) {
21626
+ class VaadinDatePickerMixin extends ControllerMixin(
21627
+ DelegateFocusMixin(InputConstraintsMixin(KeyboardMixin(subclass))),
21628
+ ) {
20894
21629
  static get properties() {
20895
21630
  return {
20896
21631
  /**
@@ -20919,7 +21654,6 @@ const DatePickerMixin = (subclass) =>
20919
21654
  */
20920
21655
  value: {
20921
21656
  type: String,
20922
- observer: '_valueChanged',
20923
21657
  notify: true,
20924
21658
  value: '',
20925
21659
  },
@@ -20975,13 +21709,6 @@ const DatePickerMixin = (subclass) =>
20975
21709
  value: '(max-width: 420px), (max-height: 420px)',
20976
21710
  },
20977
21711
 
20978
- /**
20979
- * An array of ancestor elements whose -webkit-overflow-scrolling is forced from value
20980
- * 'touch' to value 'auto' in order to prevent them from clipping the dropdown. iOS only.
20981
- * @private
20982
- */
20983
- _touchPrevented: Array,
20984
-
20985
21712
  /**
20986
21713
  * The object used to localize this component.
20987
21714
  * To change the default localization, replace the entire
@@ -21037,6 +21764,16 @@ const DatePickerMixin = (subclass) =>
21037
21764
  * // Translation of the Cancel button text.
21038
21765
  * cancel: 'Cancel',
21039
21766
  *
21767
+ * // Used for adjusting the year value when parsing dates with short years.
21768
+ * // The year values between 0 and 99 are evaluated and adjusted.
21769
+ * // Example: for a referenceDate of 1970-10-30;
21770
+ * // dateToBeParsed: 40-10-30, result: 1940-10-30
21771
+ * // dateToBeParsed: 80-10-30, result: 1980-10-30
21772
+ * // dateToBeParsed: 10-10-30, result: 2010-10-30
21773
+ * // Supported date format: ISO 8601 `"YYYY-MM-DD"` (default)
21774
+ * // The default value is the current date.
21775
+ * referenceDate: '',
21776
+ *
21040
21777
  * // A function to format given `Object` as
21041
21778
  * // date string. Object is in the format `{ day: ..., month: ..., year: ... }`
21042
21779
  * // Note: The argument month is 0-based. This means that January = 0 and December = 11.
@@ -21090,11 +21827,12 @@ const DatePickerMixin = (subclass) =>
21090
21827
  calendar: 'Calendar',
21091
21828
  today: 'Today',
21092
21829
  cancel: 'Cancel',
21093
- formatDate: (d) => {
21830
+ referenceDate: '',
21831
+ formatDate(d) {
21094
21832
  const yearStr = String(d.year).replace(/\d+/, (y) => '0000'.substr(y.length) + y);
21095
21833
  return [d.month + 1, d.day, yearStr].join('/');
21096
21834
  },
21097
- parseDate: (text) => {
21835
+ parseDate(text) {
21098
21836
  const parts = text.split('/');
21099
21837
  const today = new Date();
21100
21838
  let date,
@@ -21102,12 +21840,13 @@ const DatePickerMixin = (subclass) =>
21102
21840
  year = today.getFullYear();
21103
21841
 
21104
21842
  if (parts.length === 3) {
21843
+ month = parseInt(parts[0]) - 1;
21844
+ date = parseInt(parts[1]);
21105
21845
  year = parseInt(parts[2]);
21106
21846
  if (parts[2].length < 3 && year >= 0) {
21107
- year += year < 50 ? 2000 : 1900;
21847
+ const usedReferenceDate = this.referenceDate ? parseDate(this.referenceDate) : new Date();
21848
+ year = getAdjustedYear(usedReferenceDate, year, month, date);
21108
21849
  }
21109
- month = parseInt(parts[0]) - 1;
21110
- date = parseInt(parts[1]);
21111
21850
  } else if (parts.length === 2) {
21112
21851
  month = parseInt(parts[0]) - 1;
21113
21852
  date = parseInt(parts[1]);
@@ -21137,7 +21876,6 @@ const DatePickerMixin = (subclass) =>
21137
21876
  */
21138
21877
  min: {
21139
21878
  type: String,
21140
- observer: '_minChanged',
21141
21879
  },
21142
21880
 
21143
21881
  /**
@@ -21151,28 +21889,26 @@ const DatePickerMixin = (subclass) =>
21151
21889
  */
21152
21890
  max: {
21153
21891
  type: String,
21154
- observer: '_maxChanged',
21155
21892
  },
21156
21893
 
21157
21894
  /**
21158
21895
  * The earliest date that can be selected. All earlier dates will be disabled.
21159
- * @type {Date | string}
21896
+ * @type {Date | undefined}
21160
21897
  * @protected
21161
21898
  */
21162
21899
  _minDate: {
21163
21900
  type: Date,
21164
- // Null does not work here because minimizer passes undefined to overlay (#351)
21165
- value: '',
21901
+ computed: '__computeMinOrMaxDate(min)',
21166
21902
  },
21167
21903
 
21168
21904
  /**
21169
21905
  * The latest date that can be selected. All later dates will be disabled.
21170
- * @type {Date | string}
21906
+ * @type {Date | undefined}
21171
21907
  * @protected
21172
21908
  */
21173
21909
  _maxDate: {
21174
21910
  type: Date,
21175
- value: '',
21911
+ computed: '__computeMinOrMaxDate(max)',
21176
21912
  },
21177
21913
 
21178
21914
  /** @private */
@@ -21187,12 +21923,6 @@ const DatePickerMixin = (subclass) =>
21187
21923
  value: isIOS,
21188
21924
  },
21189
21925
 
21190
- /** @private */
21191
- _webkitOverflowScroll: {
21192
- type: Boolean,
21193
- value: document.createElement('div').style.webkitOverflowScrolling === '',
21194
- },
21195
-
21196
21926
  /** @private */
21197
21927
  _focusOverlayOnOpen: Boolean,
21198
21928
 
@@ -21208,6 +21938,10 @@ const DatePickerMixin = (subclass) =>
21208
21938
  ];
21209
21939
  }
21210
21940
 
21941
+ static get constraints() {
21942
+ return [...super.constraints, 'min', 'max'];
21943
+ }
21944
+
21211
21945
  /**
21212
21946
  * Override a getter from `InputControlMixin` to make it optional
21213
21947
  * and to prevent warning when a clear button is missing,
@@ -21268,18 +22002,13 @@ const DatePickerMixin = (subclass) =>
21268
22002
 
21269
22003
  if (!this.opened) {
21270
22004
  if (this.autoOpenDisabled) {
21271
- const parsedDate = this._getParsedDate();
21272
- if (this._isValidDate(parsedDate)) {
21273
- this._selectDate(parsedDate);
21274
- }
22005
+ this._selectParsedOrFocusedDate();
21275
22006
  }
21276
22007
 
21277
- if (this.inputElement.value === '' && this.__dispatchChange) {
21278
- this.validate();
22008
+ this.validate();
22009
+
22010
+ if (this._inputValue === '' && this.value !== '') {
21279
22011
  this.value = '';
21280
- this.__dispatchChange = false;
21281
- } else {
21282
- this.validate();
21283
22012
  }
21284
22013
  }
21285
22014
  }
@@ -21348,14 +22077,19 @@ const DatePickerMixin = (subclass) =>
21348
22077
  this.$.overlay.removeAttribute('disable-upgrade');
21349
22078
  this._overlayInitialized = true;
21350
22079
 
21351
- this.$.overlay.addEventListener('opened-changed', (e) => (this.opened = e.detail.value));
22080
+ this.$.overlay.addEventListener('opened-changed', (e) => {
22081
+ this.opened = e.detail.value;
22082
+ });
21352
22083
 
21353
22084
  this.$.overlay.addEventListener('vaadin-overlay-escape-press', () => {
21354
22085
  this._focusedDate = this._selectedDate;
21355
22086
  this._close();
21356
22087
  });
21357
22088
 
21358
- this._overlayContent.addEventListener('close', this._close.bind(this));
22089
+ this._overlayContent.addEventListener('close', () => {
22090
+ this._close();
22091
+ });
22092
+
21359
22093
  this._overlayContent.addEventListener('focus-input', this._focusAndSelect.bind(this));
21360
22094
 
21361
22095
  // User confirmed selected date by clicking the calendar.
@@ -21364,34 +22098,29 @@ const DatePickerMixin = (subclass) =>
21364
22098
 
21365
22099
  this._selectDate(e.detail.date);
21366
22100
 
21367
- this._close(e);
22101
+ this._close();
21368
22102
  });
21369
22103
 
21370
- // User confirmed selected date by pressing Enter or Today.
22104
+ // User confirmed selected date by pressing Enter, Space, or Today.
21371
22105
  this._overlayContent.addEventListener('date-selected', (e) => {
21372
- this.__userConfirmedDate = true;
22106
+ // Reset if a date is deselected.
22107
+ this.__userConfirmedDate = !!e.detail.date;
21373
22108
 
21374
22109
  this._selectDate(e.detail.date);
21375
22110
  });
21376
22111
 
21377
- // Keep focus attribute in focusElement for styling
22112
+ // Set focus-ring attribute when moving focus to the overlay
22113
+ // by pressing Tab or arrow key, after opening it on click.
21378
22114
  this._overlayContent.addEventListener('focusin', () => {
21379
- this._setFocused(true);
22115
+ if (this._keyboardActive) {
22116
+ this._setFocused(true);
22117
+ }
21380
22118
  });
21381
22119
 
21382
22120
  this.addEventListener('mousedown', () => this.__bringToFront());
21383
22121
  this.addEventListener('touchstart', () => this.__bringToFront());
21384
22122
  }
21385
22123
 
21386
- /**
21387
- * Returns true if `value` is valid, and sets the `invalid` flag appropriately.
21388
- *
21389
- * @return {boolean} True if the value is valid and sets the `invalid` flag appropriately
21390
- */
21391
- validate() {
21392
- return !(this.invalid = !this.checkValidity());
21393
- }
21394
-
21395
22124
  /**
21396
22125
  * Returns true if the current input value satisfies all constraints (if any)
21397
22126
  *
@@ -21402,7 +22131,7 @@ const DatePickerMixin = (subclass) =>
21402
22131
  checkValidity() {
21403
22132
  const inputValid =
21404
22133
  !this._inputValue ||
21405
- (this._selectedDate && this._inputValue === this._getFormattedDate(this.i18n.formatDate, this._selectedDate));
22134
+ (!!this._selectedDate && this._inputValue === this._getFormattedDate(this.i18n.formatDate, this._selectedDate));
21406
22135
  const minMaxValid = !this._selectedDate || dateAllowed(this._selectedDate, this._minDate, this._maxDate);
21407
22136
 
21408
22137
  let inputValidity = true;
@@ -21418,6 +22147,51 @@ const DatePickerMixin = (subclass) =>
21418
22147
  return inputValid && minMaxValid && inputValidity;
21419
22148
  }
21420
22149
 
22150
+ /**
22151
+ * Override method inherited from `FocusMixin`
22152
+ * to not call `_setFocused(true)` when focus
22153
+ * is restored after closing overlay on click,
22154
+ * and to avoid removing `focus-ring` attribute.
22155
+ *
22156
+ * @param {!FocusEvent} _event
22157
+ * @return {boolean}
22158
+ * @protected
22159
+ * @override
22160
+ */
22161
+ _shouldSetFocus(_event) {
22162
+ return !this._shouldKeepFocusRing;
22163
+ }
22164
+
22165
+ /**
22166
+ * Override method inherited from `FocusMixin`
22167
+ * to prevent removing the `focused` attribute:
22168
+ * - when moving focus to the overlay content,
22169
+ * - when closing on date click / outside click.
22170
+ *
22171
+ * @param {!FocusEvent} _event
22172
+ * @return {boolean}
22173
+ * @protected
22174
+ * @override
22175
+ */
22176
+ _shouldRemoveFocus(_event) {
22177
+ return !this.opened;
22178
+ }
22179
+
22180
+ /**
22181
+ * Override method inherited from `FocusMixin`
22182
+ * to store the `focus-ring` state to restore
22183
+ * it later when closing on outside click.
22184
+ *
22185
+ * @param {boolean} focused
22186
+ * @protected
22187
+ * @override
22188
+ */
22189
+ _setFocused(focused) {
22190
+ super._setFocused(focused);
22191
+
22192
+ this._shouldKeepFocusRing = focused && this._keyboardActive;
22193
+ }
22194
+
21421
22195
  /**
21422
22196
  * Select date on user interaction and set the flag
21423
22197
  * to fire change event if necessary.
@@ -21437,10 +22211,7 @@ const DatePickerMixin = (subclass) =>
21437
22211
  }
21438
22212
 
21439
22213
  /** @private */
21440
- _close(e) {
21441
- if (e) {
21442
- e.stopPropagation();
21443
- }
22214
+ _close() {
21444
22215
  this._focus();
21445
22216
  this.close();
21446
22217
  }
@@ -21452,21 +22223,6 @@ const DatePickerMixin = (subclass) =>
21452
22223
  });
21453
22224
  }
21454
22225
 
21455
- /** @private */
21456
- _parseDate(str) {
21457
- // Parsing with RegExp to ensure correct format
21458
- const parts = /^([-+]\d{1}|\d{2,4}|[-+]\d{6})-(\d{1,2})-(\d{1,2})$/.exec(str);
21459
- if (!parts) {
21460
- return;
21461
- }
21462
-
21463
- const date = new Date(0, 0); // Wrong date (1900-01-01), but with midnight in local time
21464
- date.setFullYear(parseInt(parts[1], 10));
21465
- date.setMonth(parseInt(parts[2], 10) - 1);
21466
- date.setDate(parseInt(parts[3], 10));
21467
- return date;
21468
- }
21469
-
21470
22226
  /** @private */
21471
22227
  // eslint-disable-next-line max-params
21472
22228
  _isNoInput(inputElement, fullscreen, ios, i18n, opened, autoOpenDisabled) {
@@ -21569,48 +22325,47 @@ const DatePickerMixin = (subclass) =>
21569
22325
  }
21570
22326
  }
21571
22327
 
21572
- /** @private */
21573
- _handleDateChange(property, value, oldValue) {
21574
- if (!value) {
21575
- this[property] = '';
21576
- return;
21577
- }
22328
+ /**
22329
+ * Override the value observer from `InputMixin` to implement custom
22330
+ * handling of the `value` property. The date-picker doesn't forward
22331
+ * the value directly to the input like the default implementation of `InputMixin`.
22332
+ * Instead, it parses the value into a date, puts it in `_selectedDate` which
22333
+ * is then displayed in the input with respect to the specified date format.
22334
+ *
22335
+ * @param {string | undefined} value
22336
+ * @param {string | undefined} oldValue
22337
+ * @protected
22338
+ * @override
22339
+ */
22340
+ _valueChanged(value, oldValue) {
22341
+ const newDate = parseDate(value);
21578
22342
 
21579
- const date = this._parseDate(value);
21580
- if (!date) {
22343
+ if (value && !newDate) {
22344
+ // The new value cannot be parsed, revert the old value.
21581
22345
  this.value = oldValue;
21582
22346
  return;
21583
22347
  }
21584
- if (!dateEquals(this[property], date)) {
21585
- this[property] = date;
21586
- if (this.value) {
21587
- this.validate();
21588
- }
21589
- }
21590
- }
21591
-
21592
- /** @private */
21593
- _valueChanged(value, oldValue) {
21594
- this._handleDateChange('_selectedDate', value, oldValue);
21595
22348
 
21596
- this._toggleHasValue(!!value);
21597
- }
22349
+ if (value) {
22350
+ if (!dateEquals(this._selectedDate, newDate)) {
22351
+ // Update the date instance only if the date has actually changed.
22352
+ this._selectedDate = newDate;
21598
22353
 
21599
- /** @private */
21600
- _minChanged(value, oldValue) {
21601
- this._handleDateChange('_minDate', value, oldValue);
21602
- }
22354
+ if (oldValue !== undefined) {
22355
+ // Validate only if `value` changes after initialization.
22356
+ this.validate();
22357
+ }
22358
+ }
22359
+ } else {
22360
+ this._selectedDate = null;
22361
+ }
21603
22362
 
21604
- /** @private */
21605
- _maxChanged(value, oldValue) {
21606
- this._handleDateChange('_maxDate', value, oldValue);
22363
+ this._toggleHasValue(this._hasValue);
21607
22364
  }
21608
22365
 
21609
22366
  /** @protected */
21610
22367
  _onOverlayOpened() {
21611
- this._openedWithFocusRing = this.hasAttribute('focus-ring');
21612
-
21613
- const parsedInitialPosition = this._parseDate(this.initialPosition);
22368
+ const parsedInitialPosition = parseDate(this.initialPosition);
21614
22369
 
21615
22370
  const initialPosition =
21616
22371
  this._selectedDate || this._overlayContent.initialPosition || parsedInitialPosition || new Date();
@@ -21629,10 +22384,6 @@ const DatePickerMixin = (subclass) =>
21629
22384
 
21630
22385
  window.addEventListener('scroll', this._boundOnScroll, true);
21631
22386
 
21632
- if (this._webkitOverflowScroll) {
21633
- this._touchPrevented = this._preventWebkitOverflowScrollingTouch(this.parentElement);
21634
- }
21635
-
21636
22387
  if (this._focusOverlayOnOpen) {
21637
22388
  this._overlayContent.focusDateElement();
21638
22389
  this._focusOverlayOnOpen = false;
@@ -21646,25 +22397,6 @@ const DatePickerMixin = (subclass) =>
21646
22397
  }
21647
22398
  }
21648
22399
 
21649
- // A hack needed for iOS to prevent dropdown from being clipped in an
21650
- // ancestor container with -webkit-overflow-scrolling: touch;
21651
- /** @private */
21652
- _preventWebkitOverflowScrollingTouch(element) {
21653
- const result = [];
21654
- while (element) {
21655
- if (window.getComputedStyle(element).webkitOverflowScrolling === 'touch') {
21656
- const oldInlineValue = element.style.webkitOverflowScrolling;
21657
- element.style.webkitOverflowScrolling = 'auto';
21658
- result.push({
21659
- element,
21660
- oldInlineValue,
21661
- });
21662
- }
21663
- element = element.parentElement;
21664
- }
21665
- return result;
21666
- }
21667
-
21668
22400
  /** @private */
21669
22401
  _selectParsedOrFocusedDate() {
21670
22402
  // Select the parsed input or focused date
@@ -21691,13 +22423,6 @@ const DatePickerMixin = (subclass) =>
21691
22423
  _onOverlayClosed() {
21692
22424
  window.removeEventListener('scroll', this._boundOnScroll, true);
21693
22425
 
21694
- if (this._touchPrevented) {
21695
- this._touchPrevented.forEach(
21696
- (prevented) => (prevented.element.style.webkitOverflowScrolling = prevented.oldInlineValue),
21697
- );
21698
- this._touchPrevented = [];
21699
- }
21700
-
21701
22426
  // No need to select date on close if it was confirmed by the user.
21702
22427
  if (this.__userConfirmedDate) {
21703
22428
  this.__userConfirmedDate = false;
@@ -21713,11 +22438,6 @@ const DatePickerMixin = (subclass) =>
21713
22438
  if (!this.value) {
21714
22439
  this.validate();
21715
22440
  }
21716
-
21717
- // If the input isn't focused when overlay closes (fullscreen mode), clear focused state
21718
- if (this.getRootNode().activeElement !== this.inputElement) {
21719
- this._setFocused(false);
21720
- }
21721
22441
  }
21722
22442
 
21723
22443
  /** @private */
@@ -21770,10 +22490,7 @@ const DatePickerMixin = (subclass) =>
21770
22490
  _onChange(event) {
21771
22491
  // For change event on the native <input> blur, after the input is cleared,
21772
22492
  // we schedule change event to be dispatched on date-picker blur.
21773
- if (
21774
- this.inputElement.value === '' &&
21775
- !(event.detail && event.detail.sourceEvent && event.detail.sourceEvent.__fromClearButton)
21776
- ) {
22493
+ if (this._inputValue === '') {
21777
22494
  this.__dispatchChange = true;
21778
22495
  }
21779
22496
 
@@ -21860,7 +22577,7 @@ const DatePickerMixin = (subclass) =>
21860
22577
  if (e.shiftKey) {
21861
22578
  this._overlayContent.focusCancel();
21862
22579
  } else {
21863
- this._overlayContent.focusDate(this._focusedDate);
22580
+ this._overlayContent.focusDateElement();
21864
22581
  }
21865
22582
  }
21866
22583
  break;
@@ -21875,21 +22592,15 @@ const DatePickerMixin = (subclass) =>
21875
22592
  * @override
21876
22593
  */
21877
22594
  _onEnter(_event) {
21878
- const parsedDate = this._getParsedDate();
21879
- const isValidDate = this._isValidDate(parsedDate);
22595
+ const oldValue = this.value;
21880
22596
  if (this.opened) {
21881
- if (this._overlayInitialized && this._overlayContent.focusedDate && isValidDate) {
21882
- this._selectDate(this._overlayContent.focusedDate);
21883
- }
22597
+ // Closing will implicitly select parsed or focused date
21884
22598
  this.close();
21885
- } else if (!isValidDate && this.inputElement.value !== '') {
21886
- this.validate();
21887
22599
  } else {
21888
- const oldValue = this.value;
21889
22600
  this._selectParsedOrFocusedDate();
21890
- if (oldValue === this.value) {
21891
- this.validate();
21892
- }
22601
+ }
22602
+ if (oldValue === this.value) {
22603
+ this.validate();
21893
22604
  }
21894
22605
  }
21895
22606
 
@@ -21931,7 +22642,7 @@ const DatePickerMixin = (subclass) =>
21931
22642
  /** @private */
21932
22643
  _getParsedDate(inputValue = this._inputValue) {
21933
22644
  const dateObject = this.i18n.parseDate && this.i18n.parseDate(inputValue);
21934
- const parsedDate = dateObject && this._parseDate(`${dateObject.year}-${dateObject.month + 1}-${dateObject.day}`);
22645
+ const parsedDate = dateObject && parseDate(`${dateObject.year}-${dateObject.month + 1}-${dateObject.day}`);
21935
22646
  return parsedDate;
21936
22647
  }
21937
22648
 
@@ -21953,7 +22664,7 @@ const DatePickerMixin = (subclass) =>
21953
22664
 
21954
22665
  /** @private */
21955
22666
  _userInputValueChanged() {
21956
- if (this.opened && this._inputValue) {
22667
+ if (this._inputValue) {
21957
22668
  const parsedDate = this._getParsedDate();
21958
22669
 
21959
22670
  if (this._isValidDate(parsedDate)) {
@@ -21971,6 +22682,11 @@ const DatePickerMixin = (subclass) =>
21971
22682
  return this.$.overlay.content.querySelector('#overlay-content');
21972
22683
  }
21973
22684
 
22685
+ /** @private */
22686
+ __computeMinOrMaxDate(dateString) {
22687
+ return parseDate(dateString);
22688
+ }
22689
+
21974
22690
  /**
21975
22691
  * Fired when the user commits a value change.
21976
22692
  *
@@ -22082,12 +22798,13 @@ registerStyles('vaadin-date-picker', [inputFieldShared, datePickerStyles], { mod
22082
22798
  * Note: the `theme` attribute value set on `<vaadin-date-picker>` is
22083
22799
  * propagated to the internal components listed above.
22084
22800
  *
22085
- * See [Styling Components](https://vaadin.com/docs/latest/ds/customization/styling-components) documentation.
22801
+ * See [Styling Components](https://vaadin.com/docs/latest/styling/custom-theme/styling-components) documentation.
22086
22802
  *
22087
22803
  * @fires {Event} change - Fired when the user commits a value change.
22088
22804
  * @fires {CustomEvent} invalid-changed - Fired when the `invalid` property changes.
22089
22805
  * @fires {CustomEvent} opened-changed - Fired when the `opened` property changes.
22090
22806
  * @fires {CustomEvent} value-changed - Fired when the `value` property changes.
22807
+ * @fires {CustomEvent} validated - Fired whenever the field is validated.
22091
22808
  *
22092
22809
  * @extends HTMLElement
22093
22810
  * @mixes ElementMixin
@@ -22141,7 +22858,7 @@ class DatePicker extends DatePickerMixin(InputControlMixin(ThemableMixin(Element
22141
22858
  fullscreen$="[[_fullscreen]]"
22142
22859
  theme$="[[__getOverlayTheme(_theme, _overlayInitialized)]]"
22143
22860
  on-vaadin-overlay-open="_onOverlayOpened"
22144
- on-vaadin-overlay-close="_onOverlayClosed"
22861
+ on-vaadin-overlay-closing="_onOverlayClosed"
22145
22862
  restore-focus-on-close
22146
22863
  restore-focus-node="[[inputElement]]"
22147
22864
  disable-upgrade
@@ -22162,6 +22879,8 @@ class DatePicker extends DatePickerMixin(InputControlMixin(ThemableMixin(Element
22162
22879
  ></vaadin-date-picker-overlay-content>
22163
22880
  </template>
22164
22881
  </vaadin-date-picker-overlay>
22882
+
22883
+ <slot name="tooltip"></slot>
22165
22884
  `;
22166
22885
  }
22167
22886
 
@@ -22188,6 +22907,11 @@ class DatePicker extends DatePickerMixin(InputControlMixin(ThemableMixin(Element
22188
22907
  );
22189
22908
  this.addController(new LabelledInputController(this.inputElement, this._labelController));
22190
22909
 
22910
+ this._tooltipController = new TooltipController(this);
22911
+ this.addController(this._tooltipController);
22912
+ this._tooltipController.setPosition('top');
22913
+ this._tooltipController.setShouldShow((target) => !target.opened);
22914
+
22191
22915
  const toggleButton = this.shadowRoot.querySelector('[part="toggle-button"]');
22192
22916
  toggleButton.addEventListener('mousedown', (e) => e.preventDefault());
22193
22917
  }
@@ -22201,11 +22925,6 @@ class DatePicker extends DatePickerMixin(InputControlMixin(ThemableMixin(Element
22201
22925
 
22202
22926
  /** @private */
22203
22927
  _onVaadinOverlayClose(e) {
22204
- if (this._openedWithFocusRing && this.hasAttribute('focused')) {
22205
- this.setAttribute('focus-ring', '');
22206
- } else if (!this.hasAttribute('focused')) {
22207
- this.blur();
22208
- }
22209
22928
  if (e.detail.sourceEvent && e.detail.sourceEvent.composedPath().includes(this)) {
22210
22929
  e.preventDefault();
22211
22930
  }
@@ -22333,6 +23052,7 @@ const HelperFilters = class {
22333
23052
  this.modalCloseEvent();
22334
23053
  this.showClearButton = true;
22335
23054
  this.filterSelectionHandler(this.filterData);
23055
+ console.log(this.showClearButton);
22336
23056
  }
22337
23057
  resetSearch() {
22338
23058
  this.showClearButton = false;
@@ -22349,7 +23069,7 @@ const HelperFilters = class {
22349
23069
  this.filterData.filterToCalendar = new Date(event.target.value).toISOString();
22350
23070
  }
22351
23071
  render() {
22352
- return (index.h("div", { class: "HelperFilters", ref: el => this.stylingContainer = el }, index.h("div", { class: "FilterButtonsWrapper" }, index.h("button", { class: "FilterOpen", onClick: () => this.toggleFilterModal() }, translate$2('filterOpen', this.language)), (this.showClearButton || this.quickFiltersActive) ?
23072
+ return (index.h("div", { class: "HelperFilters", ref: el => this.stylingContainer = el }, index.h("div", { class: "FilterButtonsWrapper" }, index.h("button", { class: "FilterOpen", onClick: () => this.toggleFilterModal() }, translate$2('filterOpen', this.language)), console.log('in filter Open', this.showClearButton, this.quickFiltersActive), (this.showClearButton || this.quickFiltersActive) ?
22353
23073
  index.h("button", { class: "FilterClear", onClick: () => this.resetSearch() }, translate$2('filterClear', this.language))
22354
23074
  :
22355
23075
  null), index.h("helper-modal", { "title-modal": "Filter Modal", visible: this.showFilterModal, "client-styling": this.clientStyling, "client-styling-url-content": this.clientStylingUrlContent }, index.h("div", { class: "FilterModalHeader" }, index.h("h3", { class: "FilterModalTitle" }, this.activateTicketSearch ? translate$2('filterModalTicketTitle', this.language) : translate$2('filterModalDrawTitle', this.language))), index.h("div", { class: "FilterModalBody" }, index.h("input", { id: "FilterById", type: "text", value: this.filterData.ticketDrawId, onInput: (event) => this.handleTicketDrawId(event), class: "FilterModalSearch", placeholder: this.activateTicketSearch ? translate$2('filterTicketPlaceholder', this.language) : translate$2('filterDrawPlaceholder', this.language) }), index.h("p", null, translate$2('filterOrDate', this.language)), index.h("div", { class: "FilterCalendarWrapper" }, index.h("vaadin-date-picker", { value: this.filterData.filterFromCalendar, onChange: (event) => this.handleFilterFrom(event), placeholder: translate$2('filterFromCalendar', this.language), class: "VaadinDatePicker" }), index.h("vaadin-date-picker", { value: this.filterData.filterToCalendar, onChange: (event) => this.handleFilterTo(event), placeholder: translate$2('filterToCalendar', this.language), class: "VaadinDatePicker" }))), index.h("div", { class: "FilterModalFooter" }, index.h("button", { class: "FilterModalButton", onClick: () => this.filterSearch() }, translate$2('filterModalButton', this.language))))));
@@ -22394,13 +23114,47 @@ const TRANSLATIONS = {
22394
23114
  ticketAmount: 'Valoarea biletului',
22395
23115
  winUpTo: 'Poti castiga'
22396
23116
  },
23117
+ fr: {
23118
+ drawResultsHeader: 'Résultats du dernier tirage',
23119
+ drawId: 'ID de tirage',
23120
+ drawName: 'Nom du jeu',
23121
+ drawDate: 'Date du tirage',
23122
+ drawNumbersGridDraw: 'Tirage des numéros Grille',
23123
+ drawNumbersGridTicket: 'Tirage des numéros Grille',
23124
+ ticketResult: 'Résultat du ticket',
23125
+ amountWon: 'Montant gagné',
23126
+ numberOfDraws: 'Nombre de tirages',
23127
+ multiplier: 'Multiplicateur',
23128
+ ticketPurchaseDate: 'Date d\'achat du billet',
23129
+ ticketStatus: 'Statut du ticket',
23130
+ ticketId: 'ID de billets',
23131
+ ticketAmount: 'Montant du billet',
23132
+ winUpTo: 'Gagnez jusqu\'à'
23133
+ },
23134
+ ar: {
23135
+ drawResultsHeader: 'نتائج آخر سحب',
23136
+ drawId: 'معرّف السحب',
23137
+ drawName: 'اسم اللعبة',
23138
+ drawDate: 'تاريخ السحب',
23139
+ drawNumbersGridDraw: 'شبكة أرقام السحب',
23140
+ drawNumbersGridTicket: 'شبكة أرقام السحب',
23141
+ ticketResult: 'نتيجة التذكرة',
23142
+ amountWon: 'المبلغ الذي تم ربحه',
23143
+ numberOfDraws: 'عدد السحوبات',
23144
+ multiplier: 'مضاعف',
23145
+ ticketPurchaseDate: 'تاريخ شراء التذكرة',
23146
+ ticketStatus: 'حالة التذكرة',
23147
+ ticketId: 'معرّف التذكرة',
23148
+ ticketAmount: 'مبلغ التذكرة',
23149
+ winUpTo: 'ربح يصل إلى'
23150
+ }
22397
23151
  };
22398
23152
  const translate = (key, customLang) => {
22399
23153
  const lang = customLang;
22400
23154
  return TRANSLATIONS[lang !== undefined && SUPPORTED_LANGUAGES.includes(lang) ? lang : DEFAULT_LANGUAGE][key];
22401
23155
  };
22402
23156
 
22403
- const lotteryDrawResultsCss = "@import url(\"https://fonts.googleapis.com/css2?family=Roboto:wght@100&display=swap\");:host{display:block;font-family:\"Roboto\", sans-serif}.TicketInfo{display:flex;flex-direction:row;gap:15px;background-color:#009993;color:#fff;padding:12px;font-size:14px}.DrawResultsArea{margin-top:15px}.DrawResultsArea.TicketDraws .Content{padding:0;border:0}.DrawResultsArea.TicketDraws .DrawResultsBody{padding:0;margin-bottom:5px;border-radius:0;border:0}.DrawResultsSection{max-width:600px;margin:0px auto;border-radius:4px}.DrawResultsHeader{display:flex;justify-content:space-between;padding:10px 20px;background-color:#009993;color:#fff;font-size:14px;border-radius:4px 4px 0 0}.DrawResultsHeader h4{text-transform:uppercase;font-weight:400;margin:0;padding-top:15px}.DrawResultsBody{padding:20px;margin-bottom:5px;border-radius:0 0 4px 4px;border:1px solid #009993}.DrawResultsBody>div{margin:10px 0}.DrawResultsBody .NumberOfDrawsContainer{display:table;width:100%}.DrawNumbersGrid{margin-bottom:15px}.DrawNumbersGrid label{display:block;margin-bottom:10px}.Toggle{cursor:pointer;display:inline-block}.ToggleSwitch{display:inline-block;background:#ccc;border-radius:16px;width:58px;height:24px;position:relative;vertical-align:middle;transition:background 0.25s}.ToggleSwitch:before,.ToggleSwitch:after{content:\"\"}.ToggleSwitch:before{display:block;background:linear-gradient(to bottom, #fff 0%, #eee 100%);border-radius:50%;box-shadow:0 0 0 1px rgba(0, 0, 0, 0.25);width:16px;height:16px;position:absolute;top:4px;left:4px;transition:left 0.25s}.Toggle:hover .ToggleSwitch:before{background:linear-gradient(to bottom, #fff 0%, #fff 100%);box-shadow:0 0 0 1px rgba(0, 0, 0, 0.5)}.ToggleCheckbox:checked+.ToggleSwitch{background:#56c080}.ToggleCheckbox:checked+.ToggleSwitch:before{left:38px}.ToggleCheckbox{position:absolute;visibility:hidden}.Label{position:relative}.DrawTicketsContainer{display:flex;flex-direction:column;margin:20px auto 0}.DrawMultipler{margin-top:15px}.ExpandableBoxes{position:relative;display:flex;flex-direction:column}.ExpandableBox{line-height:12px;font-weight:lighter;width:100%;height:100%;max-height:80px;float:left;margin:0 0 20px 0;border:1px solid #009993;background:#fff;border-radius:4px;padding:10px;box-sizing:border-box;-webkit-transition:all 0.6s ease-in-out;-moz-transition:all 0.6s ease-in-out;-o-transition:all 0.6s ease-in-out;-ms-transition:all 0.6s ease-in-out;transition:all 0.6s ease-in-out;overflow:hidden;box-shadow:rgba(99, 99, 99, 0.2) 0px 2px 8px 0px}.ExpandableBox:last-of-type{margin-bottom:0}.ExpandableBox.ShowBox{max-height:400px;margin:0px 0px 20p 0px}.ExpandableBox.HideBox{width:0;height:0;overflow:hidden;border:none;padding:0;margin:0;opacity:0}";
23157
+ const lotteryDrawResultsCss = "@import url(\"https://fonts.googleapis.com/css2?family=Roboto:wght@100&display=swap\");:host{display:block;font-family:\"Roboto\", sans-serif}.TicketInfo{display:flex;flex-direction:row;gap:15px;background-color:#009993;color:#fff;padding:12px;font-size:14px}.DrawResultsArea{margin-top:15px}.DrawResultsArea.TicketDraws .Content{padding:0;border:0}.DrawResultsArea.TicketDraws .DrawResultsBody{padding:0;margin-bottom:5px;border-radius:0;border:0}.DrawResultsSection{max-width:600px;margin:0px auto;border-radius:4px}.DrawResultsHeader{display:flex;justify-content:space-between;padding:10px 20px;background-color:#009993;color:#fff;font-size:14px;border-radius:4px 4px 0 0}.DrawResultsHeader h4{text-transform:uppercase;font-weight:400;margin:0;padding-top:15px}.DrawResultsBody{padding:20px;margin-bottom:5px;border-radius:0 0 4px 4px;border:1px solid #009993}.DrawResultsBody>div{margin:10px 0}.DrawResultsBody .NumberOfDrawsContainer{display:table;width:100%}.DrawNumbersGrid{display:flex;flex-direction:column;gap:5px}.DrawNumbersGrid label{display:block;margin-bottom:7px}.Toggle{cursor:pointer;display:inline-block}.ToggleSwitch{display:inline-block;background:#ccc;border-radius:16px;width:58px;height:24px;position:relative;vertical-align:middle;transition:background 0.25s}.ToggleSwitch:before,.ToggleSwitch:after{content:\"\"}.ToggleSwitch:before{display:block;background:linear-gradient(to bottom, #fff 0%, #eee 100%);border-radius:50%;box-shadow:0 0 0 1px rgba(0, 0, 0, 0.25);width:16px;height:16px;position:absolute;top:4px;left:4px;transition:left 0.25s}.Toggle:hover .ToggleSwitch:before{background:linear-gradient(to bottom, #fff 0%, #fff 100%);box-shadow:0 0 0 1px rgba(0, 0, 0, 0.5)}.ToggleCheckbox:checked+.ToggleSwitch{background:#56c080}.ToggleCheckbox:checked+.ToggleSwitch:before{left:38px}.ToggleCheckbox{position:absolute;visibility:hidden}.Label{position:relative}.DrawTicketsContainer{display:flex;flex-direction:column;margin:20px auto 0}.DrawMultipler{margin-top:15px}.ExpandableBoxes{position:relative;display:flex;flex-direction:column;border:1px solid #ccc;border-radius:5px;background-color:white}.ExpandableBox{border-bottom:1px solid #ccc;transition:height 300ms ease-in-out;overflow:hidden;height:80px}.ExpandableBox:last-child{border-bottom:0}.ExpandableBoxHeader{position:relative;list-style:none;outline:0;cursor:pointer;text-transform:uppercase;transition:color 300ms ease-in-out;margin-bottom:24px;margin-left:5px}.ShowBox>.ExpandableBoxHeader{color:#009993}.ExpandableBoxHeader::-webkit-details-marker{display:none}.ExpandableBoxHeader:before,.ExpandableBoxHeader:after{content:\"\";position:absolute}.ExpandableBoxHeader:before{right:21px;top:50%;height:2px;margin-top:-1px;width:16px;background:#009993}.ExpandableBoxHeader:after{right:28px;top:50%;height:16px;margin-top:-8px;width:2px;margin-left:-1px;background:#009993;transition:all 300ms ease-in-out}.ShowBox .ExpandableBoxHeader:after{opacity:0;transform:translateY(25%)}.ExpandableBoxBody{padding-top:0;font-weight:lighter;margin-left:5px}.ExpandableBox.ShowBox{height:300px}";
22404
23158
 
22405
23159
  const LotteryDrawResults = class {
22406
23160
  constructor(hostRef) {
@@ -22461,70 +23215,21 @@ const LotteryDrawResults = class {
22461
23215
  * Client custom styling via url content
22462
23216
  */
22463
23217
  this.clientStylingUrlContent = '';
23218
+ /**
23219
+ * Data showing the ticket's draw results details
23220
+ */
23221
+ this.ticketDrawData = '';
22464
23222
  this.multiplier = 3;
22465
23223
  this.isLoading = true;
22466
- this.rules = {};
22467
- this.toggleDrawer = [false];
22468
23224
  this.hasErrors = false;
22469
23225
  this.errorText = '';
22470
23226
  this.ticketData = [];
22471
23227
  this.ticketDataLoaded = false;
22472
23228
  this.ticketDraws = [];
22473
- this.hasDrawNumbers = false;
23229
+ this.toggleDrawer = [false];
22474
23230
  this.limitStylingAppends = false;
22475
- this.getTicketsData = () => {
22476
- let url = new URL(`${this.endpoint}/tickets`);
22477
- let drawOptions = {
22478
- method: "GET",
22479
- headers: {
22480
- 'Content-Type': "application/json",
22481
- 'Accept': 'application/json',
22482
- 'Authorization': `Bearer ${this.sessionId}`
22483
- },
22484
- };
22485
- fetch(url.href, drawOptions)
22486
- .then((response) => {
22487
- return response.json();
22488
- })
22489
- .then((data) => {
22490
- if (data) {
22491
- this.ticketData = data;
22492
- this.ticketDataLoaded = true;
22493
- }
22494
- return this.ticketData;
22495
- }).then((response) => {
22496
- response.forEach(ticket => {
22497
- if (ticket.drawResults.length) {
22498
- ticket.drawResults.forEach(draw => {
22499
- fetch(`${this.endpoint}/games/${this.gameId}/draws/${draw.drawId}`)
22500
- .then((response) => {
22501
- return response.json();
22502
- })
22503
- .then((data) => {
22504
- // check if draw id is unique
22505
- if (!this.ticketDraws.some(el => el.drawId === draw.drawId)) {
22506
- this.ticketDraws.push({ drawId: draw.drawId, drawNumbers: data.winningNumbers });
22507
- }
22508
- });
22509
- });
22510
- }
22511
- return this.ticketDraws;
22512
- });
22513
- }).then(() => {
22514
- this.hasDrawNumbers = true;
22515
- });
22516
- };
22517
- this.changeBox = (index) => {
22518
- this.toggleDrawer = this.toggleDrawer.map((item, itemIndex) => {
22519
- if (itemIndex == index) {
22520
- return !item;
22521
- }
22522
- return item;
22523
- });
22524
- if (index >= this.toggleDrawer.length) {
22525
- this.toggleDrawer.push(true);
22526
- }
22527
- };
23231
+ this.ticketDrawDetails = [];
23232
+ this.ticketDrawDetailsFlag = true;
22528
23233
  this.setClientStyling = () => {
22529
23234
  let sheet = document.createElement('style');
22530
23235
  sheet.innerHTML = this.clientStyling;
@@ -22540,18 +23245,30 @@ const LotteryDrawResults = class {
22540
23245
  }
22541
23246
  connectedCallback() {
22542
23247
  let promises = [];
22543
- promises.push(this.getGameData());
23248
+ // Split ticket numbers for each grid
23249
+ if (this.ticketNumbers) {
23250
+ this.gridNumbers = JSON.parse(this.ticketNumbers);
23251
+ }
22544
23252
  if (this.drawId) {
22545
23253
  promises.push(this.getDrawData());
22546
23254
  }
22547
- if (!this.drawMode) {
22548
- this.getTicketsData();
22549
- }
22550
23255
  Promise.all(promises)
22551
23256
  .then(() => {
22552
23257
  this.isLoading = false;
23258
+ }).catch((err) => {
23259
+ console.log('error ', err);
23260
+ this.isLoading = false;
22553
23261
  });
22554
23262
  }
23263
+ componentWillRender() {
23264
+ if (this.ticketDrawData && this.ticketDrawDetailsFlag) {
23265
+ this.ticketDrawDetails = JSON.parse(this.ticketDrawData);
23266
+ this.ticketDrawDetails.forEach((drawDetail) => {
23267
+ this.getDrawData(drawDetail.drawId).then((drawData) => drawDetail.drawData = drawData);
23268
+ });
23269
+ this.ticketDrawDetailsFlag = false;
23270
+ }
23271
+ }
22555
23272
  componentDidRender() {
22556
23273
  // start custom styling area
22557
23274
  if (!this.limitStylingAppends && this.stylingContainer) {
@@ -22563,21 +23280,24 @@ const LotteryDrawResults = class {
22563
23280
  }
22564
23281
  // end custom styling area
22565
23282
  }
22566
- getDrawData(drawID) {
23283
+ getDrawData(drawId) {
23284
+ this.isLoading = true;
22567
23285
  return new Promise((resolve, reject) => {
22568
- let url = new URL(`${this.endpoint}/games/${this.gameId}/draws/${drawID ? drawID : this.drawId}`);
23286
+ let url = new URL(`${this.endpoint}/games/${this.gameId}/draws/${drawId ? drawId : this.drawId}`);
22569
23287
  fetch(url.href)
22570
23288
  .then((response) => {
22571
23289
  // @TODO EXCEPTIONS
22572
23290
  return response.json();
22573
23291
  })
22574
23292
  .then((data) => {
22575
- this.drawData = data;
22576
- resolve(true);
22577
- this.isLoading = false;
22578
- if (drawID) {
22579
- return this.drawData.winningNumbers;
23293
+ if (drawId) {
23294
+ resolve(data);
22580
23295
  }
23296
+ else {
23297
+ this.drawData = data;
23298
+ resolve(true);
23299
+ }
23300
+ this.isLoading = false;
22581
23301
  })
22582
23302
  .catch((err) => {
22583
23303
  reject(err);
@@ -22585,29 +23305,16 @@ const LotteryDrawResults = class {
22585
23305
  });
22586
23306
  });
22587
23307
  }
22588
- getGameData() {
22589
- return new Promise((resolve, reject) => {
22590
- let url = new URL(`${this.endpoint}/games/${this.gameId}`);
22591
- fetch(url.href)
22592
- .then((response) => {
22593
- return response.json();
22594
- })
22595
- .then((data) => {
22596
- this.rules = {
22597
- maximumAllowed: data.rules.boards[0].maximumAllowed,
22598
- totalNumbers: data.rules.boards[0].totalNumbers
22599
- };
22600
- resolve(true);
22601
- this.isLoading = false;
22602
- this.hasErrors = false;
22603
- })
22604
- .catch((err) => {
22605
- this.isLoading = false;
22606
- this.hasErrors = true;
22607
- this.errorText = err;
22608
- reject(err);
22609
- });
23308
+ drawerToggle(index) {
23309
+ this.toggleDrawer = this.toggleDrawer.map((item, itemIndex) => {
23310
+ if (itemIndex == index) {
23311
+ return !item;
23312
+ }
23313
+ return item;
22610
23314
  });
23315
+ if (index >= this.toggleDrawer.length) {
23316
+ this.toggleDrawer.push(true);
23317
+ }
22611
23318
  }
22612
23319
  render() {
22613
23320
  if (this.isLoading) {
@@ -22619,14 +23326,19 @@ const LotteryDrawResults = class {
22619
23326
  else {
22620
23327
  return (index.h("section", { class: "DrawResultsSection", ref: el => this.stylingContainer = el }, this.drawMode ?
22621
23328
  index.h("div", { class: "DrawResultsArea" }, this.drawData &&
22622
- index.h("div", null, index.h("div", { class: "DrawResultsHeader" }, index.h("span", null, translate('drawId', this.language), ": ", this.drawData.id), index.h("span", null, translate('drawDate', this.language), ": ", this.drawData.date.slice(0, 10))), index.h("div", { class: "DrawResultsBody" }, index.h("div", { class: "DrawNumbersGrid" }, index.h("p", null, translate('drawNumbersGridDraw', this.language), "0:"), index.h("div", { class: "BulletContainer" }, index.h("lottery-grid", { "maximum-allowed": this.rules.maximumAllowed, "total-numbers": this.rules.totalNumbers, "selected-numbers": this.drawData.winningNumbers.join(','), "display-selected": true, selectable: false, language: this.language, "grid-type": 'ticket', "client-styling": this.clientStyling, "client-styling-url-content": this.clientStylingUrlContent })), index.h("div", { class: "DrawMultipler" }, index.h("label", { class: "Label" }, translate('multiplier', this.language), " ", this.multiplier))))))
23329
+ index.h("div", null, index.h("div", { class: "DrawResultsHeader" }, index.h("span", null, translate('drawId', this.language), ": ", this.drawData.id), index.h("span", null, translate('drawDate', this.language), ": ", this.drawData.date.slice(0, 10))), index.h("div", { class: "DrawResultsBody" }, index.h("div", { class: "DrawNumbersGrid" }, index.h("p", null, translate('drawNumbersGridDraw', this.language), "0:"), index.h("div", { class: "BulletContainer" }, index.h("lottery-grid", { "selected-numbers": this.drawData.winningNumbers.join(','), "display-selected": true, selectable: false, language: this.language, "grid-type": 'ticket', "client-styling": this.clientStyling, "client-styling-url-content": this.clientStylingUrlContent })), index.h("div", { class: "DrawMultipler" }, index.h("label", { class: "Label" }, translate('multiplier', this.language), " ", this.multiplier))))))
22623
23330
  :
22624
- index.h("div", { class: "DrawResultsArea TicketDraws" }, index.h("div", { class: "DrawResultsBody" }, index.h("div", { class: "TicketIdContainer" }, index.h("label", { class: "Label" }, translate('ticketId', this.language), ": ", index.h("span", null, this.ticketId))), index.h("div", { class: "TicketAmountContainer" }, index.h("label", { class: "Label" }, translate('ticketAmount', this.language), " ", index.h("span", null, this.ticketAmount))), index.h("div", { class: "DrawNumbersGrid" }, index.h("label", { class: "Label" }, translate('drawNumbersGridTicket', this.language), "0:"), index.h("div", { class: "BulletContainer" }, index.h("lottery-grid", { "maximum-allowed": this.rules.maximumAllowed, "total-numbers": this.rules.totalNumbers, "selected-numbers": JSON.parse(this.ticketNumbers).join(','), selectable: false, "display-selected": true, language: this.language, "grid-type": 'ticket', "client-styling": this.clientStyling, "client-styling-url-content": this.clientStylingUrlContent }))), index.h("div", { class: "DrawMultipler" }, index.h("label", { class: "Label" }, translate('multiplier', this.language), " ", JSON.stringify(this.ticketMultiplier))), index.h("div", { class: "NumberOfDrawsContainer" }, index.h("label", { class: "Label" }, translate('numberOfDraws', this.language), ": ", this.ticketDrawCount), index.h("div", { class: "DrawTicketsContainer" }, this.ticketData.map((ticket) => index.h("div", { class: "ExpandableBoxes" }, ticket.drawResults.length ?
22625
- index.h("div", null, ticket.id == this.ticketId && ticket.drawResults.map((item, index$1) => index.h("div", { class: this.toggleDrawer[index$1] ? 'ExpandableBox ShowBox' : 'ExpandableBox', onClick: () => this.changeBox(index$1) }, index.h("div", { class: "TicketResultContainer" }, index.h("p", null, translate('ticketResult', this.language), ": ", item.state)), item.state == 'won' &&
22626
- index.h("div", { class: "AmountWonContainer" }, index.h("p", null, translate('amountWon', this.language), ": ", Number(item.amount).toLocaleString('en'), " ", item.currency)), index.h("div", { class: "DrawIdContainer" }, index.h("p", null, translate('drawId', this.language), ": ", item.drawId)), index.h("div", { class: "DrawDateContainer" }, index.h("p", null, translate('drawDate', this.language), ": ", item.updatedAt.slice(0, 10), " | ", item.updatedAt.slice(11, 19))), index.h("div", { class: "DrawNumbersGrid" }, this.hasDrawNumbers && this.ticketDraws.map((ticketDraw) => item.drawId && item.drawId === ticketDraw.drawId &&
22627
- index.h("div", null, index.h("label", { class: "Label" }, translate('drawNumbersGridDraw', this.language), "A:"), index.h("lottery-grid", { "maximum-allowed": this.rules.maximumAllowed, "total-numbers": this.rules.totalNumbers, "selected-numbers": ticketDraw.drawNumbers.join(','), selectable: false, "display-selected": true, language: this.language, "grid-type": 'ticket', "client-styling": this.clientStyling, "client-styling-url-content": this.clientStylingUrlContent })))), index.h("div", { class: "DrawMultipler" }, index.h("label", { class: "Label" }, translate('multiplier', this.language), " ", item.multiplier)))))
22628
- :
22629
- index.h("span", null)))))))));
23331
+ index.h("div", { class: "DrawResultsArea TicketDraws" }, index.h("div", { class: "DrawResultsBody" }, index.h("div", { class: "TicketIdContainer" }, index.h("label", { class: "Label" }, translate('ticketId', this.language), ": ", index.h("span", null, this.ticketId))), index.h("div", { class: "TicketAmountContainer" }, index.h("label", { class: "Label" }, translate('ticketAmount', this.language), " ", index.h("span", null, this.ticketAmount))), index.h("div", { class: "DrawNumbersGrid" }, this.gridNumbers.map((grid, index$1) => index.h("div", null, index.h("label", { class: "Label" }, translate('drawNumbersGridTicket', this.language), " ", String.fromCharCode(index$1 + 65), ":"), index.h("div", { class: "BulletContainer" }, index.h("lottery-grid", { "selected-numbers": grid.join(','), selectable: false, "display-selected": true, language: this.language, "grid-type": 'ticket', "client-styling": this.clientStyling, "client-styling-url-content": this.clientStylingUrlContent }))))), index.h("div", { class: "DrawMultipler" }, index.h("label", { class: "Label" }, translate('multiplier', this.language), " ", JSON.stringify(this.ticketMultiplier))), index.h("div", { class: "NumberOfDrawsContainer" }, index.h("label", { class: "Label" }, translate('numberOfDraws', this.language), ": ", this.ticketDrawCount), index.h("div", { class: "DrawTicketsContainer" }, this.ticketDrawDetails && this.ticketDrawDetails.length > 0 &&
23332
+ index.h("div", { class: "ExpandableBoxes" }, this.ticketDrawDetails.map((drawDetail, index$1) => {
23333
+ var _a, _b, _c, _d, _e;
23334
+ return index.h("div", { class: { 'ExpandableBox': true, 'ShowBox': this.toggleDrawer[index$1] }, onClick: () => this.drawerToggle(index$1) }, index.h("div", { class: "ExpandableBoxHeader" }, index.h("div", { class: "TicketResultContainer" }, index.h("p", null, translate('ticketResult', this.language), ": ", drawDetail.state)), drawDetail.state == 'won' &&
23335
+ index.h("div", { class: "AmountWonContainer" }, index.h("p", null, translate('amountWon', this.language), ": ", Number(drawDetail.amount).toLocaleString('en'), " ", drawDetail.currency)), drawDetail.state == 'lost' &&
23336
+ index.h("div", { class: "DrawIdContainer" }, index.h("p", null, translate('drawId', this.language), ": ", drawDetail.drawId))), index.h("div", { class: "ExpandableBoxBody" }, index.h("div", { class: "DrawIdContainer" }, index.h("p", null, translate('drawId', this.language), ": ", drawDetail.drawId)), index.h("div", { class: "DrawDateContainer" }, index.h("p", null, translate('drawDate', this.language), ": ", (_a = drawDetail.drawData) === null || _a === void 0 ? void 0 :
23337
+ _a.date.slice(0, 10), " | ", (_b = drawDetail.drawData) === null || _b === void 0 ? void 0 :
23338
+ _b.date.slice(11, 19))), index.h("div", { class: "DrawNumbersGrid" }, drawDetail.drawData &&
23339
+ index.h("div", { class: 'BulletContainer' }, index.h("label", { class: "Label" }, translate('drawNumbersGridDraw', this.language), " ", String.fromCharCode(index$1 + 10), ":"), index.h("lottery-grid", { "selected-numbers": (_d = (_c = drawDetail.drawData) === null || _c === void 0 ? void 0 : _c.winningNumbers) === null || _d === void 0 ? void 0 : _d.join(','), selectable: false, "display-selected": true, language: this.language, "grid-type": 'ticket', "client-styling": this.clientStyling, "client-styling-url-content": this.clientStylingUrlContent }))), index.h("div", { class: "DrawMultipler" }, index.h("label", { class: "Label" }, translate('multiplier', this.language), " ", (_e = drawDetail.drawData) === null || _e === void 0 ? void 0 :
23340
+ _e.multiplier))));
23341
+ }))))))));
22630
23342
  }
22631
23343
  }
22632
23344
  };
@@ -22634,3 +23346,5 @@ LotteryDrawResults.style = lotteryDrawResultsCss;
22634
23346
 
22635
23347
  exports.helper_filters = HelperFilters;
22636
23348
  exports.lottery_draw_results = LotteryDrawResults;
23349
+
23350
+ //# sourceMappingURL=helper-filters_2.cjs.entry.js.map