@vaadin/component-base 23.2.0-alpha4 → 23.2.0-beta1
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 +2 -2
- package/src/active-mixin.js +11 -14
- package/src/element-mixin.js +1 -1
- package/src/focus-trap-controller.js +5 -1
- package/src/overflow-controller.d.ts +34 -0
- package/src/overflow-controller.js +115 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vaadin/component-base",
|
|
3
|
-
"version": "23.2.0-
|
|
3
|
+
"version": "23.2.0-beta1",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public"
|
|
6
6
|
},
|
|
@@ -42,5 +42,5 @@
|
|
|
42
42
|
"@vaadin/testing-helpers": "^0.3.2",
|
|
43
43
|
"sinon": "^13.0.2"
|
|
44
44
|
},
|
|
45
|
-
"gitHead": "
|
|
45
|
+
"gitHead": "82ff7254f27a1a089367e4dd005f63879e33c188"
|
|
46
46
|
}
|
package/src/active-mixin.js
CHANGED
|
@@ -79,21 +79,18 @@ export const ActiveMixin = (superclass) =>
|
|
|
79
79
|
|
|
80
80
|
if (this._shouldSetActive(event) && this._activeKeys.includes(event.key)) {
|
|
81
81
|
this._setActive(true);
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
/**
|
|
86
|
-
* Removes the `active` attribute from the element if the activation key is released.
|
|
87
|
-
*
|
|
88
|
-
* @param {KeyboardEvent} event
|
|
89
|
-
* @protected
|
|
90
|
-
* @override
|
|
91
|
-
*/
|
|
92
|
-
_onKeyUp(event) {
|
|
93
|
-
super._onKeyUp(event);
|
|
94
82
|
|
|
95
|
-
|
|
96
|
-
|
|
83
|
+
// Element can become hidden before the `keyup` event, e.g. on button click.
|
|
84
|
+
// Use document listener to ensure `active` attribute is removed correctly.
|
|
85
|
+
document.addEventListener(
|
|
86
|
+
'keyup',
|
|
87
|
+
(e) => {
|
|
88
|
+
if (this._activeKeys.includes(e.key)) {
|
|
89
|
+
this._setActive(false);
|
|
90
|
+
}
|
|
91
|
+
},
|
|
92
|
+
{ once: true },
|
|
93
|
+
);
|
|
97
94
|
}
|
|
98
95
|
}
|
|
99
96
|
|
package/src/element-mixin.js
CHANGED
|
@@ -125,7 +125,11 @@ export class FocusTrapController {
|
|
|
125
125
|
const step = backward ? -1 : 1;
|
|
126
126
|
const currentIndex = this.__focusedElementIndex;
|
|
127
127
|
const nextIndex = (focusableElements.length + currentIndex + step) % focusableElements.length;
|
|
128
|
-
focusableElements[nextIndex]
|
|
128
|
+
const element = focusableElements[nextIndex];
|
|
129
|
+
element.focus();
|
|
130
|
+
if (element.localName === 'input') {
|
|
131
|
+
element.select();
|
|
132
|
+
}
|
|
129
133
|
}
|
|
130
134
|
|
|
131
135
|
/**
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright (c) 2021 - 2022 Vaadin Ltd.
|
|
4
|
+
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
|
|
5
|
+
*/
|
|
6
|
+
import type { ReactiveController } from 'lit';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* A controller that detects if content inside the element overflows its scrolling viewport,
|
|
10
|
+
* and sets the `overflow` attribute on the host with a value that indicates the directions
|
|
11
|
+
* where content is overflowing. Supported values are: `top`, `bottom`, `start`, `end`.
|
|
12
|
+
*/
|
|
13
|
+
export class OverflowController implements ReactiveController {
|
|
14
|
+
/**
|
|
15
|
+
* The controller host element.
|
|
16
|
+
*/
|
|
17
|
+
host: HTMLElement;
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* The element that wraps scrollable content.
|
|
21
|
+
* If not set, the host element is used.
|
|
22
|
+
*/
|
|
23
|
+
scrollTarget: HTMLElement;
|
|
24
|
+
|
|
25
|
+
constructor(host: HTMLElement, scrollTarget?: HTMLElement);
|
|
26
|
+
|
|
27
|
+
hostConnected(): void;
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Setup a scroll listener and observers to update overflow.
|
|
31
|
+
* Also performs one-time update synchronously when called.
|
|
32
|
+
*/
|
|
33
|
+
protected observe(): void;
|
|
34
|
+
}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright (c) 2021 - 2022 Vaadin Ltd.
|
|
4
|
+
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
|
|
5
|
+
*/
|
|
6
|
+
import { FlattenedNodesObserver } from '@polymer/polymer/lib/utils/flattened-nodes-observer.js';
|
|
7
|
+
import { animationFrame } from './async.js';
|
|
8
|
+
import { Debouncer } from './debounce.js';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* A controller that detects if content inside the element overflows its scrolling viewport,
|
|
12
|
+
* and sets the `overflow` attribute on the host with a value that indicates the directions
|
|
13
|
+
* where content is overflowing. Supported values are: `top`, `bottom`, `start`, `end`.
|
|
14
|
+
*/
|
|
15
|
+
export class OverflowController {
|
|
16
|
+
constructor(host, scrollTarget) {
|
|
17
|
+
/**
|
|
18
|
+
* The controller host element.
|
|
19
|
+
*
|
|
20
|
+
* @type {HTMLElement}
|
|
21
|
+
*/
|
|
22
|
+
this.host = host;
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* The element that wraps scrollable content.
|
|
26
|
+
* If not set, the host element is used.
|
|
27
|
+
*
|
|
28
|
+
* @type {HTMLElement}
|
|
29
|
+
*/
|
|
30
|
+
this.scrollTarget = scrollTarget || host;
|
|
31
|
+
|
|
32
|
+
/** @private */
|
|
33
|
+
this.__boundOnScroll = this.__onScroll.bind(this);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
hostConnected() {
|
|
37
|
+
if (!this.initialized) {
|
|
38
|
+
this.initialized = true;
|
|
39
|
+
|
|
40
|
+
this.observe();
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Setup scroll listener and observers to update overflow.
|
|
46
|
+
* Also performs one-time update synchronously when called.
|
|
47
|
+
* @protected
|
|
48
|
+
*/
|
|
49
|
+
observe() {
|
|
50
|
+
this.__resizeObserver = new ResizeObserver(() => {
|
|
51
|
+
this.__debounceOverflow = Debouncer.debounce(this.__debounceOverflow, animationFrame, () => {
|
|
52
|
+
this.__updateOverflow();
|
|
53
|
+
});
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
this.__resizeObserver.observe(this.host);
|
|
57
|
+
|
|
58
|
+
this.__childObserver = new FlattenedNodesObserver(this.host, (info) => {
|
|
59
|
+
info.addedNodes.forEach((node) => {
|
|
60
|
+
if (node.nodeType === Node.ELEMENT_NODE) {
|
|
61
|
+
this.__resizeObserver.observe(node);
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
info.removedNodes.forEach((node) => {
|
|
66
|
+
if (node.nodeType === Node.ELEMENT_NODE) {
|
|
67
|
+
this.__resizeObserver.unobserve(node);
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
this.__updateOverflow();
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
// Update overflow attribute on scroll
|
|
75
|
+
this.scrollTarget.addEventListener('scroll', this.__boundOnScroll);
|
|
76
|
+
|
|
77
|
+
this.__updateOverflow();
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/** @private */
|
|
81
|
+
__onScroll() {
|
|
82
|
+
this.__updateOverflow();
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/** @private */
|
|
86
|
+
__updateOverflow() {
|
|
87
|
+
const target = this.scrollTarget;
|
|
88
|
+
|
|
89
|
+
let overflow = '';
|
|
90
|
+
|
|
91
|
+
if (target.scrollTop > 0) {
|
|
92
|
+
overflow += ' top';
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
if (target.scrollTop < target.scrollHeight - target.clientHeight) {
|
|
96
|
+
overflow += ' bottom';
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
const scrollLeft = Math.abs(target.scrollLeft);
|
|
100
|
+
if (scrollLeft > 0) {
|
|
101
|
+
overflow += ' start';
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
if (scrollLeft < target.scrollWidth - target.clientWidth) {
|
|
105
|
+
overflow += ' end';
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
overflow = overflow.trim();
|
|
109
|
+
if (overflow.length > 0 && this.host.getAttribute('overflow') !== overflow) {
|
|
110
|
+
this.host.setAttribute('overflow', overflow);
|
|
111
|
+
} else if (overflow.length === 0 && this.host.hasAttribute('overflow')) {
|
|
112
|
+
this.host.removeAttribute('overflow');
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|