@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.
@@ -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 __classPrivateFieldGet(this, _OverflowController_items, "f").at(0);
12
+ return this.#items.at(0);
7
13
  }
8
14
  get lastItem() {
9
- return __classPrivateFieldGet(this, _OverflowController_items, "f").at(-1);
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
- _OverflowController_items.set(this, []);
19
- _OverflowController_scrollTimeoutDelay.set(this, 0);
20
- _OverflowController_scrollTimeout.set(this, void 0);
21
+ this.#items = [];
22
+ this.#scrollTimeoutDelay = 0;
21
23
  /** Default state */
22
- _OverflowController_hideOverflowButtons.set(this, false);
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(__classPrivateFieldGet(this, _OverflowController_scrollTimeout, "f"));
28
- __classPrivateFieldSet(this, _OverflowController_scrollTimeout, setTimeout(() => __classPrivateFieldGet(this, _OverflowController_instances, "m", _OverflowController_setOverflowState).call(this), __classPrivateFieldGet(this, _OverflowController_scrollTimeoutDelay, "f")), "f");
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
- __classPrivateFieldSet(this, _OverflowController_hideOverflowButtons, options?.hideOverflowButtons, "f");
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
- __classPrivateFieldSet(this, _OverflowController_container, container, "f");
52
+ this.#container = container;
37
53
  // convert HTMLCollection to HTMLElement[]
38
- __classPrivateFieldSet(this, _OverflowController_items, items, "f");
54
+ this.#items = items;
39
55
  }
