@patternfly/pfe-core 2.3.0 → 2.4.0
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/controllers/cascade-controller.js +1 -1
- package/controllers/cascade-controller.js.map +1 -1
- package/controllers/floating-dom-controller.d.ts +1 -1
- package/controllers/floating-dom-controller.js +81 -83
- package/controllers/floating-dom-controller.js.map +1 -1
- package/controllers/internals-controller.js +17 -20
- package/controllers/internals-controller.js.map +1 -1
- package/controllers/logger.js +1 -1
- package/controllers/logger.js.map +1 -1
- package/controllers/overflow-controller.js +42 -40
- package/controllers/overflow-controller.js.map +1 -1
- package/controllers/property-observer-controller.js +1 -1
- package/controllers/property-observer-controller.js.map +1 -1
- package/controllers/roving-tabindex-controller.js +114 -102
- package/controllers/roving-tabindex-controller.js.map +1 -1
- package/controllers/scroll-spy-controller.js +93 -91
- package/controllers/scroll-spy-controller.js.map +1 -1
- package/controllers/slot-controller.js +1 -1
- package/controllers/slot-controller.js.map +1 -1
- package/controllers/timestamp-controller.d.ts +23 -0
- package/controllers/timestamp-controller.js +108 -0
- package/controllers/timestamp-controller.js.map +1 -0
- package/custom-elements.json +633 -450
- package/package.json +2 -1
|
@@ -1,78 +1,80 @@
|
|
|
1
|
-
var _OverflowController_instances, _OverflowController_container, _OverflowController_items, _OverflowController_scrollTimeoutDelay, _OverflowController_scrollTimeout, _OverflowController_hideOverflowButtons, _OverflowController_setOverflowState;
|
|
2
|
-
import { __classPrivateFieldGet, __classPrivateFieldSet } from "tslib";
|
|
3
1
|
import { isElementInView } from '@patternfly/pfe-core/functions/isElementInView.js';
|
|
4
2
|
export class OverflowController {
|
|
3
|
+
/** Overflow container */
|
|
4
|
+
#container;
|
|
5
|
+
/** Children that can overflow */
|
|
6
|
+
#items;
|
|
7
|
+
#scrollTimeoutDelay;
|
|
8
|
+
#scrollTimeout;
|
|
9
|
+
/** Default state */
|
|
10
|
+
#hideOverflowButtons;
|
|
5
11
|
get firstItem() {
|
|
6
|
-
return
|
|
12
|
+
return this.#items.at(0);
|
|
7
13
|
}
|
|
8
14
|
get lastItem() {
|
|
9
|
-
return
|
|
15
|
+
return this.#items.at(-1);
|
|
10
16
|
}
|
|
11
17
|
constructor(host, options) {
|
|
12
|
-
_OverflowController_instances.add(this);
|
|
13
18
|
this.host = host;
|
|
14
19
|
this.options = options;
|
|
15
|
-
/** Overflow container */
|
|
16
|
-
_OverflowController_container.set(this, void 0);
|
|
17
20
|
/** Children that can overflow */
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
_OverflowController_scrollTimeout.set(this, void 0);
|
|
21
|
+
this.#items = [];
|
|
22
|
+
this.#scrollTimeoutDelay = 0;
|
|
21
23
|
/** Default state */
|
|
22
|
-
|
|
24
|
+
this.#hideOverflowButtons = false;
|
|
23
25
|
this.showScrollButtons = false;
|
|
24
26
|
this.overflowLeft = false;
|
|
25
27
|
this.overflowRight = false;
|
|
26
28
|
this.onScroll = () => {
|
|
27
|
-
clearTimeout(
|
|
28
|
-
|
|
29
|
+
clearTimeout(this.#scrollTimeout);
|
|
30
|
+
this.#scrollTimeout = setTimeout(() => this.#setOverflowState(), this.#scrollTimeoutDelay);
|
|
29
31
|
};
|
|
30
32
|
this.host.addController(this);
|
|
31
33
|
if (options?.hideOverflowButtons) {
|
|
32
|
-
|
|
34
|
+
this.#hideOverflowButtons = options?.hideOverflowButtons;
|
|
33
35
|
}
|
|
34
36
|
}
|
|
37
|
+
#setOverflowState() {
|
|
38
|
+
if (!this.firstItem || !this.lastItem || !this.#container) {
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
this.overflowLeft = !this.#hideOverflowButtons && !isElementInView(this.#container, this.firstItem);
|
|
42
|
+
this.overflowRight = !this.#hideOverflowButtons && !isElementInView(this.#container, this.lastItem);
|
|
43
|
+
let scrollButtonsWidth = 0;
|
|
44
|
+
if (this.overflowLeft || this.overflowRight) {
|
|
45
|
+
scrollButtonsWidth = (this.#container.parentElement?.querySelector('button')?.getBoundingClientRect().width || 0) * 2;
|
|
46
|
+
}
|
|
47
|
+
this.showScrollButtons = !this.#hideOverflowButtons &&
|
|
48
|
+
this.#container.scrollWidth > (this.#container.clientWidth + scrollButtonsWidth);
|
|
49
|
+
this.host.requestUpdate();
|
|
50
|
+
}
|
|
35
51
|
init(container, items) {
|
|
36
|
-
|
|
52
|
+
this.#container = container;
|
|
37
53
|
// convert HTMLCollection to HTMLElement[]
|
|
38
|
-
|
|
54
|
+
this.#items = items;
|
|
39
55
|
}
|
|
40
56
|
scrollLeft() {
|
|
41
|
-
if (!
|
|
57
|
+
if (!this.#container) {
|
|
42
58
|
return;
|
|
43
59
|
}
|
|
44
|
-
const leftScroll =
|
|
45
|
-
|
|
46
|
-
|
|
60
|
+
const leftScroll = this.#container.scrollLeft - this.#container.clientWidth;
|
|
61
|
+
this.#container.scroll({ left: leftScroll, behavior: 'smooth' });
|
|
62
|
+
this.#setOverflowState();
|
|
47
63
|
}
|
|
48
64
|
scrollRight() {
|
|
49
|
-
if (!
|
|
65
|
+
if (!this.#container) {
|
|
50
66
|
return;
|
|
51
67
|
}
|
|
52
|
-
const leftScroll =
|
|
53
|
-
|
|
54
|
-
|
|
68
|
+
const leftScroll = this.#container.scrollLeft + this.#container.clientWidth;
|
|
69
|
+
this.#container.scroll({ left: leftScroll, behavior: 'smooth' });
|
|
70
|
+
this.#setOverflowState();
|
|
55
71
|
}
|
|
56
72
|
update() {
|
|
57
|
-
|
|
73
|
+
this.#setOverflowState();
|
|
58
74
|
}
|
|
59
75
|
hostConnected() {
|
|
60
76
|
this.onScroll();
|
|
61
|
-
|
|
77
|
+
this.#setOverflowState();
|
|
62
78
|
}
|
|
63
79
|
}
|
|
64
|
-
_OverflowController_container = new WeakMap(), _OverflowController_items = new WeakMap(), _OverflowController_scrollTimeoutDelay = new WeakMap(), _OverflowController_scrollTimeout = new WeakMap(), _OverflowController_hideOverflowButtons = new WeakMap(), _OverflowController_instances = new WeakSet(), _OverflowController_setOverflowState = function _OverflowController_setOverflowState() {
|
|
65
|
-
if (!this.firstItem || !this.lastItem || !__classPrivateFieldGet(this, _OverflowController_container, "f")) {
|
|
66
|
-
return;
|
|
67
|
-
}
|
|
68
|
-
this.overflowLeft = !__classPrivateFieldGet(this, _OverflowController_hideOverflowButtons, "f") && !isElementInView(__classPrivateFieldGet(this, _OverflowController_container, "f"), this.firstItem);
|
|
69
|
-
this.overflowRight = !__classPrivateFieldGet(this, _OverflowController_hideOverflowButtons, "f") && !isElementInView(__classPrivateFieldGet(this, _OverflowController_container, "f"), this.lastItem);
|
|
70
|
-
let scrollButtonsWidth = 0;
|
|
71
|
-
if (this.overflowLeft || this.overflowRight) {
|
|
72
|
-
scrollButtonsWidth = (__classPrivateFieldGet(this, _OverflowController_container, "f").parentElement?.querySelector('button')?.getBoundingClientRect().width || 0) * 2;
|
|
73
|
-
}
|
|
74
|
-
this.showScrollButtons = !__classPrivateFieldGet(this, _OverflowController_hideOverflowButtons, "f") &&
|
|
75
|
-
__classPrivateFieldGet(this, _OverflowController_container, "f").scrollWidth > (__classPrivateFieldGet(this, _OverflowController_container, "f").clientWidth + scrollButtonsWidth);
|
|
76
|
-
this.host.requestUpdate();
|
|
77
|
-
};
|
|
78
80
|
//# sourceMappingURL=overflow-controller.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"overflow-controller.js","sourceRoot":"","sources":["overflow-controller.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"overflow-controller.js","sourceRoot":"","sources":["overflow-controller.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ReactiveController, ReactiveControllerHost } from 'lit';\n\nimport { isElementInView } from '@patternfly/pfe-core/functions/isElementInView.js';\n\nexport interface Options {\n hideOverflowButtons?: boolean;\n}\n\nexport class OverflowController implements ReactiveController {\n /** Overflow container */\n #container?: HTMLElement;\n /** Children that can overflow */\n #items: HTMLElement[] = [];\n\n #scrollTimeoutDelay = 0;\n #scrollTimeout?: ReturnType<typeof setTimeout>;\n\n /** Default state */\n #hideOverflowButtons = false;\n showScrollButtons = false;\n overflowLeft = false;\n overflowRight = false;\n\n get firstItem(): HTMLElement | undefined {\n return this.#items.at(0);\n }\n\n get lastItem(): HTMLElement | undefined {\n return this.#items.at(-1);\n }\n\n constructor(public host: ReactiveControllerHost & Element, private options?: Options) {\n this.host.addController(this);\n if (options?.hideOverflowButtons) {\n this.#hideOverflowButtons = options?.hideOverflowButtons;\n }\n }\n\n #setOverflowState(): void {\n if (!this.firstItem || !this.lastItem || !this.#container) {\n return;\n }\n this.overflowLeft = !this.#hideOverflowButtons && !isElementInView(this.#container, this.firstItem);\n this.overflowRight = !this.#hideOverflowButtons && !isElementInView(this.#container, this.lastItem);\n let scrollButtonsWidth = 0;\n if (this.overflowLeft || this.overflowRight) {\n scrollButtonsWidth = (this.#container.parentElement?.querySelector('button')?.getBoundingClientRect().width || 0) * 2;\n }\n this.showScrollButtons = !this.#hideOverflowButtons &&\n this.#container.scrollWidth > (this.#container.clientWidth + scrollButtonsWidth);\n this.host.requestUpdate();\n }\n\n init(container: HTMLElement, items: HTMLElement[]) {\n this.#container = container;\n // convert HTMLCollection to HTMLElement[]\n this.#items = items;\n }\n\n onScroll = () => {\n clearTimeout(this.#scrollTimeout);\n this.#scrollTimeout = setTimeout(() => this.#setOverflowState(), this.#scrollTimeoutDelay);\n };\n\n scrollLeft() {\n if (!this.#container) {\n return;\n }\n const leftScroll = this.#container.scrollLeft - this.#container.clientWidth;\n this.#container.scroll({ left: leftScroll, behavior: 'smooth' });\n this.#setOverflowState();\n }\n\n scrollRight() {\n if (!this.#container) {\n return;\n }\n const leftScroll = this.#container.scrollLeft + this.#container.clientWidth;\n this.#container.scroll({ left: leftScroll, behavior: 'smooth' });\n this.#setOverflowState();\n }\n\n update() {\n this.#setOverflowState();\n }\n\n hostConnected(): void {\n this.onScroll();\n this.#setOverflowState();\n }\n}\n"]}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export const observedController = Symbol('observed properties controller');
|
|
2
2
|
/** This controller holds a cache of observed property values which were set before the element updated */
|
|
3
3
|
class PropertyObserverController {
|
|
4
|
+
static { this.hosts = new WeakMap(); }
|
|
4
5
|
delete(key) {
|
|
5
6
|
this.values.delete(key);
|
|
6
7
|
}
|
|
@@ -29,6 +30,5 @@ class PropertyObserverController {
|
|
|
29
30
|
this.values.set(key, [methodName, vals]);
|
|
30
31
|
}
|
|
31
32
|
}
|
|
32
|
-
PropertyObserverController.hosts = new WeakMap();
|
|
33
33
|
export { PropertyObserverController };
|
|
34
34
|
//# sourceMappingURL=property-observer-controller.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"property-observer-controller.js","sourceRoot":"","sources":["property-observer-controller.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,kBAAkB,GAAG,MAAM,CAAC,gCAAgC,CAAC,CAAC;AAc3E,0GAA0G;AAC1G,MAAa,0BAA0B;
|
|
1
|
+
{"version":3,"file":"property-observer-controller.js","sourceRoot":"","sources":["property-observer-controller.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,kBAAkB,GAAG,MAAM,CAAC,gCAAgC,CAAC,CAAC;AAc3E,0GAA0G;AAC1G,MAAa,0BAA0B;aACtB,UAAK,GAAqD,IAAI,OAAO,EAAE,AAAlE,CAAmE;IAI/E,MAAM,CAAC,GAAW;QACxB,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IAC1B,CAAC;IAED,YAAoB,IAAqB;QAArB,SAAI,GAAJ,IAAI,CAAiB;QANjC,WAAM,GAAG,IAAI,GAAG,EAA4D,CAAC;QAOnF,IAAI,0BAA0B,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE;YAC9C,OAAO,0BAA0B,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAA+B,CAAC;SACjF;QACD,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC;QACxB,IAA8C,CAAC,kBAAkB,CAAC,GAAG,IAAI,CAAC;IAC7E,CAAC;IAED,kFAAkF;IAClF,UAAU;QACR,KAAK,MAAM,CAAC,GAAG,EAAE,CAAC,UAAU,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,MAAM,EAAE;YAC/D,wCAAwC;YACxC,IAAI,CAAC,IAAI,CAAC,UAAmC,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;YACjE,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;SAClB;IACH,CAAC;IAED,uFAAuF;IACvF,WAAW;QACT,IAAI,CAAC,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC;IACnC,CAAC;IAED,KAAK,CAAC,GAAW,EAAE,UAAkB,EAAE,GAAG,IAAwB;QAChE,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC,CAAC;IAC3C,CAAC;;SAjCU,0BAA0B","sourcesContent":["import type { ReactiveController, ReactiveElement } from 'lit';\n\nexport const observedController = Symbol('observed properties controller');\n\nexport type ChangeCallback<T = ReactiveElement> = (\n this: T,\n old?: T[keyof T],\n newV?: T[keyof T],\n) => void;\n\nexport type ChangeCallbackName = `_${string}Changed`;\n\nexport type PropertyObserverHost<T> = T & Record<ChangeCallbackName, ChangeCallback<T>> & {\n [observedController]: PropertyObserverController;\n}\n\n/** This controller holds a cache of observed property values which were set before the element updated */\nexport class PropertyObserverController implements ReactiveController {\n private static hosts: WeakMap<HTMLElement, PropertyObserverController> = new WeakMap();\n\n private values = new Map<string, [methodName: string, values: [unknown, unknown]]>();\n\n private delete(key: string) {\n this.values.delete(key);\n }\n\n constructor(private host: ReactiveElement) {\n if (PropertyObserverController.hosts.get(host)) {\n return PropertyObserverController.hosts.get(host) as PropertyObserverController;\n }\n host.addController(this);\n (host as PropertyObserverHost<ReactiveElement>)[observedController] = this;\n }\n\n /** Set any cached valued accumulated between constructor and connectedCallback */\n hostUpdate() {\n for (const [key, [methodName, [oldVal, newVal]]] of this.values) {\n // @ts-expect-error: be cool, typescript\n this.host[methodName as keyof ReactiveElement]?.(oldVal, newVal);\n this.delete(key);\n }\n }\n\n /** Once the element has updated, we no longer need this controller, so we remove it */\n hostUpdated() {\n this.host.removeController(this);\n }\n\n cache(key: string, methodName: string, ...vals: [unknown, unknown]) {\n this.values.set(key, [methodName, vals]);\n }\n}\n"]}
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
var _RovingTabindexController_instances, _RovingTabindexController_activeItem, _RovingTabindexController_itemsContainer, _RovingTabindexController_items, _RovingTabindexController_focusableItems_get, _RovingTabindexController_activeIndex_get, _RovingTabindexController_itemIndex_get, _RovingTabindexController_onKeydown;
|
|
2
|
-
import { __classPrivateFieldGet, __classPrivateFieldSet } from "tslib";
|
|
3
1
|
const isFocusableElement = (el) => !!el &&
|
|
4
2
|
!el.hasAttribute('disabled') &&
|
|
5
3
|
!el.ariaHidden &&
|
|
@@ -10,124 +8,145 @@ const isFocusableElement = (el) => !!el &&
|
|
|
10
8
|
* tabindex](https://www.w3.org/WAI/ARIA/apg/practices/keyboard-interface/#kbd_roving_tabindex)
|
|
11
9
|
*/
|
|
12
10
|
export class RovingTabindexController {
|
|
11
|
+
/** active focusable element */
|
|
12
|
+
#activeItem;
|
|
13
|
+
/** closest ancestor containing items */
|
|
14
|
+
#itemsContainer;
|
|
15
|
+
/** array of all focusable elements */
|
|
16
|
+
#items = [];
|
|
17
|
+
/**
|
|
18
|
+
* finds focusable items from a group of items
|
|
19
|
+
*/
|
|
20
|
+
get #focusableItems() {
|
|
21
|
+
return this.#items.filter(isFocusableElement);
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* index of active item in array of focusable items
|
|
25
|
+
*/
|
|
26
|
+
get #activeIndex() {
|
|
27
|
+
return !!this.#focusableItems && !!this.activeItem ? this.#focusableItems.indexOf(this.activeItem) : -1;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* index of active item in array of items
|
|
31
|
+
*/
|
|
32
|
+
get #itemIndex() {
|
|
33
|
+
return this.activeItem ? this.#items.indexOf(this.activeItem) : -1;
|
|
34
|
+
}
|
|
13
35
|
/**
|
|
14
36
|
* active item of array of items
|
|
15
37
|
*/
|
|
16
38
|
get activeItem() {
|
|
17
|
-
return
|
|
39
|
+
return this.#activeItem;
|
|
18
40
|
}
|
|
19
41
|
/**
|
|
20
42
|
* first item in array of focusable items
|
|
21
43
|
*/
|
|
22
44
|
get firstItem() {
|
|
23
|
-
return
|
|
45
|
+
return this.#focusableItems[0];
|
|
24
46
|
}
|
|
25
47
|
/**
|
|
26
48
|
* last item in array of focusable items
|
|
27
49
|
*/
|
|
28
50
|
get lastItem() {
|
|
29
|
-
return
|
|
51
|
+
return this.#focusableItems.at(-1);
|
|
30
52
|
}
|
|
31
53
|
/**
|
|
32
54
|
* next item after active item in array of focusable items
|
|
33
55
|
*/
|
|
34
56
|
get nextItem() {
|
|
35
|
-
return (
|
|
36
|
-
:
|
|
57
|
+
return (this.#activeIndex >= this.#focusableItems.length - 1 ? this.firstItem
|
|
58
|
+
: this.#focusableItems[this.#activeIndex + 1]);
|
|
37
59
|
}
|
|
38
60
|
/**
|
|
39
61
|
* previous item after active item in array of focusable items
|
|
40
62
|
*/
|
|
41
63
|
get prevItem() {
|
|
42
|
-
return (
|
|
64
|
+
return (this.#activeIndex > 0 ? this.#focusableItems[this.#activeIndex - 1]
|
|
43
65
|
: this.lastItem);
|
|
44
66
|
}
|
|
45
67
|
constructor(host) {
|
|
46
|
-
_RovingTabindexController_instances.add(this);
|
|
47
68
|
this.host = host;
|
|
48
|
-
/** active focusable element */
|
|
49
|
-
_RovingTabindexController_activeItem.set(this, void 0);
|
|
50
|
-
/** closest ancestor containing items */
|
|
51
|
-
_RovingTabindexController_itemsContainer.set(this, void 0);
|
|
52
|
-
/** array of all focusable elements */
|
|
53
|
-
_RovingTabindexController_items.set(this, []);
|
|
54
|
-
/**
|
|
55
|
-
* handles keyboard navigation
|
|
56
|
-
*/
|
|
57
|
-
_RovingTabindexController_onKeydown.set(this, (event) => {
|
|
58
|
-
if (event.ctrlKey || event.altKey || event.metaKey || __classPrivateFieldGet(this, _RovingTabindexController_instances, "a", _RovingTabindexController_focusableItems_get).length < 1) {
|
|
59
|
-
return;
|
|
60
|
-
}
|
|
61
|
-
const item = this.activeItem;
|
|
62
|
-
let shouldPreventDefault = false;
|
|
63
|
-
const horizontalOnly = !item ? false
|
|
64
|
-
: item.tagName === 'SELECT' ||
|
|
65
|
-
item.getAttribute('role') === 'spinbutton';
|
|
66
|
-
switch (event.key) {
|
|
67
|
-
case 'ArrowLeft':
|
|
68
|
-
this.focusOnItem(this.prevItem);
|
|
69
|
-
shouldPreventDefault = true;
|
|
70
|
-
break;
|
|
71
|
-
case 'ArrowRight':
|
|
72
|
-
this.focusOnItem(this.nextItem);
|
|
73
|
-
shouldPreventDefault = true;
|
|
74
|
-
break;
|
|
75
|
-
case 'ArrowUp':
|
|
76
|
-
if (horizontalOnly) {
|
|
77
|
-
return;
|
|
78
|
-
}
|
|
79
|
-
this.focusOnItem(this.prevItem);
|
|
80
|
-
shouldPreventDefault = true;
|
|
81
|
-
break;
|
|
82
|
-
case 'ArrowDown':
|
|
83
|
-
if (horizontalOnly) {
|
|
84
|
-
return;
|
|
85
|
-
}
|
|
86
|
-
this.focusOnItem(this.nextItem);
|
|
87
|
-
shouldPreventDefault = true;
|
|
88
|
-
break;
|
|
89
|
-
case 'Home':
|
|
90
|
-
this.focusOnItem(this.firstItem);
|
|
91
|
-
shouldPreventDefault = true;
|
|
92
|
-
break;
|
|
93
|
-
case 'PageUp':
|
|
94
|
-
if (horizontalOnly) {
|
|
95
|
-
return;
|
|
96
|
-
}
|
|
97
|
-
this.focusOnItem(this.firstItem);
|
|
98
|
-
shouldPreventDefault = true;
|
|
99
|
-
break;
|
|
100
|
-
case 'End':
|
|
101
|
-
this.focusOnItem(this.lastItem);
|
|
102
|
-
shouldPreventDefault = true;
|
|
103
|
-
break;
|
|
104
|
-
case 'PageDown':
|
|
105
|
-
if (horizontalOnly) {
|
|
106
|
-
return;
|
|
107
|
-
}
|
|
108
|
-
this.focusOnItem(this.lastItem);
|
|
109
|
-
shouldPreventDefault = true;
|
|
110
|
-
break;
|
|
111
|
-
default:
|
|
112
|
-
break;
|
|
113
|
-
}
|
|
114
|
-
if (shouldPreventDefault) {
|
|
115
|
-
event.stopPropagation();
|
|
116
|
-
event.preventDefault();
|
|
117
|
-
}
|
|
118
|
-
});
|
|
119
69
|
this.host.addController(this);
|
|
120
70
|
}
|
|
71
|
+
/**
|
|
72
|
+
* handles keyboard navigation
|
|
73
|
+
*/
|
|
74
|
+
#onKeydown = (event) => {
|
|
75
|
+
if (event.ctrlKey ||
|
|
76
|
+
event.altKey ||
|
|
77
|
+
event.metaKey ||
|
|
78
|
+
!this.#focusableItems.length ||
|
|
79
|
+
!event.composedPath().some(x => this.#focusableItems.includes(x))) {
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
const item = this.activeItem;
|
|
83
|
+
let shouldPreventDefault = false;
|
|
84
|
+
const horizontalOnly = !item ? false
|
|
85
|
+
: item.tagName === 'SELECT' ||
|
|
86
|
+
item.getAttribute('role') === 'spinbutton';
|
|
87
|
+
switch (event.key) {
|
|
88
|
+
case 'ArrowLeft':
|
|
89
|
+
this.focusOnItem(this.prevItem);
|
|
90
|
+
shouldPreventDefault = true;
|
|
91
|
+
break;
|
|
92
|
+
case 'ArrowRight':
|
|
93
|
+
this.focusOnItem(this.nextItem);
|
|
94
|
+
shouldPreventDefault = true;
|
|
95
|
+
break;
|
|
96
|
+
case 'ArrowUp':
|
|
97
|
+
if (horizontalOnly) {
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
this.focusOnItem(this.prevItem);
|
|
101
|
+
shouldPreventDefault = true;
|
|
102
|
+
break;
|
|
103
|
+
case 'ArrowDown':
|
|
104
|
+
if (horizontalOnly) {
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
this.focusOnItem(this.nextItem);
|
|
108
|
+
shouldPreventDefault = true;
|
|
109
|
+
break;
|
|
110
|
+
case 'Home':
|
|
111
|
+
this.focusOnItem(this.firstItem);
|
|
112
|
+
shouldPreventDefault = true;
|
|
113
|
+
break;
|
|
114
|
+
case 'PageUp':
|
|
115
|
+
if (horizontalOnly) {
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
this.focusOnItem(this.firstItem);
|
|
119
|
+
shouldPreventDefault = true;
|
|
120
|
+
break;
|
|
121
|
+
case 'End':
|
|
122
|
+
this.focusOnItem(this.lastItem);
|
|
123
|
+
shouldPreventDefault = true;
|
|
124
|
+
break;
|
|
125
|
+
case 'PageDown':
|
|
126
|
+
if (horizontalOnly) {
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
this.focusOnItem(this.lastItem);
|
|
130
|
+
shouldPreventDefault = true;
|
|
131
|
+
break;
|
|
132
|
+
default:
|
|
133
|
+
break;
|
|
134
|
+
}
|
|
135
|
+
if (shouldPreventDefault) {
|
|
136
|
+
event.stopPropagation();
|
|
137
|
+
event.preventDefault();
|
|
138
|
+
}
|
|
139
|
+
};
|
|
121
140
|
/**
|
|
122
141
|
* sets tabindex of item based on whether or not it is active
|
|
123
142
|
*/
|
|
124
143
|
updateActiveItem(item) {
|
|
125
144
|
if (item) {
|
|
126
|
-
if (!!
|
|
127
|
-
|
|
145
|
+
if (!!this.#activeItem && item !== this.#activeItem) {
|
|
146
|
+
this.#activeItem.tabIndex = -1;
|
|
128
147
|
}
|
|
129
148
|
item.tabIndex = 0;
|
|
130
|
-
|
|
149
|
+
this.#activeItem = item;
|
|
131
150
|
}
|
|
132
151
|
}
|
|
133
152
|
/**
|
|
@@ -135,34 +154,34 @@ export class RovingTabindexController {
|
|
|
135
154
|
*/
|
|
136
155
|
focusOnItem(item) {
|
|
137
156
|
this.updateActiveItem(item || this.firstItem);
|
|
138
|
-
|
|
157
|
+
this.#activeItem?.focus();
|
|
139
158
|
this.host.requestUpdate();
|
|
140
159
|
}
|
|
141
160
|
/**
|
|
142
161
|
* Focuses next focusable item
|
|
143
162
|
*/
|
|
144
163
|
updateItems(items) {
|
|
145
|
-
const sequence = [...items.slice(
|
|
146
|
-
const first = sequence.find(item =>
|
|
164
|
+
const sequence = [...items.slice(this.#itemIndex), ...items.slice(0, this.#itemIndex)];
|
|
165
|
+
const first = sequence.find(item => this.#focusableItems.includes(item));
|
|
147
166
|
this.focusOnItem(first || this.firstItem);
|
|
148
167
|
}
|
|
149
168
|
/**
|
|
150
169
|
* from array of HTML items, and sets active items
|
|
151
170
|
*/
|
|
152
171
|
initItems(items, itemsContainer = this.host) {
|
|
153
|
-
|
|
154
|
-
const focusableItems =
|
|
172
|
+
this.#items = items ?? [];
|
|
173
|
+
const focusableItems = this.#focusableItems;
|
|
155
174
|
const [focusableItem] = focusableItems;
|
|
156
|
-
|
|
175
|
+
this.#activeItem = focusableItem;
|
|
157
176
|
for (const item of focusableItems) {
|
|
158
|
-
item.tabIndex =
|
|
177
|
+
item.tabIndex = this.#activeItem === item ? 0 : -1;
|
|
159
178
|
}
|
|
160
179
|
/**
|
|
161
180
|
* removes listener on previous contained and applies it to new container
|
|
162
181
|
*/
|
|
163
|
-
if (!
|
|
164
|
-
|
|
165
|
-
|
|
182
|
+
if (!this.#itemsContainer || itemsContainer !== this.#itemsContainer) {
|
|
183
|
+
this.#itemsContainer?.removeEventListener('keydown', this.#onKeydown);
|
|
184
|
+
this.#itemsContainer = itemsContainer;
|
|
166
185
|
this.hostConnected();
|
|
167
186
|
}
|
|
168
187
|
}
|
|
@@ -170,20 +189,13 @@ export class RovingTabindexController {
|
|
|
170
189
|
* adds event listeners to items container
|
|
171
190
|
*/
|
|
172
191
|
hostConnected() {
|
|
173
|
-
|
|
192
|
+
this.#itemsContainer?.addEventListener('keydown', this.#onKeydown);
|
|
174
193
|
}
|
|
175
194
|
/**
|
|
176
195
|
* removes event listeners from items container
|
|
177
196
|
*/
|
|
178
197
|
hostDisconnected() {
|
|
179
|
-
|
|
198
|
+
this.#itemsContainer?.removeEventListener('keydown', this.#onKeydown);
|
|
180
199
|
}
|
|
181
200
|
}
|
|
182
|
-
_RovingTabindexController_activeItem = new WeakMap(), _RovingTabindexController_itemsContainer = new WeakMap(), _RovingTabindexController_items = new WeakMap(), _RovingTabindexController_onKeydown = new WeakMap(), _RovingTabindexController_instances = new WeakSet(), _RovingTabindexController_focusableItems_get = function _RovingTabindexController_focusableItems_get() {
|
|
183
|
-
return __classPrivateFieldGet(this, _RovingTabindexController_items, "f").filter(isFocusableElement);
|
|
184
|
-
}, _RovingTabindexController_activeIndex_get = function _RovingTabindexController_activeIndex_get() {
|
|
185
|
-
return !!__classPrivateFieldGet(this, _RovingTabindexController_instances, "a", _RovingTabindexController_focusableItems_get) && !!this.activeItem ? __classPrivateFieldGet(this, _RovingTabindexController_instances, "a", _RovingTabindexController_focusableItems_get).indexOf(this.activeItem) : -1;
|
|
186
|
-
}, _RovingTabindexController_itemIndex_get = function _RovingTabindexController_itemIndex_get() {
|
|
187
|
-
return this.activeItem ? __classPrivateFieldGet(this, _RovingTabindexController_items, "f").indexOf(this.activeItem) : -1;
|
|
188
|
-
};
|
|
189
201
|
//# sourceMappingURL=roving-tabindex-controller.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"roving-tabindex-controller.js","sourceRoot":"","sources":["roving-tabindex-controller.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ReactiveController, ReactiveControllerHost } from 'lit';\n\nconst isFocusableElement = (el: Element): el is HTMLElement =>\n !!el &&\n !el.hasAttribute('disabled') &&\n !el.ariaHidden &&\n !el.hasAttribute('hidden');\n\n/**\n * Implements roving tabindex, as described in WAI-ARIA practices, [Managing Focus Within\n * Components Using a Roving\n * tabindex](https://www.w3.org/WAI/ARIA/apg/practices/keyboard-interface/#kbd_roving_tabindex)\n */\nexport class RovingTabindexController<\n ItemType extends HTMLElement = HTMLElement,\n> implements ReactiveController {\n /** active focusable element */\n #activeItem?: ItemType;\n\n /** closest ancestor containing items */\n #itemsContainer?: HTMLElement;\n\n /** array of all focusable elements */\n #items: ItemType[] = [];\n\n /**\n * finds focusable items from a group of items\n */\n get #focusableItems(): ItemType[] {\n return this.#items.filter(isFocusableElement);\n }\n\n /**\n * index of active item in array of focusable items\n */\n get #activeIndex(): number {\n return !!this.#focusableItems && !!this.activeItem ? this.#focusableItems.indexOf(this.activeItem) : -1;\n }\n\n /**\n * index of active item in array of items\n */\n get #itemIndex(): number {\n return this.activeItem ? this.#items.indexOf(this.activeItem) : -1;\n }\n\n /**\n * active item of array of items\n */\n get activeItem(): ItemType | undefined {\n return this.#activeItem;\n }\n\n /**\n * first item in array of focusable items\n */\n get firstItem(): ItemType | undefined {\n return this.#focusableItems[0];\n }\n\n /**\n * last item in array of focusable items\n */\n get lastItem(): ItemType | undefined {\n return this.#focusableItems.at(-1);\n }\n\n /**\n * next item after active item in array of focusable items\n */\n get nextItem(): ItemType | undefined {\n return (\n this.#activeIndex >= this.#focusableItems.length - 1 ? this.firstItem\n : this.#focusableItems[this.#activeIndex + 1]\n );\n }\n\n /**\n * previous item after active item in array of focusable items\n */\n get prevItem(): ItemType | undefined {\n return (\n this.#activeIndex > 0 ? this.#focusableItems[this.#activeIndex - 1]\n : this.lastItem\n );\n }\n\n constructor(public host: ReactiveControllerHost & HTMLElement) {\n this.host.addController(this);\n }\n\n /**\n * handles keyboard navigation\n */\n #onKeydown = (event: KeyboardEvent) => {\n if (event.ctrlKey || event.altKey || event.metaKey || this.#focusableItems.length < 1) {\n return;\n }\n\n const item = this.activeItem;\n let shouldPreventDefault = false;\n const horizontalOnly =\n !item ? false\n : item.tagName === 'SELECT' ||\n item.getAttribute('role') === 'spinbutton';\n\n\n switch (event.key) {\n case 'ArrowLeft':\n this.focusOnItem(this.prevItem);\n shouldPreventDefault = true;\n break;\n case 'ArrowRight':\n this.focusOnItem(this.nextItem);\n shouldPreventDefault = true;\n break;\n case 'ArrowUp':\n if (horizontalOnly) {\n return;\n }\n this.focusOnItem(this.prevItem);\n shouldPreventDefault = true;\n break;\n case 'ArrowDown':\n if (horizontalOnly) {\n return;\n }\n this.focusOnItem(this.nextItem);\n shouldPreventDefault = true;\n break;\n case 'Home':\n this.focusOnItem(this.firstItem);\n shouldPreventDefault = true;\n break;\n case 'PageUp':\n if (horizontalOnly) {\n return;\n }\n this.focusOnItem(this.firstItem);\n shouldPreventDefault = true;\n break;\n case 'End':\n this.focusOnItem(this.lastItem);\n shouldPreventDefault = true;\n break;\n case 'PageDown':\n if (horizontalOnly) {\n return;\n }\n this.focusOnItem(this.lastItem);\n shouldPreventDefault = true;\n break;\n default:\n break;\n }\n\n if (shouldPreventDefault) {\n event.stopPropagation();\n event.preventDefault();\n }\n };\n\n /**\n * sets tabindex of item based on whether or not it is active\n */\n updateActiveItem(item?: ItemType): void {\n if (item) {\n if (!!this.#activeItem && item !== this.#activeItem) {\n this.#activeItem.tabIndex = -1;\n }\n item.tabIndex = 0;\n this.#activeItem = item;\n }\n }\n\n /**\n * focuses on an item and sets it as active\n */\n focusOnItem(item?: ItemType): void {\n this.updateActiveItem(item || this.firstItem);\n this.#activeItem?.focus();\n this.host.requestUpdate();\n }\n\n /**\n * Focuses next focusable item\n */\n updateItems(items: ItemType[]) {\n const sequence = [...items.slice(this.#itemIndex), ...items.slice(0, this.#itemIndex)];\n const first = sequence.find(item => this.#focusableItems.includes(item));\n this.focusOnItem(first || this.firstItem);\n }\n\n /**\n * from array of HTML items, and sets active items\n */\n initItems(items: ItemType[], itemsContainer: HTMLElement = this.host) {\n this.#items = items ?? [];\n const focusableItems = this.#focusableItems;\n const [focusableItem] = focusableItems;\n this.#activeItem = focusableItem;\n for (const item of focusableItems) {\n item.tabIndex = this.#activeItem === item ? 0 : -1;\n }\n /**\n * removes listener on previous contained and applies it to new container\n */\n if (!this.#itemsContainer || itemsContainer !== this.#itemsContainer) {\n this.#itemsContainer?.removeEventListener('keydown', this.#onKeydown);\n this.#itemsContainer = itemsContainer;\n this.hostConnected();\n }\n }\n\n /**\n * adds event listeners to items container\n */\n hostConnected() {\n this.#itemsContainer?.addEventListener('keydown', this.#onKeydown);\n }\n\n /**\n * removes event listeners from items container\n */\n hostDisconnected() {\n this.#itemsContainer?.removeEventListener('keydown', this.#onKeydown);\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"roving-tabindex-controller.js","sourceRoot":"","sources":["roving-tabindex-controller.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ReactiveController, ReactiveControllerHost } from 'lit';\n\nconst isFocusableElement = (el: Element): el is HTMLElement =>\n !!el &&\n !el.hasAttribute('disabled') &&\n !el.ariaHidden &&\n !el.hasAttribute('hidden');\n\n/**\n * Implements roving tabindex, as described in WAI-ARIA practices, [Managing Focus Within\n * Components Using a Roving\n * tabindex](https://www.w3.org/WAI/ARIA/apg/practices/keyboard-interface/#kbd_roving_tabindex)\n */\nexport class RovingTabindexController<\n ItemType extends HTMLElement = HTMLElement,\n> implements ReactiveController {\n /** active focusable element */\n #activeItem?: ItemType;\n\n /** closest ancestor containing items */\n #itemsContainer?: HTMLElement;\n\n /** array of all focusable elements */\n #items: ItemType[] = [];\n\n /**\n * finds focusable items from a group of items\n */\n get #focusableItems(): ItemType[] {\n return this.#items.filter(isFocusableElement);\n }\n\n /**\n * index of active item in array of focusable items\n */\n get #activeIndex(): number {\n return !!this.#focusableItems && !!this.activeItem ? this.#focusableItems.indexOf(this.activeItem) : -1;\n }\n\n /**\n * index of active item in array of items\n */\n get #itemIndex(): number {\n return this.activeItem ? this.#items.indexOf(this.activeItem) : -1;\n }\n\n /**\n * active item of array of items\n */\n get activeItem(): ItemType | undefined {\n return this.#activeItem;\n }\n\n /**\n * first item in array of focusable items\n */\n get firstItem(): ItemType | undefined {\n return this.#focusableItems[0];\n }\n\n /**\n * last item in array of focusable items\n */\n get lastItem(): ItemType | undefined {\n return this.#focusableItems.at(-1);\n }\n\n /**\n * next item after active item in array of focusable items\n */\n get nextItem(): ItemType | undefined {\n return (\n this.#activeIndex >= this.#focusableItems.length - 1 ? this.firstItem\n : this.#focusableItems[this.#activeIndex + 1]\n );\n }\n\n /**\n * previous item after active item in array of focusable items\n */\n get prevItem(): ItemType | undefined {\n return (\n this.#activeIndex > 0 ? this.#focusableItems[this.#activeIndex - 1]\n : this.lastItem\n );\n }\n\n constructor(public host: ReactiveControllerHost & HTMLElement) {\n this.host.addController(this);\n }\n\n /**\n * handles keyboard navigation\n */\n #onKeydown = (event: KeyboardEvent) => {\n if (event.ctrlKey ||\n event.altKey ||\n event.metaKey ||\n !this.#focusableItems.length ||\n !event.composedPath().some(x =>\n this.#focusableItems.includes(x as ItemType))) {\n return;\n }\n const item = this.activeItem;\n let shouldPreventDefault = false;\n const horizontalOnly =\n !item ? false\n : item.tagName === 'SELECT' ||\n item.getAttribute('role') === 'spinbutton';\n\n\n switch (event.key) {\n case 'ArrowLeft':\n this.focusOnItem(this.prevItem);\n shouldPreventDefault = true;\n break;\n case 'ArrowRight':\n this.focusOnItem(this.nextItem);\n shouldPreventDefault = true;\n break;\n case 'ArrowUp':\n if (horizontalOnly) {\n return;\n }\n this.focusOnItem(this.prevItem);\n shouldPreventDefault = true;\n break;\n case 'ArrowDown':\n if (horizontalOnly) {\n return;\n }\n this.focusOnItem(this.nextItem);\n shouldPreventDefault = true;\n break;\n case 'Home':\n this.focusOnItem(this.firstItem);\n shouldPreventDefault = true;\n break;\n case 'PageUp':\n if (horizontalOnly) {\n return;\n }\n this.focusOnItem(this.firstItem);\n shouldPreventDefault = true;\n break;\n case 'End':\n this.focusOnItem(this.lastItem);\n shouldPreventDefault = true;\n break;\n case 'PageDown':\n if (horizontalOnly) {\n return;\n }\n this.focusOnItem(this.lastItem);\n shouldPreventDefault = true;\n break;\n default:\n break;\n }\n\n if (shouldPreventDefault) {\n event.stopPropagation();\n event.preventDefault();\n }\n };\n\n /**\n * sets tabindex of item based on whether or not it is active\n */\n updateActiveItem(item?: ItemType): void {\n if (item) {\n if (!!this.#activeItem && item !== this.#activeItem) {\n this.#activeItem.tabIndex = -1;\n }\n item.tabIndex = 0;\n this.#activeItem = item;\n }\n }\n\n /**\n * focuses on an item and sets it as active\n */\n focusOnItem(item?: ItemType): void {\n this.updateActiveItem(item || this.firstItem);\n this.#activeItem?.focus();\n this.host.requestUpdate();\n }\n\n /**\n * Focuses next focusable item\n */\n updateItems(items: ItemType[]) {\n const sequence = [...items.slice(this.#itemIndex), ...items.slice(0, this.#itemIndex)];\n const first = sequence.find(item => this.#focusableItems.includes(item));\n this.focusOnItem(first || this.firstItem);\n }\n\n /**\n * from array of HTML items, and sets active items\n */\n initItems(items: ItemType[], itemsContainer: HTMLElement = this.host) {\n this.#items = items ?? [];\n const focusableItems = this.#focusableItems;\n const [focusableItem] = focusableItems;\n this.#activeItem = focusableItem;\n for (const item of focusableItems) {\n item.tabIndex = this.#activeItem === item ? 0 : -1;\n }\n /**\n * removes listener on previous contained and applies it to new container\n */\n if (!this.#itemsContainer || itemsContainer !== this.#itemsContainer) {\n this.#itemsContainer?.removeEventListener('keydown', this.#onKeydown);\n this.#itemsContainer = itemsContainer;\n this.hostConnected();\n }\n }\n\n /**\n * adds event listeners to items container\n */\n hostConnected() {\n this.#itemsContainer?.addEventListener('keydown', this.#onKeydown);\n }\n\n /**\n * removes event listeners from items container\n */\n hostDisconnected() {\n this.#itemsContainer?.removeEventListener('keydown', this.#onKeydown);\n }\n}\n"]}
|