@patternfly/pfe-core 3.0.0 → 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.
Files changed (99) hide show
  1. package/controllers/activedescendant-controller.d.ts +99 -0
  2. package/controllers/activedescendant-controller.js +230 -0
  3. package/controllers/activedescendant-controller.js.map +1 -0
  4. package/controllers/at-focus-controller.d.ts +56 -0
  5. package/controllers/at-focus-controller.js +168 -0
  6. package/controllers/at-focus-controller.js.map +1 -0
  7. package/controllers/cascade-controller.d.ts +7 -2
  8. package/controllers/cascade-controller.js +6 -1
  9. package/controllers/cascade-controller.js.map +1 -1
  10. package/controllers/combobox-controller.d.ts +117 -0
  11. package/controllers/combobox-controller.js +611 -0
  12. package/controllers/combobox-controller.js.map +1 -0
  13. package/controllers/css-variable-controller.js +1 -1
  14. package/controllers/css-variable-controller.js.map +1 -1
  15. package/controllers/floating-dom-controller.d.ts +8 -1
  16. package/controllers/floating-dom-controller.js +12 -5
  17. package/controllers/floating-dom-controller.js.map +1 -1
  18. package/controllers/internals-controller.d.ts +26 -9
  19. package/controllers/internals-controller.js +45 -13
  20. package/controllers/internals-controller.js.map +1 -1
  21. package/controllers/light-dom-controller.js +2 -2
  22. package/controllers/light-dom-controller.js.map +1 -1
  23. package/controllers/listbox-controller.d.ts +118 -33
  24. package/controllers/listbox-controller.js +347 -154
  25. package/controllers/listbox-controller.js.map +1 -1
  26. package/controllers/logger.d.ts +13 -10
  27. package/controllers/logger.js +15 -11
  28. package/controllers/logger.js.map +1 -1
  29. package/controllers/overflow-controller.js +10 -6
  30. package/controllers/overflow-controller.js.map +1 -1
  31. package/controllers/perf-controller.js.map +1 -1
  32. package/controllers/property-observer-controller.d.ts +13 -16
  33. package/controllers/property-observer-controller.js +54 -25
  34. package/controllers/property-observer-controller.js.map +1 -1
  35. package/controllers/roving-tabindex-controller.d.ts +12 -61
  36. package/controllers/roving-tabindex-controller.js +57 -203
  37. package/controllers/roving-tabindex-controller.js.map +1 -1
  38. package/controllers/scroll-spy-controller.d.ts +4 -1
  39. package/controllers/scroll-spy-controller.js +9 -6
  40. package/controllers/scroll-spy-controller.js.map +1 -1
  41. package/controllers/slot-controller.d.ts +12 -16
  42. package/controllers/slot-controller.js +17 -20
  43. package/controllers/slot-controller.js.map +1 -1
  44. package/controllers/style-controller.js +3 -1
  45. package/controllers/style-controller.js.map +1 -1
  46. package/controllers/tabs-aria-controller.d.ts +2 -0
  47. package/controllers/tabs-aria-controller.js +2 -0
  48. package/controllers/tabs-aria-controller.js.map +1 -1
  49. package/controllers/test/combobox-controller.spec.d.ts +1 -0
  50. package/controllers/test/combobox-controller.spec.js +282 -0
  51. package/controllers/test/combobox-controller.spec.js.map +1 -0
  52. package/controllers/timestamp-controller.js +7 -2
  53. package/controllers/timestamp-controller.js.map +1 -1
  54. package/core.d.ts +0 -23
  55. package/core.js +1 -38
  56. package/core.js.map +1 -1
  57. package/custom-elements.json +3844 -1369
  58. package/decorators/bound.d.ts +3 -1
  59. package/decorators/bound.js +3 -1
  60. package/decorators/bound.js.map +1 -1
  61. package/decorators/cascades.d.ts +2 -1
  62. package/decorators/cascades.js +2 -1
  63. package/decorators/cascades.js.map +1 -1
  64. package/decorators/deprecation.d.ts +6 -5
  65. package/decorators/deprecation.js +6 -5
  66. package/decorators/deprecation.js.map +1 -1
  67. package/decorators/initializer.js.map +1 -1
  68. package/decorators/listen.d.ts +8 -0
  69. package/decorators/listen.js +22 -0
  70. package/decorators/listen.js.map +1 -0
  71. package/decorators/observed.d.ts +12 -16
  72. package/decorators/observed.js +39 -44
  73. package/decorators/observed.js.map +1 -1
  74. package/decorators/observes.d.ts +15 -0
  75. package/decorators/observes.js +30 -0
  76. package/decorators/observes.js.map +1 -0
  77. package/decorators/time.d.ts +1 -0
  78. package/decorators/time.js +6 -9
  79. package/decorators/time.js.map +1 -1
  80. package/decorators/trace.d.ts +4 -1
  81. package/decorators/trace.js +4 -1
  82. package/decorators/trace.js.map +1 -1
  83. package/decorators.d.ts +2 -0
  84. package/decorators.js +2 -0
  85. package/decorators.js.map +1 -1
  86. package/functions/arraysAreEquivalent.d.ts +9 -0
  87. package/functions/arraysAreEquivalent.js +28 -0
  88. package/functions/arraysAreEquivalent.js.map +1 -0
  89. package/functions/containsDeep.d.ts +2 -0
  90. package/functions/containsDeep.js +2 -0
  91. package/functions/containsDeep.js.map +1 -1
  92. package/functions/context.d.ts +3 -4
  93. package/functions/context.js +6 -2
  94. package/functions/context.js.map +1 -1
  95. package/functions/debounce.js.map +1 -1
  96. package/functions/isElementInView.d.ts +4 -6
  97. package/functions/isElementInView.js +9 -11
  98. package/functions/isElementInView.js.map +1 -1
  99. package/package.json +7 -4
