@vaadin/date-picker 23.3.0-alpha2 → 24.0.0-alpha1
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.
- package/package.json +10 -10
- package/src/vaadin-date-picker-helper.d.ts +7 -0
- package/src/vaadin-date-picker-helper.js +14 -0
- package/src/vaadin-date-picker-light.d.ts +0 -6
- package/src/vaadin-date-picker-light.js +4 -42
- package/src/vaadin-date-picker-mixin.d.ts +0 -9
- package/src/vaadin-date-picker-mixin.js +73 -52
- package/src/vaadin-date-picker-month-scroller.js +74 -0
- package/src/vaadin-date-picker-overlay-content.js +297 -175
- package/src/vaadin-date-picker-overlay.js +21 -10
- package/src/vaadin-date-picker-year-scroller.js +104 -0
- package/src/vaadin-date-picker-year.js +57 -0
- package/src/vaadin-date-picker.d.ts +19 -9
- package/src/vaadin-date-picker.js +38 -36
- package/src/vaadin-infinite-scroller.js +69 -41
- package/src/vaadin-month-calendar.js +3 -7
- package/theme/lumo/vaadin-date-picker-overlay-content-styles.js +15 -52
- package/theme/lumo/vaadin-date-picker-overlay-styles.js +1 -1
- package/theme/lumo/vaadin-date-picker-year-styles.js +32 -0
- package/theme/material/vaadin-date-picker-overlay-content-styles.js +11 -36
- package/theme/material/vaadin-date-picker-overlay-styles.js +1 -1
- package/theme/material/vaadin-date-picker-year-styles.js +28 -0
- package/web-types.json +5 -5
- package/web-types.lit.json +5 -5
- package/src/vaadin-date-picker-styles.js +0 -33
|
@@ -3,25 +3,36 @@
|
|
|
3
3
|
* Copyright (c) 2016 - 2022 Vaadin Ltd.
|
|
4
4
|
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
|
|
5
5
|
*/
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import { registerStyles } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
|
|
10
|
-
import { datePickerOverlayStyles } from './vaadin-date-picker-styles.js';
|
|
6
|
+
import { Overlay } from '@vaadin/overlay/src/vaadin-overlay.js';
|
|
7
|
+
import { PositionMixin } from '@vaadin/overlay/src/vaadin-overlay-position-mixin.js';
|
|
8
|
+
import { css, registerStyles } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
|
|
11
9
|
|
|
12
|
-
registerStyles(
|
|
13
|
-
|
|
14
|
-
|
|
10
|
+
registerStyles(
|
|
11
|
+
'vaadin-date-picker-overlay',
|
|
12
|
+
css`
|
|
13
|
+
[part='overlay'] {
|
|
14
|
+
display: flex;
|
|
15
|
+
flex: auto;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
[part~='content'] {
|
|
19
|
+
flex: auto;
|
|
20
|
+
}
|
|
21
|
+
`,
|
|
22
|
+
{
|
|
23
|
+
moduleId: 'vaadin-date-picker-overlay-styles',
|
|
24
|
+
},
|
|
25
|
+
);
|
|
15
26
|
|
|
16
27
|
let memoizedTemplate;
|
|
17
28
|
|
|
18
29
|
/**
|
|
19
30
|
* An element used internally by `<vaadin-date-picker>`. Not intended to be used separately.
|
|
20
31
|
*
|
|
21
|
-
* @extends
|
|
32
|
+
* @extends Overlay
|
|
22
33
|
* @private
|
|
23
34
|
*/
|
|
24
|
-
class DatePickerOverlay extends
|
|
35
|
+
class DatePickerOverlay extends PositionMixin(Overlay) {
|
|
25
36
|
static get is() {
|
|
26
37
|
return 'vaadin-date-picker-overlay';
|
|
27
38
|
}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright (c) 2016 - 2022 Vaadin Ltd.
|
|
4
|
+
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
|
|
5
|
+
*/
|
|
6
|
+
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
|
|
7
|
+
import { InfiniteScroller } from './vaadin-infinite-scroller.js';
|
|
8
|
+
|
|
9
|
+
const stylesTemplate = html`
|
|
10
|
+
<style>
|
|
11
|
+
:host {
|
|
12
|
+
--vaadin-infinite-scroller-item-height: 80px;
|
|
13
|
+
width: 50px;
|
|
14
|
+
display: block;
|
|
15
|
+
height: 100%;
|
|
16
|
+
position: absolute;
|
|
17
|
+
right: 0;
|
|
18
|
+
transform: translateX(100%);
|
|
19
|
+
-webkit-tap-highlight-color: transparent;
|
|
20
|
+
-webkit-user-select: none;
|
|
21
|
+
-moz-user-select: none;
|
|
22
|
+
user-select: none;
|
|
23
|
+
/* Center the year scroller position. */
|
|
24
|
+
--vaadin-infinite-scroller-buffer-offset: 50%;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
:host::before {
|
|
28
|
+
content: '';
|
|
29
|
+
display: block;
|
|
30
|
+
background: transparent;
|
|
31
|
+
width: 0;
|
|
32
|
+
height: 0;
|
|
33
|
+
position: absolute;
|
|
34
|
+
left: 0;
|
|
35
|
+
top: 50%;
|
|
36
|
+
transform: translateY(-50%);
|
|
37
|
+
border-width: 6px;
|
|
38
|
+
border-style: solid;
|
|
39
|
+
border-color: transparent;
|
|
40
|
+
border-left-color: #000;
|
|
41
|
+
}
|
|
42
|
+
</style>
|
|
43
|
+
`;
|
|
44
|
+
|
|
45
|
+
let memoizedTemplate;
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* An element used internally by `<vaadin-date-picker>`. Not intended to be used separately.
|
|
49
|
+
*
|
|
50
|
+
* @extends InfiniteScroller
|
|
51
|
+
* @mixes ThemableMixin
|
|
52
|
+
* @private
|
|
53
|
+
*/
|
|
54
|
+
class DatePickerYearScroller extends InfiniteScroller {
|
|
55
|
+
static get is() {
|
|
56
|
+
return 'vaadin-date-picker-year-scroller';
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
static get template() {
|
|
60
|
+
if (!memoizedTemplate) {
|
|
61
|
+
memoizedTemplate = super.template.cloneNode(true);
|
|
62
|
+
memoizedTemplate.content.appendChild(stylesTemplate.content.cloneNode(true));
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
return memoizedTemplate;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
static get properties() {
|
|
69
|
+
return {
|
|
70
|
+
bufferSize: {
|
|
71
|
+
type: Number,
|
|
72
|
+
value: 12,
|
|
73
|
+
},
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* @protected
|
|
79
|
+
* @override
|
|
80
|
+
*/
|
|
81
|
+
_createElement() {
|
|
82
|
+
return document.createElement('vaadin-date-picker-year');
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* @param {HTMLElement} element
|
|
87
|
+
* @param {number} index
|
|
88
|
+
* @protected
|
|
89
|
+
* @override
|
|
90
|
+
*/
|
|
91
|
+
_updateElement(element, index) {
|
|
92
|
+
element.year = this._yearAfterXYears(index);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/** @private */
|
|
96
|
+
_yearAfterXYears(index) {
|
|
97
|
+
const today = new Date();
|
|
98
|
+
const result = new Date(today);
|
|
99
|
+
result.setFullYear(parseInt(index) + today.getFullYear());
|
|
100
|
+
return result.getFullYear();
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
customElements.define(DatePickerYearScroller.is, DatePickerYearScroller);
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright (c) 2016 - 2022 Vaadin Ltd.
|
|
4
|
+
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
|
|
5
|
+
*/
|
|
6
|
+
import { html, PolymerElement } from '@polymer/polymer/polymer-element.js';
|
|
7
|
+
import { ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* An element used internally by `<vaadin-date-picker>`. Not intended to be used separately.
|
|
11
|
+
*
|
|
12
|
+
* @extends HTMLElement
|
|
13
|
+
* @mixes ThemableMixin
|
|
14
|
+
* @private
|
|
15
|
+
*/
|
|
16
|
+
export class DatePickerYear extends ThemableMixin(PolymerElement) {
|
|
17
|
+
static get is() {
|
|
18
|
+
return 'vaadin-date-picker-year';
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
static get template() {
|
|
22
|
+
return html`
|
|
23
|
+
<style>
|
|
24
|
+
:host {
|
|
25
|
+
display: block;
|
|
26
|
+
height: 100%;
|
|
27
|
+
}
|
|
28
|
+
</style>
|
|
29
|
+
<div part="year-number">[[year]]</div>
|
|
30
|
+
<div part="year-separator" aria-hidden="true"></div>
|
|
31
|
+
`;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
static get properties() {
|
|
35
|
+
return {
|
|
36
|
+
year: {
|
|
37
|
+
type: String,
|
|
38
|
+
},
|
|
39
|
+
|
|
40
|
+
selectedDate: {
|
|
41
|
+
type: Object,
|
|
42
|
+
},
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
static get observers() {
|
|
47
|
+
return ['__updateSelected(year, selectedDate)'];
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/** @private */
|
|
51
|
+
__updateSelected(year, selectedDate) {
|
|
52
|
+
this.toggleAttribute('selected', selectedDate && selectedDate.getFullYear() === year);
|
|
53
|
+
this.toggleAttribute('current', year === new Date().getFullYear());
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
customElements.define(DatePickerYear.is, DatePickerYear);
|
|
@@ -79,7 +79,6 @@ export interface DatePickerEventMap extends HTMLElementEventMap, DatePickerCusto
|
|
|
79
79
|
* Part name | Description
|
|
80
80
|
* ----------------------|--------------------
|
|
81
81
|
* `toggle-button` | Toggle button
|
|
82
|
-
* `overlay-content` | The overlay element
|
|
83
82
|
*
|
|
84
83
|
* In addition to `<vaadin-text-field>` state attributes, the following state attributes are available for theming:
|
|
85
84
|
*
|
|
@@ -99,6 +98,9 @@ export interface DatePickerEventMap extends HTMLElementEventMap, DatePickerCusto
|
|
|
99
98
|
*
|
|
100
99
|
* - `<vaadin-date-picker-overlay>` - has the same API as [`<vaadin-overlay>`](#/elements/vaadin-overlay).
|
|
101
100
|
* - `<vaadin-date-picker-overlay-content>`
|
|
101
|
+
* - `<vaadin-date-picker-month-scroller>`
|
|
102
|
+
* - `<vaadin-date-picker-year-scroller>`
|
|
103
|
+
* - `<vaadin-date-picker-year>`
|
|
102
104
|
* - `<vaadin-month-calendar>`
|
|
103
105
|
* - [`<vaadin-input-container>`](#/elements/vaadin-input-container) - an internal element wrapping the input.
|
|
104
106
|
*
|
|
@@ -111,14 +113,15 @@ export interface DatePickerEventMap extends HTMLElementEventMap, DatePickerCusto
|
|
|
111
113
|
* `clear-button` | Fullscreen mode clear button
|
|
112
114
|
* `toggle-button` | Fullscreen mode toggle button
|
|
113
115
|
* `years-toggle-button` | Fullscreen mode years scroller toggle
|
|
114
|
-
* `
|
|
115
|
-
*
|
|
116
|
-
*
|
|
117
|
-
*
|
|
118
|
-
*
|
|
119
|
-
*
|
|
120
|
-
* `
|
|
121
|
-
* `
|
|
116
|
+
* `toolbar` | Footer bar with slotted buttons
|
|
117
|
+
*
|
|
118
|
+
* The following state attributes are available on the `<vaadin-date-picker-overlay-content>` element:
|
|
119
|
+
*
|
|
120
|
+
* Attribute | Description
|
|
121
|
+
* ----------------|-------------------------------------------------
|
|
122
|
+
* `desktop` | Set when the overlay content is in desktop mode
|
|
123
|
+
* `fullscreen` | Set when the overlay content is in fullscreen mode
|
|
124
|
+
* `years-visible` | Set when the year scroller is visible in fullscreen mode
|
|
122
125
|
*
|
|
123
126
|
* In order to style the month calendar, use `<vaadin-month-calendar>` shadow DOM parts:
|
|
124
127
|
*
|
|
@@ -131,6 +134,13 @@ export interface DatePickerEventMap extends HTMLElementEventMap, DatePickerCusto
|
|
|
131
134
|
* `week-number` | Week number element
|
|
132
135
|
* `date` | Date element
|
|
133
136
|
*
|
|
137
|
+
* In order to style year scroller elements, use `<vaadin-date-picker-year>` shadow DOM parts:
|
|
138
|
+
*
|
|
139
|
+
* Part name | Description
|
|
140
|
+
* ----------------------|--------------------
|
|
141
|
+
* `year-number` | Year number
|
|
142
|
+
* `year-separator` | Year separator
|
|
143
|
+
*
|
|
134
144
|
* Note: the `theme` attribute value set on `<vaadin-date-picker>` is
|
|
135
145
|
* propagated to the internal components listed above.
|
|
136
146
|
*
|
|
@@ -15,9 +15,8 @@ import { LabelledInputController } from '@vaadin/field-base/src/labelled-input-c
|
|
|
15
15
|
import { inputFieldShared } from '@vaadin/field-base/src/styles/input-field-shared-styles.js';
|
|
16
16
|
import { registerStyles, ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
|
|
17
17
|
import { DatePickerMixin } from './vaadin-date-picker-mixin.js';
|
|
18
|
-
import { datePickerStyles } from './vaadin-date-picker-styles.js';
|
|
19
18
|
|
|
20
|
-
registerStyles('vaadin-date-picker',
|
|
19
|
+
registerStyles('vaadin-date-picker', inputFieldShared, { moduleId: 'vaadin-date-picker-styles' });
|
|
21
20
|
|
|
22
21
|
/**
|
|
23
22
|
* `<vaadin-date-picker>` is an input field that allows to enter a date by typing or by selecting from a calendar overlay.
|
|
@@ -48,7 +47,6 @@ registerStyles('vaadin-date-picker', [inputFieldShared, datePickerStyles], { mod
|
|
|
48
47
|
* Part name | Description
|
|
49
48
|
* ----------------------|--------------------
|
|
50
49
|
* `toggle-button` | Toggle button
|
|
51
|
-
* `overlay-content` | The overlay element
|
|
52
50
|
*
|
|
53
51
|
* In addition to `<vaadin-text-field>` state attributes, the following state attributes are available for theming:
|
|
54
52
|
*
|
|
@@ -68,6 +66,9 @@ registerStyles('vaadin-date-picker', [inputFieldShared, datePickerStyles], { mod
|
|
|
68
66
|
*
|
|
69
67
|
* - `<vaadin-date-picker-overlay>` - has the same API as [`<vaadin-overlay>`](#/elements/vaadin-overlay).
|
|
70
68
|
* - `<vaadin-date-picker-overlay-content>`
|
|
69
|
+
* - `<vaadin-date-picker-month-scroller>`
|
|
70
|
+
* - `<vaadin-date-picker-year-scroller>`
|
|
71
|
+
* - `<vaadin-date-picker-year>`
|
|
71
72
|
* - `<vaadin-month-calendar>`
|
|
72
73
|
* - [`<vaadin-input-container>`](#/elements/vaadin-input-container) - an internal element wrapping the input.
|
|
73
74
|
*
|
|
@@ -80,14 +81,15 @@ registerStyles('vaadin-date-picker', [inputFieldShared, datePickerStyles], { mod
|
|
|
80
81
|
* `clear-button` | Fullscreen mode clear button
|
|
81
82
|
* `toggle-button` | Fullscreen mode toggle button
|
|
82
83
|
* `years-toggle-button` | Fullscreen mode years scroller toggle
|
|
83
|
-
* `
|
|
84
|
-
*
|
|
85
|
-
*
|
|
86
|
-
*
|
|
87
|
-
*
|
|
88
|
-
*
|
|
89
|
-
* `
|
|
90
|
-
* `
|
|
84
|
+
* `toolbar` | Footer bar with slotted buttons
|
|
85
|
+
*
|
|
86
|
+
* The following state attributes are available on the `<vaadin-date-picker-overlay-content>` element:
|
|
87
|
+
*
|
|
88
|
+
* Attribute | Description
|
|
89
|
+
* ----------------|-------------------------------------------------
|
|
90
|
+
* `desktop` | Set when the overlay content is in desktop mode
|
|
91
|
+
* `fullscreen` | Set when the overlay content is in fullscreen mode
|
|
92
|
+
* `years-visible` | Set when the year scroller is visible in fullscreen mode
|
|
91
93
|
*
|
|
92
94
|
* In order to style the month calendar, use `<vaadin-month-calendar>` shadow DOM parts:
|
|
93
95
|
*
|
|
@@ -100,6 +102,13 @@ registerStyles('vaadin-date-picker', [inputFieldShared, datePickerStyles], { mod
|
|
|
100
102
|
* `week-number` | Week number element
|
|
101
103
|
* `date` | Date element
|
|
102
104
|
*
|
|
105
|
+
* In order to style year scroller elements, use `<vaadin-date-picker-year>` shadow DOM parts:
|
|
106
|
+
*
|
|
107
|
+
* Part name | Description
|
|
108
|
+
* ----------------------|--------------------
|
|
109
|
+
* `year-number` | Year number
|
|
110
|
+
* `year-separator` | Year separator
|
|
111
|
+
*
|
|
103
112
|
* Note: the `theme` attribute value set on `<vaadin-date-picker>` is
|
|
104
113
|
* propagated to the internal components listed above.
|
|
105
114
|
*
|
|
@@ -128,6 +137,15 @@ class DatePicker extends DatePickerMixin(InputControlMixin(ThemableMixin(Element
|
|
|
128
137
|
:host([opened]) {
|
|
129
138
|
pointer-events: auto;
|
|
130
139
|
}
|
|
140
|
+
|
|
141
|
+
:host([dir='rtl']) [part='input-field'] {
|
|
142
|
+
direction: ltr;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
:host([dir='rtl']) [part='input-field'] ::slotted(input)::placeholder {
|
|
146
|
+
direction: rtl;
|
|
147
|
+
text-align: left;
|
|
148
|
+
}
|
|
131
149
|
</style>
|
|
132
150
|
|
|
133
151
|
<div class="vaadin-date-picker-container">
|
|
@@ -161,29 +179,14 @@ class DatePicker extends DatePickerMixin(InputControlMixin(ThemableMixin(Element
|
|
|
161
179
|
<vaadin-date-picker-overlay
|
|
162
180
|
id="overlay"
|
|
163
181
|
fullscreen$="[[_fullscreen]]"
|
|
164
|
-
theme$="[[
|
|
182
|
+
theme$="[[_theme]]"
|
|
183
|
+
opened="{{opened}}"
|
|
184
|
+
on-vaadin-overlay-escape-press="_onOverlayEscapePress"
|
|
165
185
|
on-vaadin-overlay-open="_onOverlayOpened"
|
|
166
186
|
on-vaadin-overlay-closing="_onOverlayClosed"
|
|
167
187
|
restore-focus-on-close
|
|
168
188
|
restore-focus-node="[[inputElement]]"
|
|
169
|
-
|
|
170
|
-
>
|
|
171
|
-
<template>
|
|
172
|
-
<vaadin-date-picker-overlay-content
|
|
173
|
-
id="overlay-content"
|
|
174
|
-
i18n="[[i18n]]"
|
|
175
|
-
fullscreen$="[[_fullscreen]]"
|
|
176
|
-
label="[[label]]"
|
|
177
|
-
selected-date="[[_selectedDate]]"
|
|
178
|
-
focused-date="{{_focusedDate}}"
|
|
179
|
-
show-week-numbers="[[showWeekNumbers]]"
|
|
180
|
-
min-date="[[_minDate]]"
|
|
181
|
-
max-date="[[_maxDate]]"
|
|
182
|
-
part="overlay-content"
|
|
183
|
-
theme$="[[__getOverlayTheme(_theme, _overlayInitialized)]]"
|
|
184
|
-
></vaadin-date-picker-overlay-content>
|
|
185
|
-
</template>
|
|
186
|
-
</vaadin-date-picker-overlay>
|
|
189
|
+
></vaadin-date-picker-overlay>
|
|
187
190
|
|
|
188
191
|
<slot name="tooltip"></slot>
|
|
189
192
|
`;
|
|
@@ -219,11 +222,6 @@ class DatePicker extends DatePickerMixin(InputControlMixin(ThemableMixin(Element
|
|
|
219
222
|
|
|
220
223
|
const toggleButton = this.shadowRoot.querySelector('[part="toggle-button"]');
|
|
221
224
|
toggleButton.addEventListener('mousedown', (e) => e.preventDefault());
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
/** @protected */
|
|
225
|
-
_initOverlay() {
|
|
226
|
-
super._initOverlay();
|
|
227
225
|
|
|
228
226
|
this.$.overlay.addEventListener('vaadin-overlay-close', this._onVaadinOverlayClose.bind(this));
|
|
229
227
|
}
|
|
@@ -238,7 +236,11 @@ class DatePicker extends DatePickerMixin(InputControlMixin(ThemableMixin(Element
|
|
|
238
236
|
/** @private */
|
|
239
237
|
_toggle(e) {
|
|
240
238
|
e.stopPropagation();
|
|
241
|
-
|
|
239
|
+
if (this.$.overlay.opened) {
|
|
240
|
+
this.close();
|
|
241
|
+
} else {
|
|
242
|
+
this.open();
|
|
243
|
+
}
|
|
242
244
|
}
|
|
243
245
|
|
|
244
246
|
// Workaround https://github.com/vaadin/web-components/issues/2855
|
|
@@ -4,7 +4,6 @@
|
|
|
4
4
|
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
|
|
5
5
|
*/
|
|
6
6
|
import { afterNextRender } from '@polymer/polymer/lib/utils/render-status.js';
|
|
7
|
-
import { templatize } from '@polymer/polymer/lib/utils/templatize.js';
|
|
8
7
|
import { html, PolymerElement } from '@polymer/polymer/polymer-element.js';
|
|
9
8
|
import { timeOut } from '@vaadin/component-base/src/async.js';
|
|
10
9
|
import { isFirefox } from '@vaadin/component-base/src/browser-utils.js';
|
|
@@ -14,7 +13,7 @@ import { Debouncer } from '@vaadin/component-base/src/debounce.js';
|
|
|
14
13
|
* @extends HTMLElement
|
|
15
14
|
* @private
|
|
16
15
|
*/
|
|
17
|
-
class InfiniteScroller extends PolymerElement {
|
|
16
|
+
export class InfiniteScroller extends PolymerElement {
|
|
18
17
|
static get template() {
|
|
19
18
|
return html`
|
|
20
19
|
<style>
|
|
@@ -69,10 +68,6 @@ class InfiniteScroller extends PolymerElement {
|
|
|
69
68
|
`;
|
|
70
69
|
}
|
|
71
70
|
|
|
72
|
-
static get is() {
|
|
73
|
-
return 'vaadin-infinite-scroller';
|
|
74
|
-
}
|
|
75
|
-
|
|
76
71
|
static get properties() {
|
|
77
72
|
return {
|
|
78
73
|
/**
|
|
@@ -89,6 +84,7 @@ class InfiniteScroller extends PolymerElement {
|
|
|
89
84
|
/**
|
|
90
85
|
* The amount of initial scroll top. Needed in order for the
|
|
91
86
|
* user to be able to scroll backwards.
|
|
87
|
+
* @private
|
|
92
88
|
*/
|
|
93
89
|
_initialScroll: {
|
|
94
90
|
value: 500000,
|
|
@@ -96,17 +92,22 @@ class InfiniteScroller extends PolymerElement {
|
|
|
96
92
|
|
|
97
93
|
/**
|
|
98
94
|
* The index/position mapped at _initialScroll point.
|
|
95
|
+
* @private
|
|
99
96
|
*/
|
|
100
97
|
_initialIndex: {
|
|
101
98
|
value: 0,
|
|
102
99
|
},
|
|
103
100
|
|
|
101
|
+
/** @private */
|
|
104
102
|
_buffers: Array,
|
|
105
103
|
|
|
104
|
+
/** @private */
|
|
106
105
|
_preventScrollEvent: Boolean,
|
|
107
106
|
|
|
107
|
+
/** @private */
|
|
108
108
|
_mayHaveMomentum: Boolean,
|
|
109
109
|
|
|
110
|
+
/** @private */
|
|
110
111
|
_initialized: Boolean,
|
|
111
112
|
|
|
112
113
|
active: {
|
|
@@ -116,26 +117,14 @@ class InfiniteScroller extends PolymerElement {
|
|
|
116
117
|
};
|
|
117
118
|
}
|
|
118
119
|
|
|
120
|
+
/** @protected */
|
|
119
121
|
ready() {
|
|
120
122
|
super.ready();
|
|
121
123
|
|
|
122
|
-
this._buffers =
|
|
124
|
+
this._buffers = [...this.shadowRoot.querySelectorAll('.buffer')];
|
|
123
125
|
|
|
124
126
|
this.$.fullHeight.style.height = `${this._initialScroll * 2}px`;
|
|
125
127
|
|
|
126
|
-
const tpl = this.querySelector('template');
|
|
127
|
-
this._TemplateClass = templatize(tpl, this, {
|
|
128
|
-
forwardHostProp(prop, value) {
|
|
129
|
-
if (prop !== 'index') {
|
|
130
|
-
this._buffers.forEach((buffer) => {
|
|
131
|
-
[].forEach.call(buffer.children, (insertionPoint) => {
|
|
132
|
-
insertionPoint._itemWrapper.instance[prop] = value;
|
|
133
|
-
});
|
|
134
|
-
});
|
|
135
|
-
}
|
|
136
|
-
},
|
|
137
|
-
});
|
|
138
|
-
|
|
139
128
|
// Firefox interprets elements with overflow:auto as focusable
|
|
140
129
|
// https://bugzilla.mozilla.org/show_bug.cgi?id=1069739
|
|
141
130
|
if (isFirefox) {
|
|
@@ -143,6 +132,37 @@ class InfiniteScroller extends PolymerElement {
|
|
|
143
132
|
}
|
|
144
133
|
}
|
|
145
134
|
|
|
135
|
+
/**
|
|
136
|
+
* Force the scroller to update clones after a reset, without
|
|
137
|
+
* waiting for the debouncer to resolve.
|
|
138
|
+
*/
|
|
139
|
+
forceUpdate() {
|
|
140
|
+
if (this._debouncerUpdateClones) {
|
|
141
|
+
this._buffers[0].updated = this._buffers[1].updated = false;
|
|
142
|
+
this._updateClones();
|
|
143
|
+
this._debouncerUpdateClones.cancel();
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* @protected
|
|
149
|
+
* @override
|
|
150
|
+
*/
|
|
151
|
+
_createElement() {
|
|
152
|
+
// To be implemented.
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* @param {HTMLElement} _element
|
|
157
|
+
* @param {number} _index
|
|
158
|
+
* @protected
|
|
159
|
+
* @override
|
|
160
|
+
*/
|
|
161
|
+
_updateElement(_element, _index) {
|
|
162
|
+
// To be implemented.
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/** @private */
|
|
146
166
|
_activated(active) {
|
|
147
167
|
if (active && !this._initialized) {
|
|
148
168
|
this._createPool();
|
|
@@ -150,11 +170,14 @@ class InfiniteScroller extends PolymerElement {
|
|
|
150
170
|
}
|
|
151
171
|
}
|
|
152
172
|
|
|
173
|
+
/** @private */
|
|
153
174
|
_finishInit() {
|
|
154
175
|
if (!this._initDone) {
|
|
155
176
|
// Once the first set of items start fading in, stamp the rest
|
|
156
177
|
this._buffers.forEach((buffer) => {
|
|
157
|
-
[].forEach
|
|
178
|
+
[...buffer.children].forEach((slot) => {
|
|
179
|
+
this._ensureStampedInstance(slot._itemWrapper);
|
|
180
|
+
});
|
|
158
181
|
});
|
|
159
182
|
|
|
160
183
|
if (!this._buffers[0].translateY) {
|
|
@@ -162,9 +185,11 @@ class InfiniteScroller extends PolymerElement {
|
|
|
162
185
|
}
|
|
163
186
|
|
|
164
187
|
this._initDone = true;
|
|
188
|
+
this.dispatchEvent(new CustomEvent('init-done'));
|
|
165
189
|
}
|
|
166
190
|
}
|
|
167
191
|
|
|
192
|
+
/** @private */
|
|
168
193
|
_translateBuffer(up) {
|
|
169
194
|
const index = up ? 1 : 0;
|
|
170
195
|
this._buffers[index].translateY = this._buffers[index ? 0 : 1].translateY + this._bufferHeight * (index ? -1 : 1);
|
|
@@ -173,6 +198,7 @@ class InfiniteScroller extends PolymerElement {
|
|
|
173
198
|
this._buffers.reverse();
|
|
174
199
|
}
|
|
175
200
|
|
|
201
|
+
/** @private */
|
|
176
202
|
_scroll() {
|
|
177
203
|
if (this._scrollDisabled) {
|
|
178
204
|
return;
|
|
@@ -269,10 +295,12 @@ class InfiniteScroller extends PolymerElement {
|
|
|
269
295
|
return this._itemHeightVal;
|
|
270
296
|
}
|
|
271
297
|
|
|
298
|
+
/** @private */
|
|
272
299
|
get _bufferHeight() {
|
|
273
300
|
return this.itemHeight * this.bufferSize;
|
|
274
301
|
}
|
|
275
302
|
|
|
303
|
+
/** @private */
|
|
276
304
|
_reset() {
|
|
277
305
|
this._scrollDisabled = true;
|
|
278
306
|
this.$.scroller.scrollTop = this._initialScroll;
|
|
@@ -292,6 +320,7 @@ class InfiniteScroller extends PolymerElement {
|
|
|
292
320
|
this._scrollDisabled = false;
|
|
293
321
|
}
|
|
294
322
|
|
|
323
|
+
/** @private */
|
|
295
324
|
_createPool() {
|
|
296
325
|
const container = this.getBoundingClientRect();
|
|
297
326
|
this._buffers.forEach((buffer) => {
|
|
@@ -303,28 +332,27 @@ class InfiniteScroller extends PolymerElement {
|
|
|
303
332
|
const contentId = (InfiniteScroller._contentIndex = InfiniteScroller._contentIndex + 1 || 0);
|
|
304
333
|
const slotName = `vaadin-infinite-scroller-item-content-${contentId}`;
|
|
305
334
|
|
|
306
|
-
const
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
buffer.appendChild(
|
|
335
|
+
const slot = document.createElement('slot');
|
|
336
|
+
slot.setAttribute('name', slotName);
|
|
337
|
+
slot._itemWrapper = itemWrapper;
|
|
338
|
+
buffer.appendChild(slot);
|
|
310
339
|
|
|
311
340
|
itemWrapper.setAttribute('slot', slotName);
|
|
312
341
|
this.appendChild(itemWrapper);
|
|
313
342
|
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
}
|
|
319
|
-
}, 1); // Wait for first reset
|
|
343
|
+
// Only stamp the visible instances first
|
|
344
|
+
if (this._isVisible(itemWrapper, container)) {
|
|
345
|
+
this._ensureStampedInstance(itemWrapper);
|
|
346
|
+
}
|
|
320
347
|
}
|
|
321
348
|
});
|
|
322
349
|
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
}
|
|
350
|
+
afterNextRender(this, () => {
|
|
351
|
+
this._finishInit();
|
|
352
|
+
});
|
|
326
353
|
}
|
|
327
354
|
|
|
355
|
+
/** @private */
|
|
328
356
|
_ensureStampedInstance(itemWrapper) {
|
|
329
357
|
if (itemWrapper.firstElementChild) {
|
|
330
358
|
return;
|
|
@@ -332,14 +360,15 @@ class InfiniteScroller extends PolymerElement {
|
|
|
332
360
|
|
|
333
361
|
const tmpInstance = itemWrapper.instance;
|
|
334
362
|
|
|
335
|
-
itemWrapper.instance =
|
|
336
|
-
itemWrapper.appendChild(itemWrapper.instance
|
|
363
|
+
itemWrapper.instance = this._createElement();
|
|
364
|
+
itemWrapper.appendChild(itemWrapper.instance);
|
|
337
365
|
|
|
338
366
|
Object.keys(tmpInstance).forEach((prop) => {
|
|
339
367
|
itemWrapper.instance.set(prop, tmpInstance[prop]);
|
|
340
368
|
});
|
|
341
369
|
}
|
|
342
370
|
|
|
371
|
+
/** @private */
|
|
343
372
|
_updateClones(viewPortOnly) {
|
|
344
373
|
this._firstIndex = ~~((this._buffers[0].translateY - this._initialScroll) / this.itemHeight) + this._initialIndex;
|
|
345
374
|
|
|
@@ -348,10 +377,10 @@ class InfiniteScroller extends PolymerElement {
|
|
|
348
377
|
if (!buffer.updated) {
|
|
349
378
|
const firstIndex = this._firstIndex + this.bufferSize * bufferIndex;
|
|
350
379
|
|
|
351
|
-
[].forEach
|
|
352
|
-
const itemWrapper =
|
|
380
|
+
[...buffer.children].forEach((slot, index) => {
|
|
381
|
+
const itemWrapper = slot._itemWrapper;
|
|
353
382
|
if (!viewPortOnly || this._isVisible(itemWrapper, scrollerRect)) {
|
|
354
|
-
itemWrapper.instance
|
|
383
|
+
this._updateElement(itemWrapper.instance, firstIndex + index);
|
|
355
384
|
}
|
|
356
385
|
});
|
|
357
386
|
buffer.updated = true;
|
|
@@ -359,10 +388,9 @@ class InfiniteScroller extends PolymerElement {
|
|
|
359
388
|
});
|
|
360
389
|
}
|
|
361
390
|
|
|
391
|
+
/** @private */
|
|
362
392
|
_isVisible(element, container) {
|
|
363
393
|
const rect = element.getBoundingClientRect();
|
|
364
394
|
return rect.bottom > container.top && rect.top < container.bottom;
|
|
365
395
|
}
|
|
366
396
|
}
|
|
367
|
-
|
|
368
|
-
customElements.define(InfiniteScroller.is, InfiniteScroller);
|
|
@@ -80,7 +80,9 @@ class MonthCalendar extends FocusMixin(ThemableMixin(PolymerElement)) {
|
|
|
80
80
|
is="dom-repeat"
|
|
81
81
|
items="[[_getWeekDayNames(i18n.weekdays, i18n.weekdaysShort, showWeekNumbers, i18n.firstDayOfWeek)]]"
|
|
82
82
|
>
|
|
83
|
-
<th role="columnheader" part="weekday" scope="col" abbr$="[[item.weekDay]]">
|
|
83
|
+
<th role="columnheader" part="weekday" scope="col" abbr$="[[item.weekDay]]" aria-hidden="true">
|
|
84
|
+
[[item.weekDayShort]]
|
|
85
|
+
</th>
|
|
84
86
|
</template>
|
|
85
87
|
</tr>
|
|
86
88
|
</thead>
|
|
@@ -426,12 +428,6 @@ class MonthCalendar extends FocusMixin(ThemableMixin(PolymerElement)) {
|
|
|
426
428
|
|
|
427
429
|
return '-1';
|
|
428
430
|
}
|
|
429
|
-
|
|
430
|
-
__getWeekNumbers(dates) {
|
|
431
|
-
return dates
|
|
432
|
-
.map((date) => this.__getWeekNumber(date, dates))
|
|
433
|
-
.filter((week, index, arr) => arr.indexOf(week) === index);
|
|
434
|
-
}
|
|
435
431
|
}
|
|
436
432
|
|
|
437
433
|
customElements.define(MonthCalendar.is, MonthCalendar);
|