@patternfly/pfe-core 2.4.1 → 4.0.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/README.md +0 -1
- package/controllers/activedescendant-controller.d.ts +99 -0
- package/controllers/activedescendant-controller.js +230 -0
- package/controllers/activedescendant-controller.js.map +1 -0
- package/controllers/at-focus-controller.d.ts +56 -0
- package/controllers/at-focus-controller.js +168 -0
- package/controllers/at-focus-controller.js.map +1 -0
- package/controllers/cascade-controller.d.ts +11 -0
- package/controllers/cascade-controller.js +10 -3
- package/controllers/cascade-controller.js.map +1 -1
- package/controllers/combobox-controller.d.ts +117 -0
- package/controllers/combobox-controller.js +611 -0
- package/controllers/combobox-controller.js.map +1 -0
- package/controllers/css-variable-controller.js +1 -1
- package/controllers/css-variable-controller.js.map +1 -1
- package/controllers/floating-dom-controller.d.ts +10 -3
- package/controllers/floating-dom-controller.js +93 -83
- package/controllers/floating-dom-controller.js.map +1 -1
- package/controllers/internals-controller.d.ts +104 -42
- package/controllers/internals-controller.js +354 -36
- package/controllers/internals-controller.js.map +1 -1
- package/controllers/light-dom-controller.js +2 -2
- package/controllers/light-dom-controller.js.map +1 -1
- package/controllers/listbox-controller.d.ts +143 -0
- package/controllers/listbox-controller.js +443 -0
- package/controllers/listbox-controller.js.map +1 -0
- package/controllers/logger.d.ts +33 -6
- package/controllers/logger.js +58 -13
- package/controllers/logger.js.map +1 -1
- package/controllers/overflow-controller.d.ts +10 -3
- package/controllers/overflow-controller.js +79 -44
- package/controllers/overflow-controller.js.map +1 -1
- package/controllers/perf-controller.js.map +1 -1
- package/controllers/property-observer-controller.d.ts +13 -16
- package/controllers/property-observer-controller.js +55 -27
- package/controllers/property-observer-controller.js.map +1 -1
- package/controllers/roving-tabindex-controller.d.ts +19 -50
- package/controllers/roving-tabindex-controller.js +64 -183
- package/controllers/roving-tabindex-controller.js.map +1 -1
- package/controllers/scroll-spy-controller.d.ts +4 -1
- package/controllers/scroll-spy-controller.js +94 -93
- package/controllers/scroll-spy-controller.js.map +1 -1
- package/controllers/slot-controller.d.ts +26 -19
- package/controllers/slot-controller.js +94 -83
- package/controllers/slot-controller.js.map +1 -1
- package/controllers/style-controller.js +3 -1
- package/controllers/style-controller.js.map +1 -1
- package/controllers/tabs-aria-controller.d.ts +31 -0
- package/controllers/tabs-aria-controller.js +97 -0
- package/controllers/tabs-aria-controller.js.map +1 -0
- package/controllers/test/combobox-controller.spec.d.ts +1 -0
- package/controllers/test/combobox-controller.spec.js +282 -0
- package/controllers/test/combobox-controller.spec.js.map +1 -0
- package/controllers/timestamp-controller.js +73 -70
- package/controllers/timestamp-controller.js.map +1 -1
- package/core.d.ts +3 -23
- package/core.js +1 -38
- package/core.js.map +1 -1
- package/custom-elements.json +7302 -2817
- package/decorators/bound.d.ts +3 -1
- package/decorators/bound.js +3 -1
- package/decorators/bound.js.map +1 -1
- package/decorators/cascades.d.ts +2 -0
- package/decorators/cascades.js +2 -0
- package/decorators/cascades.js.map +1 -1
- package/decorators/deprecation.d.ts +6 -5
- package/decorators/deprecation.js +6 -5
- package/decorators/deprecation.js.map +1 -1
- package/decorators/initializer.js.map +1 -1
- package/decorators/listen.d.ts +8 -0
- package/decorators/listen.js +22 -0
- package/decorators/listen.js.map +1 -0
- package/decorators/observed.d.ts +12 -16
- package/decorators/observed.js +39 -44
- package/decorators/observed.js.map +1 -1
- package/decorators/observes.d.ts +15 -0
- package/decorators/observes.js +30 -0
- package/decorators/observes.js.map +1 -0
- package/decorators/time.d.ts +1 -0
- package/decorators/time.js +6 -9
- package/decorators/time.js.map +1 -1
- package/decorators/trace.d.ts +4 -1
- package/decorators/trace.js +4 -1
- package/decorators/trace.js.map +1 -1
- package/decorators.d.ts +2 -0
- package/decorators.js +2 -0
- package/decorators.js.map +1 -1
- package/functions/arraysAreEquivalent.d.ts +9 -0
- package/functions/arraysAreEquivalent.js +28 -0
- package/functions/arraysAreEquivalent.js.map +1 -0
- package/functions/containsDeep.d.ts +8 -0
- package/functions/containsDeep.js +23 -0
- package/functions/containsDeep.js.map +1 -0
- package/functions/context.d.ts +8 -0
- package/functions/context.js +21 -0
- package/functions/context.js.map +1 -0
- package/functions/debounce.js.map +1 -1
- package/functions/isElementInView.d.ts +4 -6
- package/functions/isElementInView.js +9 -11
- package/functions/isElementInView.js.map +1 -1
- package/package.json +10 -4
- package/functions/deprecatedCustomEvent.d.ts +0 -5
- package/functions/deprecatedCustomEvent.js +0 -12
- package/functions/deprecatedCustomEvent.js.map +0 -1
|
@@ -1,55 +1,24 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { type ReactiveControllerHost } from 'lit';
|
|
2
|
+
import { ATFocusController, type ATFocusControllerOptions } from './at-focus-controller.js';
|
|
3
|
+
export type RovingTabindexControllerOptions<Item extends HTMLElement> = ATFocusControllerOptions<Item>;
|
|
2
4
|
/**
|
|
3
5
|
* Implements roving tabindex, as described in WAI-ARIA practices, [Managing Focus Within
|
|
4
|
-
* Components Using a Roving
|
|
5
|
-
*
|
|
6
|
+
* Components Using a Roving tabindex][rti]
|
|
7
|
+
*
|
|
8
|
+
* [rti]: https://www.w3.org/WAI/ARIA/apg/practices/keyboard-interface/#kbd_roving_tabindex
|
|
6
9
|
*/
|
|
7
|
-
export declare class RovingTabindexController<
|
|
10
|
+
export declare class RovingTabindexController<Item extends HTMLElement = HTMLElement> extends ATFocusController<Item> {
|
|
8
11
|
#private;
|
|
9
|
-
host: ReactiveControllerHost
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
get
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
get lastItem(): ItemType | undefined;
|
|
22
|
-
/**
|
|
23
|
-
* next item after active item in array of focusable items
|
|
24
|
-
*/
|
|
25
|
-
get nextItem(): ItemType | undefined;
|
|
26
|
-
/**
|
|
27
|
-
* previous item after active item in array of focusable items
|
|
28
|
-
*/
|
|
29
|
-
get prevItem(): ItemType | undefined;
|
|
30
|
-
constructor(host: ReactiveControllerHost & HTMLElement);
|
|
31
|
-
/**
|
|
32
|
-
* sets tabindex of item based on whether or not it is active
|
|
33
|
-
*/
|
|
34
|
-
updateActiveItem(item?: ItemType): void;
|
|
35
|
-
/**
|
|
36
|
-
* focuses on an item and sets it as active
|
|
37
|
-
*/
|
|
38
|
-
focusOnItem(item?: ItemType): void;
|
|
39
|
-
/**
|
|
40
|
-
* Focuses next focusable item
|
|
41
|
-
*/
|
|
42
|
-
updateItems(items: ItemType[]): void;
|
|
43
|
-
/**
|
|
44
|
-
* from array of HTML items, and sets active items
|
|
45
|
-
*/
|
|
46
|
-
initItems(items: ItemType[], itemsContainer?: HTMLElement): void;
|
|
47
|
-
/**
|
|
48
|
-
* adds event listeners to items container
|
|
49
|
-
*/
|
|
50
|
-
hostConnected(): void;
|
|
51
|
-
/**
|
|
52
|
-
* removes event listeners from items container
|
|
53
|
-
*/
|
|
54
|
-
hostDisconnected(): void;
|
|
12
|
+
host: ReactiveControllerHost;
|
|
13
|
+
static of<Item extends HTMLElement>(host: ReactiveControllerHost, options: RovingTabindexControllerOptions<Item>): RovingTabindexController<Item>;
|
|
14
|
+
get atFocusedItemIndex(): number;
|
|
15
|
+
/**
|
|
16
|
+
* Sets the DOM Focus on the item with assistive technology focus
|
|
17
|
+
* @param item item
|
|
18
|
+
*/
|
|
19
|
+
set atFocusedItemIndex(index: number);
|
|
20
|
+
get items(): Item[];
|
|
21
|
+
set items(items: Item[]);
|
|
22
|
+
private constructor();
|
|
23
|
+
protected onKeydown(event: KeyboardEvent): void;
|
|
55
24
|
}
|
|
@@ -1,201 +1,82 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
var _RovingTabindexController_logger, _RovingTabindexController_gainedInitialFocus, _RovingTabindexController_itemsSet;
|
|
2
|
+
import { __classPrivateFieldGet, __classPrivateFieldSet, __decorate } from "tslib";
|
|
3
|
+
import { isServer } from 'lit';
|
|
4
|
+
import { ATFocusController } from './at-focus-controller.js';
|
|
5
|
+
import { Logger } from './logger.js';
|
|
6
|
+
import { bound } from '../decorators/bound.js';
|
|
5
7
|
/**
|
|
6
8
|
* Implements roving tabindex, as described in WAI-ARIA practices, [Managing Focus Within
|
|
7
|
-
* Components Using a Roving
|
|
8
|
-
*
|
|
9
|
+
* Components Using a Roving tabindex][rti]
|
|
10
|
+
*
|
|
11
|
+
* [rti]: https://www.w3.org/WAI/ARIA/apg/practices/keyboard-interface/#kbd_roving_tabindex
|
|
9
12
|
*/
|
|
10
|
-
export class RovingTabindexController {
|
|
11
|
-
|
|
12
|
-
|
|
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;
|
|
13
|
+
export class RovingTabindexController extends ATFocusController {
|
|
14
|
+
static of(host, options) {
|
|
15
|
+
return new RovingTabindexController(host, options);
|
|
34
16
|
}
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
*/
|
|
38
|
-
get activeItem() {
|
|
39
|
-
return this.#activeItem;
|
|
17
|
+
get atFocusedItemIndex() {
|
|
18
|
+
return super.atFocusedItemIndex;
|
|
40
19
|
}
|
|
41
20
|
/**
|
|
42
|
-
*
|
|
21
|
+
* Sets the DOM Focus on the item with assistive technology focus
|
|
22
|
+
* @param item item
|
|
43
23
|
*/
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
24
|
+
set atFocusedItemIndex(index) {
|
|
25
|
+
super.atFocusedItemIndex = index;
|
|
26
|
+
const item = this.items.at(this.atFocusedItemIndex);
|
|
27
|
+
for (const i of this.items) {
|
|
28
|
+
i.tabIndex = item === i ? 0 : -1;
|
|
29
|
+
}
|
|
30
|
+
if (__classPrivateFieldGet(this, _RovingTabindexController_gainedInitialFocus, "f")) {
|
|
31
|
+
item?.focus();
|
|
32
|
+
}
|
|
33
|
+
this.host.requestUpdate();
|
|
52
34
|
}
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
*/
|
|
56
|
-
get nextItem() {
|
|
57
|
-
return (this.#activeIndex >= this.#focusableItems.length - 1 ? this.firstItem
|
|
58
|
-
: this.#focusableItems[this.#activeIndex + 1]);
|
|
35
|
+
get items() {
|
|
36
|
+
return this._items;
|
|
59
37
|
}
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
38
|
+
set items(items) {
|
|
39
|
+
this._items = items;
|
|
40
|
+
__classPrivateFieldSet(this, _RovingTabindexController_itemsSet, new Set(items), "f");
|
|
41
|
+
const pivot = Math.max(0, this.atFocusedItemIndex);
|
|
42
|
+
const [firstFocusable] = this.atFocusableItems;
|
|
43
|
+
const firstFocusableIndex = firstFocusable ? items.indexOf(firstFocusable) : -1;
|
|
44
|
+
const pivotFocusableIndex = items.indexOf(this.items
|
|
45
|
+
.slice(pivot)
|
|
46
|
+
.concat(this.items.slice(0, pivot))
|
|
47
|
+
.find(item => this.atFocusableItems.includes(item)));
|
|
48
|
+
this.atFocusedItemIndex = Math.max(firstFocusableIndex, pivotFocusableIndex);
|
|
49
|
+
this.host.requestUpdate();
|
|
66
50
|
}
|
|
67
|
-
constructor(host) {
|
|
51
|
+
constructor(host, options) {
|
|
52
|
+
super(host, options);
|
|
68
53
|
this.host = host;
|
|
69
|
-
this.host
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
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
|
-
};
|
|
140
|
-
/**
|
|
141
|
-
* sets tabindex of item based on whether or not it is active
|
|
142
|
-
*/
|
|
143
|
-
updateActiveItem(item) {
|
|
144
|
-
if (item) {
|
|
145
|
-
if (!!this.#activeItem && item !== this.#activeItem) {
|
|
146
|
-
this.#activeItem.tabIndex = -1;
|
|
54
|
+
_RovingTabindexController_logger.set(this, new Logger(this.host));
|
|
55
|
+
_RovingTabindexController_gainedInitialFocus.set(this, false);
|
|
56
|
+
_RovingTabindexController_itemsSet.set(this, new Set());
|
|
57
|
+
this.initItems();
|
|
58
|
+
const container = options.getItemsContainer?.() ?? this.host;
|
|
59
|
+
if (!isServer) {
|
|
60
|
+
if (container instanceof HTMLElement) {
|
|
61
|
+
container.addEventListener('focusin', () => __classPrivateFieldSet(this, _RovingTabindexController_gainedInitialFocus, true, "f"), { once: true });
|
|
62
|
+
}
|
|
63
|
+
else {
|
|
64
|
+
__classPrivateFieldGet(this, _RovingTabindexController_logger, "f").warn('RovingTabindexController requires a getItemsContainer function');
|
|
147
65
|
}
|
|
148
|
-
item.tabIndex = 0;
|
|
149
|
-
this.#activeItem = item;
|
|
150
66
|
}
|
|
151
67
|
}
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
}
|
|
160
|
-
/**
|
|
161
|
-
* Focuses next focusable item
|
|
162
|
-
*/
|
|
163
|
-
updateItems(items) {
|
|
164
|
-
const sequence = [...items.slice(this.#itemIndex), ...items.slice(0, this.#itemIndex)];
|
|
165
|
-
const first = sequence.find(item => this.#focusableItems.includes(item));
|
|
166
|
-
this.focusOnItem(first || this.firstItem);
|
|
167
|
-
}
|
|
168
|
-
/**
|
|
169
|
-
* from array of HTML items, and sets active items
|
|
170
|
-
*/
|
|
171
|
-
initItems(items, itemsContainer = this.host) {
|
|
172
|
-
this.#items = items ?? [];
|
|
173
|
-
const focusableItems = this.#focusableItems;
|
|
174
|
-
const [focusableItem] = focusableItems;
|
|
175
|
-
this.#activeItem = focusableItem;
|
|
176
|
-
for (const item of focusableItems) {
|
|
177
|
-
item.tabIndex = this.#activeItem === item ? 0 : -1;
|
|
178
|
-
}
|
|
179
|
-
/**
|
|
180
|
-
* removes listener on previous contained and applies it to new container
|
|
181
|
-
*/
|
|
182
|
-
if (!this.#itemsContainer || itemsContainer !== this.#itemsContainer) {
|
|
183
|
-
this.#itemsContainer?.removeEventListener('keydown', this.#onKeydown);
|
|
184
|
-
this.#itemsContainer = itemsContainer;
|
|
185
|
-
this.hostConnected();
|
|
68
|
+
onKeydown(event) {
|
|
69
|
+
if (!event.ctrlKey
|
|
70
|
+
&& !event.altKey
|
|
71
|
+
&& !event.metaKey
|
|
72
|
+
&& !!this.atFocusableItems.length
|
|
73
|
+
&& !!event.composedPath().some(node => __classPrivateFieldGet(this, _RovingTabindexController_itemsSet, "f").has(node))) {
|
|
74
|
+
super.onKeydown(event);
|
|
186
75
|
}
|
|
187
76
|
}
|
|
188
|
-
/**
|
|
189
|
-
* adds event listeners to items container
|
|
190
|
-
*/
|
|
191
|
-
hostConnected() {
|
|
192
|
-
this.#itemsContainer?.addEventListener('keydown', this.#onKeydown);
|
|
193
|
-
}
|
|
194
|
-
/**
|
|
195
|
-
* removes event listeners from items container
|
|
196
|
-
*/
|
|
197
|
-
hostDisconnected() {
|
|
198
|
-
this.#itemsContainer?.removeEventListener('keydown', this.#onKeydown);
|
|
199
|
-
}
|
|
200
77
|
}
|
|
78
|
+
_RovingTabindexController_logger = new WeakMap(), _RovingTabindexController_gainedInitialFocus = new WeakMap(), _RovingTabindexController_itemsSet = new WeakMap();
|
|
79
|
+
__decorate([
|
|
80
|
+
bound
|
|
81
|
+
], RovingTabindexController.prototype, "onKeydown", null);
|
|
201
82
|
//# 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 ||\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"]}
|
|
1
|
+
{"version":3,"file":"roving-tabindex-controller.js","sourceRoot":"","sources":["roving-tabindex-controller.ts"],"names":[],"mappings":"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","sourcesContent":["import { isServer, type ReactiveControllerHost } from 'lit';\nimport { ATFocusController, type ATFocusControllerOptions } from './at-focus-controller.js';\nimport { Logger } from './logger.js';\nimport { bound } from '../decorators/bound.js';\n\nexport type RovingTabindexControllerOptions<Item extends HTMLElement> =\n ATFocusControllerOptions<Item>;\n\n/**\n * Implements roving tabindex, as described in WAI-ARIA practices, [Managing Focus Within\n * Components Using a Roving tabindex][rti]\n *\n * [rti]: https://www.w3.org/WAI/ARIA/apg/practices/keyboard-interface/#kbd_roving_tabindex\n */\nexport class RovingTabindexController<\n Item extends HTMLElement = HTMLElement\n> extends ATFocusController<Item> {\n static of<Item extends HTMLElement>(\n host: ReactiveControllerHost,\n options: RovingTabindexControllerOptions<Item>,\n ): RovingTabindexController<Item> {\n return new RovingTabindexController(host, options);\n }\n\n #logger = new Logger(this.host);\n\n #gainedInitialFocus = false;\n\n #itemsSet = new Set<Item>();\n\n get atFocusedItemIndex(): number {\n return super.atFocusedItemIndex;\n }\n\n /**\n * Sets the DOM Focus on the item with assistive technology focus\n * @param item item\n */\n set atFocusedItemIndex(index: number) {\n super.atFocusedItemIndex = index;\n const item = this.items.at(this.atFocusedItemIndex);\n for (const i of this.items) {\n i.tabIndex = item === i ? 0 : -1;\n }\n if (this.#gainedInitialFocus) {\n item?.focus();\n }\n this.host.requestUpdate();\n }\n\n get items() {\n return this._items;\n }\n\n public set items(items: Item[]) {\n this._items = items;\n this.#itemsSet = new Set(items);\n const pivot = Math.max(0, this.atFocusedItemIndex);\n const [firstFocusable] = this.atFocusableItems;\n const firstFocusableIndex = firstFocusable ? items.indexOf(firstFocusable) : -1;\n const pivotFocusableIndex = items.indexOf(this.items\n .slice(pivot)\n .concat(this.items.slice(0, pivot))\n .find(item => this.atFocusableItems.includes(item))!);\n this.atFocusedItemIndex = Math.max(firstFocusableIndex, pivotFocusableIndex);\n this.host.requestUpdate();\n }\n\n private constructor(\n public host: ReactiveControllerHost,\n options: RovingTabindexControllerOptions<Item>,\n ) {\n super(host, options);\n this.initItems();\n const container = options.getItemsContainer?.() ?? this.host;\n if (!isServer) {\n if (container instanceof HTMLElement) {\n container.addEventListener('focusin', () =>\n this.#gainedInitialFocus = true, { once: true });\n } else {\n this.#logger.warn('RovingTabindexController requires a getItemsContainer function');\n }\n }\n }\n\n @bound\n protected override onKeydown(event: KeyboardEvent): void {\n if (!event.ctrlKey\n && !event.altKey\n && !event.metaKey\n && !!this.atFocusableItems.length\n && !!event.composedPath().some(node => this.#itemsSet.has(node as Item))) {\n super.onKeydown(event);\n }\n }\n}\n"]}
|
|
@@ -32,6 +32,9 @@ export declare class ScrollSpyController implements ReactiveController {
|
|
|
32
32
|
set threshold(v: number | number[]);
|
|
33
33
|
constructor(host: ReactiveControllerHost & HTMLElement, options: ScrollSpyControllerOptions);
|
|
34
34
|
hostConnected(): void;
|
|
35
|
-
/**
|
|
35
|
+
/**
|
|
36
|
+
* Explicitly set the active item
|
|
37
|
+
* @param link usually an `<a>`
|
|
38
|
+
*/
|
|
36
39
|
setActive(link: EventTarget | null): Promise<void>;
|
|
37
40
|
}
|
|
@@ -1,122 +1,123 @@
|
|
|
1
|
+
var _ScrollSpyController_instances, _ScrollSpyController_tagNames, _ScrollSpyController_activeAttribute, _ScrollSpyController_io, _ScrollSpyController_passedLinks, _ScrollSpyController_force, _ScrollSpyController_intersected, _ScrollSpyController_root, _ScrollSpyController_rootMargin, _ScrollSpyController_threshold, _ScrollSpyController_getRootNode, _ScrollSpyController_getHash, _ScrollSpyController_linkChildren_get, _ScrollSpyController_initIo, _ScrollSpyController_markPassed, _ScrollSpyController_setActive, _ScrollSpyController_nextIntersection, _ScrollSpyController_onIo;
|
|
2
|
+
import { __classPrivateFieldGet, __classPrivateFieldSet } from "tslib";
|
|
1
3
|
export class ScrollSpyController {
|
|
2
|
-
#tagNames;
|
|
3
|
-
#activeAttribute;
|
|
4
|
-
#io;
|
|
5
|
-
/** Which link's targets have already scrolled past? */
|
|
6
|
-
#passedLinks = new Set();
|
|
7
|
-
/** Ignore intersections? */
|
|
8
|
-
#force = false;
|
|
9
|
-
/** Has the intersection observer found an element? */
|
|
10
|
-
#intersected = false;
|
|
11
|
-
#root;
|
|
12
|
-
#rootMargin;
|
|
13
|
-
#threshold;
|
|
14
|
-
#rootNode;
|
|
15
|
-
#getHash;
|
|
16
|
-
get #linkChildren() {
|
|
17
|
-
return Array.from(this.host.querySelectorAll(this.#tagNames.join(',')))
|
|
18
|
-
.filter(this.#getHash);
|
|
19
|
-
}
|
|
20
4
|
get root() {
|
|
21
|
-
return this
|
|
5
|
+
return __classPrivateFieldGet(this, _ScrollSpyController_root, "f");
|
|
22
6
|
}
|
|
23
7
|
set root(v) {
|
|
24
|
-
this
|
|
25
|
-
this
|
|
26
|
-
this
|
|
8
|
+
__classPrivateFieldSet(this, _ScrollSpyController_root, v, "f");
|
|
9
|
+
__classPrivateFieldGet(this, _ScrollSpyController_io, "f")?.disconnect();
|
|
10
|
+
__classPrivateFieldGet(this, _ScrollSpyController_instances, "m", _ScrollSpyController_initIo).call(this);
|
|
27
11
|
}
|
|
28
12
|
get rootMargin() {
|
|
29
|
-
return this
|
|
13
|
+
return __classPrivateFieldGet(this, _ScrollSpyController_rootMargin, "f");
|
|
30
14
|
}
|
|
31
15
|
set rootMargin(v) {
|
|
32
|
-
this
|
|
33
|
-
this
|
|
34
|
-
this
|
|
16
|
+
__classPrivateFieldSet(this, _ScrollSpyController_rootMargin, v, "f");
|
|
17
|
+
__classPrivateFieldGet(this, _ScrollSpyController_io, "f")?.disconnect();
|
|
18
|
+
__classPrivateFieldGet(this, _ScrollSpyController_instances, "m", _ScrollSpyController_initIo).call(this);
|
|
35
19
|
}
|
|
36
20
|
get threshold() {
|
|
37
|
-
return this
|
|
21
|
+
return __classPrivateFieldGet(this, _ScrollSpyController_threshold, "f");
|
|
38
22
|
}
|
|
39
23
|
set threshold(v) {
|
|
40
|
-
this
|
|
41
|
-
this
|
|
42
|
-
this
|
|
24
|
+
__classPrivateFieldSet(this, _ScrollSpyController_threshold, v, "f");
|
|
25
|
+
__classPrivateFieldGet(this, _ScrollSpyController_io, "f")?.disconnect();
|
|
26
|
+
__classPrivateFieldGet(this, _ScrollSpyController_instances, "m", _ScrollSpyController_initIo).call(this);
|
|
43
27
|
}
|
|
44
28
|
constructor(host, options) {
|
|
29
|
+
_ScrollSpyController_instances.add(this);
|
|
45
30
|
this.host = host;
|
|
31
|
+
_ScrollSpyController_tagNames.set(this, void 0);
|
|
32
|
+
_ScrollSpyController_activeAttribute.set(this, void 0);
|
|
33
|
+
_ScrollSpyController_io.set(this, void 0);
|
|
34
|
+
/** Which link's targets have already scrolled past? */
|
|
35
|
+
_ScrollSpyController_passedLinks.set(this, new Set());
|
|
36
|
+
/** Ignore intersections? */
|
|
37
|
+
_ScrollSpyController_force.set(this, false);
|
|
38
|
+
/** Has the intersection observer found an element? */
|
|
39
|
+
_ScrollSpyController_intersected.set(this, false);
|
|
40
|
+
_ScrollSpyController_root.set(this, void 0);
|
|
41
|
+
_ScrollSpyController_rootMargin.set(this, void 0);
|
|
42
|
+
_ScrollSpyController_threshold.set(this, void 0);
|
|
43
|
+
_ScrollSpyController_getRootNode.set(this, void 0);
|
|
44
|
+
_ScrollSpyController_getHash.set(this, void 0);
|
|
46
45
|
host.addController(this);
|
|
47
|
-
this
|
|
48
|
-
this
|
|
49
|
-
this
|
|
50
|
-
this
|
|
51
|
-
this
|
|
52
|
-
this
|
|
53
|
-
this
|
|
46
|
+
__classPrivateFieldSet(this, _ScrollSpyController_tagNames, options.tagNames, "f");
|
|
47
|
+
__classPrivateFieldSet(this, _ScrollSpyController_root, options.root, "f");
|
|
48
|
+
__classPrivateFieldSet(this, _ScrollSpyController_rootMargin, options.rootMargin, "f");
|
|
49
|
+
__classPrivateFieldSet(this, _ScrollSpyController_activeAttribute, options.activeAttribute ?? 'active', "f");
|
|
50
|
+
__classPrivateFieldSet(this, _ScrollSpyController_threshold, options.threshold ?? 0.85, "f");
|
|
51
|
+
__classPrivateFieldSet(this, _ScrollSpyController_getRootNode, () => options.rootNode ?? host.getRootNode(), "f");
|
|
52
|
+
__classPrivateFieldSet(this, _ScrollSpyController_getHash, options?.getHash ?? ((el) => el.getAttribute('href')), "f");
|
|
54
53
|
}
|
|
55
54
|
hostConnected() {
|
|
56
|
-
this
|
|
55
|
+
__classPrivateFieldGet(this, _ScrollSpyController_instances, "m", _ScrollSpyController_initIo).call(this);
|
|
57
56
|
}
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
57
|
+
/**
|
|
58
|
+
* Explicitly set the active item
|
|
59
|
+
* @param link usually an `<a>`
|
|
60
|
+
*/
|
|
61
|
+
async setActive(link) {
|
|
62
|
+
__classPrivateFieldSet(this, _ScrollSpyController_force, true, "f");
|
|
63
|
+
__classPrivateFieldGet(this, _ScrollSpyController_instances, "m", _ScrollSpyController_setActive).call(this, link);
|
|
64
|
+
let sawActive = false;
|
|
65
|
+
for (const child of __classPrivateFieldGet(this, _ScrollSpyController_instances, "a", _ScrollSpyController_linkChildren_get)) {
|
|
66
|
+
__classPrivateFieldGet(this, _ScrollSpyController_instances, "m", _ScrollSpyController_markPassed).call(this, child, !sawActive);
|
|
67
|
+
if (child === link) {
|
|
68
|
+
sawActive = true;
|
|
69
|
+
}
|
|
69
70
|
}
|
|
71
|
+
await __classPrivateFieldGet(this, _ScrollSpyController_instances, "m", _ScrollSpyController_nextIntersection).call(this);
|
|
72
|
+
__classPrivateFieldSet(this, _ScrollSpyController_force, false, "f");
|
|
70
73
|
}
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
74
|
+
}
|
|
75
|
+
_ScrollSpyController_tagNames = new WeakMap(), _ScrollSpyController_activeAttribute = new WeakMap(), _ScrollSpyController_io = new WeakMap(), _ScrollSpyController_passedLinks = new WeakMap(), _ScrollSpyController_force = new WeakMap(), _ScrollSpyController_intersected = new WeakMap(), _ScrollSpyController_root = new WeakMap(), _ScrollSpyController_rootMargin = new WeakMap(), _ScrollSpyController_threshold = new WeakMap(), _ScrollSpyController_getRootNode = new WeakMap(), _ScrollSpyController_getHash = new WeakMap(), _ScrollSpyController_instances = new WeakSet(), _ScrollSpyController_linkChildren_get = function _ScrollSpyController_linkChildren_get() {
|
|
76
|
+
return Array.from(this.host.querySelectorAll(__classPrivateFieldGet(this, _ScrollSpyController_tagNames, "f").join(',')))
|
|
77
|
+
.filter(__classPrivateFieldGet(this, _ScrollSpyController_getHash, "f"));
|
|
78
|
+
}, _ScrollSpyController_initIo = function _ScrollSpyController_initIo() {
|
|
79
|
+
const rootNode = __classPrivateFieldGet(this, _ScrollSpyController_getRootNode, "f").call(this);
|
|
80
|
+
if (rootNode instanceof Document || rootNode instanceof ShadowRoot) {
|
|
81
|
+
const { rootMargin, threshold, root } = this;
|
|
82
|
+
__classPrivateFieldSet(this, _ScrollSpyController_io, new IntersectionObserver(r => __classPrivateFieldGet(this, _ScrollSpyController_instances, "m", _ScrollSpyController_onIo).call(this, r), { root, rootMargin, threshold }), "f");
|
|
83
|
+
__classPrivateFieldGet(this, _ScrollSpyController_instances, "a", _ScrollSpyController_linkChildren_get)
|
|
84
|
+
.map(x => __classPrivateFieldGet(this, _ScrollSpyController_getHash, "f").call(this, x))
|
|
85
|
+
.filter((x) => !!x)
|
|
86
|
+
.map(x => rootNode.getElementById(x.replace('#', '')))
|
|
87
|
+
.filter((x) => !!x)
|
|
88
|
+
.forEach(target => __classPrivateFieldGet(this, _ScrollSpyController_io, "f")?.observe(target));
|
|
78
89
|
}
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
}
|
|
90
|
+
}, _ScrollSpyController_markPassed = function _ScrollSpyController_markPassed(link, force) {
|
|
91
|
+
if (force) {
|
|
92
|
+
__classPrivateFieldGet(this, _ScrollSpyController_passedLinks, "f").add(link);
|
|
83
93
|
}
|
|
84
|
-
|
|
85
|
-
this
|
|
86
|
-
// safeguard the loop
|
|
87
|
-
setTimeout(() => this.#intersected = false, 3000);
|
|
88
|
-
while (!this.#intersected) {
|
|
89
|
-
await new Promise(requestAnimationFrame);
|
|
90
|
-
}
|
|
94
|
+
else {
|
|
95
|
+
__classPrivateFieldGet(this, _ScrollSpyController_passedLinks, "f").delete(link);
|
|
91
96
|
}
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
const selector = `:is(${this.#tagNames.join(',')})[href="#${target.id}"]`;
|
|
96
|
-
const link = this.host.querySelector(selector);
|
|
97
|
-
if (link) {
|
|
98
|
-
this.#markPassed(link, boundingClientRect.top < intersectionRect.top);
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
const link = [...this.#passedLinks];
|
|
102
|
-
const last = link.at(-1);
|
|
103
|
-
this.#setActive(last ?? this.#linkChildren.at(0));
|
|
104
|
-
}
|
|
105
|
-
this.#intersected = true;
|
|
97
|
+
}, _ScrollSpyController_setActive = function _ScrollSpyController_setActive(link) {
|
|
98
|
+
for (const child of __classPrivateFieldGet(this, _ScrollSpyController_instances, "a", _ScrollSpyController_linkChildren_get)) {
|
|
99
|
+
child.toggleAttribute(__classPrivateFieldGet(this, _ScrollSpyController_activeAttribute, "f"), child === link);
|
|
106
100
|
}
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
101
|
+
}, _ScrollSpyController_nextIntersection = async function _ScrollSpyController_nextIntersection() {
|
|
102
|
+
__classPrivateFieldSet(this, _ScrollSpyController_intersected, false, "f");
|
|
103
|
+
// safeguard the loop
|
|
104
|
+
setTimeout(() => __classPrivateFieldSet(this, _ScrollSpyController_intersected, false, "f"), 3000);
|
|
105
|
+
while (!__classPrivateFieldGet(this, _ScrollSpyController_intersected, "f")) {
|
|
106
|
+
await new Promise(requestAnimationFrame);
|
|
107
|
+
}
|
|
108
|
+
}, _ScrollSpyController_onIo = async function _ScrollSpyController_onIo(entries) {
|
|
109
|
+
if (!__classPrivateFieldGet(this, _ScrollSpyController_force, "f")) {
|
|
110
|
+
for (const { target, boundingClientRect, intersectionRect } of entries) {
|
|
111
|
+
const selector = `:is(${__classPrivateFieldGet(this, _ScrollSpyController_tagNames, "f").join(',')})[href="#${target.id}"]`;
|
|
112
|
+
const link = this.host.querySelector(selector);
|
|
113
|
+
if (link) {
|
|
114
|
+
__classPrivateFieldGet(this, _ScrollSpyController_instances, "m", _ScrollSpyController_markPassed).call(this, link, boundingClientRect.top < intersectionRect.top);
|
|
116
115
|
}
|
|
117
116
|
}
|
|
118
|
-
|
|
119
|
-
|
|
117
|
+
const link = [...__classPrivateFieldGet(this, _ScrollSpyController_passedLinks, "f")];
|
|
118
|
+
const last = link.at(-1);
|
|
119
|
+
__classPrivateFieldGet(this, _ScrollSpyController_instances, "m", _ScrollSpyController_setActive).call(this, last ?? __classPrivateFieldGet(this, _ScrollSpyController_instances, "a", _ScrollSpyController_linkChildren_get).at(0));
|
|
120
120
|
}
|
|
121
|
-
|
|
121
|
+
__classPrivateFieldSet(this, _ScrollSpyController_intersected, true, "f");
|
|
122
|
+
};
|
|
122
123
|
//# sourceMappingURL=scroll-spy-controller.js.map
|