@@ -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,MAAM,OAAO,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,CAAC;YAC/C,OAAO,0BAA0B,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAA+B,CAAC;QAClF,CAAC;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,CAAC;YAChE,wCAAwC;YACxC,IAAI,CAAC,IAAI,CAAC,UAAmC,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;YACjE,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACnB,CAAC;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","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,OAAO,EAAE,QAAQ,EAAE,MAAM,KAAK,CAAC;AAc/B,MAAM,aAAa,GAAG,MAAM,CAAC,eAAe,CAAC,CAAC;AAE9C,MAAM,OAAO,0BAA0B;IAKrC,YACU,IAAO,EACP,OAAmC;;QADnC,SAAI,GAAJ,IAAI,CAAG;QACP,YAAO,GAAP,OAAO,CAA4B;QAJrC,WAAM,GAAe,aAA2B,CAAC;QAQzD,+CAAY,IAAI,EAAC;IAFjB,CAAC;IAID,aAAa;QACX,uBAAA,IAAI,+EAAM,MAAV,IAAI,CAAQ,CAAC;IACf,CAAC;IAiBD,kFAAkF;IAClF,KAAK,CAAC,UAAU;QACd,uBAAA,IAAI,+EAAM,MAAV,IAAI,CAAQ,CAAC;QACb,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,EAAE,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,EAAE,GAAG,IAAI,CAAC;QACtE,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,MAAM,IAAI,KAAK,CAAC,mBAAmB,YAAY,EAAE,CAAC,CAAC;QACrD,CAAC;QACD,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;QACvC,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,MAAM,KAAK,MAAM,EAAE,CAAC;YACtB,QAAQ,OAAO,EAAE,CAAC;gBAChB,KAAK,WAAW;oBACd,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC;wBAC3B,MAAM,aAAa,GAAG,IAAI,CAAC,IAAI,CAAC,iBAAiB,CAAC;wBAClD,MAAM,IAAI,OAAO,CAAO,OAAO,CAAC,EAAE;4BAChC,IAAI,CAAC,IAAI,CAAC,iBAAiB,GAAG;gCAC5B,OAAO,CAAC,aAAa,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;4BACrC,CAAC,CAAC;wBACJ,CAAC,CAAC,CAAC;oBACL,CAAC;oBACD,MAAM;gBACR,KAAK,cAAc;oBACjB,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC;wBAC1B,MAAM,IAAI,CAAC,IAAI,CAAC,cAAc,CAAC;oBACjC,CAAC;oBACD,MAAM;gBACR,KAAK,SAAS;oBACZ,MAAM,IAAI,CAAC,IAAI,CAAC,cAAc,CAAC;oBAC/B,MAAM;YACV,CAAC;QACH,CAAC;QACD,MAAM,KAAK,GAAI,IAAI,CAAC,IAAI,CAAC,WAAsC,CAAC;QAChE,MAAM,UAAU,GAAG,KAAK;aACnB,kBAAkB,CAAC,IAAI,CAAC,OAAO,CAAC,YAAY,CAAC;aAC7C,UAAU,IAAI,QAAQ,CAAC;QAC5B,IAAI,uBAAA,IAAI,4CAAU,IAAI,UAAU,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,CAAC;YACjD,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,MAAoB,EAAE,MAAM,CAAC,CAAC;YACvD,uBAAA,IAAI,wCAAa,KAAK,MAAA,CAAC;QACzB,CAAC;IACH,CAAC;CACF;;IA7CG,IAAI,IAAI,CAAC,MAAM,KAAK,aAAa,EAAE,CAAC;QAClC,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;IACrD,CAAC;AACH,CAAC","sourcesContent":["import type { ReactiveController, ReactiveElement } from 'lit';\n\nimport { notEqual } from 'lit';\n\nexport type ChangeCallback<T extends ReactiveElement, V = T[keyof T]> = (\n this: T,\n old?: V,\n newV?: V,\n) => void;\n\nexport interface PropertyObserverOptions<T extends ReactiveElement> {\n propertyName: string & keyof T;\n callback: ChangeCallback<T>;\n waitFor?: 'connected' | 'updated' | 'firstUpdated';\n}\n\nconst UNINITIALIZED = Symbol('uninitialized');\n\nexport class PropertyObserverController<\n T extends ReactiveElement\n> implements ReactiveController {\n private oldVal: T[keyof T] = UNINITIALIZED as T[keyof T];\n\n constructor(\n private host: T,\n private options: PropertyObserverOptions<T>\n ) {\n }\n\n #neverRan = true;\n\n hostConnected(): void {\n this.#init();\n }\n\n /**\n * Because of how typescript transpiles private fields,\n * the __accessPrivate helper might not be entirely initialized\n * by the time this constructor runs (in `addInitializer`'s instance callback')\n * Therefore, we pull this shtick.\n *\n * When browser support improves to the point we can ship decorated private fields,\n * we'll be able to get rid of this.\n */\n #init() {\n if (this.oldVal === UNINITIALIZED) {\n this.oldVal = this.host[this.options.propertyName];\n }\n }\n\n /** Set any cached valued accumulated between constructor and connectedCallback */\n async hostUpdate(): Promise<void> {\n this.#init();\n const { oldVal, options: { waitFor, propertyName, callback } } = this;\n if (!callback) {\n throw new Error(`no callback for ${propertyName}`);\n }\n const newVal = this.host[propertyName];\n this.oldVal = newVal;\n if (newVal !== oldVal) {\n switch (waitFor) {\n case 'connected':\n if (!this.host.isConnected) {\n const origConnected = this.host.connectedCallback;\n await new Promise<void>(resolve => {\n this.host.connectedCallback = function() {\n resolve(origConnected?.call(this));\n };\n });\n }\n break;\n case 'firstUpdated':\n if (!this.host.hasUpdated) {\n await this.host.updateComplete;\n }\n break;\n case 'updated':\n await this.host.updateComplete;\n break;\n }\n }\n const Class = (this.host.constructor as typeof ReactiveElement);\n const hasChanged = Class\n .getPropertyOptions(this.options.propertyName)\n .hasChanged ?? notEqual;\n if (this.#neverRan || hasChanged(oldVal, newVal)) {\n callback.call(this.host, oldVal as T[keyof T], newVal);\n this.#neverRan = false;\n }\n }\n}\n"]}
@@ -1,73 +1,24 @@
1
- import type { ReactiveController, ReactiveControllerHost } from 'lit';
2
- export interface RovingTabindexControllerOptions<Item extends HTMLElement> {
3
- /** @deprecated use getHTMLElement */
4
- getElement?: () => Element | null;
5
- getHTMLElement?: () => HTMLElement | null;
6
- getItems?: () => Item[];
7
- getItemContainer?: () => HTMLElement;
8
- }
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>;
9
4
  /**
10
5
  * Implements roving tabindex, as described in WAI-ARIA practices, [Managing Focus Within
11
6
  * Components Using a Roving tabindex][rti]
12
7
  *
13
8
  * [rti]: https://www.w3.org/WAI/ARIA/apg/practices/keyboard-interface/#kbd_roving_tabindex
14
9
  */
15
- export declare class RovingTabindexController<Item extends HTMLElement = HTMLElement> implements ReactiveController {
10
+ export declare class RovingTabindexController<Item extends HTMLElement = HTMLElement> extends ATFocusController<Item> {
16
11
  #private;
17
12
  host: ReactiveControllerHost;
18
- private static hosts;
19
- static of<Item extends HTMLElement>(host: ReactiveControllerHost, options: RovingTabindexControllerOptions<Item> & {
20
- getItems(): Item[];
21
- }): RovingTabindexController<Item>;
22
- /** @internal */
23
- static elements: WeakMap<Element, RovingTabindexController<HTMLElement>>;
24
- /**
25
- * active item of array of items
26
- */
27
- get activeItem(): Item | undefined;
13
+ static of<Item extends HTMLElement>(host: ReactiveControllerHost, options: RovingTabindexControllerOptions<Item>): RovingTabindexController<Item>;
14
+ get atFocusedItemIndex(): number;
28
15
  /**
29
- * all items from array
16
+ * Sets the DOM Focus on the item with assistive technology focus
17
+ * @param item item
30
18
  */
19
+ set atFocusedItemIndex(index: number);
31
20
  get items(): Item[];
32
- /**
33
- * all focusable items from array
34
- */
35
- get focusableItems(): Item[];
36
- /**
37
- * first item in array of focusable items
38
- */
39
- get firstItem(): Item | undefined;
40
- /**
41
- * last item in array of focusable items
42
- */
43
- get lastItem(): Item | undefined;
44
- /**
45
- * next item after active item in array of focusable items
46
- */
47
- get nextItem(): Item | undefined;
48
- /**
49
- * previous item after active item in array of focusable items
50
- */
51
- get prevItem(): Item | undefined;
52
- constructor(host: ReactiveControllerHost, options?: RovingTabindexControllerOptions<Item>);
53
- hostUpdated(): void;
54
- /**
55
- * removes event listeners from items container
56
- */
57
- hostDisconnected(): void;
58
- /**
59
- * Sets the active item and focuses it
60
- */
61
- setActiveItem(item?: Item): void;
62
- /**
63
- * Focuses next focusable item
64
- */
65
- updateItems(items?: Item[]): void;
66
- /** @deprecated use setActiveItem */
67
- focusOnItem(item?: Item): void;
68
- /**
69
- * from array of HTML items, and sets active items
70
- * @deprecated: use getItems and getItemContainer option functions
71
- */
72
- initItems(items: Item[], itemsContainer?: Element): void;
21
+ set items(items: Item[]);
22
+ private constructor();
23
+ protected onKeydown(event: KeyboardEvent): void;
73
24
  }
@@ -1,228 +1,82 @@
1
- var _RovingTabindexController_instances, _a, _RovingTabindexController_activeItem, _RovingTabindexController_itemsContainer, _RovingTabindexController_items, _RovingTabindexController_gainedInitialFocus, _RovingTabindexController_focusableItems_get, _RovingTabindexController_activeIndex_get, _RovingTabindexController_itemIndex_get, _RovingTabindexController_options, _RovingTabindexController_initContainer, _RovingTabindexController_onKeydown;
2
- import { __classPrivateFieldGet, __classPrivateFieldSet } from "tslib";
3
- const isFocusableElement = (el) => !!el &&
4
- !el.ariaHidden &&
5
- !el.hasAttribute('hidden');
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';
6
7
  /**
7
8
  * Implements roving tabindex, as described in WAI-ARIA practices, [Managing Focus Within
8
9
  * Components Using a Roving tabindex][rti]
9
10
  *
10
11
  * [rti]: https://www.w3.org/WAI/ARIA/apg/practices/keyboard-interface/#kbd_roving_tabindex
11
12
  */
12
- export class RovingTabindexController {
13
+ export class RovingTabindexController extends ATFocusController {
13
14
  static of(host, options) {
14
- return new _a(host, options);
15
+ return new RovingTabindexController(host, options);
15
16
  }
16
- /**
17
- * active item of array of items
18
- */
19
- get activeItem() {
20
- return __classPrivateFieldGet(this, _RovingTabindexController_activeItem, "f");
21
- }
22
- /**
23
- * all items from array
24
- */
25
- get items() {
26
- return __classPrivateFieldGet(this, _RovingTabindexController_items, "f");
17
+ get atFocusedItemIndex() {
18
+ return super.atFocusedItemIndex;
27
19
  }
28
20
  /**
29
- * all focusable items from array
21
+ * Sets the DOM Focus on the item with assistive technology focus
22
+ * @param item item
30
23
  */
31
- get focusableItems() {
32
- return __classPrivateFieldGet(this, _RovingTabindexController_instances, "a", _RovingTabindexController_focusableItems_get);
33
- }
34
- /**
35
- * first item in array of focusable items
36
- */
37
- get firstItem() {
38
- return __classPrivateFieldGet(this, _RovingTabindexController_instances, "a", _RovingTabindexController_focusableItems_get)[0];
39
- }
40
- /**
41
- * last item in array of focusable items
42
- */
43
- get lastItem() {
44
- return __classPrivateFieldGet(this, _RovingTabindexController_instances, "a", _RovingTabindexController_focusableItems_get).at(-1);
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();
45
34
  }
46
- /**
47
- * next item after active item in array of focusable items
48
- */
49
- get nextItem() {
50
- return (__classPrivateFieldGet(this, _RovingTabindexController_instances, "a", _RovingTabindexController_activeIndex_get) >= __classPrivateFieldGet(this, _RovingTabindexController_instances, "a", _RovingTabindexController_focusableItems_get).length - 1 ? this.firstItem
51
- : __classPrivateFieldGet(this, _RovingTabindexController_instances, "a", _RovingTabindexController_focusableItems_get)[__classPrivateFieldGet(this, _RovingTabindexController_instances, "a", _RovingTabindexController_activeIndex_get) + 1]);
35
+ get items() {
36
+ return this._items;
52
37
  }
53
- /**
54
- * previous item after active item in array of focusable items
55
- */
56
- get prevItem() {
57
- 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]
58
- : this.lastItem);
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();
59
50
  }
60
51
  constructor(host, options) {
61
- _RovingTabindexController_instances.add(this);
52
+ super(host, options);
62
53
  this.host = host;
63
- /** active focusable element */
64
- _RovingTabindexController_activeItem.set(this, void 0);
65
- /** closest ancestor containing items */
66
- _RovingTabindexController_itemsContainer.set(this, void 0);
67
- /** array of all focusable elements */
68
- _RovingTabindexController_items.set(this, []);
69
- /** flags whether the host's element has gained focus at least once */
54
+ _RovingTabindexController_logger.set(this, new Logger(this.host));
70
55
  _RovingTabindexController_gainedInitialFocus.set(this, false);
71
- _RovingTabindexController_options.set(this, void 0);
72
- /**
73
- * handles keyboard navigation
74
- */
75
- _RovingTabindexController_onKeydown.set(this, (event) => {
76
- if (!(event instanceof KeyboardEvent) ||
77
- event.ctrlKey ||
78
- event.altKey ||
79
- event.metaKey ||
80
- !__classPrivateFieldGet(this, _RovingTabindexController_instances, "a", _RovingTabindexController_focusableItems_get).length ||
81
- !event.composedPath().some(x => __classPrivateFieldGet(this, _RovingTabindexController_instances, "a", _RovingTabindexController_focusableItems_get).includes(x))) {
82
- return;
83
- }
84
- const orientation = __classPrivateFieldGet(this, _RovingTabindexController_options, "f").getHTMLElement()?.getAttribute('aria-orientation');
85
- const item = this.activeItem;
86
- let shouldPreventDefault = false;
87
- const horizontalOnly = !item ? false
88
- : item.tagName === 'SELECT' ||
89
- item.getAttribute('role') === 'spinbutton' || orientation === 'horizontal';
90
- const verticalOnly = orientation === 'vertical';
91
- switch (event.key) {
92
- case 'ArrowLeft':
93
- if (verticalOnly) {
94
- return;
95
- }
96
- this.setActiveItem(this.prevItem);
97
- shouldPreventDefault = true;
98
- break;
99
- case 'ArrowRight':
100
- if (verticalOnly) {
101
- return;
102
- }
103
- this.setActiveItem(this.nextItem);
104
- shouldPreventDefault = true;
105
- break;
106
- case 'ArrowUp':
107
- if (horizontalOnly) {
108
- return;
109
- }
110
- this.setActiveItem(this.prevItem);
111
- shouldPreventDefault = true;
112
- break;
113
- case 'ArrowDown':
114
- if (horizontalOnly) {
115
- return;
116
- }
117
- this.setActiveItem(this.nextItem);
118
- shouldPreventDefault = true;
119
- break;
120
- case 'Home':
121
- this.setActiveItem(this.firstItem);
122
- shouldPreventDefault = true;
123
- break;
124
- case 'End':
125
- this.setActiveItem(this.lastItem);
126
- shouldPreventDefault = true;
127
- break;
128
- default:
129
- break;
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 });
130
62
  }
131
- if (shouldPreventDefault) {
132
- event.stopPropagation();
133
- event.preventDefault();
63
+ else {
64
+ __classPrivateFieldGet(this, _RovingTabindexController_logger, "f").warn('RovingTabindexController requires a getItemsContainer function');
134
65
  }
135
- });
136
- __classPrivateFieldSet(this, _RovingTabindexController_options, {
137
- getHTMLElement: options?.getHTMLElement ??
138
- options?.getElement ??
139
- (() => host instanceof HTMLElement ? host : null),
140
- getItems: options?.getItems,
141
- getItemContainer: options?.getItemContainer,
142
- }, "f");
143
- const instance = _a.hosts.get(host);
144
- if (instance) {
145
- return instance;
146
- }
147
- _a.hosts.set(host, this);
148
- this.host.addController(this);
149
- this.updateItems();
150
- }
151
- hostUpdated() {
152
- const oldContainer = __classPrivateFieldGet(this, _RovingTabindexController_itemsContainer, "f");
153
- const newContainer = __classPrivateFieldGet(this, _RovingTabindexController_options, "f").getHTMLElement();
154
- if (oldContainer !== newContainer) {
155
- oldContainer?.removeEventListener('keydown', __classPrivateFieldGet(this, _RovingTabindexController_onKeydown, "f"));
156
- _a.elements.delete(oldContainer);
157
- this.updateItems();
158
- }
159
- if (newContainer) {
160
- __classPrivateFieldGet(this, _RovingTabindexController_instances, "m", _RovingTabindexController_initContainer).call(this, newContainer);
161
66
  }
162
67
  }
163
- /**
164
- * removes event listeners from items container
165
- */
166
- hostDisconnected() {
167
- __classPrivateFieldGet(this, _RovingTabindexController_itemsContainer, "f")?.removeEventListener('keydown', __classPrivateFieldGet(this, _RovingTabindexController_onKeydown, "f"));
168
- __classPrivateFieldSet(this, _RovingTabindexController_itemsContainer, undefined, "f");
169
- __classPrivateFieldSet(this, _RovingTabindexController_gainedInitialFocus, false, "f");
170
- }
171
- /**
172
- * Sets the active item and focuses it
173
- */
174
- setActiveItem(item) {
175
- __classPrivateFieldSet(this, _RovingTabindexController_activeItem, item, "f");
176
- for (const item of __classPrivateFieldGet(this, _RovingTabindexController_instances, "a", _RovingTabindexController_focusableItems_get)) {
177
- item.tabIndex = __classPrivateFieldGet(this, _RovingTabindexController_activeItem, "f") === item ? 0 : -1;
178
- }
179
- this.host.requestUpdate();
180
- if (__classPrivateFieldGet(this, _RovingTabindexController_gainedInitialFocus, "f")) {
181
- __classPrivateFieldGet(this, _RovingTabindexController_activeItem, "f")?.focus();
182
- }
183
- }
184
- /**
185
- * Focuses next focusable item
186
- */
187
- updateItems(items = __classPrivateFieldGet(this, _RovingTabindexController_options, "f").getItems?.() ?? []) {
188
- __classPrivateFieldSet(this, _RovingTabindexController_items, items, "f");
189
- const sequence = [...__classPrivateFieldGet(this, _RovingTabindexController_items, "f").slice(__classPrivateFieldGet(this, _RovingTabindexController_instances, "a", _RovingTabindexController_itemIndex_get) - 1), ...__classPrivateFieldGet(this, _RovingTabindexController_items, "f").slice(0, __classPrivateFieldGet(this, _RovingTabindexController_instances, "a", _RovingTabindexController_itemIndex_get) - 1)];
190
- const first = sequence.find(item => __classPrivateFieldGet(this, _RovingTabindexController_instances, "a", _RovingTabindexController_focusableItems_get).includes(item));
191
- const [focusableItem] = __classPrivateFieldGet(this, _RovingTabindexController_instances, "a", _RovingTabindexController_focusableItems_get);
192
- const activeItem = focusableItem ?? first ?? this.firstItem;
193
- this.setActiveItem(activeItem);
194
- }
195
- /** @deprecated use setActiveItem */
196
- focusOnItem(item) {
197
- this.setActiveItem(item);
198
- }
199
- /**
200
- * from array of HTML items, and sets active items
201
- * @deprecated: use getItems and getItemContainer option functions
202
- */
203
- initItems(items, itemsContainer) {
204
- const element = itemsContainer ?? __classPrivateFieldGet(this, _RovingTabindexController_options, "f")?.getItemContainer?.() ?? __classPrivateFieldGet(this, _RovingTabindexController_options, "f").getHTMLElement();
205
- if (element) {
206
- __classPrivateFieldGet(this, _RovingTabindexController_instances, "m", _RovingTabindexController_initContainer).call(this, element);
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);
207
75
  }
208
- this.updateItems(items);
209
76
  }
210
77
  }
211
- _a = RovingTabindexController, _RovingTabindexController_activeItem = new WeakMap(), _RovingTabindexController_itemsContainer = new WeakMap(), _RovingTabindexController_items = new WeakMap(), _RovingTabindexController_gainedInitialFocus = new WeakMap(), _RovingTabindexController_options = new WeakMap(), _RovingTabindexController_onKeydown = new WeakMap(), _RovingTabindexController_instances = new WeakSet(), _RovingTabindexController_focusableItems_get = function _RovingTabindexController_focusableItems_get() {
212
- return __classPrivateFieldGet(this, _RovingTabindexController_items, "f").filter(isFocusableElement);
213
- }, _RovingTabindexController_activeIndex_get = function _RovingTabindexController_activeIndex_get() {
214
- return !!__classPrivateFieldGet(this, _RovingTabindexController_instances, "a", _RovingTabindexController_focusableItems_get) && !!this.activeItem ? __classPrivateFieldGet(this, _RovingTabindexController_instances, "a", _RovingTabindexController_focusableItems_get).indexOf(this.activeItem) : -1;
215
- }, _RovingTabindexController_itemIndex_get = function _RovingTabindexController_itemIndex_get() {
216
- return this.activeItem ? __classPrivateFieldGet(this, _RovingTabindexController_items, "f").indexOf(this.activeItem) : -1;
217
- }, _RovingTabindexController_initContainer = function _RovingTabindexController_initContainer(container) {
218
- _a.elements.set(container, this);
219
- __classPrivateFieldSet(this, _RovingTabindexController_itemsContainer, container, "f");
220
- __classPrivateFieldGet(this, _RovingTabindexController_itemsContainer, "f").addEventListener('keydown', __classPrivateFieldGet(this, _RovingTabindexController_onKeydown, "f"));
221
- __classPrivateFieldGet(this, _RovingTabindexController_itemsContainer, "f").addEventListener('focusin', () => {
222
- __classPrivateFieldSet(this, _RovingTabindexController_gainedInitialFocus, true, "f");
223
- }, { once: true });
224
- };
225
- RovingTabindexController.hosts = new WeakMap();
226
- /** @internal */
227
- RovingTabindexController.elements = new WeakMap();
78
+ _RovingTabindexController_logger = new WeakMap(), _RovingTabindexController_gainedInitialFocus = new WeakMap(), _RovingTabindexController_itemsSet = new WeakMap();
79
+ __decorate([
80
+ bound
81
+ ], RovingTabindexController.prototype, "onKeydown", null);
228
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';\nimport type { RequireProps } from '../core.js';\n\nconst isFocusableElement = (el: Element): el is HTMLElement =>\n !!el &&\n !el.ariaHidden &&\n !el.hasAttribute('hidden');\n\nexport interface RovingTabindexControllerOptions<Item extends HTMLElement> {\n /** @deprecated use getHTMLElement */\n getElement?: () => Element | null;\n getHTMLElement?: () => HTMLElement | null;\n getItems?: () => Item[];\n getItemContainer?: () => HTMLElement;\n}\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> implements ReactiveController {\n private static hosts = new WeakMap<ReactiveControllerHost, RovingTabindexController>();\n\n static of<Item extends HTMLElement>(\n host: ReactiveControllerHost,\n options: RovingTabindexControllerOptions<Item> & { getItems(): Item[] },\n ) {\n return new RovingTabindexController(host, options);\n }\n\n /** @internal */\n static elements = new WeakMap<Element, RovingTabindexController>();\n\n /** active focusable element */\n #activeItem?: Item;\n\n /** closest ancestor containing items */\n #itemsContainer?: Element;\n\n /** array of all focusable elements */\n #items: Item[] = [];\n\n /** flags whether the host's element has gained focus at least once */\n #gainedInitialFocus = false;\n\n /**\n * finds focusable items from a group of items\n */\n get #focusableItems(): Item[] {\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(): Item | undefined {\n return this.#activeItem;\n }\n\n /**\n * all items from array\n */\n get items() {\n return this.#items;\n }\n\n /**\n * all focusable items from array\n */\n get focusableItems() {\n return this.#focusableItems;\n }\n\n /**\n * first item in array of focusable items\n */\n get firstItem(): Item | undefined {\n return this.#focusableItems[0];\n }\n\n /**\n * last item in array of focusable items\n */\n get lastItem(): Item | 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(): Item | 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(): Item | undefined {\n return (\n this.#activeIndex > 0 ? this.#focusableItems[this.#activeIndex - 1]\n : this.lastItem\n );\n }\n\n #options: RequireProps<RovingTabindexControllerOptions<Item>, 'getHTMLElement'>;\n\n constructor(\n public host: ReactiveControllerHost,\n options?: RovingTabindexControllerOptions<Item>,\n ) {\n this.#options = {\n getHTMLElement: options?.getHTMLElement ??\n (options?.getElement as (() => HTMLElement | null)) ??\n (() => host instanceof HTMLElement ? host : null),\n getItems: options?.getItems,\n getItemContainer: options?.getItemContainer,\n };\n const instance = RovingTabindexController.hosts.get(host);\n if (instance) {\n return instance as RovingTabindexController<Item>;\n }\n RovingTabindexController.hosts.set(host, this);\n this.host.addController(this);\n this.updateItems();\n }\n\n hostUpdated() {\n const oldContainer = this.#itemsContainer;\n const newContainer = this.#options.getHTMLElement();\n if (oldContainer !== newContainer) {\n oldContainer?.removeEventListener('keydown', this.#onKeydown);\n RovingTabindexController.elements.delete(oldContainer!);\n this.updateItems();\n }\n if (newContainer) {\n this.#initContainer(newContainer);\n }\n }\n\n /**\n * removes event listeners from items container\n */\n hostDisconnected() {\n this.#itemsContainer?.removeEventListener('keydown', this.#onKeydown);\n this.#itemsContainer = undefined;\n this.#gainedInitialFocus = false;\n }\n\n #initContainer(container: Element) {\n RovingTabindexController.elements.set(container, this);\n this.#itemsContainer = container;\n this.#itemsContainer.addEventListener('keydown', this.#onKeydown);\n this.#itemsContainer.addEventListener('focusin', () => {\n this.#gainedInitialFocus = true;\n }, { once: true });\n }\n\n /**\n * handles keyboard navigation\n */\n #onKeydown = (event: Event) => {\n if (!(event instanceof KeyboardEvent) ||\n event.ctrlKey ||\n event.altKey ||\n event.metaKey ||\n !this.#focusableItems.length ||\n !event.composedPath().some(x =>\n this.#focusableItems.includes(x as Item))) {\n return;\n }\n\n const orientation = this.#options.getHTMLElement()?.getAttribute('aria-orientation');\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' || orientation === 'horizontal';\n const verticalOnly = orientation === 'vertical';\n switch (event.key) {\n case 'ArrowLeft':\n if (verticalOnly) {\n return;\n }\n this.setActiveItem(this.prevItem);\n shouldPreventDefault = true;\n break;\n case 'ArrowRight':\n if (verticalOnly) {\n return;\n }\n\n this.setActiveItem(this.nextItem);\n shouldPreventDefault = true;\n break;\n case 'ArrowUp':\n if (horizontalOnly) {\n return;\n }\n this.setActiveItem(this.prevItem);\n shouldPreventDefault = true;\n break;\n case 'ArrowDown':\n if (horizontalOnly) {\n return;\n }\n this.setActiveItem(this.nextItem);\n shouldPreventDefault = true;\n break;\n case 'Home':\n this.setActiveItem(this.firstItem);\n shouldPreventDefault = true;\n break;\n case 'End':\n this.setActiveItem(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 the active item and focuses it\n */\n setActiveItem(item?: Item): void {\n this.#activeItem = item;\n for (const item of this.#focusableItems) {\n item.tabIndex = this.#activeItem === item ? 0 : -1;\n }\n this.host.requestUpdate();\n if (this.#gainedInitialFocus) {\n this.#activeItem?.focus();\n }\n }\n\n /**\n * Focuses next focusable item\n */\n updateItems(items: Item[] = this.#options.getItems?.() ?? []) {\n this.#items = items;\n const sequence = [...this.#items.slice(this.#itemIndex - 1), ...this.#items.slice(0, this.#itemIndex - 1)];\n const first = sequence.find(item => this.#focusableItems.includes(item));\n const [focusableItem] = this.#focusableItems;\n const activeItem = focusableItem ?? first ?? this.firstItem;\n this.setActiveItem(activeItem);\n }\n\n /** @deprecated use setActiveItem */\n focusOnItem(item?: Item): void {\n this.setActiveItem(item);\n }\n\n /**\n * from array of HTML items, and sets active items\n * @deprecated: use getItems and getItemContainer option functions\n */\n initItems(items: Item[], itemsContainer?: Element) {\n const element = itemsContainer ?? this.#options?.getItemContainer?.() ?? this.#options.getHTMLElement();\n if (element) {\n this.#initContainer(element);\n }\n this.updateItems(items);\n }\n}\n"]}
1
+ {"version":3,"file":"roving-tabindex-controller.js","sourceRoot":"","sources":["roving-tabindex-controller.ts"],"names":[],"mappings":";;AAAA,OAAO,EAAE,QAAQ,EAA+B,MAAM,KAAK,CAAC;AAC5D,OAAO,EAAE,iBAAiB,EAAiC,MAAM,0BAA0B,CAAC;AAC5F,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,KAAK,EAAE,MAAM,wBAAwB,CAAC;AAK/C;;;;;GAKG;AACH,MAAM,OAAO,wBAEX,SAAQ,iBAAuB;IAC/B,MAAM,CAAC,EAAE,CACP,IAA4B,EAC5B,OAA8C;QAE9C,OAAO,IAAI,wBAAwB,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IACrD,CAAC;IAQD,IAAI,kBAAkB;QACpB,OAAO,KAAK,CAAC,kBAAkB,CAAC;IAClC,CAAC;IAED;;;OAGG;IACH,IAAI,kBAAkB,CAAC,KAAa;QAClC,KAAK,CAAC,kBAAkB,GAAG,KAAK,CAAC;QACjC,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC;QACpD,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YAC3B,CAAC,CAAC,QAAQ,GAAG,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACnC,CAAC;QACD,IAAI,uBAAA,IAAI,oDAAoB,EAAE,CAAC;YAC7B,IAAI,EAAE,KAAK,EAAE,CAAC;QAChB,CAAC;QACD,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,CAAC;IAC5B,CAAC;IAED,IAAI,KAAK;QACP,OAAO,IAAI,CAAC,MAAM,CAAC;IACrB,CAAC;IAED,IAAW,KAAK,CAAC,KAAa;QAC5B,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC;QACpB,uBAAA,IAAI,sCAAa,IAAI,GAAG,CAAC,KAAK,CAAC,MAAA,CAAC;QAChC,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,kBAAkB,CAAC,CAAC;QACnD,MAAM,CAAC,cAAc,CAAC,GAAG,IAAI,CAAC,gBAAgB,CAAC;QAC/C,MAAM,mBAAmB,GAAG,cAAc,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAChF,MAAM,mBAAmB,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK;aAC/C,KAAK,CAAC,KAAK,CAAC;aACZ,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;aAClC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,gBAAgB,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAE,CAAC,CAAC;QAC1D,IAAI,CAAC,kBAAkB,GAAG,IAAI,CAAC,GAAG,CAAC,mBAAmB,EAAE,mBAAmB,CAAC,CAAC;QAC7E,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,CAAC;IAC5B,CAAC;IAED,YACS,IAA4B,EACnC,OAA8C;QAE9C,KAAK,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QAHd,SAAI,GAAJ,IAAI,CAAwB;QA7CrC,2CAAU,IAAI,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,EAAC;QAEhC,uDAAsB,KAAK,EAAC;QAE5B,6CAAY,IAAI,GAAG,EAAQ,EAAC;QA6C1B,IAAI,CAAC,SAAS,EAAE,CAAC;QACjB,MAAM,SAAS,GAAG,OAAO,CAAC,iBAAiB,EAAE,EAAE,IAAI,IAAI,CAAC,IAAI,CAAC;QAC7D,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,IAAI,SAAS,YAAY,WAAW,EAAE,CAAC;gBACrC,SAAS,CAAC,gBAAgB,CAAC,SAAS,EAAE,GAAG,EAAE,CACzC,uBAAA,IAAI,gDAAuB,IAAI,MAAA,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;YACrD,CAAC;iBAAM,CAAC;gBACN,uBAAA,IAAI,wCAAQ,CAAC,IAAI,CAAC,gEAAgE,CAAC,CAAC;YACtF,CAAC;QACH,CAAC;IACH,CAAC;IAGkB,SAAS,CAAC,KAAoB;QAC/C,IAAI,CAAC,KAAK,CAAC,OAAO;eACX,CAAC,KAAK,CAAC,MAAM;eACb,CAAC,KAAK,CAAC,OAAO;eACd,CAAC,CAAC,IAAI,CAAC,gBAAgB,CAAC,MAAM;eAC9B,CAAC,CAAC,KAAK,CAAC,YAAY,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,uBAAA,IAAI,0CAAU,CAAC,GAAG,CAAC,IAAY,CAAC,CAAC,EAAE,CAAC;YAC7E,KAAK,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;QACzB,CAAC;IACH,CAAC;CACF;;AAToB;IADlB,KAAK;yDASL","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
- /** Explicitly set the active item */
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,4 +1,4 @@
1
- var _ScrollSpyController_instances, _ScrollSpyController_tagNames, _ScrollSpyController_activeAttribute, _ScrollSpyController_io, _ScrollSpyController_passedLinks, _ScrollSpyController_force, _ScrollSpyController_intersected, _ScrollSpyController_root, _ScrollSpyController_rootMargin, _ScrollSpyController_threshold, _ScrollSpyController_rootNode, _ScrollSpyController_getHash, _ScrollSpyController_linkChildren_get, _ScrollSpyController_initIo, _ScrollSpyController_markPassed, _ScrollSpyController_setActive, _ScrollSpyController_nextIntersection, _ScrollSpyController_onIo;
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
2
  import { __classPrivateFieldGet, __classPrivateFieldSet } from "tslib";
3
3
  export class ScrollSpyController {
4
4
  get root() {
@@ -40,7 +40,7 @@ export class ScrollSpyController {
40
40
  _ScrollSpyController_root.set(this, void 0);
41
41
  _ScrollSpyController_rootMargin.set(this, void 0);
42
42
  _ScrollSpyController_threshold.set(this, void 0);
43
- _ScrollSpyController_rootNode.set(this, void 0);
43
+ _ScrollSpyController_getRootNode.set(this, void 0);
44
44
  _ScrollSpyController_getHash.set(this, void 0);
45
45
  host.addController(this);
46
46
  __classPrivateFieldSet(this, _ScrollSpyController_tagNames, options.tagNames, "f");
@@ -48,13 +48,16 @@ export class ScrollSpyController {
48
48
  __classPrivateFieldSet(this, _ScrollSpyController_rootMargin, options.rootMargin, "f");
49
49
  __classPrivateFieldSet(this, _ScrollSpyController_activeAttribute, options.activeAttribute ?? 'active', "f");
50
50
  __classPrivateFieldSet(this, _ScrollSpyController_threshold, options.threshold ?? 0.85, "f");
51
- __classPrivateFieldSet(this, _ScrollSpyController_rootNode, options.rootNode ?? host.getRootNode(), "f");
51
+ __classPrivateFieldSet(this, _ScrollSpyController_getRootNode, () => options.rootNode ?? host.getRootNode(), "f");
52
52
  __classPrivateFieldSet(this, _ScrollSpyController_getHash, options?.getHash ?? ((el) => el.getAttribute('href')), "f");
53
53
  }
54
54
  hostConnected() {
55
55
  __classPrivateFieldGet(this, _ScrollSpyController_instances, "m", _ScrollSpyController_initIo).call(this);
56
56
  }
57
- /** Explicitly set the active item */
57
+ /**
58
+ * Explicitly set the active item
59
+ * @param link usually an `<a>`
60
+ */
58
61
  async setActive(link) {
59
62
  __classPrivateFieldSet(this, _ScrollSpyController_force, true, "f");
60
63
  __classPrivateFieldGet(this, _ScrollSpyController_instances, "m", _ScrollSpyController_setActive).call(this, link);
@@ -69,11 +72,11 @@ export class ScrollSpyController {
69
72
  __classPrivateFieldSet(this, _ScrollSpyController_force, false, "f");
70
73
  }
71
74
  }
72
- _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_rootNode = new WeakMap(), _ScrollSpyController_getHash = new WeakMap(), _ScrollSpyController_instances = new WeakSet(), _ScrollSpyController_linkChildren_get = function _ScrollSpyController_linkChildren_get() {
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() {
73
76
  return Array.from(this.host.querySelectorAll(__classPrivateFieldGet(this, _ScrollSpyController_tagNames, "f").join(',')))
74
77
  .filter(__classPrivateFieldGet(this, _ScrollSpyController_getHash, "f"));
75
78
  }, _ScrollSpyController_initIo = function _ScrollSpyController_initIo() {
76
- const rootNode = __classPrivateFieldGet(this, _ScrollSpyController_rootNode, "f");
79
+ const rootNode = __classPrivateFieldGet(this, _ScrollSpyController_getRootNode, "f").call(this);
77
80
  if (rootNode instanceof Document || rootNode instanceof ShadowRoot) {
78
81
  const { rootMargin, threshold, root } = this;
79
82
  __classPrivateFieldSet(this, _ScrollSpyController_io, new IntersectionObserver(r => __classPrivateFieldGet(this, _ScrollSpyController_instances, "m", _ScrollSpyController_onIo).call(this, r), { root, rootMargin, threshold }), "f");
@@ -1 +1 @@
1
- {"version":3,"file":"scroll-spy-controller.js","sourceRoot":"","sources":["scroll-spy-controller.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ReactiveController, ReactiveControllerHost } from 'lit';\n\nexport interface ScrollSpyControllerOptions extends IntersectionObserverInit {\n /**\n * Tag names of legal link children.\n * Legal children must have an `href` property/attribute pair, like `<a>`.\n */\n tagNames: string[];\n\n /**\n * Attribute to set on the active link element.\n * @default 'active'\n */\n activeAttribute?: string;\n\n /**\n * The root node to query content for\n * @default the host's root node\n */\n rootNode?: Node;\n /**\n * function to call on link children to get their URL hash (i.e. id to scroll to)\n * @default el => el.getAttribute('href');\n */\n getHash?: (el: Element) => string | null;\n}\n\nexport class ScrollSpyController implements ReactiveController {\n #tagNames: string[];\n #activeAttribute: string;\n\n #io?: IntersectionObserver;\n\n /** Which link's targets have already scrolled past? */\n #passedLinks = new Set<Element>();\n\n /** Ignore intersections? */\n #force = false;\n\n /** Has the intersection observer found an element? */\n #intersected = false;\n\n #root: ScrollSpyControllerOptions['root'];\n #rootMargin?: string;\n #threshold: number | number[];\n\n #rootNode: Node;\n #getHash: (el: Element) => string | null;\n\n get #linkChildren(): Element[] {\n return Array.from(this.host.querySelectorAll(this.#tagNames.join(',')))\n .filter(this.#getHash);\n }\n\n get root() {\n return this.#root;\n }\n\n set root(v) {\n this.#root = v;\n this.#io?.disconnect();\n this.#initIo();\n }\n\n get rootMargin() {\n return this.#rootMargin;\n }\n\n set rootMargin(v) {\n this.#rootMargin = v;\n this.#io?.disconnect();\n this.#initIo();\n }\n\n get threshold() {\n return this.#threshold;\n }\n\n set threshold(v) {\n this.#threshold = v;\n this.#io?.disconnect();\n this.#initIo();\n }\n\n constructor(\n private host: ReactiveControllerHost & HTMLElement,\n options: ScrollSpyControllerOptions,\n ) {\n host.addController(this);\n this.#tagNames = options.tagNames;\n this.#root = options.root;\n this.#rootMargin = options.rootMargin;\n this.#activeAttribute = options.activeAttribute ?? 'active';\n this.#threshold = options.threshold ?? 0.85;\n this.#rootNode = options.rootNode ?? host.getRootNode();\n this.#getHash = options?.getHash ?? ((el: Element) => el.getAttribute('href'));\n }\n\n hostConnected() {\n this.#initIo();\n }\n\n #initIo() {\n const rootNode = this.#rootNode;\n if (rootNode instanceof Document || rootNode instanceof ShadowRoot) {\n const { rootMargin, threshold, root } = this;\n this.#io = new IntersectionObserver(r => this.#onIo(r), { root, rootMargin, threshold });\n this.#linkChildren\n .map(x => this.#getHash(x))\n .filter((x): x is string => !!x)\n .map(x => rootNode.getElementById(x.replace('#', '')))\n .filter((x): x is HTMLElement => !!x)\n .forEach(target => this.#io?.observe(target));\n }\n }\n\n #markPassed(link: Element, force: boolean) {\n if (force) {\n this.#passedLinks.add(link);\n } else {\n this.#passedLinks.delete(link);\n }\n }\n\n #setActive(link?: EventTarget | null) {\n for (const child of this.#linkChildren) {\n child.toggleAttribute(this.#activeAttribute, child === link);\n }\n }\n\n async #nextIntersection() {\n this.#intersected = false;\n // safeguard the loop\n setTimeout(() => this.#intersected = false, 3000);\n while (!this.#intersected) {\n await new Promise(requestAnimationFrame);\n }\n }\n\n async #onIo(entries: IntersectionObserverEntry[]) {\n if (!this.#force) {\n for (const { target, boundingClientRect, intersectionRect } of entries) {\n const selector = `:is(${this.#tagNames.join(',')})[href=\"#${target.id}\"]`;\n const link = this.host.querySelector(selector);\n if (link) {\n this.#markPassed(link, boundingClientRect.top < intersectionRect.top);\n }\n }\n const link = [...this.#passedLinks];\n const last = link.at(-1);\n this.#setActive(last ?? this.#linkChildren.at(0));\n }\n this.#intersected = true;\n }\n\n /** Explicitly set the active item */\n public async setActive(link: EventTarget | null) {\n this.#force = true;\n this.#setActive(link);\n let sawActive = false;\n for (const child of this.#linkChildren) {\n this.#markPassed(child, !sawActive);\n if (child === link) {\n sawActive = true;\n }\n }\n await this.#nextIntersection();\n this.#force = false;\n }\n}\n"]}
1
+ {"version":3,"file":"scroll-spy-controller.js","sourceRoot":"","sources":["scroll-spy-controller.ts"],"names":[],"mappings":";;AA2BA,MAAM,OAAO,mBAAmB;IA2B9B,IAAI,IAAI;QACN,OAAO,uBAAA,IAAI,iCAAM,CAAC;IACpB,CAAC;IAED,IAAI,IAAI,CAAC,CAAC;QACR,uBAAA,IAAI,6BAAS,CAAC,MAAA,CAAC;QACf,uBAAA,IAAI,+BAAI,EAAE,UAAU,EAAE,CAAC;QACvB,uBAAA,IAAI,mEAAQ,MAAZ,IAAI,CAAU,CAAC;IACjB,CAAC;IAED,IAAI,UAAU;QACZ,OAAO,uBAAA,IAAI,uCAAY,CAAC;IAC1B,CAAC;IAED,IAAI,UAAU,CAAC,CAAC;QACd,uBAAA,IAAI,mCAAe,CAAC,MAAA,CAAC;QACrB,uBAAA,IAAI,+BAAI,EAAE,UAAU,EAAE,CAAC;QACvB,uBAAA,IAAI,mEAAQ,MAAZ,IAAI,CAAU,CAAC;IACjB,CAAC;IAED,IAAI,SAAS;QACX,OAAO,uBAAA,IAAI,sCAAW,CAAC;IACzB,CAAC;IAED,IAAI,SAAS,CAAC,CAAC;QACb,uBAAA,IAAI,kCAAc,CAAC,MAAA,CAAC;QACpB,uBAAA,IAAI,+BAAI,EAAE,UAAU,EAAE,CAAC;QACvB,uBAAA,IAAI,mEAAQ,MAAZ,IAAI,CAAU,CAAC;IACjB,CAAC;IAED,YACU,IAA0C,EAClD,OAAmC;;QAD3B,SAAI,GAAJ,IAAI,CAAsC;QAzDpD,gDAAoB;QACpB,uDAAyB;QAEzB,0CAA2B;QAE3B,uDAAuD;QACvD,2CAAe,IAAI,GAAG,EAAW,EAAC;QAElC,4BAA4B;QAC5B,qCAAS,KAAK,EAAC;QAEf,sDAAsD;QACtD,2CAAe,KAAK,EAAC;QAErB,4CAA0C;QAC1C,kDAAqB;QACrB,iDAA8B;QAE9B,mDAAyB;QACzB,+CAAyC;QAyCvC,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC;QACzB,uBAAA,IAAI,iCAAa,OAAO,CAAC,QAAQ,MAAA,CAAC;QAClC,uBAAA,IAAI,6BAAS,OAAO,CAAC,IAAI,MAAA,CAAC;QAC1B,uBAAA,IAAI,mCAAe,OAAO,CAAC,UAAU,MAAA,CAAC;QACtC,uBAAA,IAAI,wCAAoB,OAAO,CAAC,eAAe,IAAI,QAAQ,MAAA,CAAC;QAC5D,uBAAA,IAAI,kCAAc,OAAO,CAAC,SAAS,IAAI,IAAI,MAAA,CAAC;QAC5C,uBAAA,IAAI,oCAAgB,GAAG,EAAE,CAAC,OAAO,CAAC,QAAQ,IAAI,IAAI,CAAC,WAAW,EAAE,MAAA,CAAC;QACjE,uBAAA,IAAI,gCAAY,OAAO,EAAE,OAAO,IAAI,CAAC,CAAC,EAAW,EAAE,EAAE,CAAC,EAAE,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC,MAAA,CAAC;IACjF,CAAC;IAED,aAAa;QACX,uBAAA,IAAI,mEAAQ,MAAZ,IAAI,CAAU,CAAC;IACjB,CAAC;IAuDD;;;OAGG;IACI,KAAK,CAAC,SAAS,CAAC,IAAwB;QAC7C,uBAAA,IAAI,8BAAU,IAAI,MAAA,CAAC;QACnB,uBAAA,IAAI,sEAAW,MAAf,IAAI,EAAY,IAAI,CAAC,CAAC;QACtB,IAAI,SAAS,GAAG,KAAK,CAAC;QACtB,KAAK,MAAM,KAAK,IAAI,uBAAA,IAAI,6EAAc,EAAE,CAAC;YACvC,uBAAA,IAAI,uEAAY,MAAhB,IAAI,EAAa,KAAK,EAAE,CAAC,SAAS,CAAC,CAAC;YACpC,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;gBACnB,SAAS,GAAG,IAAI,CAAC;YACnB,CAAC;QACH,CAAC;QACD,MAAM,uBAAA,IAAI,6EAAkB,MAAtB,IAAI,CAAoB,CAAC;QAC/B,uBAAA,IAAI,8BAAU,KAAK,MAAA,CAAC;IACtB,CAAC;CACF;;IA1HG,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,gBAAgB,CAAC,uBAAA,IAAI,qCAAU,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;SAClE,MAAM,CAAC,uBAAA,IAAI,oCAAS,CAAC,CAAC;AAC7B,CAAC;IAmDC,MAAM,QAAQ,GAAG,uBAAA,IAAI,wCAAa,MAAjB,IAAI,CAAe,CAAC;IACrC,IAAI,QAAQ,YAAY,QAAQ,IAAI,QAAQ,YAAY,UAAU,EAAE,CAAC;QACnE,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,IAAI,EAAE,GAAG,IAAI,CAAC;QAC7C,uBAAA,IAAI,2BAAO,IAAI,oBAAoB,CAAC,CAAC,CAAC,EAAE,CAAC,uBAAA,IAAI,iEAAM,MAAV,IAAI,EAAO,CAAC,CAAC,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE,SAAS,EAAE,CAAC,MAAA,CAAC;QACzF,uBAAA,IAAI,6EAAc;aACb,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,uBAAA,IAAI,oCAAS,MAAb,IAAI,EAAU,CAAC,CAAC,CAAC;aAC1B,MAAM,CAAC,CAAC,CAAC,EAAe,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;aAC/B,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,CAAC;aACrD,MAAM,CAAC,CAAC,CAAC,EAAoB,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;aACpC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC,uBAAA,IAAI,+BAAI,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC;IACpD,CAAC;AACH,CAAC,6EAEW,IAAa,EAAE,KAAc;IACvC,IAAI,KAAK,EAAE,CAAC;QACV,uBAAA,IAAI,wCAAa,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAC9B,CAAC;SAAM,CAAC;QACN,uBAAA,IAAI,wCAAa,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IACjC,CAAC;AACH,CAAC,2EAEU,IAAyB;IAClC,KAAK,MAAM,KAAK,IAAI,uBAAA,IAAI,6EAAc,EAAE,CAAC;QACvC,KAAK,CAAC,eAAe,CAAC,uBAAA,IAAI,4CAAiB,EAAE,KAAK,KAAK,IAAI,CAAC,CAAC;IAC/D,CAAC;AACH,CAAC,0CAED,KAAK;IACH,uBAAA,IAAI,oCAAgB,KAAK,MAAA,CAAC;IAC1B,qBAAqB;IACrB,UAAU,CAAC,GAAG,EAAE,CAAC,uBAAA,IAAI,oCAAgB,KAAK,MAAA,EAAE,IAAI,CAAC,CAAC;IAClD,OAAO,CAAC,uBAAA,IAAI,wCAAa,EAAE,CAAC;QAC1B,MAAM,IAAI,OAAO,CAAC,qBAAqB,CAAC,CAAC;IAC3C,CAAC;AACH,CAAC,8BAED,KAAK,oCAAO,OAAoC;IAC9C,IAAI,CAAC,uBAAA,IAAI,kCAAO,EAAE,CAAC;QACjB,KAAK,MAAM,EAAE,MAAM,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,IAAI,OAAO,EAAE,CAAC;YACvE,MAAM,QAAQ,GAAG,OAAO,uBAAA,IAAI,qCAAU,CAAC,IAAI,CAAC,GAAG,CAAC,YAAY,MAAM,CAAC,EAAE,IAAI,CAAC;YAC1E,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC;YAC/C,IAAI,IAAI,EAAE,CAAC;gBACT,uBAAA,IAAI,uEAAY,MAAhB,IAAI,EAAa,IAAI,EAAE,kBAAkB,CAAC,GAAG,GAAG,gBAAgB,CAAC,GAAG,CAAC,CAAC;YACxE,CAAC;QACH,CAAC;QACD,MAAM,IAAI,GAAG,CAAC,GAAG,uBAAA,IAAI,wCAAa,CAAC,CAAC;QACpC,MAAM,IAAI,GAAG,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;QACzB,uBAAA,IAAI,sEAAW,MAAf,IAAI,EAAY,IAAI,IAAI,uBAAA,IAAI,6EAAc,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;IACpD,CAAC;IACD,uBAAA,IAAI,oCAAgB,IAAI,MAAA,CAAC;AAC3B,CAAC","sourcesContent":["import type { ReactiveController, ReactiveControllerHost } from 'lit';\n\nexport interface ScrollSpyControllerOptions extends IntersectionObserverInit {\n /**\n * Tag names of legal link children.\n * Legal children must have an `href` property/attribute pair, like `<a>`.\n */\n tagNames: string[];\n\n /**\n * Attribute to set on the active link element.\n * @default 'active'\n */\n activeAttribute?: string;\n\n /**\n * The root node to query content for\n * @default the host's root node\n */\n rootNode?: Node;\n /**\n * function to call on link children to get their URL hash (i.e. id to scroll to)\n * @default el => el.getAttribute('href');\n */\n getHash?: (el: Element) => string | null;\n}\n\nexport class ScrollSpyController implements ReactiveController {\n #tagNames: string[];\n #activeAttribute: string;\n\n #io?: IntersectionObserver;\n\n /** Which link's targets have already scrolled past? */\n #passedLinks = new Set<Element>();\n\n /** Ignore intersections? */\n #force = false;\n\n /** Has the intersection observer found an element? */\n #intersected = false;\n\n #root: ScrollSpyControllerOptions['root'];\n #rootMargin?: string;\n #threshold: number | number[];\n\n #getRootNode: () => Node;\n #getHash: (el: Element) => string | null;\n\n get #linkChildren(): Element[] {\n return Array.from(this.host.querySelectorAll(this.#tagNames.join(',')))\n .filter(this.#getHash);\n }\n\n get root(): Element | Document | null | undefined {\n return this.#root;\n }\n\n set root(v) {\n this.#root = v;\n this.#io?.disconnect();\n this.#initIo();\n }\n\n get rootMargin(): string | undefined {\n return this.#rootMargin;\n }\n\n set rootMargin(v) {\n this.#rootMargin = v;\n this.#io?.disconnect();\n this.#initIo();\n }\n\n get threshold(): number | number[] {\n return this.#threshold;\n }\n\n set threshold(v) {\n this.#threshold = v;\n this.#io?.disconnect();\n this.#initIo();\n }\n\n constructor(\n private host: ReactiveControllerHost & HTMLElement,\n options: ScrollSpyControllerOptions,\n ) {\n host.addController(this);\n this.#tagNames = options.tagNames;\n this.#root = options.root;\n this.#rootMargin = options.rootMargin;\n this.#activeAttribute = options.activeAttribute ?? 'active';\n this.#threshold = options.threshold ?? 0.85;\n this.#getRootNode = () => options.rootNode ?? host.getRootNode();\n this.#getHash = options?.getHash ?? ((el: Element) => el.getAttribute('href'));\n }\n\n hostConnected(): void {\n this.#initIo();\n }\n\n #initIo() {\n const rootNode = this.#getRootNode();\n if (rootNode instanceof Document || rootNode instanceof ShadowRoot) {\n const { rootMargin, threshold, root } = this;\n this.#io = new IntersectionObserver(r => this.#onIo(r), { root, rootMargin, threshold });\n this.#linkChildren\n .map(x => this.#getHash(x))\n .filter((x): x is string => !!x)\n .map(x => rootNode.getElementById(x.replace('#', '')))\n .filter((x): x is HTMLElement => !!x)\n .forEach(target => this.#io?.observe(target));\n }\n }\n\n #markPassed(link: Element, force: boolean) {\n if (force) {\n this.#passedLinks.add(link);\n } else {\n this.#passedLinks.delete(link);\n }\n }\n\n #setActive(link?: EventTarget | null) {\n for (const child of this.#linkChildren) {\n child.toggleAttribute(this.#activeAttribute, child === link);\n }\n }\n\n async #nextIntersection() {\n this.#intersected = false;\n // safeguard the loop\n setTimeout(() => this.#intersected = false, 3000);\n while (!this.#intersected) {\n await new Promise(requestAnimationFrame);\n }\n }\n\n async #onIo(entries: IntersectionObserverEntry[]) {\n if (!this.#force) {\n for (const { target, boundingClientRect, intersectionRect } of entries) {\n const selector = `:is(${this.#tagNames.join(',')})[href=\"#${target.id}\"]`;\n const link = this.host.querySelector(selector);\n if (link) {\n this.#markPassed(link, boundingClientRect.top < intersectionRect.top);\n }\n }\n const link = [...this.#passedLinks];\n const last = link.at(-1);\n this.#setActive(last ?? this.#linkChildren.at(0));\n }\n this.#intersected = true;\n }\n\n /**\n * Explicitly set the active item\n * @param link usually an `<a>`\n */\n public async setActive(link: EventTarget | null): Promise<void> {\n this.#force = true;\n this.#setActive(link);\n let sawActive = false;\n for (const child of this.#linkChildren) {\n this.#markPassed(child, !sawActive);\n if (child === link) {\n sawActive = true;\n }\n }\n await this.#nextIntersection();\n this.#force = false;\n }\n}\n"]}
@@ -38,37 +38,33 @@ export declare class SlotController implements ReactiveController {
38
38
  /**
39
39
  * Given a slot name or slot names, returns elements assigned to the requested slots as an array.
40
40
  * If no value is provided, it returns all children not assigned to a slot (without a slot attribute).
41
- *
41
+ * @param slotNames slots to query
42
42
  * @example Get header-slotted elements
43
- * ```js
44
- * this.getSlotted('header')
45
- * ```
46
- *
43
+ * ```js
44
+ * this.getSlotted('header')
45
+ * ```
47
46
  * @example Get header- and footer-slotted elements
48
- * ```js
49
- * this.getSlotted('header', 'footer')
50
- * ```
51
- *
47
+ * ```js
48
+ * this.getSlotted('header', 'footer')
49
+ * ```
52
50
  * @example Get default-slotted elements
53
- * ```js
54
- * this.getSlotted();
55
- * ```
51
+ * ```js
52
+ * this.getSlotted();
53
+ * ```
56
54
  */
57
55
  getSlotted<T extends Element = Element>(...slotNames: string[]): T[];
58
56
  /**
59
57
  * Returns a boolean statement of whether or not any of those slots exists in the light DOM.
60
- *
61
58
  * @param names The slot names to check.
62
59
  * @example this.hasSlotted('header');
63
60
  */
64
61
  hasSlotted(...names: (string | null | undefined)[]): boolean;
65
62
  /**
66
63
  * Whether or not all the requested slots are empty.
67
- *
68
- * @param slots The slot name. If no value is provided, it returns the default slot.
64
+ * @param names The slot names to query. If no value is provided, it returns the default slot.
69
65
  * @example this.isEmpty('header', 'footer');
70
66
  * @example this.isEmpty();
71
- * @returns {Boolean}
67
+ * @returns
72
68
  */
73
69
  isEmpty(...names: (string | null | undefined)[]): boolean;
74
70
  }