40
56
  scrollLeft() {
41
- if (!__classPrivateFieldGet(this, _OverflowController_container, "f")) {
57
+ if (!this.#container) {
42
58
  return;
43
59
  }
44
- const leftScroll = __classPrivateFieldGet(this, _OverflowController_container, "f").scrollLeft - __classPrivateFieldGet(this, _OverflowController_container, "f").clientWidth;
45
- __classPrivateFieldGet(this, _OverflowController_container, "f").scroll({ left: leftScroll, behavior: 'smooth' });
46
- __classPrivateFieldGet(this, _OverflowController_instances, "m", _OverflowController_setOverflowState).call(this);
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 (!__classPrivateFieldGet(this, _OverflowController_container, "f")) {
65
+ if (!this.#container) {
50
66
  return;
51
67
  }
52
- const leftScroll = __classPrivateFieldGet(this, _OverflowController_container, "f").scrollLeft + __classPrivateFieldGet(this, _OverflowController_container, "f").clientWidth;
53
- __classPrivateFieldGet(this, _OverflowController_container, "f").scroll({ left: leftScroll, behavior: 'smooth' });
54
- __classPrivateFieldGet(this, _OverflowController_instances, "m", _OverflowController_setOverflowState).call(this);
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
- __classPrivateFieldGet(this, _OverflowController_instances, "m", _OverflowController_setOverflowState).call(this);
73
+ this.#setOverflowState();
58
74
  }
59
75
  hostConnected() {
60
76
  this.onScroll();
61
- __classPrivateFieldGet(this, _OverflowController_instances, "m", _OverflowController_setOverflowState).call(this);
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":"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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
+ {"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;IAK7B,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;;AAhCc,gCAAK,GAAqD,IAAI,OAAO,EAAE,AAAlE,CAAmE;SAD5E,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
+ {"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 __classPrivateFieldGet(this, _RovingTabindexController_activeItem, "f");
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 __classPrivateFieldGet(this, _RovingTabindexController_instances, "a", _RovingTabindexController_focusableItems_get)[0];
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 __classPrivateFieldGet(this, _RovingTabindexController_instances, "a", _RovingTabindexController_focusableItems_get).at(-1);
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 (__classPrivateFieldGet(this, _RovingTabindexController_instances, "a", _RovingTabindexController_activeIndex_get) >= __classPrivateFieldGet(this, _RovingTabindexController_instances, "a", _RovingTabindexController_focusableItems_get).length - 1 ? this.firstItem
36
- : __classPrivateFieldGet(this, _RovingTabindexController_instances, "a", _RovingTabindexController_focusableItems_get)[__classPrivateFieldGet(this, _RovingTabindexController_instances, "a", _RovingTabindexController_activeIndex_get) + 1]);
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 (__classPrivateFieldGet(this, _RovingTabindexController_instances, "a", _RovingTabindexController_activeIndex_get) > 0 ? __classPrivateFieldGet(this, _RovingTabindexController_instances, "a", _RovingTabindexController_focusableItems_get)[__classPrivateFieldGet(this, _RovingTabindexController_instances, "a", _RovingTabindexController_activeIndex_get) - 1]
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 (!!__classPrivateFieldGet(this, _RovingTabindexController_activeItem, "f") && item !== __classPrivateFieldGet(this, _RovingTabindexController_activeItem, "f")) {
127
- __classPrivateFieldGet(this, _RovingTabindexController_activeItem, "f").tabIndex = -1;
145
+ if (!!this.#activeItem && item !== this.#activeItem) {
146
+ this.#activeItem.tabIndex = -1;
128
147
  }
129
148
  item.tabIndex = 0;
130
- __classPrivateFieldSet(this, _RovingTabindexController_activeItem, item, "f");
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
- __classPrivateFieldGet(this, _RovingTabindexController_activeItem, "f")?.focus();
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(__classPrivateFieldGet(this, _RovingTabindexController_instances, "a", _RovingTabindexController_itemIndex_get)), ...items.slice(0, __classPrivateFieldGet(this, _RovingTabindexController_instances, "a", _RovingTabindexController_itemIndex_get))];
146
- const first = sequence.find(item => __classPrivateFieldGet(this, _RovingTabindexController_instances, "a", _RovingTabindexController_focusableItems_get).includes(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
- __classPrivateFieldSet(this, _RovingTabindexController_items, items ?? [], "f");
154
- const focusableItems = __classPrivateFieldGet(this, _RovingTabindexController_instances, "a", _RovingTabindexController_focusableItems_get);
172
+ this.#items = items ?? [];
173
+ const focusableItems = this.#focusableItems;
155
174
  const [focusableItem] = focusableItems;
156
- __classPrivateFieldSet(this, _RovingTabindexController_activeItem, focusableItem, "f");
175
+ this.#activeItem = focusableItem;
157
176
  for (const item of focusableItems) {
158
- item.tabIndex = __classPrivateFieldGet(this, _RovingTabindexController_activeItem, "f") === item ? 0 : -1;
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 (!__classPrivateFieldGet(this, _RovingTabindexController_itemsContainer, "f") || itemsContainer !== __classPrivateFieldGet(this, _RovingTabindexController_itemsContainer, "f")) {
164
- __classPrivateFieldGet(this, _RovingTabindexController_itemsContainer, "f")?.removeEventListener('keydown', __classPrivateFieldGet(this, _RovingTabindexController_onKeydown, "f"));
165
- __classPrivateFieldSet(this, _RovingTabindexController_itemsContainer, itemsContainer, "f");
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
- __classPrivateFieldGet(this, _RovingTabindexController_itemsContainer, "f")?.addEventListener('keydown', __classPrivateFieldGet(this, _RovingTabindexController_onKeydown, "f"));
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
- __classPrivateFieldGet(this, _RovingTabindexController_itemsContainer, "f")?.removeEventListener('keydown', __classPrivateFieldGet(this, _RovingTabindexController_onKeydown, "f"));
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":"AAEA,MAAM,kBAAkB,GAAG,CAAC,EAAW,EAAqB,EAAE,CAC5D,CAAC,CAAC,EAAE;IACJ,CAAC,EAAE,CAAC,YAAY,CAAC,UAAU,CAAC;IAC5B,CAAC,EAAE,CAAC,UAAU;IACd,CAAC,EAAE,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC;AAE7B;;;;GAIG;AACH,MAAM,OAAO,wBAAwB;IAGnC,+BAA+B;IAC/B,WAAW,CAAY;IAEvB,wCAAwC;IACxC,eAAe,CAAe;IAE9B,sCAAsC;IACtC,MAAM,GAAe,EAAE,CAAC;IAExB;;OAEG;IACH,IAAI,eAAe;QACjB,OAAO,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,kBAAkB,CAAC,CAAC;IAChD,CAAC;IAED;;OAEG;IACH,IAAI,YAAY;QACd,OAAO,CAAC,CAAC,IAAI,CAAC,eAAe,IAAI,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,eAAe,CAAC,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC1G,CAAC;IAED;;OAEG;IACH,IAAI,UAAU;QACZ,OAAO,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACrE,CAAC;IAED;;OAEG;IACH,IAAI,UAAU;QACZ,OAAO,IAAI,CAAC,WAAW,CAAC;IAC1B,CAAC;IAED;;OAEG;IACH,IAAI,SAAS;QACX,OAAO,IAAI,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC;IACjC,CAAC;IAED;;OAEG;IACH,IAAI,QAAQ;QACV,OAAO,IAAI,CAAC,eAAe,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;IACrC,CAAC;IAED;;OAEG;IACH,IAAI,QAAQ;QACV,OAAO,CACH,IAAI,CAAC,YAAY,IAAI,IAAI,CAAC,eAAe,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS;YACvE,CAAC,CAAC,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,YAAY,GAAG,CAAC,CAAC,CAC9C,CAAC;IACJ,CAAC;IAED;;OAEG;IACH,IAAI,QAAQ;QACV,OAAO,CACH,IAAI,CAAC,YAAY,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,YAAY,GAAG,CAAC,CAAC;YACrE,CAAC,CAAC,IAAI,CAAC,QAAQ,CAChB,CAAC;IACJ,CAAC;IAED,YAAmB,IAA0C;QAA1C,SAAI,GAAJ,IAAI,CAAsC;QAC3D,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC;IAChC,CAAC;IAED;;OAEG;IACH,UAAU,GAAG,CAAC,KAAoB,EAAE,EAAE;QACpC,IAAI,KAAK,CAAC,OAAO;YACb,KAAK,CAAC,MAAM;YACZ,KAAK,CAAC,OAAO;YACb,CAAC,IAAI,CAAC,eAAe,CAAC,MAAM;YAC5B,CAAC,KAAK,CAAC,YAAY,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAC7B,IAAI,CAAC,eAAe,CAAC,QAAQ,CAAC,CAAa,CAAC,CAAC,EAAE;YACnD,OAAO;SACR;QACD,MAAM,IAAI,GAAG,IAAI,CAAC,UAAU,CAAC;QAC7B,IAAI,oBAAoB,GAAG,KAAK,CAAC;QACjC,MAAM,cAAc,GAChB,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK;YACf,CAAC,CAAC,IAAI,CAAC,OAAO,KAAK,QAAQ;gBACzB,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,KAAK,YAAY,CAAC;QAG/C,QAAQ,KAAK,CAAC,GAAG,EAAE;YACjB,KAAK,WAAW;gBACd,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;gBAChC,oBAAoB,GAAG,IAAI,CAAC;gBAC5B,MAAM;YACR,KAAK,YAAY;gBACf,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;gBAChC,oBAAoB,GAAG,IAAI,CAAC;gBAC5B,MAAM;YACR,KAAK,SAAS;gBACZ,IAAI,cAAc,EAAE;oBAClB,OAAO;iBACR;gBACD,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;gBAChC,oBAAoB,GAAG,IAAI,CAAC;gBAC5B,MAAM;YACR,KAAK,WAAW;gBACd,IAAI,cAAc,EAAE;oBAClB,OAAO;iBACR;gBACD,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;gBAChC,oBAAoB,GAAG,IAAI,CAAC;gBAC5B,MAAM;YACR,KAAK,MAAM;gBACT,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;gBACjC,oBAAoB,GAAG,IAAI,CAAC;gBAC5B,MAAM;YACR,KAAK,QAAQ;gBACX,IAAI,cAAc,EAAE;oBAClB,OAAO;iBACR;gBACD,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;gBACjC,oBAAoB,GAAG,IAAI,CAAC;gBAC5B,MAAM;YACR,KAAK,KAAK;gBACR,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;gBAChC,oBAAoB,GAAG,IAAI,CAAC;gBAC5B,MAAM;YACR,KAAK,UAAU;gBACb,IAAI,cAAc,EAAE;oBAClB,OAAO;iBACR;gBACD,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;gBAChC,oBAAoB,GAAG,IAAI,CAAC;gBAC5B,MAAM;YACR;gBACE,MAAM;SACT;QAED,IAAI,oBAAoB,EAAE;YACxB,KAAK,CAAC,eAAe,EAAE,CAAC;YACxB,KAAK,CAAC,cAAc,EAAE,CAAC;SACxB;IACH,CAAC,CAAC;IAEF;;OAEG;IACH,gBAAgB,CAAC,IAAe;QAC9B,IAAI,IAAI,EAAE;YACR,IAAI,CAAC,CAAC,IAAI,CAAC,WAAW,IAAI,IAAI,KAAK,IAAI,CAAC,WAAW,EAAE;gBACnD,IAAI,CAAC,WAAW,CAAC,QAAQ,GAAG,CAAC,CAAC,CAAC;aAChC;YACD,IAAI,CAAC,QAAQ,GAAG,CAAC,CAAC;YAClB,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC;SACzB;IACH,CAAC;IAED;;OAEG;IACH,WAAW,CAAC,IAAe;QACzB,IAAI,CAAC,gBAAgB,CAAC,IAAI,IAAI,IAAI,CAAC,SAAS,CAAC,CAAC;QAC9C,IAAI,CAAC,WAAW,EAAE,KAAK,EAAE,CAAC;QAC1B,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,CAAC;IAC5B,CAAC;IAED;;OAEG;IACH,WAAW,CAAC,KAAiB;QAC3B,MAAM,QAAQ,GAAG,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC;QACvF,MAAM,KAAK,GAAG,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,eAAe,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC;QACzE,IAAI,CAAC,WAAW,CAAC,KAAK,IAAI,IAAI,CAAC,SAAS,CAAC,CAAC;IAC5C,CAAC;IAED;;OAEG;IACH,SAAS,CAAC,KAAiB,EAAE,iBAA8B,IAAI,CAAC,IAAI;QAClE,IAAI,CAAC,MAAM,GAAG,KAAK,IAAI,EAAE,CAAC;QAC1B,MAAM,cAAc,GAAG,IAAI,CAAC,eAAe,CAAC;QAC5C,MAAM,CAAC,aAAa,CAAC,GAAG,cAAc,CAAC;QACvC,IAAI,CAAC,WAAW,GAAG,aAAa,CAAC;QACjC,KAAK,MAAM,IAAI,IAAI,cAAc,EAAE;YACjC,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,WAAW,KAAK,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;SACpD;QACD;;WAEG;QACH,IAAI,CAAC,IAAI,CAAC,eAAe,IAAI,cAAc,KAAK,IAAI,CAAC,eAAe,EAAE;YACpE,IAAI,CAAC,eAAe,EAAE,mBAAmB,CAAC,SAAS,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC;YACtE,IAAI,CAAC,eAAe,GAAG,cAAc,CAAC;YACtC,IAAI,CAAC,aAAa,EAAE,CAAC;SACtB;IACH,CAAC;IAED;;OAEG;IACH,aAAa;QACX,IAAI,CAAC,eAAe,EAAE,gBAAgB,CAAC,SAAS,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC;IACrE,CAAC;IAED;;OAEG;IACH,gBAAgB;QACd,IAAI,CAAC,eAAe,EAAE,mBAAmB,CAAC,SAAS,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC;IACxE,CAAC;CACF","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"]}