123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899 |
- // https://www.jsdelivr.com/package/npm/scroll-behavior-polyfill?path=dist
- /*!
- scroll-behavior-polyfill 2.0.6
- license: MIT (https://github.com/wessberg/scroll-behavior-polyfill/blob/master/LICENSE.md)
- Copyright © 2019 Frederik Wessberg <frederikwessberg@hotmail.com>
- */
-
- (function () {
- 'use strict';
-
- /**
- * Is true if the browser natively supports the 'scroll-behavior' CSS-property.
- * @type {boolean}
- */
- var SUPPORTS_SCROLL_BEHAVIOR = "scrollBehavior" in document.documentElement.style;
-
-
-
- /*! *****************************************************************************
- Copyright (c) Microsoft Corporation. All rights reserved.
- Licensed under the Apache License, Version 2.0 (the "License"); you may not use
- this file except in compliance with the License. You may obtain a copy of the
- License at http://www.apache.org/licenses/LICENSE-2.0
-
- THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
- WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
- MERCHANTABLITY OR NON-INFRINGEMENT.
-
- See the Apache Version 2.0 License for specific language governing permissions
- and limitations under the License.
- ***************************************************************************** */
-
- var __assign = function() {
- __assign = Object.assign || function __assign(t) {
- for (var s, i = 1, n = arguments.length; i < n; i++) {
- s = arguments[i];
- for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
- }
- return t;
- };
- return __assign.apply(this, arguments);
- };
-
- function __read(o, n) {
- var m = typeof Symbol === "function" && o[Symbol.iterator];
- if (!m) return o;
- var i = m.call(o), r, ar = [], e;
- try {
- while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
- }
- catch (error) { e = { error: error }; }
- finally {
- try {
- if (r && !r.done && (m = i["return"])) m.call(i);
- }
- finally { if (e) throw e.error; }
- }
- return ar;
- }
-
- var styleDeclarationPropertyName = "scrollBehavior";
- var styleAttributePropertyName = "scroll-behavior";
- var styleAttributePropertyNameRegex = new RegExp(styleAttributePropertyName + ":\\s*([^;]*)");
- /**
- * Determines the scroll behavior to use, depending on the given ScrollOptions and the position of the Element
- * within the DOM
- * @param {Element|HTMLElement|Window} inputTarget
- * @param {ScrollOptions} [options]
- * @returns {ScrollBehavior}
- */
- function getScrollBehavior(inputTarget, options) {
- // If the given 'behavior' is 'smooth', apply smooth scrolling no matter what
- if (options != null && options.behavior === "smooth")
- return "smooth";
- var target = "style" in inputTarget ? inputTarget : document.scrollingElement != null ? document.scrollingElement : document.documentElement;
- var value;
- if ("style" in target) {
- // Check if scroll-behavior is set as a property on the CSSStyleDeclaration
- var scrollBehaviorPropertyValue = target.style[styleDeclarationPropertyName];
- // Return it if it is given and has a proper value
- if (scrollBehaviorPropertyValue != null && scrollBehaviorPropertyValue !== "") {
- value = scrollBehaviorPropertyValue;
- }
- }
- if (value == null) {
- var attributeValue = target.getAttribute("scroll-behavior");
- if (attributeValue != null && attributeValue !== "") {
- value = attributeValue;
- }
- }
- if (value == null) {
- // Otherwise, check if it is set as an inline style
- var styleAttributeValue = target.getAttribute("style");
- if (styleAttributeValue != null && styleAttributeValue.includes(styleAttributePropertyName)) {
- var match = styleAttributeValue.match(styleAttributePropertyNameRegex);
- if (match != null) {
- var _a = __read(match, 2), behavior = _a[1];
- if (behavior != null && behavior !== "") {
- value = behavior;
- }
- }
- }
- }
- if (value == null) {
- // Take the computed style for the element and see if it contains a specific 'scroll-behavior' value
- var computedStyle = getComputedStyle(target);
- var computedStyleValue = computedStyle.getPropertyValue("scrollBehavior");
- if (computedStyleValue != null && computedStyleValue !== "") {
- value = computedStyleValue;
- }
- }
- // In all other cases, use the value from the CSSOM
- return value;
- }
-
-
-
- var HALF = 0.5;
- /**
- * The easing function to use when applying the smooth scrolling
- * @param {number} k
- * @returns {number}
- */
- function ease(k) {
- return HALF * (1 - Math.cos(Math.PI * k));
- }
-
- /**
- * The duration of a smooth scroll
- * @type {number}
- */
- var SCROLL_TIME = 15000;
- /**
- * Performs a smooth repositioning of the scroll
- * @param {ISmoothScrollOptions} options
- */
- function smoothScroll(options) {
- var startTime = options.startTime, startX = options.startX, startY = options.startY, endX = options.endX, endY = options.endY, method = options.method;
- var timeLapsed = 0;
- var distanceX = endX - startX;
- var distanceY = endY - startY;
- var speed = Math.max(Math.abs((distanceX / 1000) * SCROLL_TIME), Math.abs((distanceY / 1000) * SCROLL_TIME));
- requestAnimationFrame(function animate(timestamp) {
- timeLapsed += timestamp - startTime;
- var percentage = Math.max(0, Math.min(1, speed === 0 ? 0 : timeLapsed / speed));
- var positionX = Math.floor(startX + distanceX * ease(percentage));
- var positionY = Math.floor(startY + distanceY * ease(percentage));
- method(positionX, positionY);
- if (positionX !== endX || positionY !== endY) {
- requestAnimationFrame(animate);
- }
- });
- }
-
- /**
- * Returns a High Resolution timestamp if possible, otherwise fallbacks to Date.now()
- * @returns {number}
- */
- function now() {
- if ("performance" in window)
- return performance.now();
- return Date.now();
- }
-
-
-
- var ELEMENT_ORIGINAL_SCROLL = Element.prototype.scroll;
-
- var WINDOW_ORIGINAL_SCROLL = window.scroll;
-
- var ELEMENT_ORIGINAL_SCROLL_BY = Element.prototype.scrollBy;
-
- var WINDOW_ORIGINAL_SCROLL_BY = window.scrollBy;
-
- var ELEMENT_ORIGINAL_SCROLL_TO = Element.prototype.scrollTo;
-
- var WINDOW_ORIGINAL_SCROLL_TO = window.scrollTo;
-
- /**
- * A fallback if Element.prototype.scroll is not defined
- * @param {number} x
- * @param {number} y
- */
- function elementPrototypeScrollFallback(x, y) {
- this.__adjustingScrollPosition = true;
- this.scrollLeft = x;
- this.scrollTop = y;
- delete this.__adjustingScrollPosition;
- }
- /**
- * A fallback if Element.prototype.scrollTo is not defined
- * @param {number} x
- * @param {number} y
- */
- function elementPrototypeScrollToFallback(x, y) {
- return elementPrototypeScrollFallback.call(this, x, y);
- }
- /**
- * A fallback if Element.prototype.scrollBy is not defined
- * @param {number} x
- * @param {number} y
- */
- function elementPrototypeScrollByFallback(x, y) {
- this.__adjustingScrollPosition = true;
- this.scrollLeft += x;
- this.scrollTop += y;
- delete this.__adjustingScrollPosition;
- }
- /**
- * Gets the original non-patched prototype method for the given kind
- * @param {ScrollMethodName} kind
- * @param {Element|Window} element
- * @return {Function}
- */
- function getOriginalScrollMethodForKind(kind, element) {
- switch (kind) {
- case "scroll":
- if (element instanceof Element) {
- if (ELEMENT_ORIGINAL_SCROLL != null) {
- return ELEMENT_ORIGINAL_SCROLL;
- }
- else {
- return elementPrototypeScrollFallback;
- }
- }
- else {
- return WINDOW_ORIGINAL_SCROLL;
- }
- case "scrollBy":
- if (element instanceof Element) {
- if (ELEMENT_ORIGINAL_SCROLL_BY != null) {
- return ELEMENT_ORIGINAL_SCROLL_BY;
- }
- else {
- return elementPrototypeScrollByFallback;
- }
- }
- else {
- return WINDOW_ORIGINAL_SCROLL_BY;
- }
- case "scrollTo":
- if (element instanceof Element) {
- if (ELEMENT_ORIGINAL_SCROLL_TO != null) {
- return ELEMENT_ORIGINAL_SCROLL_TO;
- }
- else {
- return elementPrototypeScrollToFallback;
- }
- }
- else {
- return WINDOW_ORIGINAL_SCROLL_TO;
- }
- }
- }
-
- /**
- * Gets the Smooth Scroll Options to use for the step function
- * @param {Element|Window} element
- * @param {number} x
- * @param {number} y
- * @param {ScrollMethodName} kind
- * @returns {ISmoothScrollOptions}
- */
- function getSmoothScrollOptions(element, x, y, kind) {
- var startTime = now();
- if (!(element instanceof Element)) {
- // Use window as the scroll container
- var scrollX_1 = window.scrollX, pageXOffset_1 = window.pageXOffset, scrollY_1 = window.scrollY, pageYOffset_1 = window.pageYOffset;
- var startX = scrollX_1 == null || scrollX_1 === 0 ? pageXOffset_1 : scrollX_1;
- var startY = scrollY_1 == null || scrollY_1 === 0 ? pageYOffset_1 : scrollY_1;
- return {
- startTime: startTime,
- startX: startX,
- startY: startY,
- endX: Math.floor(kind === "scrollBy" ? startX + x : x),
- endY: Math.floor(kind === "scrollBy" ? startY + y : y),
- method: getOriginalScrollMethodForKind("scrollTo", window).bind(window)
- };
- }
- else {
- var scrollLeft = element.scrollLeft, scrollTop = element.scrollTop;
- var startX = scrollLeft;
- var startY = scrollTop;
- return {
- startTime: startTime,
- startX: startX,
- startY: startY,
- endX: Math.floor(kind === "scrollBy" ? startX + x : x),
- endY: Math.floor(kind === "scrollBy" ? startY + y : y),
- method: getOriginalScrollMethodForKind("scrollTo", element).bind(element)
- };
- }
- }
-
- /**
- * Ensures that the given value is numeric
- * @param {number} value
- * @return {number}
- */
- function ensureNumeric(value) {
- if (value == null)
- return 0;
- else if (typeof value === "number") {
- return value;
- }
- else if (typeof value === "string") {
- return parseFloat(value);
- }
- else {
- return 0;
- }
- }
-
- /**
- * Returns true if the given value is some ScrollToOptions
- * @param {number | ScrollToOptions} value
- * @return {value is ScrollToOptions}
- */
- function isScrollToOptions(value) {
- return value != null && typeof value === "object";
- }
-
- /**
- * Handles a scroll method
- * @param {Element|Window} element
- * @param {ScrollMethodName} kind
- * @param {number | ScrollToOptions} optionsOrX
- * @param {number} y
- */
- function handleScrollMethod(element, kind, optionsOrX, y) {
- onScrollWithOptions(getScrollToOptionsWithValidation(optionsOrX, y), element, kind);
- }
- /**
- * Invoked when a 'ScrollToOptions' dict is provided to 'scroll()' as the first argument
- * @param {ScrollToOptions} options
- * @param {Element|Window} element
- * @param {ScrollMethodName} kind
- */
- function onScrollWithOptions(options, element, kind) {
- var behavior = getScrollBehavior(element, options);
- // If the behavior is 'auto' apply instantaneous scrolling
- if (behavior == null || behavior === "auto") {
- getOriginalScrollMethodForKind(kind, element).call(element, options.left, options.top);
- }
- else {
- smoothScroll(getSmoothScrollOptions(element, options.left, options.top, kind));
- }
- }
- /**
- * Normalizes the given scroll coordinates
- * @param {number?} x
- * @param {number?} y
- * @return {Required<Pick<ScrollToOptions, "top" | "left">>}
- */
- function normalizeScrollCoordinates(x, y) {
- return {
- left: ensureNumeric(x),
- top: ensureNumeric(y)
- };
- }
- /**
- * Gets ScrollToOptions based on the given arguments. Will throw if validation fails
- * @param {number | ScrollToOptions} optionsOrX
- * @param {number} y
- * @return {Required<ScrollToOptions>}
- */
- function getScrollToOptionsWithValidation(optionsOrX, y) {
- // If only one argument is given, and it isn't an options object, throw a TypeError
- if (y === undefined && !isScrollToOptions(optionsOrX)) {
- throw new TypeError("Failed to execute 'scroll' on 'Element': parameter 1 ('options') is not an object.");
- }
- // Scroll based on the primitive values given as arguments
- if (!isScrollToOptions(optionsOrX)) {
- return __assign({}, normalizeScrollCoordinates(optionsOrX, y), { behavior: "auto" });
- }
- // Scroll based on the received options object
- else {
- return __assign({}, normalizeScrollCoordinates(optionsOrX.left, optionsOrX.top), { behavior: optionsOrX.behavior == null ? "auto" : optionsOrX.behavior });
- }
- }
-
- /**
- * Patches the 'scroll' method on the Element prototype
- */
- function patchElementScroll() {
- Element.prototype.scroll = function (optionsOrX, y) {
- handleScrollMethod(this, "scroll", optionsOrX, y);
- };
- }
-
- /**
- * Patches the 'scrollBy' method on the Element prototype
- */
- function patchElementScrollBy() {
- Element.prototype.scrollBy = function (optionsOrX, y) {
- handleScrollMethod(this, "scrollBy", optionsOrX, y);
- };
- }
-
- /**
- * Patches the 'scrollTo' method on the Element prototype
- */
- function patchElementScrollTo() {
- Element.prototype.scrollTo = function (optionsOrX, y) {
- handleScrollMethod(this, "scrollTo", optionsOrX, y);
- };
- }
-
- /**
- * Patches the 'scroll' method on the Window prototype
- */
- function patchWindowScroll() {
- window.scroll = function (optionsOrX, y) {
- handleScrollMethod(this, "scroll", optionsOrX, y);
- };
- }
-
- /**
- * Patches the 'scrollBy' method on the Window prototype
- */
- function patchWindowScrollBy() {
- window.scrollBy = function (optionsOrX, y) {
- handleScrollMethod(this, "scrollBy", optionsOrX, y);
- };
- }
-
- /**
- * Patches the 'scrollTo' method on the Window prototype
- */
- function patchWindowScrollTo() {
- window.scrollTo = function (optionsOrX, y) {
- handleScrollMethod(this, "scrollTo", optionsOrX, y);
- };
- }
-
- // tslint:disable:no-any
- /**
- * Gets the parent of an element, taking into account DocumentFragments, ShadowRoots, as well as the root context (window)
- * @param {EventTarget} currentElement
- * @returns {EventTarget | null}
- */
- function getParent(currentElement) {
- if ("nodeType" in currentElement && currentElement.nodeType === 1) {
- return currentElement.parentNode;
- }
- if ("ShadowRoot" in window && currentElement instanceof window.ShadowRoot) {
- return currentElement.host;
- }
- else if (currentElement === document) {
- return window;
- }
- else if (currentElement instanceof Node)
- return currentElement.parentNode;
- return null;
- }
-
- var scrollingElement = document.scrollingElement != null ? document.scrollingElement : document.documentElement;
- /**
- * Returns true if the given overflow property represents a scrollable overflow value
- * @param {string | null} overflow
- * @return {boolean}
- */
- function canOverflow(overflow) {
- return overflow !== "visible" && overflow !== "clip";
- }
- /**
- * Returns true if the given element is scrollable
- * @param {Element} element
- * @return {boolean}
- */
- function isScrollable(element) {
- if (element.clientHeight < element.scrollHeight || element.clientWidth < element.scrollWidth) {
- var style = getComputedStyle(element, null);
- return canOverflow(style.overflowY) || canOverflow(style.overflowX);
- }
- return false;
- }
- /**
- * Finds the nearest ancestor of an element that can scroll
- * @param {Element} target
- * @returns {Element|Window?}
- */
- function findNearestAncestorsWithScrollBehavior(target) {
- var currentElement = target;
- while (currentElement != null) {
- var behavior = getScrollBehavior(currentElement);
- if (behavior != null && (currentElement === scrollingElement || isScrollable(currentElement))) {
- return [currentElement, behavior];
- }
- var parent_1 = getParent(currentElement);
- currentElement = parent_1;
- }
- // No such element could be found. Start over, but this time find the nearest ancestor that can simply scroll
- currentElement = target;
- while (currentElement != null) {
- if (currentElement === scrollingElement || isScrollable(currentElement)) {
- return [currentElement, "auto"];
- }
- var parent_2 = getParent(currentElement);
- currentElement = parent_2;
- }
- // Default to the scrolling element
- return [scrollingElement, "auto"];
- }
-
- // tslint:disable:no-any
- /**
- * Finds the nearest root from an element
- * @param {Element} target
- * @returns {Document|ShadowRoot}
- */
- function findNearestRoot(target) {
- var currentElement = target;
- while (currentElement != null) {
- if ("ShadowRoot" in window && currentElement instanceof window.ShadowRoot) {
- // Assume this is a ShadowRoot
- return currentElement;
- }
- var parent_1 = getParent(currentElement);
- if (parent_1 === currentElement) {
- return document;
- }
- currentElement = parent_1;
- }
- return document;
- }
-
- /**
- * A Regular expression that matches id's of the form "#[digit]"
- * @type {RegExp}
- */
- var ID_WITH_LEADING_DIGIT_REGEXP = /^#\d/;
- /**
- * Catches anchor navigation to IDs within the same root and ensures that they can be smooth-scrolled
- * if the scroll behavior is smooth in the first rooter within that context
- */
- function catchNavigation() {
- // Listen for 'click' events globally
- window.addEventListener("click", function (e) {
- // Only work with trusted events on HTMLAnchorElements
- if (!e.isTrusted || !(e.target instanceof HTMLAnchorElement))
- return;
- var hrefAttributeValue = e.target.getAttribute("href");
- // Only work with HTMLAnchorElements that navigates to a specific ID
- if (hrefAttributeValue == null || !hrefAttributeValue.startsWith("#")) {
- return;
- }
- // Find the nearest root, whether it be a ShadowRoot or the document itself
- var root = findNearestRoot(e.target);
- // Attempt to match the selector from that root. querySelector' doesn't support IDs that start with a digit, so work around that limitation
- var elementMatch = hrefAttributeValue.match(ID_WITH_LEADING_DIGIT_REGEXP) != null ? root.getElementById(hrefAttributeValue.slice(1)) : root.querySelector(hrefAttributeValue);
- // If no selector could be found, don't proceed
- if (elementMatch == null)
- return;
- // Find the nearest ancestor that can be scrolled
- var _a = __read(findNearestAncestorsWithScrollBehavior(elementMatch), 2), ancestorWithScrollBehavior = _a[0], behavior = _a[1];
- // If the behavior isn't smooth, don't proceed
- if (behavior !== "smooth")
- return;
- // Otherwise, first prevent the default action.
- e.preventDefault();
- // Now, scroll to the element with that ID
- ancestorWithScrollBehavior.scrollTo({
- behavior: behavior,
- top: elementMatch.offsetTop,
- left: elementMatch.offsetLeft
- });
- });
- }
-
- var ELEMENT_ORIGINAL_SCROLL_INTO_VIEW = Element.prototype.scrollIntoView;
-
- /**
- * The majority of this file is based on https://github.com/stipsan/compute-scroll-into-view (MIT license),
- * but has been rewritten to accept a scroller as an argument.
- */
- /**
- * Find out which edge to align against when logical scroll position is "nearest"
- * Interesting fact: "nearest" works similarly to "if-needed", if the element is fully visible it will not scroll it
- *
- * Legends:
- * ┌────────┐ ┏ ━ ━ ━ ┓
- * │ target │ frame
- * └────────┘ ┗ ━ ━ ━ ┛
- */
- function alignNearest(scrollingEdgeStart, scrollingEdgeEnd, scrollingSize, scrollingBorderStart, scrollingBorderEnd, elementEdgeStart, elementEdgeEnd, elementSize) {
- /**
- * If element edge A and element edge B are both outside scrolling box edge A and scrolling box edge B
- *
- * ┌──┐
- * ┏━│━━│━┓
- * │ │
- * ┃ │ │ ┃ do nothing
- * │ │
- * ┗━│━━│━┛
- * └──┘
- *
- * If element edge C and element edge D are both outside scrolling box edge C and scrolling box edge D
- *
- * ┏ ━ ━ ━ ━ ┓
- * ┌───────────┐
- * │┃ ┃│ do nothing
- * └───────────┘
- * ┗ ━ ━ ━ ━ ┛
- */
- if ((elementEdgeStart < scrollingEdgeStart && elementEdgeEnd > scrollingEdgeEnd) || (elementEdgeStart > scrollingEdgeStart && elementEdgeEnd < scrollingEdgeEnd)) {
- return 0;
- }
- /**
- * If element edge A is outside scrolling box edge A and element height is less than scrolling box height
- *
- * ┌──┐
- * ┏━│━━│━┓ ┏━┌━━┐━┓
- * └──┘ │ │
- * from ┃ ┃ to ┃ └──┘ ┃
- *
- * ┗━ ━━ ━┛ ┗━ ━━ ━┛
- *
- * If element edge B is outside scrolling box edge B and element height is greater than scrolling box height
- *
- * ┏━ ━━ ━┓ ┏━┌━━┐━┓
- * │ │
- * from ┃ ┌──┐ ┃ to ┃ │ │ ┃
- * │ │ │ │
- * ┗━│━━│━┛ ┗━│━━│━┛
- * │ │ └──┘
- * │ │
- * └──┘
- *
- * If element edge C is outside scrolling box edge C and element width is less than scrolling box width
- *
- * from to
- * ┏ ━ ━ ━ ━ ┓ ┏ ━ ━ ━ ━ ┓
- * ┌───┐ ┌───┐
- * │ ┃ │ ┃ ┃ │ ┃
- * └───┘ └───┘
- * ┗ ━ ━ ━ ━ ┛ ┗ ━ ━ ━ ━ ┛
- *
- * If element edge D is outside scrolling box edge D and element width is greater than scrolling box width
- *
- * from to
- * ┏ ━ ━ ━ ━ ┓ ┏ ━ ━ ━ ━ ┓
- * ┌───────────┐ ┌───────────┐
- * ┃ │ ┃ │ ┃ ┃ │
- * └───────────┘ └───────────┘
- * ┗ ━ ━ ━ ━ ┛ ┗ ━ ━ ━ ━ ┛
- */
- if ((elementEdgeStart <= scrollingEdgeStart && elementSize <= scrollingSize) || (elementEdgeEnd >= scrollingEdgeEnd && elementSize >= scrollingSize)) {
- return elementEdgeStart - scrollingEdgeStart - scrollingBorderStart;
- }
- /**
- * If element edge B is outside scrolling box edge B and element height is less than scrolling box height
- *
- * ┏━ ━━ ━┓ ┏━ ━━ ━┓
- *
- * from ┃ ┃ to ┃ ┌──┐ ┃
- * ┌──┐ │ │
- * ┗━│━━│━┛ ┗━└━━┘━┛
- * └──┘
- *
- * If element edge A is outside scrolling box edge A and element height is greater than scrolling box height
- *
- * ┌──┐
- * │ │
- * │ │ ┌──┐
- * ┏━│━━│━┓ ┏━│━━│━┓
- * │ │ │ │
- * from ┃ └──┘ ┃ to ┃ │ │ ┃
- * │ │
- * ┗━ ━━ ━┛ ┗━└━━┘━┛
- *
- * If element edge C is outside scrolling box edge C and element width is greater than scrolling box width
- *
- * from to
- * ┏ ━ ━ ━ ━ ┓ ┏ ━ ━ ━ ━ ┓
- * ┌───────────┐ ┌───────────┐
- * │ ┃ │ ┃ │ ┃ ┃
- * └───────────┘ └───────────┘
- * ┗ ━ ━ ━ ━ ┛ ┗ ━ ━ ━ ━ ┛
- *
- * If element edge D is outside scrolling box edge D and element width is less than scrolling box width
- *
- * from to
- * ┏ ━ ━ ━ ━ ┓ ┏ ━ ━ ━ ━ ┓
- * ┌───┐ ┌───┐
- * ┃ │ ┃ │ ┃ │ ┃
- * └───┘ └───┘
- * ┗ ━ ━ ━ ━ ┛ ┗ ━ ━ ━ ━ ┛
- *
- */
- if ((elementEdgeEnd > scrollingEdgeEnd && elementSize < scrollingSize) || (elementEdgeStart < scrollingEdgeStart && elementSize > scrollingSize)) {
- return elementEdgeEnd - scrollingEdgeEnd + scrollingBorderEnd;
- }
- return 0;
- }
- function computeScrollIntoView(target, scroller, options) {
- var block = options.block, inline = options.inline;
- // Used to handle the top most element that can be scrolled
- var scrollingElement = document.scrollingElement || document.documentElement;
- // Support pinch-zooming properly, making sure elements scroll into the visual viewport
- // Browsers that don't support visualViewport will report the layout viewport dimensions on document.documentElement.clientWidth/Height
- // and viewport dimensions on window.innerWidth/Height
- // https://www.quirksmode.org/mobile/viewports2.html
- // https://bokand.github.io/viewport/index.html
- var viewportWidth = window.visualViewport != null ? visualViewport.width : innerWidth;
- var viewportHeight = window.visualViewport != null ? visualViewport.height : innerHeight;
- var viewportX = window.scrollX != null ? window.scrollX : window.pageXOffset;
- var viewportY = window.scrollY != null ? window.scrollY : window.pageYOffset;
- var _a = target.getBoundingClientRect(), targetHeight = _a.height, targetWidth = _a.width, targetTop = _a.top, targetRight = _a.right, targetBottom = _a.bottom, targetLeft = _a.left;
- // These values mutate as we loop through and generate scroll coordinates
- var targetBlock = block === "start" || block === "nearest" ? targetTop : block === "end" ? targetBottom : targetTop + targetHeight / 2; // block === 'center
- var targetInline = inline === "center" ? targetLeft + targetWidth / 2 : inline === "end" ? targetRight : targetLeft; // inline === 'start || inline === 'nearest
- var _b = scroller.getBoundingClientRect(), height = _b.height, width = _b.width, top = _b.top, right = _b.right, bottom = _b.bottom, left = _b.left;
- var frameStyle = getComputedStyle(scroller);
- var borderLeft = parseInt(frameStyle.borderLeftWidth, 10);
- var borderTop = parseInt(frameStyle.borderTopWidth, 10);
- var borderRight = parseInt(frameStyle.borderRightWidth, 10);
- var borderBottom = parseInt(frameStyle.borderBottomWidth, 10);
- var blockScroll = 0;
- var inlineScroll = 0;
- // The property existance checks for offset[Width|Height] is because only HTMLElement objects have them, but any Element might pass by here
- // @TODO find out if the "as HTMLElement" overrides can be dropped
- var scrollbarWidth = "offsetWidth" in scroller ? scroller.offsetWidth - scroller.clientWidth - borderLeft - borderRight : 0;
- var scrollbarHeight = "offsetHeight" in scroller ? scroller.offsetHeight - scroller.clientHeight - borderTop - borderBottom : 0;
- if (scrollingElement === scroller) {
- // Handle viewport logic (document.documentElement or document.body)
- if (block === "start") {
- blockScroll = targetBlock;
- }
- else if (block === "end") {
- blockScroll = targetBlock - viewportHeight;
- }
- else if (block === "nearest") {
- blockScroll = alignNearest(viewportY, viewportY + viewportHeight, viewportHeight, borderTop, borderBottom, viewportY + targetBlock, viewportY + targetBlock + targetHeight, targetHeight);
- }
- else {
- // block === 'center' is the default
- blockScroll = targetBlock - viewportHeight / 2;
- }
- if (inline === "start") {
- inlineScroll = targetInline;
- }
- else if (inline === "center") {
- inlineScroll = targetInline - viewportWidth / 2;
- }
- else if (inline === "end") {
- inlineScroll = targetInline - viewportWidth;
- }
- else {
- // inline === 'nearest' is the default
- inlineScroll = alignNearest(viewportX, viewportX + viewportWidth, viewportWidth, borderLeft, borderRight, viewportX + targetInline, viewportX + targetInline + targetWidth, targetWidth);
- }
- // Apply scroll position offsets and ensure they are within bounds
- // @TODO add more test cases to cover this 100%
- blockScroll = Math.max(0, blockScroll + viewportY);
- inlineScroll = Math.max(0, inlineScroll + viewportX);
- }
- else {
- // Handle each scrolling frame that might exist between the target and the viewport
- if (block === "start") {
- blockScroll = targetBlock - top - borderTop;
- }
- else if (block === "end") {
- blockScroll = targetBlock - bottom + borderBottom + scrollbarHeight;
- }
- else if (block === "nearest") {
- blockScroll = alignNearest(top, bottom, height, borderTop, borderBottom + scrollbarHeight, targetBlock, targetBlock + targetHeight, targetHeight);
- }
- else {
- // block === 'center' is the default
- blockScroll = targetBlock - (top + height / 2) + scrollbarHeight / 2;
- }
- if (inline === "start") {
- inlineScroll = targetInline - left - borderLeft;
- }
- else if (inline === "center") {
- inlineScroll = targetInline - (left + width / 2) + scrollbarWidth / 2;
- }
- else if (inline === "end") {
- inlineScroll = targetInline - right + borderRight + scrollbarWidth;
- }
- else {
- // inline === 'nearest' is the default
- inlineScroll = alignNearest(left, right, width, borderLeft, borderRight + scrollbarWidth, targetInline, targetInline + targetWidth, targetWidth);
- }
- var scrollLeft = scroller.scrollLeft, scrollTop = scroller.scrollTop;
- // Ensure scroll coordinates are not out of bounds while applying scroll offsets
- blockScroll = Math.max(0, Math.min(scrollTop + blockScroll, scroller.scrollHeight - height + scrollbarHeight));
- inlineScroll = Math.max(0, Math.min(scrollLeft + inlineScroll, scroller.scrollWidth - width + scrollbarWidth));
- }
- return {
- top: blockScroll,
- left: inlineScroll
- };
- }
-
- /**
- * Patches the 'scrollIntoView' method on the Element prototype
- */
- function patchElementScrollIntoView() {
- Element.prototype.scrollIntoView = function (arg) {
- var normalizedOptions = arg == null || arg === true
- ? {
- block: "start",
- inline: "nearest"
- }
- : arg === false
- ? {
- block: "end",
- inline: "nearest"
- }
- : arg;
- // Find the nearest ancestor that can be scrolled
- var _a = __read(findNearestAncestorsWithScrollBehavior(this), 2), ancestorWithScroll = _a[0], ancestorWithScrollBehavior = _a[1];
- var behavior = normalizedOptions.behavior != null ? normalizedOptions.behavior : ancestorWithScrollBehavior;
- // If the behavior isn't smooth, simply invoke the original implementation and do no more
- if (behavior !== "smooth") {
- // Assert that 'scrollIntoView' is actually defined
- if (ELEMENT_ORIGINAL_SCROLL_INTO_VIEW != null) {
- ELEMENT_ORIGINAL_SCROLL_INTO_VIEW.call(this, normalizedOptions);
- }
- // Otherwise, invoke 'scrollTo' instead and provide the scroll coordinates
- else {
- var _b = computeScrollIntoView(this, ancestorWithScroll, normalizedOptions), top_1 = _b.top, left = _b.left;
- getOriginalScrollMethodForKind("scrollTo", this).call(this, left, top_1);
- }
- return;
- }
- ancestorWithScroll.scrollTo(__assign({ behavior: behavior }, computeScrollIntoView(this, ancestorWithScroll, normalizedOptions)));
- };
- }
-
- var ELEMENT_ORIGINAL_SCROLL_TOP_SET_DESCRIPTOR = Object.getOwnPropertyDescriptor(Element.prototype, "scrollTop").set;
-
- /**
- * Patches the 'scrollTop' property descriptor on the Element prototype
- */
- function patchElementScrollTop() {
- Object.defineProperty(Element.prototype, "scrollTop", {
- set: function (scrollTop) {
- if (this.__adjustingScrollPosition) {
- return ELEMENT_ORIGINAL_SCROLL_TOP_SET_DESCRIPTOR.call(this, scrollTop);
- }
- handleScrollMethod(this, "scrollTo", this.scrollLeft, scrollTop);
- return scrollTop;
- }
- });
- }
-
- var ELEMENT_ORIGINAL_SCROLL_LEFT_SET_DESCRIPTOR = Object.getOwnPropertyDescriptor(Element.prototype, "scrollLeft").set;
-
- /**
- * Patches the 'scrollLeft' property descriptor on the Element prototype
- */
- function patchElementScrollLeft() {
- Object.defineProperty(Element.prototype, "scrollLeft", {
- set: function (scrollLeft) {
- if (this.__adjustingScrollPosition) {
- return ELEMENT_ORIGINAL_SCROLL_LEFT_SET_DESCRIPTOR.call(this, scrollLeft);
- }
- handleScrollMethod(this, "scrollTo", scrollLeft, this.scrollTop);
- return scrollLeft;
- }
- });
- }
-
- /**
- * Applies the polyfill
- */
- function patch() {
- // Element.prototype methods
- patchElementScroll();
- patchElementScrollBy();
- patchElementScrollTo();
- patchElementScrollIntoView();
- // Element.prototype descriptors
- patchElementScrollLeft();
- patchElementScrollTop();
- // window methods
- patchWindowScroll();
- patchWindowScrollBy();
- patchWindowScrollTo();
- // Navigation
- catchNavigation();
- }
-
- /**
- * Is true if the browser natively supports the Element.prototype.[scroll|scrollTo|scrollBy|scrollIntoView] methods
- * @type {boolean}
- */
- var SUPPORTS_ELEMENT_PROTOTYPE_SCROLL_METHODS = "scroll" in Element.prototype && "scrollTo" in Element.prototype && "scrollBy" in Element.prototype && "scrollIntoView" in Element.prototype;
-
- if (!SUPPORTS_SCROLL_BEHAVIOR || !SUPPORTS_ELEMENT_PROTOTYPE_SCROLL_METHODS) {
- patch();
- }
-
- }());
|