@everymatrix/helper-filters 0.1.5 → 0.1.20

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.
@@ -1,5 +1,4 @@
1
- import { r as registerInstance, c as createEvent, h as h$2 } from './index-f5eea413.js';
2
- import '@everymatrix/helper-modal';
1
+ import { r as registerInstance, c as createEvent, h as h$2 } from './index-5f4ed338.js';
3
2
 
4
3
  const DEFAULT_LANGUAGE = 'en';
5
4
  const SUPPORTED_LANGUAGES = ['ro', 'en'];
@@ -41,7 +40,7 @@ const translate$1 = (key, customLang) => {
41
40
  */
42
41
  class Lumo extends HTMLElement {
43
42
  static get version() {
44
- return '23.2.0';
43
+ return '23.1.5';
45
44
  }
46
45
  }
47
46
 
@@ -97,7 +96,7 @@ const ThemePropertyMixin = (superClass) =>
97
96
  * **NOTE:** Extending the mixin only provides the property for binding,
98
97
  * and does not make the propagation alone.
99
98
  *
100
- * See [Styling Components: Sub-components](https://vaadin.com/docs/latest/styling/custom-theme/styling-components/#sub-components).
99
+ * See [Styling Components: Sub-components](https://vaadin.com/docs/latest/ds/customization/styling-components/#sub-components).
101
100
  * page for more information.
102
101
  *
103
102
  * @deprecated The `theme` property is not supposed for public use and will be dropped in Vaadin 24.
@@ -122,7 +121,7 @@ const ThemePropertyMixin = (superClass) =>
122
121
  * **NOTE:** Extending the mixin only provides the property for binding,
123
122
  * and does not make the propagation alone.
124
123
  *
125
- * See [Styling Components: Sub-components](https://vaadin.com/docs/latest/styling/custom-theme/styling-components/#sub-components).
124
+ * See [Styling Components: Sub-components](https://vaadin.com/docs/latest/ds/customization/styling-components/#sub-components).
126
125
  * page for more information.
127
126
  *
128
127
  * @protected
@@ -227,9 +226,9 @@ function matchesThemeFor(themeFor, tagName) {
227
226
  */
228
227
  function getIncludePriority(moduleName = '') {
229
228
  let includePriority = 0;
230
- if (moduleName.startsWith('lumo-') || moduleName.startsWith('material-')) {
229
+ if (moduleName.indexOf('lumo-') === 0 || moduleName.indexOf('material-') === 0) {
231
230
  includePriority = 1;
232
- } else if (moduleName.startsWith('vaadin-')) {
231
+ } else if (moduleName.indexOf('vaadin-') === 0) {
233
232
  includePriority = 2;
234
233
  }
235
234
  return includePriority;
@@ -10114,38 +10113,6 @@ const ControllerMixin = dedupingMixin(
10114
10113
  * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
10115
10114
  */
10116
10115
 
10117
- // We consider the keyboard to be active if the window has received a keydown
10118
- // event since the last mousedown event.
10119
- let keyboardActive = false;
10120
-
10121
- // Listen for top-level keydown and mousedown events.
10122
- // Use capture phase so we detect events even if they're handled.
10123
- window.addEventListener(
10124
- 'keydown',
10125
- () => {
10126
- keyboardActive = true;
10127
- },
10128
- { capture: true },
10129
- );
10130
-
10131
- window.addEventListener(
10132
- 'mousedown',
10133
- () => {
10134
- keyboardActive = false;
10135
- },
10136
- { capture: true },
10137
- );
10138
-
10139
- /**
10140
- * Returns true if the window has received a keydown
10141
- * event since the last mousedown event.
10142
- *
10143
- * @return {boolean}
10144
- */
10145
- function isKeyboardActive() {
10146
- return keyboardActive;
10147
- }
10148
-
10149
10116
  /**
10150
10117
  * Returns true if the element is hidden directly with `display: none` or `visibility: hidden`,
10151
10118
  * false otherwise.
@@ -10586,7 +10553,7 @@ class FocusTrapController {
10586
10553
  * ---|---|---
10587
10554
  * `--vaadin-overlay-viewport-bottom` | Bottom offset of the visible viewport area | `0` or detected offset
10588
10555
  *
10589
- * See [Styling Components](https://vaadin.com/docs/latest/styling/custom-theme/styling-components) documentation.
10556
+ * See [Styling Components](https://vaadin.com/docs/latest/ds/customization/styling-components) documentation.
10590
10557
  *
10591
10558
  * @fires {CustomEvent} opened-changed - Fired when the `opened` property changes.
10592
10559
  * @fires {CustomEvent} vaadin-overlay-open - Fired after the overlay is opened.
@@ -12856,7 +12823,7 @@ const registered = new Set();
12856
12823
  const ElementMixin = (superClass) =>
12857
12824
  class VaadinElementMixin extends DirMixin(superClass) {
12858
12825
  static get version() {
12859
- return '23.2.0';
12826
+ return '23.1.5';
12860
12827
  }
12861
12828
 
12862
12829
  /** @protected */
@@ -13154,7 +13121,7 @@ function _handleNative(ev) {
13154
13121
  }
13155
13122
  if (!ev[HANDLED_OBJ]) {
13156
13123
  ev[HANDLED_OBJ] = {};
13157
- if (type.startsWith('touch')) {
13124
+ if (type.slice(0, 5) === 'touch') {
13158
13125
  const t = ev.changedTouches[0];
13159
13126
  if (type === 'touchstart') {
13160
13127
  // Only handle the first finger
@@ -14013,6 +13980,28 @@ const ActiveMixin = (superclass) =>
14013
13980
  * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
14014
13981
  */
14015
13982
 
13983
+ // We consider the keyboard to be active if the window has received a keydown
13984
+ // event since the last mousedown event.
13985
+ let keyboardActive = false;
13986
+
13987
+ // Listen for top-level keydown and mousedown events.
13988
+ // Use capture phase so we detect events even if they're handled.
13989
+ window.addEventListener(
13990
+ 'keydown',
13991
+ () => {
13992
+ keyboardActive = true;
13993
+ },
13994
+ { capture: true },
13995
+ );
13996
+
13997
+ window.addEventListener(
13998
+ 'mousedown',
13999
+ () => {
14000
+ keyboardActive = false;
14001
+ },
14002
+ { capture: true },
14003
+ );
14004
+
14016
14005
  /**
14017
14006
  * A mixin to handle `focused` and `focus-ring` attributes based on focus.
14018
14007
  *
@@ -14026,7 +14015,7 @@ const FocusMixin = dedupingMixin(
14026
14015
  * @return {boolean}
14027
14016
  */
14028
14017
  get _keyboardActive() {
14029
- return isKeyboardActive();
14018
+ return keyboardActive;
14030
14019
  }
14031
14020
 
14032
14021
  /** @protected */
@@ -14290,7 +14279,7 @@ const ButtonMixin = (superClass) =>
14290
14279
  * `focus-ring` | Set when the button is focused using the keyboard.
14291
14280
  * `focused` | Set when the button is focused.
14292
14281
  *
14293
- * See [Styling Components](https://vaadin.com/docs/latest/styling/custom-theme/styling-components) documentation.
14282
+ * See [Styling Components](https://vaadin.com/docs/latest/ds/customization/styling-components) documentation.
14294
14283
  *
14295
14284
  * @extends HTMLElement
14296
14285
  * @mixes ButtonMixin
@@ -14372,6 +14361,7 @@ registerStyles(
14372
14361
  i$1`
14373
14362
  :host {
14374
14363
  position: relative;
14364
+ background-color: transparent;
14375
14365
  /* Background for the year scroller, placed here as we are using a mask image on the actual years part */
14376
14366
  background-image: linear-gradient(var(--lumo-shade-5pct), var(--lumo-shade-5pct));
14377
14367
  background-size: 57px 100%;
@@ -14479,10 +14469,17 @@ registerStyles(
14479
14469
 
14480
14470
  [part='toolbar'] {
14481
14471
  padding: var(--lumo-space-s);
14472
+ box-shadow: 0 -1px 0 0 var(--lumo-contrast-10pct);
14482
14473
  border-bottom-left-radius: var(--lumo-border-radius-l);
14483
14474
  margin-right: 57px;
14484
14475
  }
14485
14476
 
14477
+ @supports (mask-image: linear-gradient(#000, #000)) or (-webkit-mask-image: linear-gradient(#000, #000)) {
14478
+ [part='toolbar'] {
14479
+ box-shadow: none;
14480
+ }
14481
+ }
14482
+
14486
14483
  /* Today and Cancel buttons */
14487
14484
 
14488
14485
  [part='toolbar'] [part\$='button'] {
@@ -14515,6 +14512,8 @@ registerStyles(
14515
14512
  /* Very narrow screen (year scroller initially hidden) */
14516
14513
 
14517
14514
  [part='years-toggle-button'] {
14515
+ position: relative;
14516
+ right: auto;
14518
14517
  display: flex;
14519
14518
  align-items: center;
14520
14519
  height: var(--lumo-size-s);
@@ -14532,6 +14531,10 @@ registerStyles(
14532
14531
  color: var(--lumo-primary-contrast-color);
14533
14532
  }
14534
14533
 
14534
+ [part='years-toggle-button']::before {
14535
+ content: none;
14536
+ }
14537
+
14535
14538
  /* TODO magic number (same as used for iron-media-query in vaadin-date-picker-overlay-content) */
14536
14539
  @media screen and (max-width: 374px) {
14537
14540
  :host {
@@ -14707,9 +14710,9 @@ registerStyles(
14707
14710
  { moduleId: 'lumo-month-calendar' },
14708
14711
  );
14709
14712
 
14710
- const template$1 = document.createElement('template');
14713
+ const $_documentContainer$1 = document.createElement('template');
14711
14714
 
14712
- template$1.innerHTML = `
14715
+ $_documentContainer$1.innerHTML = `
14713
14716
  <style>
14714
14717
  @keyframes vaadin-date-picker-month-calendar-focus-date {
14715
14718
  50% {
@@ -14719,7 +14722,7 @@ template$1.innerHTML = `
14719
14722
  </style>
14720
14723
  `;
14721
14724
 
14722
- document.head.appendChild(template$1.content);
14725
+ document.head.appendChild($_documentContainer$1.content);
14723
14726
 
14724
14727
  /**
14725
14728
  * @license
@@ -14727,9 +14730,9 @@ document.head.appendChild(template$1.content);
14727
14730
  * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
14728
14731
  */
14729
14732
 
14730
- const template = document.createElement('template');
14733
+ const $_documentContainer = document.createElement('template');
14731
14734
 
14732
- template.innerHTML = `
14735
+ $_documentContainer.innerHTML = `
14733
14736
  <style>
14734
14737
  @font-face {
14735
14738
  font-family: 'lumo-icons';
@@ -14785,7 +14788,7 @@ template.innerHTML = `
14785
14788
  </style>
14786
14789
  `;
14787
14790
 
14788
- document.head.appendChild(template.content);
14791
+ document.head.appendChild($_documentContainer.content);
14789
14792
 
14790
14793
  /**
14791
14794
  * @license
@@ -15352,57 +15355,6 @@ function getAncestorRootNodes(node) {
15352
15355
  return result;
15353
15356
  }
15354
15357
 
15355
- /**
15356
- * @param {string} value
15357
- * @return {Set<string>}
15358
- */
15359
- function deserializeAttributeValue(value) {
15360
- if (!value) {
15361
- return new Set();
15362
- }
15363
-
15364
- return new Set(value.split(' '));
15365
- }
15366
-
15367
- /**
15368
- * @param {Set<string>} values
15369
- * @return {string}
15370
- */
15371
- function serializeAttributeValue(values) {
15372
- return [...values].join(' ');
15373
- }
15374
-
15375
- /**
15376
- * Adds a value to an attribute containing space-delimited values.
15377
- *
15378
- * @param {HTMLElement} element
15379
- * @param {string} attr
15380
- * @param {string} value
15381
- */
15382
- function addValueToAttribute(element, attr, value) {
15383
- const values = deserializeAttributeValue(element.getAttribute(attr));
15384
- values.add(value);
15385
- element.setAttribute(attr, serializeAttributeValue(values));
15386
- }
15387
-
15388
- /**
15389
- * Removes a value from an attribute containing space-delimited values.
15390
- * If the value is the last one, the whole attribute is removed.
15391
- *
15392
- * @param {HTMLElement} element
15393
- * @param {string} attr
15394
- * @param {string} value
15395
- */
15396
- function removeValueFromAttribute(element, attr, value) {
15397
- const values = deserializeAttributeValue(element.getAttribute(attr));
15398
- values.delete(value);
15399
- if (values.size === 0) {
15400
- element.removeAttribute(attr);
15401
- return;
15402
- }
15403
- element.setAttribute(attr, serializeAttributeValue(values));
15404
- }
15405
-
15406
15358
  /**
15407
15359
  * @license
15408
15360
  * Copyright (c) 2017 - 2022 Vaadin Ltd.
@@ -17127,9 +17079,7 @@ class MonthCalendar extends FocusMixin(ThemableMixin(PolymerElement)) {
17127
17079
 
17128
17080
  _onMonthGridTouchStart() {
17129
17081
  this._notTapping = false;
17130
- setTimeout(() => {
17131
- this._notTapping = true;
17132
- }, 300);
17082
+ setTimeout(() => (this._notTapping = true), 300);
17133
17083
  }
17134
17084
 
17135
17085
  _dateAdd(date, delta) {
@@ -17464,7 +17414,7 @@ class InfiniteScroller extends PolymerElement {
17464
17414
  // Once the first set of items start fading in, stamp the rest
17465
17415
  this._buffers.forEach((buffer) => {
17466
17416
  [].forEach.call(buffer.children, (insertionPoint) => this._ensureStampedInstance(insertionPoint._itemWrapper));
17467
- });
17417
+ }, this);
17468
17418
 
17469
17419
  if (!this._buffers[0].translateY) {
17470
17420
  this._reset();
@@ -17627,7 +17577,7 @@ class InfiniteScroller extends PolymerElement {
17627
17577
  }
17628
17578
  }, 1); // Wait for first reset
17629
17579
  }
17630
- });
17580
+ }, this);
17631
17581
 
17632
17582
  setTimeout(() => {
17633
17583
  afterNextRender(this, this._finishInit.bind(this));
@@ -17665,7 +17615,7 @@ class InfiniteScroller extends PolymerElement {
17665
17615
  });
17666
17616
  buffer.updated = true;
17667
17617
  }
17668
- });
17618
+ }, this);
17669
17619
  }
17670
17620
 
17671
17621
  _isVisible(element, container) {
@@ -17764,6 +17714,7 @@ class DatePickerOverlayContent extends ControllerMixin(ThemableMixin(DirMixin(Po
17764
17714
  height: 100%;
17765
17715
  width: 100%;
17766
17716
  outline: none;
17717
+ background: #fff;
17767
17718
  }
17768
17719
 
17769
17720
  [part='overlay-header'] {
@@ -17781,14 +17732,22 @@ class DatePickerOverlayContent extends ControllerMixin(ThemableMixin(DirMixin(Po
17781
17732
  flex-grow: 1;
17782
17733
  }
17783
17734
 
17784
- [hidden] {
17785
- display: none !important;
17735
+ [part='clear-button']:not([showclear]) {
17736
+ display: none;
17786
17737
  }
17787
17738
 
17788
17739
  [part='years-toggle-button'] {
17789
17740
  display: flex;
17790
17741
  }
17791
17742
 
17743
+ [part='years-toggle-button'][desktop] {
17744
+ display: none;
17745
+ }
17746
+
17747
+ :host(:not([years-visible])) [part='years-toggle-button']::before {
17748
+ transform: rotate(180deg);
17749
+ }
17750
+
17792
17751
  #scrollers {
17793
17752
  display: flex;
17794
17753
  height: 100%;
@@ -17862,14 +17821,27 @@ class DatePickerOverlayContent extends ControllerMixin(ThemableMixin(DirMixin(Po
17862
17821
  z-index: 2;
17863
17822
  flex-shrink: 0;
17864
17823
  }
17824
+
17825
+ [part~='overlay-header']:not([desktop]) {
17826
+ padding-bottom: 40px;
17827
+ }
17828
+
17829
+ [part~='years-toggle-button'] {
17830
+ position: absolute;
17831
+ top: auto;
17832
+ right: 8px;
17833
+ bottom: 0;
17834
+ z-index: 1;
17835
+ padding: 8px;
17836
+ }
17865
17837
  </style>
17866
17838
 
17867
17839
  <div part="overlay-header" on-touchend="_preventDefault" desktop$="[[_desktopMode]]" aria-hidden="true">
17868
17840
  <div part="label">[[_formatDisplayed(selectedDate, i18n.formatDate, label)]]</div>
17869
- <div part="clear-button" hidden$="[[!selectedDate]]"></div>
17841
+ <div part="clear-button" showclear$="[[_showClear(selectedDate)]]"></div>
17870
17842
  <div part="toggle-button"></div>
17871
17843
 
17872
- <div part="years-toggle-button" hidden$="[[_desktopMode]]" aria-hidden="true">
17844
+ <div part="years-toggle-button" desktop$="[[_desktopMode]]" aria-hidden="true">
17873
17845
  [[_yearAfterXMonths(_visibleMonthIndex)]]
17874
17846
  </div>
17875
17847
  </div>
@@ -17955,7 +17927,6 @@ class DatePickerOverlayContent extends ControllerMixin(ThemableMixin(DirMixin(Po
17955
17927
  */
17956
17928
  selectedDate: {
17957
17929
  type: Date,
17958
- value: null,
17959
17930
  },
17960
17931
 
17961
17932
  /**
@@ -18031,12 +18002,10 @@ class DatePickerOverlayContent extends ControllerMixin(ThemableMixin(DirMixin(Po
18031
18002
  return this.getAttribute('dir') === 'rtl';
18032
18003
  }
18033
18004
 
18034
- get calendars() {
18035
- return [...this.shadowRoot.querySelectorAll('vaadin-month-calendar')];
18036
- }
18037
-
18038
18005
  get focusableDateElement() {
18039
- return this.calendars.map((calendar) => calendar.focusableDateElement).find(Boolean);
18006
+ return [...this.shadowRoot.querySelectorAll('vaadin-month-calendar')]
18007
+ .map((calendar) => calendar.focusableDateElement)
18008
+ .find(Boolean);
18040
18009
  }
18041
18010
 
18042
18011
  ready() {
@@ -18044,6 +18013,7 @@ class DatePickerOverlayContent extends ControllerMixin(ThemableMixin(DirMixin(Po
18044
18013
 
18045
18014
  this.setAttribute('role', 'dialog');
18046
18015
 
18016
+ addListener(this, 'tap', this._stopPropagation);
18047
18017
  addListener(this.$.scrollers, 'track', this._track.bind(this));
18048
18018
  addListener(this.shadowRoot.querySelector('[part="clear-button"]'), 'tap', this._clear.bind(this));
18049
18019
  addListener(this.shadowRoot.querySelector('[part="today-button"]'), 'tap', this._onTodayTap.bind(this));
@@ -18165,9 +18135,7 @@ class DatePickerOverlayContent extends ControllerMixin(ThemableMixin(DirMixin(Po
18165
18135
 
18166
18136
  _onYearScrollTouchStart() {
18167
18137
  this._notTapping = false;
18168
- setTimeout(() => {
18169
- this._notTapping = true;
18170
- }, 300);
18138
+ setTimeout(() => (this._notTapping = true), 300);
18171
18139
 
18172
18140
  this._repositionMonthScroller();
18173
18141
  }
@@ -18178,9 +18146,7 @@ class DatePickerOverlayContent extends ControllerMixin(ThemableMixin(DirMixin(Po
18178
18146
 
18179
18147
  _doIgnoreTaps() {
18180
18148
  this._ignoreTaps = true;
18181
- this._debouncer = Debouncer$1.debounce(this._debouncer, timeOut.after(300), () => {
18182
- this._ignoreTaps = false;
18183
- });
18149
+ this._debouncer = Debouncer$1.debounce(this._debouncer, timeOut.after(300), () => (this._ignoreTaps = false));
18184
18150
  }
18185
18151
 
18186
18152
  _formatDisplayed(date, formatDate, label) {
@@ -18211,6 +18177,10 @@ class DatePickerOverlayContent extends ControllerMixin(ThemableMixin(DirMixin(Po
18211
18177
  this.scrollToDate(new Date(), true);
18212
18178
  }
18213
18179
 
18180
+ _showClear(selectedDate) {
18181
+ return !!selectedDate;
18182
+ }
18183
+
18214
18184
  _onYearTap(e) {
18215
18185
  if (!this._ignoreTaps && !this._notTapping) {
18216
18186
  const scrollDelta =
@@ -18236,11 +18206,6 @@ class DatePickerOverlayContent extends ControllerMixin(ThemableMixin(DirMixin(Po
18236
18206
 
18237
18207
  this._targetPosition = targetPosition;
18238
18208
 
18239
- let revealResolve;
18240
- this._revealPromise = new Promise((resolve) => {
18241
- revealResolve = resolve;
18242
- });
18243
-
18244
18209
  // http://gizma.com/easing/
18245
18210
  const easingFunction = (t, b, c, d) => {
18246
18211
  t /= d / 2;
@@ -18281,9 +18246,7 @@ class DatePickerOverlayContent extends ControllerMixin(ThemableMixin(DirMixin(Po
18281
18246
 
18282
18247
  this.$.monthScroller.position = this._targetPosition;
18283
18248
  this._targetPosition = undefined;
18284
-
18285
- revealResolve();
18286
- this._revealPromise = undefined;
18249
+ this.__tryFocusDate();
18287
18250
  }
18288
18251
 
18289
18252
  setTimeout(this._repositionYearScroller.bind(this), 1);
@@ -18493,44 +18456,51 @@ class DatePickerOverlayContent extends ControllerMixin(ThemableMixin(DirMixin(Po
18493
18456
  switch (section) {
18494
18457
  case 'calendar':
18495
18458
  if (event.shiftKey) {
18459
+ // Return focus back to the input field.
18496
18460
  event.preventDefault();
18497
-
18498
- if (this.hasAttribute('fullscreen')) {
18499
- // Trap focus in the overlay
18500
- this.$.cancelButton.focus();
18501
- } else {
18502
- this.__focusInput();
18503
- }
18461
+ this.__focusInput();
18504
18462
  }
18505
18463
  break;
18506
18464
  case 'today':
18507
18465
  if (event.shiftKey) {
18508
- event.preventDefault();
18509
- this.focusDateElement();
18466
+ // Browser returns focus back to the calendar.
18467
+ // We need to move the scroll to focused date.
18468
+ setTimeout(() => this.revealDate(this.focusedDate), 1);
18510
18469
  }
18511
18470
  break;
18512
18471
  case 'cancel':
18513
18472
  if (!event.shiftKey) {
18473
+ // Return focus back to the input field.
18514
18474
  event.preventDefault();
18515
-
18516
- if (this.hasAttribute('fullscreen')) {
18517
- // Trap focus in the overlay
18518
- this.focusDateElement();
18519
- } else {
18520
- this.__focusInput();
18521
- }
18475
+ this.__focusInput();
18522
18476
  }
18523
18477
  break;
18524
18478
  }
18525
18479
  }
18526
18480
 
18527
18481
  __onTodayButtonKeyDown(event) {
18482
+ if (this.hasAttribute('fullscreen')) {
18483
+ // Do not prevent closing on Esc
18484
+ if (event.key !== 'Escape') {
18485
+ event.stopPropagation();
18486
+ }
18487
+ return;
18488
+ }
18489
+
18528
18490
  if (event.key === 'Tab') {
18529
18491
  this._onTabKeyDown(event, 'today');
18530
18492
  }
18531
18493
  }
18532
18494
 
18533
18495
  __onCancelButtonKeyDown(event) {
18496
+ if (this.hasAttribute('fullscreen')) {
18497
+ // Do not prevent closing on Esc
18498
+ if (event.key !== 'Escape') {
18499
+ event.stopPropagation();
18500
+ }
18501
+ return;
18502
+ }
18503
+
18534
18504
  if (event.key === 'Tab') {
18535
18505
  this._onTabKeyDown(event, 'cancel');
18536
18506
  }
@@ -18559,29 +18529,15 @@ class DatePickerOverlayContent extends ControllerMixin(ThemableMixin(DirMixin(Po
18559
18529
  if (!keepMonth) {
18560
18530
  this._focusedMonthDate = dateToFocus.getDate();
18561
18531
  }
18562
- await this.focusDateElement(false);
18532
+ await this.focusDateElement();
18563
18533
  }
18564
18534
 
18565
- async focusDateElement(reveal = true) {
18535
+ async focusDateElement() {
18566
18536
  this.__pendingDateFocus = this.focusedDate;
18567
18537
 
18568
- // Wait for `vaadin-month-calendar` elements to be rendered
18569
- if (!this.calendars.length) {
18570
- await new Promise((resolve) => {
18571
- setTimeout(resolve);
18572
- });
18573
- }
18574
-
18575
- // Reveal focused date unless it has been just set,
18576
- // which triggers `revealDate()` in the observer.
18577
- if (reveal) {
18578
- this.revealDate(this.focusedDate);
18579
- }
18580
-
18581
- if (this._revealPromise) {
18582
- // Wait for focused date to be scrolled into view.
18583
- await this._revealPromise;
18584
- }
18538
+ await new Promise((resolve) => {
18539
+ requestAnimationFrame(resolve);
18540
+ });
18585
18541
 
18586
18542
  this.__tryFocusDate();
18587
18543
  }
@@ -18679,6 +18635,10 @@ class DatePickerOverlayContent extends ControllerMixin(ThemableMixin(DirMixin(Po
18679
18635
  todayMidnight.setDate(today.getDate());
18680
18636
  return this._dateAllowed(todayMidnight, min, max);
18681
18637
  }
18638
+
18639
+ _stopPropagation(e) {
18640
+ e.stopPropagation();
18641
+ }
18682
18642
  }
18683
18643
 
18684
18644
  customElements.define(DatePickerOverlayContent.is, DatePickerOverlayContent);
@@ -18909,24 +18869,6 @@ const DelegateFocusMixin = dedupingMixin(
18909
18869
  },
18910
18870
  );
18911
18871
 
18912
- /**
18913
- * @license
18914
- * Copyright (c) 2021 - 2022 Vaadin Ltd.
18915
- * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
18916
- */
18917
-
18918
- let uniqueId = 0;
18919
-
18920
- /**
18921
- * Returns a unique integer id.
18922
- *
18923
- * @return {number}
18924
- */
18925
- function generateUniqueId() {
18926
- // eslint-disable-next-line no-plusplus
18927
- return uniqueId++;
18928
- }
18929
-
18930
18872
  /**
18931
18873
  * @license
18932
18874
  * Copyright (c) 2021 - 2022 Vaadin Ltd.
@@ -18947,21 +18889,24 @@ class SlotController extends EventTarget {
18947
18889
  */
18948
18890
  static generateId(slotName, host) {
18949
18891
  const prefix = slotName || 'default';
18950
- return `${prefix}-${host.localName}-${generateUniqueId()}`;
18892
+
18893
+ // Support dash-case slot names e.g. "error-message"
18894
+ const field = `${dashToCamelCase(prefix)}Id`;
18895
+
18896
+ // Maintain the unique ID counter for a given prefix.
18897
+ this[field] = 1 + this[field] || 0;
18898
+
18899
+ return `${prefix}-${host.localName}-${this[field]}`;
18951
18900
  }
18952
18901
 
18953
- constructor(host, slotName, slotFactory, slotInitializer, useUniqueId) {
18902
+ constructor(host, slotName, slotFactory, slotInitializer) {
18954
18903
  super();
18955
18904
 
18956
18905
  this.host = host;
18957
18906
  this.slotName = slotName;
18958
18907
  this.slotFactory = slotFactory;
18959
18908
  this.slotInitializer = slotInitializer;
18960
-
18961
- // Only generate the default ID if requested by the controller.
18962
- if (useUniqueId) {
18963
- this.defaultId = SlotController.generateId(slotName, host);
18964
- }
18909
+ this.defaultId = SlotController.generateId(slotName, host);
18965
18910
  }
18966
18911
 
18967
18912
  hostConnected() {
@@ -19116,7 +19061,6 @@ class ErrorController extends SlotController {
19116
19061
 
19117
19062
  this.__updateHasError();
19118
19063
  },
19119
- true,
19120
19064
  );
19121
19065
  }
19122
19066
 
@@ -19231,6 +19175,63 @@ class ErrorController extends SlotController {
19231
19175
  }
19232
19176
  }
19233
19177
 
19178
+ /**
19179
+ * @license
19180
+ * Copyright (c) 2021 - 2022 Vaadin Ltd.
19181
+ * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
19182
+ */
19183
+
19184
+ /**
19185
+ * @param {string} value
19186
+ * @return {Set<string>}
19187
+ */
19188
+ function deserializeAttributeValue(value) {
19189
+ if (!value) {
19190
+ return new Set();
19191
+ }
19192
+
19193
+ return new Set(value.split(' '));
19194
+ }
19195
+
19196
+ /**
19197
+ * @param {Set<string>} values
19198
+ * @return {string}
19199
+ */
19200
+ function serializeAttributeValue(values) {
19201
+ return [...values].join(' ');
19202
+ }
19203
+
19204
+ /**
19205
+ * Adds a value to an attribute containing space-delimited values.
19206
+ *
19207
+ * @param {HTMLElement} element
19208
+ * @param {string} attr
19209
+ * @param {string} value
19210
+ */
19211
+ function addValueToAttribute(element, attr, value) {
19212
+ const values = deserializeAttributeValue(element.getAttribute(attr));
19213
+ values.add(value);
19214
+ element.setAttribute(attr, serializeAttributeValue(values));
19215
+ }
19216
+
19217
+ /**
19218
+ * Removes a value from an attribute containing space-delimited values.
19219
+ * If the value is the last one, the whole attribute is removed.
19220
+ *
19221
+ * @param {HTMLElement} element
19222
+ * @param {string} attr
19223
+ * @param {string} value
19224
+ */
19225
+ function removeValueFromAttribute(element, attr, value) {
19226
+ const values = deserializeAttributeValue(element.getAttribute(attr));
19227
+ values.delete(value);
19228
+ if (values.size === 0) {
19229
+ element.removeAttribute(attr);
19230
+ return;
19231
+ }
19232
+ element.setAttribute(attr, serializeAttributeValue(values));
19233
+ }
19234
+
19234
19235
  /**
19235
19236
  * @license
19236
19237
  * Copyright (c) 2021 - 2022 Vaadin Ltd.
@@ -19405,7 +19406,7 @@ class FieldAriaController {
19405
19406
 
19406
19407
  /**
19407
19408
  * @license
19408
- * Copyright (c) 2021 - 2022 Vaadin Ltd.
19409
+ * Copyright (c) 2021 Vaadin Ltd.
19409
19410
  * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
19410
19411
  */
19411
19412
 
@@ -19415,7 +19416,7 @@ class FieldAriaController {
19415
19416
  class HelperController extends SlotController {
19416
19417
  constructor(host) {
19417
19418
  // Do not provide slot factory, as only create helper lazily.
19418
- super(host, 'helper', null, null, true);
19419
+ super(host, 'helper');
19419
19420
  }
19420
19421
 
19421
19422
  get helperId() {
@@ -19612,7 +19613,6 @@ class LabelController extends SlotController {
19612
19613
 
19613
19614
  this.__observeLabel(node);
19614
19615
  },
19615
- true,
19616
19616
  );
19617
19617
  }
19618
19618
 
@@ -19819,12 +19819,6 @@ const LabelMixin = dedupingMixin(
19819
19819
  super();
19820
19820
 
19821
19821
  this._labelController = new LabelController(this);
19822
- }
19823
-
19824
- /** @protected */
19825
- ready() {
19826
- super.ready();
19827
-
19828
19822
  this.addController(this._labelController);
19829
19823
  }
19830
19824
 
@@ -19872,17 +19866,12 @@ const ValidateMixin = dedupingMixin(
19872
19866
  }
19873
19867
 
19874
19868
  /**
19875
- * Validates the field and sets the `invalid` property based on the result.
19876
- *
19877
- * The method fires a `validated` event with the result of the validation.
19869
+ * Returns true if field is valid, and sets `invalid` based on the field validity.
19878
19870
  *
19879
19871
  * @return {boolean} True if the value is valid.
19880
19872
  */
19881
19873
  validate() {
19882
- const isValid = this.checkValidity();
19883
- this._setInvalid(!isValid);
19884
- this.dispatchEvent(new CustomEvent('validated', { detail: { valid: isValid } }));
19885
- return isValid;
19874
+ return !(this.invalid = !this.checkValidity());
19886
19875
  }
19887
19876
 
19888
19877
  /**
@@ -19893,37 +19882,8 @@ const ValidateMixin = dedupingMixin(
19893
19882
  checkValidity() {
19894
19883
  return !this.required || !!this.value;
19895
19884
  }
19896
-
19897
- /**
19898
- * @param {boolean} invalid
19899
- * @protected
19900
- */
19901
- _setInvalid(invalid) {
19902
- if (this._shouldSetInvalid(invalid)) {
19903
- this.invalid = invalid;
19904
- }
19905
- }
19906
-
19907
- /**
19908
- * Override this method to define whether the given `invalid` state should be set.
19909
- *
19910
- * @param {boolean} _invalid
19911
- * @return {boolean}
19912
- * @protected
19913
- */
19914
- _shouldSetInvalid(_invalid) {
19915
- return true;
19916
- }
19917
-
19918
- /**
19919
- * Fired whenever the field is validated.
19920
- *
19921
- * @event validated
19922
- * @param {Object} detail
19923
- * @param {boolean} detail.valid the result of the validation.
19924
- */
19925
- },
19926
- );
19885
+ },
19886
+ );
19927
19887
 
19928
19888
  /**
19929
19889
  * @license
@@ -20010,6 +19970,10 @@ const FieldMixin = (superclass) =>
20010
19970
  this._helperController = new HelperController(this);
20011
19971
  this._errorController = new ErrorController(this);
20012
19972
 
19973
+ this.addController(this._fieldAriaController);
19974
+ this.addController(this._helperController);
19975
+ this.addController(this._errorController);
19976
+
20013
19977
  this._labelController.addEventListener('label-changed', (event) => {
20014
19978
  const { hasLabel, node } = event.detail;
20015
19979
  this.__labelChanged(hasLabel, node);
@@ -20021,15 +19985,6 @@ const FieldMixin = (superclass) =>
20021
19985
  });
20022
19986
  }
20023
19987
 
20024
- /** @protected */
20025
- ready() {
20026
- super.ready();
20027
-
20028
- this.addController(this._fieldAriaController);
20029
- this.addController(this._helperController);
20030
- this.addController(this._errorController);
20031
- }
20032
-
20033
19988
  /** @private */
20034
19989
  __helperChanged(hasHelper, helperNode) {
20035
19990
  if (hasHelper) {
@@ -20085,7 +20040,7 @@ const FieldMixin = (superclass) =>
20085
20040
  }
20086
20041
 
20087
20042
  /**
20088
- * @param {boolean} invalid
20043
+ * @param {boolean} required
20089
20044
  * @protected
20090
20045
  */
20091
20046
  _invalidChanged(invalid) {
@@ -20285,23 +20240,13 @@ const InputMixin = dedupingMixin(
20285
20240
  observer: '_valueChanged',
20286
20241
  notify: true,
20287
20242
  },
20288
-
20289
- /**
20290
- * When true, the input element has a non-empty value entered by the user.
20291
- * @protected
20292
- */
20293
- _hasInputValue: {
20294
- type: Boolean,
20295
- value: false,
20296
- observer: '_hasInputValueChanged',
20297
- },
20298
20243
  };
20299
20244
  }
20300
20245
 
20301
20246
  constructor() {
20302
20247
  super();
20303
20248
 
20304
- this._boundOnInput = this.__onInput.bind(this);
20249
+ this._boundOnInput = this._onInput.bind(this);
20305
20250
  this._boundOnChange = this._onChange.bind(this);
20306
20251
  }
20307
20252
 
@@ -20316,7 +20261,6 @@ const InputMixin = dedupingMixin(
20316
20261
  * Add event listeners to the input element instance.
20317
20262
  * Override this method to add custom listeners.
20318
20263
  * @param {!HTMLElement} input
20319
- * @protected
20320
20264
  */
20321
20265
  _addInputListeners(input) {
20322
20266
  input.addEventListener('input', this._boundOnInput);
@@ -20326,7 +20270,6 @@ const InputMixin = dedupingMixin(
20326
20270
  /**
20327
20271
  * Remove event listeners from the input element instance.
20328
20272
  * @param {!HTMLElement} input
20329
- * @protected
20330
20273
  */
20331
20274
  _removeInputListeners(input) {
20332
20275
  input.removeEventListener('input', this._boundOnInput);
@@ -20340,6 +20283,7 @@ const InputMixin = dedupingMixin(
20340
20283
  * for example to skip this in certain conditions.
20341
20284
  * @param {string} value
20342
20285
  * @protected
20286
+ * @override
20343
20287
  */
20344
20288
  _forwardInputValue(value) {
20345
20289
  // Value might be set before an input element is initialized.
@@ -20356,11 +20300,7 @@ const InputMixin = dedupingMixin(
20356
20300
  }
20357
20301
  }
20358
20302
 
20359
- /**
20360
- * @param {HTMLElement | undefined} input
20361
- * @param {HTMLElement | undefined} oldInput
20362
- * @protected
20363
- */
20303
+ /** @protected */
20364
20304
  _inputElementChanged(input, oldInput) {
20365
20305
  if (input) {
20366
20306
  this._addInputListeners(input);
@@ -20369,47 +20309,17 @@ const InputMixin = dedupingMixin(
20369
20309
  }
20370
20310
  }
20371
20311
 
20372
- /**
20373
- * Observer to notify about the change of private property.
20374
- *
20375
- * @private
20376
- */
20377
- _hasInputValueChanged(hasValue, oldHasValue) {
20378
- if (hasValue || oldHasValue) {
20379
- this.dispatchEvent(new CustomEvent('has-input-value-changed'));
20380
- }
20381
- }
20382
-
20383
- /**
20384
- * An input event listener used to update `_hasInputValue` property.
20385
- * Do not override this method.
20386
- *
20387
- * @param {Event} event
20388
- * @private
20389
- */
20390
- __onInput(event) {
20391
- // In the case a custom web component is passed as `inputElement`,
20392
- // the actual native input element, on which the event occurred,
20393
- // can be inside shadow trees.
20394
- const target = event.composedPath()[0];
20395
- this._hasInputValue = target.value.length > 0;
20396
- this._onInput(event);
20397
- }
20398
-
20399
20312
  /**
20400
20313
  * An input event listener used to update the field value.
20401
- *
20402
- * @param {Event} event
20314
+ * Override this method with an actual implementation.
20315
+ * @param {Event} _event
20403
20316
  * @protected
20317
+ * @override
20404
20318
  */
20405
20319
  _onInput(event) {
20406
- // In the case a custom web component is passed as `inputElement`,
20407
- // the actual native input element, on which the event occurred,
20408
- // can be inside shadow trees.
20409
- const target = event.composedPath()[0];
20410
20320
  // Ignore fake input events e.g. used by clear button.
20411
20321
  this.__userInput = event.isTrusted;
20412
- this.value = target.value;
20322
+ this.value = event.target.value;
20413
20323
  this.__userInput = false;
20414
20324
  }
20415
20325
 
@@ -20418,12 +20328,12 @@ const InputMixin = dedupingMixin(
20418
20328
  * Override this method with an actual implementation.
20419
20329
  * @param {Event} _event
20420
20330
  * @protected
20331
+ * @override
20421
20332
  */
20422
20333
  _onChange(_event) {}
20423
20334
 
20424
20335
  /**
20425
20336
  * Toggle the has-value attribute based on the value property.
20426
- *
20427
20337
  * @param {boolean} hasValue
20428
20338
  * @protected
20429
20339
  */
@@ -20436,9 +20346,10 @@ const InputMixin = dedupingMixin(
20436
20346
  * @param {string | undefined} newVal
20437
20347
  * @param {string | undefined} oldVal
20438
20348
  * @protected
20349
+ * @override
20439
20350
  */
20440
20351
  _valueChanged(newVal, oldVal) {
20441
- this._toggleHasValue(this._hasValue);
20352
+ this._toggleHasValue(newVal !== '' && newVal != null);
20442
20353
 
20443
20354
  // Setting initial value to empty string, do nothing.
20444
20355
  if (newVal === '' && oldVal === undefined) {
@@ -20453,16 +20364,6 @@ const InputMixin = dedupingMixin(
20453
20364
  // Setting a value programmatically, sync it to input element.
20454
20365
  this._forwardInputValue(newVal);
20455
20366
  }
20456
-
20457
- /**
20458
- * Indicates whether the value is different from the default one.
20459
- * Override if the `value` property has a type other than `string`.
20460
- *
20461
- * @protected
20462
- */
20463
- get _hasValue() {
20464
- return this.value != null && this.value !== '';
20465
- }
20466
20367
  },
20467
20368
  );
20468
20369
 
@@ -20534,32 +20435,26 @@ const InputConstraintsMixin = dedupingMixin(
20534
20435
  _createConstraintsObserver() {
20535
20436
  // This complex observer needs to be added dynamically instead of using `static get observers()`
20536
20437
  // to make it possible to tweak this behavior in classes that apply this mixin.
20537
- this._createMethodObserver(`_constraintsChanged(stateTarget, ${this.constructor.constraints.join(', ')})`);
20438
+ this._createMethodObserver(`_constraintsChanged(${this.constructor.constraints.join(', ')})`);
20538
20439
  }
20539
20440
 
20540
20441
  /**
20541
20442
  * Override this method to implement custom validation constraints.
20542
- * @param {HTMLElement | undefined} stateTarget
20543
20443
  * @param {unknown[]} constraints
20544
20444
  * @protected
20545
20445
  */
20546
- _constraintsChanged(stateTarget, ...constraints) {
20547
- // The input element's validity cannot be determined until
20548
- // all the necessary constraint attributes aren't set on it.
20549
- if (!stateTarget) {
20446
+ _constraintsChanged(...constraints) {
20447
+ // Prevent marking field as invalid when setting required state
20448
+ // or any other constraint before a user has entered the value.
20449
+ if (!this.invalid) {
20550
20450
  return;
20551
20451
  }
20552
20452
 
20553
- const hasConstraints = this._hasValidConstraints(constraints);
20554
- const isLastConstraintRemoved = this.__previousHasConstraints && !hasConstraints;
20555
-
20556
- if ((this._hasValue || this.invalid) && hasConstraints) {
20453
+ if (this._hasValidConstraints(constraints)) {
20557
20454
  this.validate();
20558
- } else if (isLastConstraintRemoved) {
20559
- this._setInvalid(false);
20455
+ } else {
20456
+ this.invalid = false;
20560
20457
  }
20561
-
20562
- this.__previousHasConstraints = hasConstraints;
20563
20458
  }
20564
20459
 
20565
20460
  /**
@@ -20615,22 +20510,6 @@ const InputControlMixin = (superclass) =>
20615
20510
  ) {
20616
20511
  static get properties() {
20617
20512
  return {
20618
- /**
20619
- * A pattern matched against individual characters the user inputs.
20620
- *
20621
- * When set, the field will prevent:
20622
- * - `keydown` events if the entered key doesn't match `/^allowedCharPattern$/`
20623
- * - `paste` events if the pasted text doesn't match `/^allowedCharPattern*$/`
20624
- * - `drop` events if the dropped text doesn't match `/^allowedCharPattern*$/`
20625
- *
20626
- * For example, to allow entering only numbers and minus signs, use:
20627
- * `allowedCharPattern = "[\\d-]"`
20628
- */
20629
- allowedCharPattern: {
20630
- type: String,
20631
- observer: '_allowedCharPatternChanged',
20632
- },
20633
-
20634
20513
  /**
20635
20514
  * If true, the input text gets fully selected when the field is focused using click or touch / tap.
20636
20515
  */
@@ -20688,14 +20567,6 @@ const InputControlMixin = (superclass) =>
20688
20567
  return [...super.delegateAttrs, 'name', 'type', 'placeholder', 'readonly', 'invalid', 'title'];
20689
20568
  }
20690
20569
 
20691
- constructor() {
20692
- super();
20693
-
20694
- this._boundOnPaste = this._onPaste.bind(this);
20695
- this._boundOnDrop = this._onDrop.bind(this);
20696
- this._boundOnBeforeInput = this._onBeforeInput.bind(this);
20697
- }
20698
-
20699
20570
  /**
20700
20571
  * Any element extending this mixin is required to implement this getter.
20701
20572
  * It returns the reference to the clear button element.
@@ -20788,115 +20659,6 @@ const InputControlMixin = (superclass) =>
20788
20659
  this.inputElement.dispatchEvent(new Event('change', { bubbles: true }));
20789
20660
  }
20790
20661
 
20791
- /**
20792
- * Override a method from `InputMixin`.
20793
- * @param {!HTMLElement} input
20794
- * @protected
20795
- * @override
20796
- */
20797
- _addInputListeners(input) {
20798
- super._addInputListeners(input);
20799
-
20800
- input.addEventListener('paste', this._boundOnPaste);
20801
- input.addEventListener('drop', this._boundOnDrop);
20802
- input.addEventListener('beforeinput', this._boundOnBeforeInput);
20803
- }
20804
-
20805
- /**
20806
- * Override a method from `InputMixin`.
20807
- * @param {!HTMLElement} input
20808
- * @protected
20809
- * @override
20810
- */
20811
- _removeInputListeners(input) {
20812
- super._removeInputListeners(input);
20813
-
20814
- input.removeEventListener('paste', this._boundOnPaste);
20815
- input.removeEventListener('drop', this._boundOnDrop);
20816
- input.removeEventListener('beforeinput', this._boundOnBeforeInput);
20817
- }
20818
-
20819
- /**
20820
- * Override an event listener from `KeyboardMixin`.
20821
- * @param {!KeyboardEvent} event
20822
- * @protected
20823
- * @override
20824
- */
20825
- _onKeyDown(event) {
20826
- super._onKeyDown(event);
20827
-
20828
- if (this.allowedCharPattern && !this.__shouldAcceptKey(event)) {
20829
- event.preventDefault();
20830
- this._markInputPrevented();
20831
- }
20832
- }
20833
-
20834
- /** @protected */
20835
- _markInputPrevented() {
20836
- // Add input-prevented attribute for 200ms
20837
- this.setAttribute('input-prevented', '');
20838
- this._preventInputDebouncer = Debouncer$1.debounce(this._preventInputDebouncer, timeOut.after(200), () => {
20839
- this.removeAttribute('input-prevented');
20840
- });
20841
- }
20842
-
20843
- /** @private */
20844
- __shouldAcceptKey(event) {
20845
- return (
20846
- event.metaKey ||
20847
- event.ctrlKey ||
20848
- !event.key || // Allow typing anything if event.key is not supported
20849
- event.key.length !== 1 || // Allow "Backspace", "ArrowLeft" etc.
20850
- this.__allowedCharRegExp.test(event.key)
20851
- );
20852
- }
20853
-
20854
- /** @private */
20855
- _onPaste(e) {
20856
- if (this.allowedCharPattern) {
20857
- const pastedText = e.clipboardData.getData('text');
20858
- if (!this.__allowedTextRegExp.test(pastedText)) {
20859
- e.preventDefault();
20860
- this._markInputPrevented();
20861
- }
20862
- }
20863
- }
20864
-
20865
- /** @private */
20866
- _onDrop(e) {
20867
- if (this.allowedCharPattern) {
20868
- const draggedText = e.dataTransfer.getData('text');
20869
- if (!this.__allowedTextRegExp.test(draggedText)) {
20870
- e.preventDefault();
20871
- this._markInputPrevented();
20872
- }
20873
- }
20874
- }
20875
-
20876
- /** @private */
20877
- _onBeforeInput(e) {
20878
- // The `beforeinput` event covers all the cases for `allowedCharPattern`: keyboard, pasting and dropping,
20879
- // but it is still experimental technology so we can't rely on it. It's used here just as an additional check,
20880
- // because it seems to be the only way to detect and prevent specific keys on mobile devices.
20881
- // See https://github.com/vaadin/vaadin-text-field/issues/429
20882
- if (this.allowedCharPattern && e.data && !this.__allowedTextRegExp.test(e.data)) {
20883
- e.preventDefault();
20884
- this._markInputPrevented();
20885
- }
20886
- }
20887
-
20888
- /** @private */
20889
- _allowedCharPatternChanged(charPattern) {
20890
- if (charPattern) {
20891
- try {
20892
- this.__allowedCharRegExp = new RegExp(`^${charPattern}$`);
20893
- this.__allowedTextRegExp = new RegExp(`^${charPattern}*$`);
20894
- } catch (e) {
20895
- console.error(e);
20896
- }
20897
- }
20898
- }
20899
-
20900
20662
  /**
20901
20663
  * Fired when the user commits a value change.
20902
20664
  *
@@ -20935,13 +20697,14 @@ class InputController extends SlotController {
20935
20697
  }
20936
20698
 
20937
20699
  // Ensure every instance has unique ID
20938
- node.id = this.defaultId;
20700
+ const uniqueId = (InputController._uniqueInputId = 1 + InputController._uniqueInputId || 0);
20701
+ host._inputId = `${host.localName}-${uniqueId}`;
20702
+ node.id = host._inputId;
20939
20703
 
20940
20704
  if (typeof callback === 'function') {
20941
20705
  callback(node);
20942
20706
  }
20943
20707
  },
20944
- true,
20945
20708
  );
20946
20709
  }
20947
20710
  }
@@ -21123,9 +20886,7 @@ class VirtualKeyboardController {
21123
20886
  * @param {function(new:HTMLElement)} subclass
21124
20887
  */
21125
20888
  const DatePickerMixin = (subclass) =>
21126
- class VaadinDatePickerMixin extends ControllerMixin(
21127
- DelegateFocusMixin(InputConstraintsMixin(KeyboardMixin(subclass))),
21128
- ) {
20889
+ class VaadinDatePickerMixin extends ControllerMixin(DelegateFocusMixin(InputMixin(KeyboardMixin(subclass)))) {
21129
20890
  static get properties() {
21130
20891
  return {
21131
20892
  /**
@@ -21154,6 +20915,7 @@ const DatePickerMixin = (subclass) =>
21154
20915
  */
21155
20916
  value: {
21156
20917
  type: String,
20918
+ observer: '_valueChanged',
21157
20919
  notify: true,
21158
20920
  value: '',
21159
20921
  },
@@ -21209,6 +20971,13 @@ const DatePickerMixin = (subclass) =>
21209
20971
  value: '(max-width: 420px), (max-height: 420px)',
21210
20972
  },
21211
20973
 
20974
+ /**
20975
+ * An array of ancestor elements whose -webkit-overflow-scrolling is forced from value
20976
+ * 'touch' to value 'auto' in order to prevent them from clipping the dropdown. iOS only.
20977
+ * @private
20978
+ */
20979
+ _touchPrevented: Array,
20980
+
21212
20981
  /**
21213
20982
  * The object used to localize this component.
21214
20983
  * To change the default localization, replace the entire
@@ -21364,6 +21133,7 @@ const DatePickerMixin = (subclass) =>
21364
21133
  */
21365
21134
  min: {
21366
21135
  type: String,
21136
+ observer: '_minChanged',
21367
21137
  },
21368
21138
 
21369
21139
  /**
@@ -21377,26 +21147,28 @@ const DatePickerMixin = (subclass) =>
21377
21147
  */
21378
21148
  max: {
21379
21149
  type: String,
21150
+ observer: '_maxChanged',
21380
21151
  },
21381
21152
 
21382
21153
  /**
21383
21154
  * The earliest date that can be selected. All earlier dates will be disabled.
21384
- * @type {Date | undefined}
21155
+ * @type {Date | string}
21385
21156
  * @protected
21386
21157
  */
21387
21158
  _minDate: {
21388
21159
  type: Date,
21389
- computed: '__computeMinOrMaxDate(min)',
21160
+ // Null does not work here because minimizer passes undefined to overlay (#351)
21161
+ value: '',
21390
21162
  },
21391
21163
 
21392
21164
  /**
21393
21165
  * The latest date that can be selected. All later dates will be disabled.
21394
- * @type {Date | undefined}
21166
+ * @type {Date | string}
21395
21167
  * @protected
21396
21168
  */
21397
21169
  _maxDate: {
21398
21170
  type: Date,
21399
- computed: '__computeMinOrMaxDate(max)',
21171
+ value: '',
21400
21172
  },
21401
21173
 
21402
21174
  /** @private */
@@ -21411,6 +21183,12 @@ const DatePickerMixin = (subclass) =>
21411
21183
  value: isIOS,
21412
21184
  },
21413
21185
 
21186
+ /** @private */
21187
+ _webkitOverflowScroll: {
21188
+ type: Boolean,
21189
+ value: document.createElement('div').style.webkitOverflowScrolling === '',
21190
+ },
21191
+
21414
21192
  /** @private */
21415
21193
  _focusOverlayOnOpen: Boolean,
21416
21194
 
@@ -21426,10 +21204,6 @@ const DatePickerMixin = (subclass) =>
21426
21204
  ];
21427
21205
  }
21428
21206
 
21429
- static get constraints() {
21430
- return [...super.constraints, 'min', 'max'];
21431
- }
21432
-
21433
21207
  /**
21434
21208
  * Override a getter from `InputControlMixin` to make it optional
21435
21209
  * and to prevent warning when a clear button is missing,
@@ -21496,10 +21270,12 @@ const DatePickerMixin = (subclass) =>
21496
21270
  }
21497
21271
  }
21498
21272
 
21499
- this.validate();
21500
-
21501
- if (this._inputValue === '' && this.value !== '') {
21273
+ if (this.inputElement.value === '' && this.__dispatchChange) {
21274
+ this.validate();
21502
21275
  this.value = '';
21276
+ this.__dispatchChange = false;
21277
+ } else {
21278
+ this.validate();
21503
21279
  }
21504
21280
  }
21505
21281
  }
@@ -21568,19 +21344,14 @@ const DatePickerMixin = (subclass) =>
21568
21344
  this.$.overlay.removeAttribute('disable-upgrade');
21569
21345
  this._overlayInitialized = true;
21570
21346
 
21571
- this.$.overlay.addEventListener('opened-changed', (e) => {
21572
- this.opened = e.detail.value;
21573
- });
21347
+ this.$.overlay.addEventListener('opened-changed', (e) => (this.opened = e.detail.value));
21574
21348
 
21575
21349
  this.$.overlay.addEventListener('vaadin-overlay-escape-press', () => {
21576
21350
  this._focusedDate = this._selectedDate;
21577
21351
  this._close();
21578
21352
  });
21579
21353
 
21580
- this._overlayContent.addEventListener('close', () => {
21581
- this._close();
21582
- });
21583
-
21354
+ this._overlayContent.addEventListener('close', this._close.bind(this));
21584
21355
  this._overlayContent.addEventListener('focus-input', this._focusAndSelect.bind(this));
21585
21356
 
21586
21357
  // User confirmed selected date by clicking the calendar.
@@ -21589,7 +21360,7 @@ const DatePickerMixin = (subclass) =>
21589
21360
 
21590
21361
  this._selectDate(e.detail.date);
21591
21362
 
21592
- this._close();
21363
+ this._close(e);
21593
21364
  });
21594
21365
 
21595
21366
  // User confirmed selected date by pressing Enter or Today.
@@ -21599,18 +21370,24 @@ const DatePickerMixin = (subclass) =>
21599
21370
  this._selectDate(e.detail.date);
21600
21371
  });
21601
21372
 
21602
- // Set focus-ring attribute when moving focus to the overlay
21603
- // by pressing Tab or arrow key, after opening it on click.
21373
+ // Keep focus attribute in focusElement for styling
21604
21374
  this._overlayContent.addEventListener('focusin', () => {
21605
- if (this._keyboardActive) {
21606
- this._setFocused(true);
21607
- }
21375
+ this._setFocused(true);
21608
21376
  });
21609
21377
 
21610
21378
  this.addEventListener('mousedown', () => this.__bringToFront());
21611
21379
  this.addEventListener('touchstart', () => this.__bringToFront());
21612
21380
  }
21613
21381
 
21382
+ /**
21383
+ * Returns true if `value` is valid, and sets the `invalid` flag appropriately.
21384
+ *
21385
+ * @return {boolean} True if the value is valid and sets the `invalid` flag appropriately
21386
+ */
21387
+ validate() {
21388
+ return !(this.invalid = !this.checkValidity());
21389
+ }
21390
+
21614
21391
  /**
21615
21392
  * Returns true if the current input value satisfies all constraints (if any)
21616
21393
  *
@@ -21621,7 +21398,7 @@ const DatePickerMixin = (subclass) =>
21621
21398
  checkValidity() {
21622
21399
  const inputValid =
21623
21400
  !this._inputValue ||
21624
- (!!this._selectedDate && this._inputValue === this._getFormattedDate(this.i18n.formatDate, this._selectedDate));
21401
+ (this._selectedDate && this._inputValue === this._getFormattedDate(this.i18n.formatDate, this._selectedDate));
21625
21402
  const minMaxValid = !this._selectedDate || dateAllowed(this._selectedDate, this._minDate, this._maxDate);
21626
21403
 
21627
21404
  let inputValidity = true;
@@ -21637,51 +21414,6 @@ const DatePickerMixin = (subclass) =>
21637
21414
  return inputValid && minMaxValid && inputValidity;
21638
21415
  }
21639
21416
 
21640
- /**
21641
- * Override method inherited from `FocusMixin`
21642
- * to not call `_setFocused(true)` when focus
21643
- * is restored after closing overlay on click,
21644
- * and to avoid removing `focus-ring` attribute.
21645
- *
21646
- * @param {!FocusEvent} _event
21647
- * @return {boolean}
21648
- * @protected
21649
- * @override
21650
- */
21651
- _shouldSetFocus(_event) {
21652
- return !this._shouldKeepFocusRing;
21653
- }
21654
-
21655
- /**
21656
- * Override method inherited from `FocusMixin`
21657
- * to prevent removing the `focused` attribute:
21658
- * - when moving focus to the overlay content,
21659
- * - when closing on date click / outside click.
21660
- *
21661
- * @param {!FocusEvent} _event
21662
- * @return {boolean}
21663
- * @protected
21664
- * @override
21665
- */
21666
- _shouldRemoveFocus(_event) {
21667
- return !this.opened;
21668
- }
21669
-
21670
- /**
21671
- * Override method inherited from `FocusMixin`
21672
- * to store the `focus-ring` state to restore
21673
- * it later when closing on outside click.
21674
- *
21675
- * @param {boolean} focused
21676
- * @protected
21677
- * @override
21678
- */
21679
- _setFocused(focused) {
21680
- super._setFocused(focused);
21681
-
21682
- this._shouldKeepFocusRing = focused && this._keyboardActive;
21683
- }
21684
-
21685
21417
  /**
21686
21418
  * Select date on user interaction and set the flag
21687
21419
  * to fire change event if necessary.
@@ -21701,7 +21433,10 @@ const DatePickerMixin = (subclass) =>
21701
21433
  }
21702
21434
 
21703
21435
  /** @private */
21704
- _close() {
21436
+ _close(e) {
21437
+ if (e) {
21438
+ e.stopPropagation();
21439
+ }
21705
21440
  this._focus();
21706
21441
  this.close();
21707
21442
  }
@@ -21830,46 +21565,47 @@ const DatePickerMixin = (subclass) =>
21830
21565
  }
21831
21566
  }
21832
21567
 
21833
- /**
21834
- * Override the value observer from `InputMixin` to implement custom
21835
- * handling of the `value` property. The date-picker doesn't forward
21836
- * the value directly to the input like the default implementation of `InputMixin`.
21837
- * Instead, it parses the value into a date, puts it in `_selectedDate` which
21838
- * is then displayed in the input with respect to the specified date format.
21839
- *
21840
- * @param {string | undefined} value
21841
- * @param {string | undefined} oldValue
21842
- * @protected
21843
- * @override
21844
- */
21845
- _valueChanged(value, oldValue) {
21846
- const newDate = this._parseDate(value);
21568
+ /** @private */
21569
+ _handleDateChange(property, value, oldValue) {
21570
+ if (!value) {
21571
+ this[property] = '';
21572
+ return;
21573
+ }
21847
21574
 
21848
- if (value && !newDate) {
21849
- // The new value cannot be parsed, revert the old value.
21575
+ const date = this._parseDate(value);
21576
+ if (!date) {
21850
21577
  this.value = oldValue;
21851
21578
  return;
21852
21579
  }
21853
-
21854
- if (value) {
21855
- if (!dateEquals(this._selectedDate, newDate)) {
21856
- // Update the date instance only if the date has actually changed.
21857
- this._selectedDate = newDate;
21858
-
21859
- if (oldValue !== undefined) {
21860
- // Validate only if `value` changes after initialization.
21861
- this.validate();
21862
- }
21580
+ if (!dateEquals(this[property], date)) {
21581
+ this[property] = date;
21582
+ if (this.value) {
21583
+ this.validate();
21863
21584
  }
21864
- } else {
21865
- this._selectedDate = null;
21866
21585
  }
21586
+ }
21587
+
21588
+ /** @private */
21589
+ _valueChanged(value, oldValue) {
21590
+ this._handleDateChange('_selectedDate', value, oldValue);
21867
21591
 
21868
- this._toggleHasValue(this._hasValue);
21592
+ this._toggleHasValue(!!value);
21593
+ }
21594
+
21595
+ /** @private */
21596
+ _minChanged(value, oldValue) {
21597
+ this._handleDateChange('_minDate', value, oldValue);
21598
+ }
21599
+
21600
+ /** @private */
21601
+ _maxChanged(value, oldValue) {
21602
+ this._handleDateChange('_maxDate', value, oldValue);
21869
21603
  }
21870
21604
 
21871
21605
  /** @protected */
21872
21606
  _onOverlayOpened() {
21607
+ this._openedWithFocusRing = this.hasAttribute('focus-ring');
21608
+
21873
21609
  const parsedInitialPosition = this._parseDate(this.initialPosition);
21874
21610
 
21875
21611
  const initialPosition =
@@ -21889,6 +21625,10 @@ const DatePickerMixin = (subclass) =>
21889
21625
 
21890
21626
  window.addEventListener('scroll', this._boundOnScroll, true);
21891
21627
 
21628
+ if (this._webkitOverflowScroll) {
21629
+ this._touchPrevented = this._preventWebkitOverflowScrollingTouch(this.parentElement);
21630
+ }
21631
+
21892
21632
  if (this._focusOverlayOnOpen) {
21893
21633
  this._overlayContent.focusDateElement();
21894
21634
  this._focusOverlayOnOpen = false;
@@ -21902,6 +21642,25 @@ const DatePickerMixin = (subclass) =>
21902
21642
  }
21903
21643
  }
21904
21644
 
21645
+ // A hack needed for iOS to prevent dropdown from being clipped in an
21646
+ // ancestor container with -webkit-overflow-scrolling: touch;
21647
+ /** @private */
21648
+ _preventWebkitOverflowScrollingTouch(element) {
21649
+ const result = [];
21650
+ while (element) {
21651
+ if (window.getComputedStyle(element).webkitOverflowScrolling === 'touch') {
21652
+ const oldInlineValue = element.style.webkitOverflowScrolling;
21653
+ element.style.webkitOverflowScrolling = 'auto';
21654
+ result.push({
21655
+ element,
21656
+ oldInlineValue,
21657
+ });
21658
+ }
21659
+ element = element.parentElement;
21660
+ }
21661
+ return result;
21662
+ }
21663
+
21905
21664
  /** @private */
21906
21665
  _selectParsedOrFocusedDate() {
21907
21666
  // Select the parsed input or focused date
@@ -21928,6 +21687,13 @@ const DatePickerMixin = (subclass) =>
21928
21687
  _onOverlayClosed() {
21929
21688
  window.removeEventListener('scroll', this._boundOnScroll, true);
21930
21689
 
21690
+ if (this._touchPrevented) {
21691
+ this._touchPrevented.forEach(
21692
+ (prevented) => (prevented.element.style.webkitOverflowScrolling = prevented.oldInlineValue),
21693
+ );
21694
+ this._touchPrevented = [];
21695
+ }
21696
+
21931
21697
  // No need to select date on close if it was confirmed by the user.
21932
21698
  if (this.__userConfirmedDate) {
21933
21699
  this.__userConfirmedDate = false;
@@ -21943,6 +21709,11 @@ const DatePickerMixin = (subclass) =>
21943
21709
  if (!this.value) {
21944
21710
  this.validate();
21945
21711
  }
21712
+
21713
+ // If the input isn't focused when overlay closes (fullscreen mode), clear focused state
21714
+ if (this.getRootNode().activeElement !== this.inputElement) {
21715
+ this._setFocused(false);
21716
+ }
21946
21717
  }
21947
21718
 
21948
21719
  /** @private */
@@ -21995,7 +21766,10 @@ const DatePickerMixin = (subclass) =>
21995
21766
  _onChange(event) {
21996
21767
  // For change event on the native <input> blur, after the input is cleared,
21997
21768
  // we schedule change event to be dispatched on date-picker blur.
21998
- if (this._inputValue === '') {
21769
+ if (
21770
+ this.inputElement.value === '' &&
21771
+ !(event.detail && event.detail.sourceEvent && event.detail.sourceEvent.__fromClearButton)
21772
+ ) {
21999
21773
  this.__dispatchChange = true;
22000
21774
  }
22001
21775
 
@@ -22082,7 +21856,7 @@ const DatePickerMixin = (subclass) =>
22082
21856
  if (e.shiftKey) {
22083
21857
  this._overlayContent.focusCancel();
22084
21858
  } else {
22085
- this._overlayContent.focusDateElement();
21859
+ this._overlayContent.focusDate(this._focusedDate);
22086
21860
  }
22087
21861
  }
22088
21862
  break;
@@ -22193,11 +21967,6 @@ const DatePickerMixin = (subclass) =>
22193
21967
  return this.$.overlay.content.querySelector('#overlay-content');
22194
21968
  }
22195
21969
 
22196
- /** @private */
22197
- __computeMinOrMaxDate(dateString) {
22198
- return this._parseDate(dateString);
22199
- }
22200
-
22201
21970
  /**
22202
21971
  * Fired when the user commits a value change.
22203
21972
  *
@@ -22309,13 +22078,12 @@ registerStyles('vaadin-date-picker', [inputFieldShared, datePickerStyles], { mod
22309
22078
  * Note: the `theme` attribute value set on `<vaadin-date-picker>` is
22310
22079
  * propagated to the internal components listed above.
22311
22080
  *
22312
- * See [Styling Components](https://vaadin.com/docs/latest/styling/custom-theme/styling-components) documentation.
22081
+ * See [Styling Components](https://vaadin.com/docs/latest/ds/customization/styling-components) documentation.
22313
22082
  *
22314
22083
  * @fires {Event} change - Fired when the user commits a value change.
22315
22084
  * @fires {CustomEvent} invalid-changed - Fired when the `invalid` property changes.
22316
22085
  * @fires {CustomEvent} opened-changed - Fired when the `opened` property changes.
22317
22086
  * @fires {CustomEvent} value-changed - Fired when the `value` property changes.
22318
- * @fires {CustomEvent} validated - Fired whenever the field is validated.
22319
22087
  *
22320
22088
  * @extends HTMLElement
22321
22089
  * @mixes ElementMixin
@@ -22369,7 +22137,7 @@ class DatePicker extends DatePickerMixin(InputControlMixin(ThemableMixin(Element
22369
22137
  fullscreen$="[[_fullscreen]]"
22370
22138
  theme$="[[__getOverlayTheme(_theme, _overlayInitialized)]]"
22371
22139
  on-vaadin-overlay-open="_onOverlayOpened"
22372
- on-vaadin-overlay-closing="_onOverlayClosed"
22140
+ on-vaadin-overlay-close="_onOverlayClosed"
22373
22141
  restore-focus-on-close
22374
22142
  restore-focus-node="[[inputElement]]"
22375
22143
  disable-upgrade
@@ -22429,6 +22197,11 @@ class DatePicker extends DatePickerMixin(InputControlMixin(ThemableMixin(Element
22429
22197
 
22430
22198
  /** @private */
22431
22199
  _onVaadinOverlayClose(e) {
22200
+ if (this._openedWithFocusRing && this.hasAttribute('focused')) {
22201
+ this.setAttribute('focus-ring', '');
22202
+ } else if (!this.hasAttribute('focused')) {
22203
+ this.blur();
22204
+ }
22432
22205
  if (e.detail.sourceEvent && e.detail.sourceEvent.composedPath().includes(this)) {
22433
22206
  e.preventDefault();
22434
22207
  }
@@ -22488,26 +22261,55 @@ const HelperFilters = class {
22488
22261
  * Language
22489
22262
  */
22490
22263
  this.language = 'en';
22264
+ /**
22265
+ * Notifies if the quick filters from tickets are active
22266
+ */
22267
+ this.quickFiltersActive = false;
22268
+ /**
22269
+ * Client custom styling via string
22270
+ */
22271
+ this.clientStyling = '';
22272
+ /**
22273
+ * Client custom styling via url content
22274
+ */
22275
+ this.clientStylingUrlContent = '';
22491
22276
  this.showFilterModal = false;
22492
22277
  this.showClearButton = false;
22493
22278
  this.filterData = {};
22494
22279
  this.filterDataReset = { ticketDrawId: '', filterFromCalendar: '', filterToCalendar: '' };
22280
+ this.limitStylingAppends = false;
22281
+ this.setClientStyling = () => {
22282
+ let sheet = document.createElement('style');
22283
+ sheet.innerHTML = this.clientStyling;
22284
+ this.stylingContainer.prepend(sheet);
22285
+ };
22286
+ this.setClientStylingURL = () => {
22287
+ let cssFile = document.createElement('style');
22288
+ setTimeout(() => {
22289
+ cssFile.innerHTML = this.clientStylingUrlContent;
22290
+ this.stylingContainer.prepend(cssFile);
22291
+ }, 1);
22292
+ };
22495
22293
  }
22496
22294
  // reset field values each time the filter modal opens
22497
22295
  componentDidRender() {
22498
- this.filterData.ticketDrawId = null;
22499
- this.filterData.filterFromCalendar = null;
22500
- this.filterData.filterToCalendar = null;
22501
22296
  // @TODO: to way binding?
22502
22297
  if (document.getElementById('#FilterById'))
22503
22298
  document.getElementById('#FilterById').value = '';
22299
+ // start custom styling area
22300
+ if (!this.limitStylingAppends && this.stylingContainer) {
22301
+ if (this.clientStyling)
22302
+ this.setClientStyling();
22303
+ if (this.clientStylingUrlContent)
22304
+ this.setClientStylingURL();
22305
+ this.limitStylingAppends = true;
22306
+ }
22307
+ // end custom styling area
22504
22308
  }
22505
22309
  filterSelectionHandler(event) {
22506
22310
  if (this.postMessage)
22507
22311
  window.postMessage({ type: 'filterSelection', event }, window.location.href);
22508
- if (this.filterData.ticketDrawId)
22509
- this.filterDraw.emit(event);
22510
- if (this.filterData.filterFromCalendar || this.filterData.filterToCalendar)
22312
+ if (this.filterData.ticketDrawId || this.filterData.filterFromCalendar || this.filterData.filterToCalendar)
22511
22313
  this.filterSelection.emit(event);
22512
22314
  }
22513
22315
  filterSelectionResetHandler(event) {
@@ -22543,9 +22345,49 @@ const HelperFilters = class {
22543
22345
  this.filterData.filterToCalendar = new Date(event.target.value).toISOString();
22544
22346
  }
22545
22347
  render() {
22546
- return (h$2("div", { class: "HelperFilters" }, h$2("div", { class: "FilterButtonsWrapper" }, h$2("button", { class: "FilterOpen", onClick: () => this.toggleFilterModal() }, translate$1('filterOpen', this.language)), this.showClearButton ? h$2("button", { class: "FilterClear", onClick: () => this.resetSearch() }, translate$1('filterClear', this.language)) : null), h$2("helper-modal", { "title-modal": "Filter Modal", visible: this.showFilterModal }, h$2("div", { class: "FilterModalHeader" }, h$2("h3", { class: "FilterModalTitle" }, this.activateTicketSearch ? translate$1('filterModalTicketTitle', this.language) : translate$1('filterModalDrawTitle', this.language))), h$2("div", { class: "FilterModalBody" }, h$2("input", { id: "FilterById", type: "text", value: this.filterData.ticketDrawId, onInput: (event) => this.handleTicketDrawId(event), class: "FilterModalSearch", placeholder: this.activateTicketSearch ? translate$1('filterTicketPlaceholder', this.language) : translate$1('filterDrawPlaceholder', this.language) }), h$2("p", null, translate$1('filterOrDate', this.language)), h$2("div", { class: "FilterCalendarWrapper" }, h$2("vaadin-date-picker", { value: this.filterData.filterFromCalendar, onChange: (event) => this.handleFilterFrom(event), placeholder: translate$1('filterFromCalendar', this.language), class: "VaadinDatePicker" }), h$2("vaadin-date-picker", { value: this.filterData.filterToCalendar, onChange: (event) => this.handleFilterTo(event), placeholder: translate$1('filterToCalendar', this.language), class: "VaadinDatePicker" }))), h$2("div", { class: "FilterModalFooter" }, h$2("button", { class: "FilterModalButton", onClick: () => this.filterSearch() }, translate$1('filterModalButton', this.language))))));
22348
+ return (h$2("div", { class: "HelperFilters", ref: el => this.stylingContainer = el }, h$2("div", { class: "FilterButtonsWrapper" }, h$2("button", { class: "FilterOpen", onClick: () => this.toggleFilterModal() }, translate$1('filterOpen', this.language)), (this.showClearButton || this.quickFiltersActive) ?
22349
+ h$2("button", { class: "FilterClear", onClick: () => this.resetSearch() }, translate$1('filterClear', this.language))
22350
+ :
22351
+ null), h$2("helper-modal", { "title-modal": "Filter Modal", visible: this.showFilterModal, "client-styling": this.clientStyling, "client-styling-url-content": this.clientStylingUrlContent }, h$2("div", { class: "FilterModalHeader" }, h$2("h3", { class: "FilterModalTitle" }, this.activateTicketSearch ? translate$1('filterModalTicketTitle', this.language) : translate$1('filterModalDrawTitle', this.language))), h$2("div", { class: "FilterModalBody" }, h$2("input", { id: "FilterById", type: "text", value: this.filterData.ticketDrawId, onInput: (event) => this.handleTicketDrawId(event), class: "FilterModalSearch", placeholder: this.activateTicketSearch ? translate$1('filterTicketPlaceholder', this.language) : translate$1('filterDrawPlaceholder', this.language) }), h$2("p", null, translate$1('filterOrDate', this.language)), h$2("div", { class: "FilterCalendarWrapper" }, h$2("vaadin-date-picker", { value: this.filterData.filterFromCalendar, onChange: (event) => this.handleFilterFrom(event), placeholder: translate$1('filterFromCalendar', this.language), class: "VaadinDatePicker" }), h$2("vaadin-date-picker", { value: this.filterData.filterToCalendar, onChange: (event) => this.handleFilterTo(event), placeholder: translate$1('filterToCalendar', this.language), class: "VaadinDatePicker" }))), h$2("div", { class: "FilterModalFooter" }, h$2("button", { class: "FilterModalButton", onClick: () => this.filterSearch() }, translate$1('filterModalButton', this.language))))));
22547
22352
  }
22548
22353
  };
22549
22354
  HelperFilters.style = helperFiltersCss;
22550
22355
 
22551
- export { HelperFilters as helper_filters };
22356
+ /**
22357
+ * @name isMobile
22358
+ * @description A method that returns if the browser used to access the app is from a mobile device or not
22359
+ * @param {String} userAgent window.navigator.userAgent
22360
+ * @returns {Boolean} true or false
22361
+ */
22362
+ const isMobile = (userAgent) => {
22363
+ return !!(userAgent.toLowerCase().match(/android/i) ||
22364
+ userAgent.toLowerCase().match(/blackberry|bb/i) ||
22365
+ userAgent.toLowerCase().match(/iphone|ipad|ipod/i) ||
22366
+ userAgent.toLowerCase().match(/windows phone|windows mobile|iemobile|wpdesktop/i));
22367
+ };
22368
+
22369
+ const helperModalCss = ":host{display:block}.HelperModalWrapper{position:fixed;left:0;top:0;width:100%;height:100%;background:rgba(0, 0, 0, 0.7);opacity:0;visibility:hidden;transform:scale(1.1);transition:visibility 0s linear 0.25s, opacity 0.25s 0s, transform 0.25s;z-index:1}.HelperModalVisible{opacity:1;visibility:visible;transform:scale(1);transition:visibility 0s linear 0s, opacity 0.25s 0s, transform 0.25s}.HelperModalContent{position:relative;border:solid 1px #848e97;box-shadow:2px 2px 2px rgba(0, 0, 0, 0.007);font-size:14px;padding:10px 10px 5px 10px;background-color:#fff;position:absolute;top:50%;left:50%;transform:translate(-50%, -50%);border-radius:4px;width:600px;max-height:600px;overflow-y:scroll}.HelperModalMobileContent{background:#FFF;top:50%;left:50%;transform:translate(-50%, -50%);border-radius:4px;width:80%;max-height:350px}.HelperModalClose{cursor:pointer;position:absolute;top:15px;right:15px;font-size:20px;color:#000}.HelperModalMobileClose{position:absolute;top:15px;right:15px;font-size:20px;color:#000}";
22370
+
22371
+ const HelperModal = class {
22372
+ constructor(hostRef) {
22373
+ registerInstance(this, hostRef);
22374
+ this.cancel = createEvent(this, "modalCloseEvent", 7);
22375
+ /**
22376
+ * Toggles if the helper is visible or not
22377
+ */
22378
+ this.visible = true;
22379
+ this.userAgent = window.navigator.userAgent;
22380
+ }
22381
+ handleHelperModalClose() {
22382
+ this.visible = false;
22383
+ this.cancel.emit();
22384
+ }
22385
+ ;
22386
+ render() {
22387
+ return ((this.visible &&
22388
+ h$2("div", { class: this.visible ? "HelperModalWrapper HelperModalVisible" : "HelperModalWrapper" }, h$2("div", { class: "HelperModalWrapper HelperModalVisible" }, h$2("div", { class: "HelperModalContent" + (isMobile(this.userAgent) ? ' HelperModalMobileContent' : '') }, h$2("span", { class: "HelperModalClose" + (isMobile(this.userAgent) ? ' HelperModalMobileClose' : ''), onClick: this.handleHelperModalClose.bind(this) }, "X"), h$2("slot", null))))));
22389
+ }
22390
+ };
22391
+ HelperModal.style = helperModalCss;
22392
+
22393
+ export { HelperFilters as helper_filters, HelperModal as helper_modal };