scrollspy.cjs.map 14 KB

1
  1. {"version":3,"file":"scrollspy.cjs","sources":["../../src/strings/scrollspyString.ts","../../src/strings/scrollspyComponent.ts","../../src/components/scrollspy.ts"],"sourcesContent":["/** @type {string} */\nconst scrollspyString = \"scrollspy\";\nexport default scrollspyString;\n","/** @type {string} */\nconst scrollspyComponent = \"ScrollSpy\";\nexport default scrollspyComponent;\n","/* Native JavaScript for Bootstrap 5 | ScrollSpy\n------------------------------------------------ */\nimport {\n addClass,\n closest,\n createCustomEvent,\n dispatchEvent,\n getAttribute,\n getBoundingClientRect,\n getDocument,\n getDocumentElement,\n getElementById,\n getElementsByTagName,\n getInstance,\n hasClass,\n mouseclickEvent,\n MouseEvent,\n querySelector,\n removeClass,\n} from \"@thednp/shorty\";\n\nimport PositionObserver from \"@thednp/position-observer\";\nimport { addListener, removeListener } from \"@thednp/event-listener\";\n\nimport activeClass from \"~/strings/activeClass\";\nimport scrollspyString from \"~/strings/scrollspyString\";\nimport scrollspyComponent from \"~/strings/scrollspyComponent\";\nimport isDisabled from \"~/util/isDisabled\";\nimport BaseComponent from \"./base-component\";\nimport { ScrollSpyEvent, ScrollSpyOptions } from \"~/interface/scrollspy\";\n\n// SCROLLSPY PRIVATE GC\n// ====================\nconst scrollspySelector = '[data-bs-spy=\"scroll\"]';\nconst scrollSpyAnchorSelector = \"[href]\";\n\nconst scrollspyDefaults: Partial<ScrollSpyOptions> = {\n offset: 10,\n target: undefined,\n};\n\ntype ScrollSpyEventProps = {\n relatedTarget: HTMLElement;\n};\n\n/**\n * Static method which returns an existing `ScrollSpy` instance associated\n * to a target `Element`.\n */\nconst getScrollSpyInstance = (element: Element) =>\n getInstance<ScrollSpy>(element, scrollspyComponent);\n\n/**\n * A `ScrollSpy` initialization callback.\n */\nconst scrollspyInitCallback = (element: Element) => new ScrollSpy(element);\n\n// SCROLLSPY CUSTOM EVENT\n// ======================\nconst activateScrollSpy = createCustomEvent<\n ScrollSpyEventProps,\n ScrollSpyEvent\n>(`activate.bs.${scrollspyString}`);\n\n// SCROLLSPY PRIVATE METHODS\n// =========================\n/**\n * Update the state of all items.\n *\n * @param self the `ScrollSpy` instance\n */\nconst updateSpyTargets = (self: ScrollSpy) => {\n const {\n target,\n _itemsLength,\n _observables,\n } = self;\n\n const links = getElementsByTagName<HTMLAnchorElement>(\"A\", target);\n const doc = getDocument(target);\n\n // only update items once or with each mutation\n // istanbul ignore else @preserve\n if (!links.length || _itemsLength === _observables.size) return;\n // reset arrays & update\n _observables.clear();\n\n Array.from(links).forEach((link) => {\n const hash = getAttribute(link, \"href\")?.slice(1);\n const targetItem = hash?.length ? doc.getElementById(hash) : null;\n\n if (targetItem && !isDisabled(link)) {\n self._observables.set(targetItem, link);\n }\n });\n self._itemsLength = self._observables.size;\n};\n\n/**\n * Clear all items of the target.\n *\n * @param target a single item\n */\nconst clear = (target: Element) => {\n Array.from(getElementsByTagName<HTMLAnchorElement>(\"A\", target)).forEach(\n (item) => {\n if (hasClass(item, activeClass)) removeClass(item, activeClass);\n },\n );\n};\n\n/**\n * Activates a new item.\n *\n * @param self the `ScrollSpy` instance\n * @param item a single item\n */\nconst activate = (self: ScrollSpy, item: HTMLElement) => {\n const { target, element } = self;\n\n // istanbul ignore else @preserve\n clear(target);\n\n self._activeItem = item;\n addClass(item, activeClass);\n\n // activate all parents\n let parentItem = item;\n while (parentItem !== target) {\n parentItem = parentItem.parentElement as HTMLElement;\n if (\n [\"nav\", \"dropdown-menu\", \"list-group\"].some((c) =>\n hasClass(parentItem, c)\n )\n ) {\n const parentLink = parentItem.previousElementSibling as\n | HTMLElement\n | null;\n\n // istanbul ignore else @preserve\n if (parentLink && !hasClass(parentLink, activeClass)) {\n addClass(parentLink, activeClass);\n }\n }\n }\n\n // dispatch\n activateScrollSpy.relatedTarget = item;\n dispatchEvent(element, activateScrollSpy);\n};\n\nconst getOffset = (self: ScrollSpy, target: HTMLElement) => {\n const { scrollTarget, element, options } = self;\n\n return (scrollTarget !== element\n ? getBoundingClientRect(target).top + scrollTarget.scrollTop\n : target.offsetTop) - (options.offset as number || 10);\n};\n\n// SCROLLSPY DEFINITION\n// ====================\n/** Returns a new `ScrollSpy` instance. */\nexport default class ScrollSpy extends BaseComponent {\n static selector = scrollspySelector;\n static init = scrollspyInitCallback;\n static getInstance = getScrollSpyInstance;\n declare element: HTMLElement;\n declare options: ScrollSpyOptions;\n declare target: HTMLElement;\n declare scrollTarget: HTMLElement;\n declare _itemsLength: number;\n declare _activeItem: HTMLElement | null;\n declare _observables: Map<HTMLElement, HTMLElement>;\n declare _observer: PositionObserver; //| IntersectionObserver;\n\n /**\n * @param target the target element\n * @param config the instance options\n */\n constructor(\n target: Element | string,\n config?: Partial<ScrollSpyOptions>,\n ) {\n super(target, config);\n\n // initialization element & options\n const { element, options } = this;\n\n // get target\n const spyTarget = querySelector(\n options.target,\n getDocument(element),\n );\n\n // invalidate\n if (!spyTarget) return;\n this.target = spyTarget;\n\n // set initial state\n this.scrollTarget = element.clientHeight < element.scrollHeight\n ? element\n : getDocumentElement(element);\n this._observables = new Map();\n\n // run an initial burst, we need to know the targets\n this.refresh();\n // updateSpyTargets(this);\n\n // create observer\n this._observer = new PositionObserver(() => {\n requestAnimationFrame(() => this.refresh());\n }, {\n root: this.scrollTarget,\n });\n\n // add event handlers\n this._toggleEventListeners(true);\n }\n\n /* eslint-disable */\n /**\n * Returns component name string.\n */\n get name() {\n return scrollspyComponent;\n }\n /**\n * Returns component default options.\n */\n get defaults() {\n return scrollspyDefaults;\n }\n /* eslint-enable */\n\n // SCROLLSPY PUBLIC METHODS\n // ========================\n /** Updates all items. */\n refresh = () => {\n const { target, scrollTarget } = this;\n // check if target is visible and invalidate\n // istanbul ignore if @preserve\n if (!target || target.offsetHeight === 0) return;\n\n updateSpyTargets(this);\n const { _itemsLength, _observables, _activeItem } = this;\n\n // istanbul ignore if @preserve\n if (!_itemsLength) return;\n const entries = _observables.entries().toArray();\n\n const { scrollTop, scrollHeight, clientHeight } = scrollTarget;\n\n if (scrollTop >= scrollHeight - clientHeight) {\n const newActiveItem = entries[_itemsLength - 1]?.[1];\n\n // istanbul ignore else @preserve\n if (_activeItem !== newActiveItem) activate(this, newActiveItem);\n return;\n }\n\n const firstOffset = entries[0]?.[0]\n ? getOffset(this, entries[0][0])\n : /* istanbul ignore next */ null;\n if (\n firstOffset !== null && scrollTop < firstOffset &&\n firstOffset > 0\n ) {\n this._activeItem = null;\n clear(target);\n return;\n }\n\n for (let i = 0; i < _itemsLength; i += 1) {\n const [targetItem, item] = entries[i];\n const offsetTop = getOffset(this, targetItem);\n const nextTarget = entries[i + 1]?.[0];\n const nextOffsetTop = nextTarget\n ? getOffset(this, nextTarget)\n : /* istanbul ignore next */ null;\n\n // istanbul ignore else @preserve\n if (\n _activeItem !== item &&\n scrollTop >= offsetTop &&\n (nextOffsetTop === null || scrollTop < nextOffsetTop)\n ) {\n activate(this, item);\n break;\n }\n }\n };\n\n /**\n * This method provides an event handle\n * for scrollspy\n * @param e the event listener object\n */\n _scrollTo = (e: MouseEvent<HTMLAnchorElement>) => {\n const item = closest(e.target, scrollSpyAnchorSelector);\n const hash = item && getAttribute(item, \"href\")?.slice(1);\n const targetItem = hash && getElementById(hash, this.target);\n\n // istanbul ignore else @preserve\n if (targetItem) {\n this.scrollTarget.scrollTo({\n top: targetItem.offsetTop,\n behavior: \"smooth\",\n });\n e.preventDefault();\n }\n };\n\n /**\n * Toggles on/off the component observer.\n *\n * @param self the ScrollSpy instance\n * @param add when `true`, listener is added\n */\n _toggleEventListeners = (\n add?: boolean,\n ) => {\n const { target, _observables, _observer, _scrollTo } = this;\n const action = add ? addListener : removeListener;\n action(target, mouseclickEvent, _scrollTo);\n\n if (add) {\n _observables?.forEach((_, targetItem) => _observer.observe(targetItem));\n } else _observer.disconnect();\n };\n\n /** Removes `ScrollSpy` from the target element. */\n dispose() {\n this._toggleEventListeners();\n super.dispose();\n }\n}\n"],"names":["scrollspyString","scrollspyComponent","scrollspySelector","scrollSpyAnchorSelector","scrollspyDefaults","getScrollSpyInstance","element","getInstance","scrollspyInitCallback","ScrollSpy","activateScrollSpy","createCustomEvent","updateSpyTargets","self","target","_itemsLength","_observables","links","getElementsByTagName","doc","getDocument","link","hash","getAttribute","targetItem","isDisabled","clear","item","hasClass","activeClass","removeClass","activate","addClass","parentItem","parentLink","dispatchEvent","getOffset","scrollTarget","options","getBoundingClientRect","BaseComponent","config","spyTarget","querySelector","getDocumentElement","PositionObserver","_activeItem","entries","scrollTop","scrollHeight","clientHeight","newActiveItem","firstOffset","i","offsetTop","nextTarget","nextOffsetTop","e","closest","getElementById","add","_observer","_scrollTo","addListener","removeListener","mouseclickEvent","_"],"mappings":"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"}