@patternfly/pfe-core 5.0.6 → 5.0.7

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,6 +1,5 @@
1
1
  import { isServer } from 'lit';
2
2
  export class Logger {
3
- static { this.instances = new WeakMap(); }
4
3
  get prefix() {
5
4
  if (!isServer && this.host instanceof HTMLElement) {
6
5
  return `[${this.host.localName}${this.host.id ? `#${this.host.id}` : ''}]`;
@@ -133,4 +132,5 @@ export class Logger {
133
132
  this.debug('connected');
134
133
  }
135
134
  }
135
+ Logger.instances = new WeakMap();
136
136
  //# sourceMappingURL=logger.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"logger.js","sourceRoot":"","sources":["logger.ts"],"names":[],"mappings":"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","sourcesContent":["import { isServer, type ReactiveController, type ReactiveControllerHost } from 'lit';\n\nexport class Logger implements ReactiveController {\n private static logDebug: boolean;\n\n private static instances = new WeakMap<ReactiveControllerHost, Logger>();\n\n private get prefix() {\n if (!isServer && this.host instanceof HTMLElement) {\n return `[${this.host.localName}${this.host.id ? `#${this.host.id}` : ''}]`;\n } else {\n return `[${this.host.constructor.name}]`;\n }\n }\n\n /**\n * A boolean value that indicates if the logging should be printed to the console; used for debugging.\n * For use in a JS file or script tag; can also be added in the constructor of a component during development.\n * @example Logger.debugLog(true);\n * @param [preference=null]\n */\n static debugLog(preference = null): boolean {\n // wrap localStorage references in a try/catch; merely referencing it can\n // throw errors in some locked down environments\n try {\n if (preference !== null) {\n Logger.logDebug = !!preference;\n localStorage.pfeLog = !!preference;\n }\n return localStorage.pfeLog === 'true';\n } catch {\n return Logger.logDebug;\n }\n }\n\n /* eslint-disable no-console */\n\n /**\n * A logging wrapper which checks the debugLog boolean and prints to the console if true.\n * @example Logger.debug(\"Hello\");\n * @param msgs console.log params\n */\n static debug(...msgs: unknown[]): void {\n if (Logger.debugLog()) {\n console.debug(...msgs);\n }\n }\n\n /**\n * A logging wrapper which checks the debugLog boolean and prints to the console if true.\n * @example Logger.info(\"Hello\");\n * @param msgs console.log params\n */\n static info(...msgs: unknown[]): void {\n if (Logger.debugLog()) {\n console.info(...msgs);\n }\n }\n\n /**\n * A logging wrapper which checks the debugLog boolean and prints to the console if true.\n * @example Logger.log(\"Hello\");\n * @param msgs console.log params\n */\n static log(...msgs: unknown[]): void {\n if (Logger.debugLog()) {\n console.log(...msgs);\n }\n }\n\n /**\n * A console warning wrapper which formats your output with useful debugging information.\n * @example Logger.warn(\"Hello\");\n * @param msgs console.log params\n */\n static warn(...msgs: unknown[]): void {\n console.warn(...msgs);\n }\n\n /**\n * A console error wrapper which formats your output with useful debugging information.\n * For use inside a component's function.\n * @example Logger.error(\"Hello\");\n * @param msgs console.log params\n */\n static error(...msgs: unknown[]): void {\n console.error([...msgs].join(' '));\n }\n\n /* eslint-enable no-console */\n\n /**\n * Debug logging that outputs the tag name as a prefix automatically\n * @example this.logger.log(\"Hello\");\n * @param msgs console.log params\n */\n debug(...msgs: unknown[]): void {\n Logger.debug(this.prefix, ...msgs);\n }\n\n /**\n * Info logging that outputs the tag name as a prefix automatically\n * @example this.logger.log(\"Hello\");\n * @param msgs console.log params\n */\n info(...msgs: unknown[]): void {\n Logger.info(this.prefix, ...msgs);\n }\n\n /**\n * Local logging that outputs the tag name as a prefix automatically\n * @example this.logger.log(\"Hello\");\n * @param msgs console.log params\n */\n log(...msgs: unknown[]): void {\n Logger.log(this.prefix, ...msgs);\n }\n\n /**\n * Local warning wrapper that outputs the tag name as a prefix automatically.\n * For use inside a component's function.\n * @example this.logger.warn(\"Hello\");\n * @param msgs console.log params\n */\n warn(...msgs: unknown[]): void {\n Logger.warn(this.prefix, ...msgs);\n }\n\n /**\n * Local error wrapper that outputs the tag name as a prefix automatically.\n * For use inside a component's function.\n * @example this.logger.error(\"Hello\");\n * @param msgs console.log params\n */\n error(...msgs: unknown[]): void {\n Logger.error(this.prefix, ...msgs);\n }\n\n constructor(private host: ReactiveControllerHost) {\n // We only need one logger instance per host\n if (Logger.instances.get(host)) {\n return Logger.instances.get(host) as Logger;\n }\n host.addController(this);\n Logger.instances.set(host, this);\n }\n\n hostConnected(): void {\n this.debug('connected');\n }\n}\n"]}
1
+ {"version":3,"file":"logger.js","sourceRoot":"","sources":["logger.ts"],"names":[],"mappings":"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","sourcesContent":["import { isServer, type ReactiveController, type ReactiveControllerHost } from 'lit';\n\nexport class Logger implements ReactiveController {\n private static logDebug: boolean;\n\n private static instances = new WeakMap<ReactiveControllerHost, Logger>();\n\n private get prefix() {\n if (!isServer && this.host instanceof HTMLElement) {\n return `[${this.host.localName}${this.host.id ? `#${this.host.id}` : ''}]`;\n } else {\n return `[${this.host.constructor.name}]`;\n }\n }\n\n /**\n * A boolean value that indicates if the logging should be printed to the console; used for debugging.\n * For use in a JS file or script tag; can also be added in the constructor of a component during development.\n * @example Logger.debugLog(true);\n * @param [preference=null]\n */\n static debugLog(preference = null): boolean {\n // wrap localStorage references in a try/catch; merely referencing it can\n // throw errors in some locked down environments\n try {\n if (preference !== null) {\n Logger.logDebug = !!preference;\n localStorage.pfeLog = !!preference;\n }\n return localStorage.pfeLog === 'true';\n } catch {\n return Logger.logDebug;\n }\n }\n\n /* eslint-disable no-console */\n\n /**\n * A logging wrapper which checks the debugLog boolean and prints to the console if true.\n * @example Logger.debug(\"Hello\");\n * @param msgs console.log params\n */\n static debug(...msgs: unknown[]): void {\n if (Logger.debugLog()) {\n console.debug(...msgs);\n }\n }\n\n /**\n * A logging wrapper which checks the debugLog boolean and prints to the console if true.\n * @example Logger.info(\"Hello\");\n * @param msgs console.log params\n */\n static info(...msgs: unknown[]): void {\n if (Logger.debugLog()) {\n console.info(...msgs);\n }\n }\n\n /**\n * A logging wrapper which checks the debugLog boolean and prints to the console if true.\n * @example Logger.log(\"Hello\");\n * @param msgs console.log params\n */\n static log(...msgs: unknown[]): void {\n if (Logger.debugLog()) {\n console.log(...msgs);\n }\n }\n\n /**\n * A console warning wrapper which formats your output with useful debugging information.\n * @example Logger.warn(\"Hello\");\n * @param msgs console.log params\n */\n static warn(...msgs: unknown[]): void {\n console.warn(...msgs);\n }\n\n /**\n * A console error wrapper which formats your output with useful debugging information.\n * For use inside a component's function.\n * @example Logger.error(\"Hello\");\n * @param msgs console.log params\n */\n static error(...msgs: unknown[]): void {\n console.error([...msgs].join(' '));\n }\n\n /* eslint-enable no-console */\n\n /**\n * Debug logging that outputs the tag name as a prefix automatically\n * @example this.logger.log(\"Hello\");\n * @param msgs console.log params\n */\n debug(...msgs: unknown[]): void {\n Logger.debug(this.prefix, ...msgs);\n }\n\n /**\n * Info logging that outputs the tag name as a prefix automatically\n * @example this.logger.log(\"Hello\");\n * @param msgs console.log params\n */\n info(...msgs: unknown[]): void {\n Logger.info(this.prefix, ...msgs);\n }\n\n /**\n * Local logging that outputs the tag name as a prefix automatically\n * @example this.logger.log(\"Hello\");\n * @param msgs console.log params\n */\n log(...msgs: unknown[]): void {\n Logger.log(this.prefix, ...msgs);\n }\n\n /**\n * Local warning wrapper that outputs the tag name as a prefix automatically.\n * For use inside a component's function.\n * @example this.logger.warn(\"Hello\");\n * @param msgs console.log params\n */\n warn(...msgs: unknown[]): void {\n Logger.warn(this.prefix, ...msgs);\n }\n\n /**\n * Local error wrapper that outputs the tag name as a prefix automatically.\n * For use inside a component's function.\n * @example this.logger.error(\"Hello\");\n * @param msgs console.log params\n */\n error(...msgs: unknown[]): void {\n Logger.error(this.prefix, ...msgs);\n }\n\n constructor(private host: ReactiveControllerHost) {\n // We only need one logger instance per host\n if (Logger.instances.get(host)) {\n return Logger.instances.get(host) as Logger;\n }\n host.addController(this);\n Logger.instances.set(host, this);\n }\n\n hostConnected(): void {\n this.debug('connected');\n }\n}\n"]}
@@ -1,4 +1,4 @@
1
- var _ScrollSpyController_instances, _a, _ScrollSpyController_instances_1, _ScrollSpyController_tagNames, _ScrollSpyController_activeAttribute, _ScrollSpyController_io, _ScrollSpyController_passedLinks, _ScrollSpyController_force, _ScrollSpyController_intersected, _ScrollSpyController_root, _ScrollSpyController_rootMargin, _ScrollSpyController_threshold, _ScrollSpyController_intersectingTargets, _ScrollSpyController_linkTargetMap, _ScrollSpyController_getRootNode, _ScrollSpyController_getHash, _ScrollSpyController_onIntersection, _ScrollSpyController_linkChildren_get, _ScrollSpyController_initializing, _ScrollSpyController_initIo, _ScrollSpyController_markPassed, _ScrollSpyController_setActive, _ScrollSpyController_activateHash, _ScrollSpyController_nextIntersection, _ScrollSpyController_onIo;
1
+ var _ScrollSpyController_instances, _a, _ScrollSpyController_instances_1, _ScrollSpyController_tagNames, _ScrollSpyController_activeAttribute, _ScrollSpyController_io, _ScrollSpyController_passedLinks, _ScrollSpyController_force, _ScrollSpyController_forceAbort, _ScrollSpyController_forceTimeout, _ScrollSpyController_intersected, _ScrollSpyController_root, _ScrollSpyController_rootMargin, _ScrollSpyController_threshold, _ScrollSpyController_intersectingTargets, _ScrollSpyController_linkTargetMap, _ScrollSpyController_getRootNode, _ScrollSpyController_getHash, _ScrollSpyController_onIntersection, _ScrollSpyController_linkChildren_get, _ScrollSpyController_initializing, _ScrollSpyController_releaseForce, _ScrollSpyController_initIo, _ScrollSpyController_markPassed, _ScrollSpyController_setActive, _ScrollSpyController_activateHash, _ScrollSpyController_nextIntersection, _ScrollSpyController_onIo;
2
2
  import { __classPrivateFieldGet, __classPrivateFieldSet } from "tslib";
3
3
  import { isServer } from 'lit';
4
4
  export class ScrollSpyController {
@@ -36,6 +36,10 @@ export class ScrollSpyController {
36
36
  _ScrollSpyController_passedLinks.set(this, new Set());
37
37
  /** Ignore intersections? */
38
38
  _ScrollSpyController_force.set(this, false);
39
+ /** AbortController to cancel previous force-release listeners */
40
+ _ScrollSpyController_forceAbort.set(this, void 0);
41
+ /** Timeout handle for force-release safety valve */
42
+ _ScrollSpyController_forceTimeout.set(this, void 0);
39
43
  /** Has the intersection observer found an element? */
40
44
  _ScrollSpyController_intersected.set(this, false);
41
45
  _ScrollSpyController_root.set(this, void 0);
@@ -64,12 +68,16 @@ export class ScrollSpyController {
64
68
  hostDisconnected() {
65
69
  __classPrivateFieldGet(_a, _a, "f", _ScrollSpyController_instances_1).delete(this);
66
70
  __classPrivateFieldGet(this, _ScrollSpyController_io, "f")?.disconnect();
71
+ __classPrivateFieldGet(this, _ScrollSpyController_instances, "m", _ScrollSpyController_releaseForce).call(this);
67
72
  }
68
73
  /**
69
74
  * Explicitly set the active item
70
75
  * @param link usually an `<a>`
71
76
  */
72
77
  async setActive(link) {
78
+ // Cancel any previous programmatic scroll's force state
79
+ __classPrivateFieldGet(this, _ScrollSpyController_forceAbort, "f")?.abort();
80
+ clearTimeout(__classPrivateFieldGet(this, _ScrollSpyController_forceTimeout, "f"));
73
81
  __classPrivateFieldSet(this, _ScrollSpyController_force, true, "f");
74
82
  __classPrivateFieldGet(this, _ScrollSpyController_instances, "m", _ScrollSpyController_setActive).call(this, link);
75
83
  let sawActive = false;
@@ -79,11 +87,15 @@ export class ScrollSpyController {
79
87
  sawActive = true;
80
88
  }
81
89
  }
82
- await __classPrivateFieldGet(this, _ScrollSpyController_instances, "m", _ScrollSpyController_nextIntersection).call(this);
83
- __classPrivateFieldSet(this, _ScrollSpyController_force, false, "f");
90
+ // Force is released when the scroll completes (scrollend event),
91
+ // or after a 3-second safety timeout
92
+ __classPrivateFieldSet(this, _ScrollSpyController_forceAbort, new AbortController(), "f");
93
+ const { signal } = __classPrivateFieldGet(this, _ScrollSpyController_forceAbort, "f");
94
+ addEventListener('scrollend', () => __classPrivateFieldGet(this, _ScrollSpyController_instances, "m", _ScrollSpyController_releaseForce).call(this), { once: true, signal });
95
+ __classPrivateFieldSet(this, _ScrollSpyController_forceTimeout, setTimeout(() => __classPrivateFieldGet(this, _ScrollSpyController_instances, "m", _ScrollSpyController_releaseForce).call(this), 3000), "f");
84
96
  }
85
97
  }
86
- _a = ScrollSpyController, _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_intersectingTargets = new WeakMap(), _ScrollSpyController_linkTargetMap = new WeakMap(), _ScrollSpyController_getRootNode = new WeakMap(), _ScrollSpyController_getHash = new WeakMap(), _ScrollSpyController_onIntersection = new WeakMap(), _ScrollSpyController_initializing = new WeakMap(), _ScrollSpyController_instances = new WeakSet(), _ScrollSpyController_linkChildren_get = function _ScrollSpyController_linkChildren_get() {
98
+ _a = ScrollSpyController, _ScrollSpyController_tagNames = new WeakMap(), _ScrollSpyController_activeAttribute = new WeakMap(), _ScrollSpyController_io = new WeakMap(), _ScrollSpyController_passedLinks = new WeakMap(), _ScrollSpyController_force = new WeakMap(), _ScrollSpyController_forceAbort = new WeakMap(), _ScrollSpyController_forceTimeout = new WeakMap(), _ScrollSpyController_intersected = new WeakMap(), _ScrollSpyController_root = new WeakMap(), _ScrollSpyController_rootMargin = new WeakMap(), _ScrollSpyController_threshold = new WeakMap(), _ScrollSpyController_intersectingTargets = new WeakMap(), _ScrollSpyController_linkTargetMap = new WeakMap(), _ScrollSpyController_getRootNode = new WeakMap(), _ScrollSpyController_getHash = new WeakMap(), _ScrollSpyController_onIntersection = new WeakMap(), _ScrollSpyController_initializing = new WeakMap(), _ScrollSpyController_instances = new WeakSet(), _ScrollSpyController_linkChildren_get = function _ScrollSpyController_linkChildren_get() {
87
99
  if (isServer) {
88
100
  return [];
89
101
  }
@@ -91,6 +103,15 @@ _a = ScrollSpyController, _ScrollSpyController_tagNames = new WeakMap(), _Scroll
91
103
  return Array.from(this.host.querySelectorAll(__classPrivateFieldGet(this, _ScrollSpyController_tagNames, "f").join(',')))
92
104
  .filter(__classPrivateFieldGet(this, _ScrollSpyController_getHash, "f"));
93
105
  }
106
+ }, _ScrollSpyController_releaseForce = function _ScrollSpyController_releaseForce() {
107
+ if (!__classPrivateFieldGet(this, _ScrollSpyController_force, "f")) {
108
+ return;
109
+ }
110
+ __classPrivateFieldSet(this, _ScrollSpyController_force, false, "f");
111
+ __classPrivateFieldGet(this, _ScrollSpyController_forceAbort, "f")?.abort();
112
+ __classPrivateFieldSet(this, _ScrollSpyController_forceAbort, undefined, "f");
113
+ clearTimeout(__classPrivateFieldGet(this, _ScrollSpyController_forceTimeout, "f"));
114
+ __classPrivateFieldSet(this, _ScrollSpyController_forceTimeout, undefined, "f");
94
115
  }, _ScrollSpyController_initIo = async function _ScrollSpyController_initIo() {
95
116
  const rootNode = __classPrivateFieldGet(this, _ScrollSpyController_getRootNode, "f").call(this);
96
117
  if (rootNode instanceof Document || rootNode instanceof ShadowRoot) {
@@ -130,23 +151,32 @@ _a = ScrollSpyController, _ScrollSpyController_tagNames = new WeakMap(), _Scroll
130
151
  }
131
152
  }, _ScrollSpyController_nextIntersection = async function _ScrollSpyController_nextIntersection() {
132
153
  __classPrivateFieldSet(this, _ScrollSpyController_intersected, false, "f");
133
- // safeguard the loop
134
- setTimeout(() => __classPrivateFieldSet(this, _ScrollSpyController_intersected, false, "f"), 3000);
154
+ // safeguard: break the loop after 3s even if no intersection fires
155
+ const timer = setTimeout(() => __classPrivateFieldSet(this, _ScrollSpyController_intersected, true, "f"), 3000);
135
156
  while (!__classPrivateFieldGet(this, _ScrollSpyController_intersected, "f")) {
136
157
  await new Promise(requestAnimationFrame);
137
158
  }
159
+ clearTimeout(timer);
138
160
  }, _ScrollSpyController_onIo = async function _ScrollSpyController_onIo(entries) {
139
161
  if (!__classPrivateFieldGet(this, _ScrollSpyController_force, "f")) {
140
- for (const { target, boundingClientRect, intersectionRect } of entries) {
162
+ for (const entry of entries) {
163
+ const { target, boundingClientRect } = entry;
141
164
  const selector = `:is(${__classPrivateFieldGet(this, _ScrollSpyController_tagNames, "f").join(',')})[href="#${target.id}"]`;
142
165
  const link = this.host.querySelector(selector);
143
166
  if (link) {
144
- __classPrivateFieldGet(this, _ScrollSpyController_instances, "m", _ScrollSpyController_markPassed).call(this, link, boundingClientRect.top < intersectionRect.top);
167
+ // Mark as passed if the element's top has reached the root's top edge.
168
+ // Using rootBounds (not intersectionRect) so that elements exactly AT the
169
+ // viewport top are correctly considered "passed" (the current section).
170
+ const rootTop = entry.rootBounds?.top ?? 0;
171
+ __classPrivateFieldGet(this, _ScrollSpyController_instances, "m", _ScrollSpyController_markPassed).call(this, link, boundingClientRect.top <= rootTop + 2);
145
172
  }
146
173
  }
147
- const link = [...__classPrivateFieldGet(this, _ScrollSpyController_passedLinks, "f")];
148
- const last = link.at(-1);
149
- __classPrivateFieldGet(this, _ScrollSpyController_instances, "m", _ScrollSpyController_setActive).call(this, last ?? __classPrivateFieldGet(this, _ScrollSpyController_instances, "a", _ScrollSpyController_linkChildren_get).at(0));
174
+ // Sort passed links by DOM order rather than Set insertion order
175
+ const linkOrder = __classPrivateFieldGet(this, _ScrollSpyController_instances, "a", _ScrollSpyController_linkChildren_get);
176
+ const passed = [...__classPrivateFieldGet(this, _ScrollSpyController_passedLinks, "f")]
177
+ .sort((a, b) => linkOrder.indexOf(a) - linkOrder.indexOf(b));
178
+ const last = passed.at(-1);
179
+ __classPrivateFieldGet(this, _ScrollSpyController_instances, "m", _ScrollSpyController_setActive).call(this, last ?? linkOrder.at(0));
150
180
  }
151
181
  __classPrivateFieldSet(this, _ScrollSpyController_intersected, true, "f");
152
182
  __classPrivateFieldGet(this, _ScrollSpyController_intersectingTargets, "f").clear();
@@ -1 +1 @@
1
- {"version":3,"file":"scroll-spy-controller.js","sourceRoot":"","sources":["scroll-spy-controller.ts"],"names":[],"mappings":"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","sourcesContent":["import { isServer, type ReactiveController, type 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 /**\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 /**\n * Optional callback for when an intersection occurs\n */\n onIntersection?(): void;\n}\n\nexport class ScrollSpyController implements ReactiveController {\n static #instances = new Set<ScrollSpyController>;\n\n static {\n if (!isServer) {\n addEventListener('scroll', () => {\n if (Math.round(window.innerHeight + window.scrollY) >= document.body.scrollHeight) {\n this.#instances.forEach(ssc => {\n ssc.#setActive(ssc.#linkChildren.at(-1));\n });\n }\n }, { passive: true });\n addEventListener('hashchange', () => {\n this.#instances.forEach(ssc => {\n ssc.#activateHash();\n });\n });\n }\n }\n\n #tagNames: string[];\n\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\n #rootMargin?: string;\n\n #threshold: number | number[];\n\n #intersectingTargets = new Set<Element>();\n\n #linkTargetMap = new Map<Element, Element | null>();\n\n #getRootNode: () => Node | null;\n\n #getHash: (el: Element) => string | null;\n\n #onIntersection?: () => void;\n\n get #linkChildren(): Element[] {\n if (isServer) {\n return [];\n } else {\n return Array.from(this.host.querySelectorAll(this.#tagNames.join(',')))\n .filter(this.#getHash);\n }\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?.() ?? null;\n this.#getHash = options?.getHash ?? ((el: Element) => el.getAttribute('href'));\n this.#onIntersection = options?.onIntersection;\n }\n\n hostConnected(): void {\n ScrollSpyController.#instances.add(this);\n this.#initIo();\n }\n\n hostDisconnected(): void {\n ScrollSpyController.#instances.delete(this);\n this.#io?.disconnect();\n }\n\n #initializing = true;\n\n async #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 for (const link of this.#linkChildren) {\n const id = this.#getHash(link)?.replace('#', '');\n if (id) {\n const target = document.getElementById(id);\n if (target) {\n this.#io?.observe(target);\n this.#linkTargetMap.set(link, target);\n }\n }\n }\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 #activateHash() {\n const links = this.#linkChildren;\n const { hash } = location;\n if (!hash) {\n this.setActive(links.at(0) ?? null);\n } else {\n await this.#nextIntersection();\n this.setActive(links.find(x => this.#getHash(x) === hash) ?? null);\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 this.#intersectingTargets.clear();\n for (const entry of entries) {\n if (entry.isIntersecting) {\n this.#intersectingTargets.add(entry.target);\n }\n }\n if (this.#initializing) {\n const ints = entries?.filter(x => x.isIntersecting) ?? [];\n if (this.#intersectingTargets.size > 0) {\n const [{ target = null } = {}] = ints;\n const { id } = target ?? {};\n if (id) {\n const link = this.#linkChildren.find(link => this.#getHash(link) === `#${id}`);\n if (link) {\n this.#setActive(link);\n }\n }\n }\n this.#initializing = false;\n }\n this.#onIntersection?.();\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"]}
1
+ {"version":3,"file":"scroll-spy-controller.js","sourceRoot":"","sources":["scroll-spy-controller.ts"],"names":[],"mappings":"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","sourcesContent":["import { isServer, type ReactiveController, type 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 /**\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 /**\n * Optional callback for when an intersection occurs\n */\n onIntersection?(): void;\n}\n\nexport class ScrollSpyController implements ReactiveController {\n static #instances = new Set<ScrollSpyController>;\n\n static {\n if (!isServer) {\n addEventListener('scroll', () => {\n if (Math.round(window.innerHeight + window.scrollY) >= document.body.scrollHeight) {\n this.#instances.forEach(ssc => {\n ssc.#setActive(ssc.#linkChildren.at(-1));\n });\n }\n }, { passive: true });\n addEventListener('hashchange', () => {\n this.#instances.forEach(ssc => {\n ssc.#activateHash();\n });\n });\n }\n }\n\n #tagNames: string[];\n\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 /** AbortController to cancel previous force-release listeners */\n #forceAbort?: AbortController;\n\n /** Timeout handle for force-release safety valve */\n #forceTimeout?: ReturnType<typeof setTimeout>;\n\n /** Has the intersection observer found an element? */\n #intersected = false;\n\n #root: ScrollSpyControllerOptions['root'];\n\n #rootMargin?: string;\n\n #threshold: number | number[];\n\n #intersectingTargets = new Set<Element>();\n\n #linkTargetMap = new Map<Element, Element | null>();\n\n #getRootNode: () => Node | null;\n\n #getHash: (el: Element) => string | null;\n\n #onIntersection?: () => void;\n\n get #linkChildren(): Element[] {\n if (isServer) {\n return [];\n } else {\n return Array.from(this.host.querySelectorAll(this.#tagNames.join(',')))\n .filter(this.#getHash);\n }\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?.() ?? null;\n this.#getHash = options?.getHash ?? ((el: Element) => el.getAttribute('href'));\n this.#onIntersection = options?.onIntersection;\n }\n\n hostConnected(): void {\n ScrollSpyController.#instances.add(this);\n this.#initIo();\n }\n\n hostDisconnected(): void {\n ScrollSpyController.#instances.delete(this);\n this.#io?.disconnect();\n this.#releaseForce();\n }\n\n #initializing = true;\n\n /** Cancel force mode and clean up associated listeners */\n #releaseForce() {\n if (!this.#force) {\n return;\n }\n this.#force = false;\n this.#forceAbort?.abort();\n this.#forceAbort = undefined;\n clearTimeout(this.#forceTimeout);\n this.#forceTimeout = undefined;\n }\n\n async #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 for (const link of this.#linkChildren) {\n const id = this.#getHash(link)?.replace('#', '');\n if (id) {\n const target = document.getElementById(id);\n if (target) {\n this.#io?.observe(target);\n this.#linkTargetMap.set(link, target);\n }\n }\n }\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 #activateHash() {\n const links = this.#linkChildren;\n const { hash } = location;\n if (!hash) {\n this.setActive(links.at(0) ?? null);\n } else {\n await this.#nextIntersection();\n this.setActive(links.find(x => this.#getHash(x) === hash) ?? null);\n }\n }\n\n async #nextIntersection() {\n this.#intersected = false;\n // safeguard: break the loop after 3s even if no intersection fires\n const timer = setTimeout(() => this.#intersected = true, 3000);\n while (!this.#intersected) {\n await new Promise(requestAnimationFrame);\n }\n clearTimeout(timer);\n }\n\n async #onIo(entries: IntersectionObserverEntry[]) {\n if (!this.#force) {\n for (const entry of entries) {\n const { target, boundingClientRect } = entry;\n const selector = `:is(${this.#tagNames.join(',')})[href=\"#${target.id}\"]`;\n const link = this.host.querySelector(selector);\n if (link) {\n // Mark as passed if the element's top has reached the root's top edge.\n // Using rootBounds (not intersectionRect) so that elements exactly AT the\n // viewport top are correctly considered \"passed\" (the current section).\n const rootTop = entry.rootBounds?.top ?? 0;\n this.#markPassed(link, boundingClientRect.top <= rootTop + 2);\n }\n }\n // Sort passed links by DOM order rather than Set insertion order\n const linkOrder = this.#linkChildren;\n const passed = [...this.#passedLinks]\n .sort((a, b) => linkOrder.indexOf(a) - linkOrder.indexOf(b));\n const last = passed.at(-1);\n this.#setActive(last ?? linkOrder.at(0));\n }\n this.#intersected = true;\n this.#intersectingTargets.clear();\n for (const entry of entries) {\n if (entry.isIntersecting) {\n this.#intersectingTargets.add(entry.target);\n }\n }\n if (this.#initializing) {\n const ints = entries?.filter(x => x.isIntersecting) ?? [];\n if (this.#intersectingTargets.size > 0) {\n const [{ target = null } = {}] = ints;\n const { id } = target ?? {};\n if (id) {\n const link = this.#linkChildren.find(link => this.#getHash(link) === `#${id}`);\n if (link) {\n this.#setActive(link);\n }\n }\n }\n this.#initializing = false;\n }\n this.#onIntersection?.();\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 // Cancel any previous programmatic scroll's force state\n this.#forceAbort?.abort();\n clearTimeout(this.#forceTimeout);\n\n this.#force = true;\n this.#setActive(link);\n\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\n // Force is released when the scroll completes (scrollend event),\n // or after a 3-second safety timeout\n this.#forceAbort = new AbortController();\n const { signal } = this.#forceAbort;\n addEventListener('scrollend', () => this.#releaseForce(), { once: true, signal });\n this.#forceTimeout = setTimeout(() => this.#releaseForce(), 3000);\n }\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@patternfly/pfe-core",
3
- "version": "5.0.6",
3
+ "version": "5.0.7",
4
4
  "license": "MIT",
5
5
  "description": "PatternFly Elements Core Library",
6
6
  "customElements": "custom-elements.json",