lisn.js
Version:
Simply handle user gestures and actions. Includes widgets.
1 lines • 60.1 kB
Source Map (JSON)
{"version":3,"file":"scrollbar.cjs","names":["MC","_interopRequireWildcard","require","MH","_settings","_browser","_cssAlter","_domAlter","_domOptimize","_event","_log","_misc","_scroll","_text","_validation","_scrollWatcher","_sizeWatcher","_widget","_debug","_interopRequireDefault","e","__esModule","default","t","WeakMap","r","n","o","i","f","__proto__","has","get","set","hasOwnProperty","call","Object","defineProperty","getOwnPropertyDescriptor","_defineProperty","_toPropertyKey","value","enumerable","configurable","writable","_toPrimitive","Symbol","toPrimitive","TypeError","String","Number","Scrollbar","Widget","scrollable","mainWidget","getDocElement","getBody","instance","DUMMY_ID","isInstanceOf","enableMain","config","ScrollWatcher","fetchMainScrollableElement","widget","onDestroy","register","registerWidget","WIDGET_NAME","element","isHTMLElement","logError","usageError","configValidator","constructor","_Scrollbar$get","destroyPromise","destroy","id","props","getScrollableProps","ourScrollable","promiseResolve","then","isDestroyed","init","getScrollable","exports","PREFIXED_NAME","prefixName","PREFIX_ROOT","PREFIX_CONTAINER","PREFIX_CONTENT","PREFIX_BAR","PREFIX_WRAPPER","PREFIX_FILL","PREFIX_SPACER","PREFIX_HANDLE","PREFIX_DRAGGABLE","PREFIX_CLICKABLE","PREFIX_HAS_WRAPPER","PREFIX_ALLOW_COLLAPSE","PREFIX_HAS_V_SCROLL","PREFIX_HAS_SCROLLBAR","PREFIX_HIDE_SCROLL","S_SET_POINTER_CAPTURE","S_RELEASE_POINTER_CAPTURE","S_ARIA_VALUENOW","ARIA_PREFIX","S_SCROLLBAR","validateString","className","validateStrList","hideNative","validateBoolean","onMobile","positionH","positionV","autoHide","validateNumber","clickScroll","dragScroll","useHandle","containerElement","mainScrollableElement","tryGetMainScrollableElement","body","defaultScrollable","getDefaultScrollingElement","isBody","isMainScrollable","root","isBodyInQuirks","isInQuirksMode","allowedToWrap","isAllowedToWrap","barParent","hasVScroll","isScrollable","axis","contentWrapper","supported","hasExistingWrapper","getContentWrapper","_classNames","isNullish","warnMsgPrefix","createElement","supportsSticky","logWarn","needsSticky","_config$onMobile","_config$hideNative","_config$autoHide","_config$clickScroll","_config$dragScroll","_config$useHandle","logger","debug","Logger","name","formatAsString","logAtCreation","settings","scrollbarOnMobile","scrollbarHideNative","scrollbarPositionH","scrollbarPositionV","autoHideDelay","scrollbarAutoHide","scrollbarClickScroll","scrollbarDragScroll","scrollbarUseHandle","isMobile","mapScrollable","newScrollbar","wrapper","position","barIsHorizontal","S_TOP","S_BOTTOM","scrollbar","addClassesNow","setDataNow","PREFIX_ORIENTATION","S_HORIZONTAL","S_VERTICAL","PREFIX_PLACE","setAttr","S_ROLE","S_ARIA_CONTROLS","scrollDomID","fill","handle","setBooleanDataNow","moveElementNow","to","_bar","_handle","_fill","setProgress","scrollData","tracksH","scrollbarH","scrollbarV","hasBarPrefix","completeFraction","S_SCROLL_LEFT_FRACTION","S_SCROLL_TOP_FRACTION","viewFraction","S_CLIENT_WIDTH","S_SCROLL_WIDTH","S_CLIENT_HEIGHT","S_SCROLL_HEIGHT","debug9","round","setNumericStyleJsVars","viewFr","completeFr","_numDecimal","scrollAxis","canScroll","noCache","setBooleanData","displayElement","delData","undisplayElement","updateProgress","target","setBoxMeasureProps","showElement","hideElement","updatePropsOnResize","sizeData","barHeight","border","S_HEIGHT","_units","isDragging","lastOffset","lastTargetFraction","scrollAction","onClickOrDrag","event","preventDefault","handleH","handleV","targetOf","isMouseEvent","eventType","type","isClick","S_POINTERDOWN","S_MOUSEDOWN","isHandleClick","hasClass","startsDrag","setOrReleasePointerCapture","debug10","waitForMeasureTime","isHorizontal","barLength","currScrollOffset","S_SCROLL_LEFT","S_SCROLL_TOP","maxScrollOffset","getClientWidthNow","getClientHeightNow","rect","getBoundingClientRect","offset","clientX","left","clientY","top","deltaOffset","handleLength","parseFloat","getComputedStylePropNow","S_WIDTH","targetScrollOffset","targetCoordinates","scrollWatcher","scrollTo","weCanInterrupt","_scrollAction","cancel","elScrollTo","onRelease","onClickOrDragH","onClickOrDragV","onReleaseH","onReleaseV","maybeSetNativeHidden","addClasses","setNativeShown","removeClasses","addWatchers","trackScroll","threshold","sizeWatcher","onResize","removeWatchers","noTrackScroll","offResize","reuse","S_DEBOUNCE_WINDOW","SizeWatcher","wrapChildren","ignoreMove","origDomID","toArrayIfSingle","getOrAssignID","preventSelect","PREFIX_NO_TOUCH_ACTION","setData","PREFIX_POSITION","S_FIXED","S_STICKY","moveElement","addEventListenerTo","S_POINTERMOVE","S_POINTERUP","onDisable","onEnable","unmapScrollable","waitForMutateTime","unwrapContentNow","removeEventListenerFrom","removeClassesNow","S_LEFT","S_RIGHT","delDataNow","getData","side","key","getComputedStyleProp","setStyleProp","prefixCssJsVar","method","isPointerEvent","pointerId"],"sources":["../../../src/ts/widgets/scrollbar.ts"],"sourcesContent":["/**\n * @module Widgets\n */\n\n// [TODO v2]: Instead of wrapping children and changing which element is the\n// actual scrollable (and having to mapScrollable, etc), use the provided\n// element as the scrolling one but wrap IT (not its children) and insert the\n// scrollbars before it. Then remove, \"id\" and \"className\" config options.\n\nimport * as MC from \"@lisn/globals/minification-constants\";\nimport * as MH from \"@lisn/globals/minification-helpers\";\n\nimport { settings } from \"@lisn/globals/settings\";\n\nimport { Position } from \"@lisn/globals/types\";\n\nimport { supportsSticky, isMobile, isInQuirksMode } from \"@lisn/utils/browser\";\nimport {\n showElement,\n hideElement,\n displayElement,\n undisplayElement,\n hasClass,\n addClasses,\n addClassesNow,\n removeClasses,\n removeClassesNow,\n getData,\n setData,\n setBooleanData,\n setBooleanDataNow,\n setDataNow,\n delData,\n delDataNow,\n getComputedStyleProp,\n getComputedStylePropNow,\n setStyleProp,\n setNumericStyleJsVars,\n} from \"@lisn/utils/css-alter\";\nimport {\n moveElementNow,\n moveElement,\n isAllowedToWrap,\n getContentWrapper,\n wrapChildren,\n unwrapContentNow,\n getOrAssignID,\n} from \"@lisn/utils/dom-alter\";\nimport {\n waitForMeasureTime,\n waitForMutateTime,\n} from \"@lisn/utils/dom-optimize\";\nimport {\n addEventListenerTo,\n removeEventListenerFrom,\n preventSelect,\n} from \"@lisn/utils/event\";\nimport { logError, logWarn } from \"@lisn/utils/log\";\nimport { toArrayIfSingle } from \"@lisn/utils/misc\";\nimport {\n isScrollable,\n getDefaultScrollingElement,\n getClientWidthNow,\n getClientHeightNow,\n mapScrollable,\n unmapScrollable,\n tryGetMainScrollableElement,\n ScrollAction,\n} from \"@lisn/utils/scroll\";\nimport { formatAsString } from \"@lisn/utils/text\";\nimport {\n validateStrList,\n validateNumber,\n validateBoolean,\n validateString,\n} from \"@lisn/utils/validation\";\n\nimport { ScrollWatcher, ScrollData } from \"@lisn/watchers/scroll-watcher\";\nimport { SizeWatcher, SizeData } from \"@lisn/watchers/size-watcher\";\n\nimport {\n Widget,\n WidgetConfigValidatorObject,\n registerWidget,\n} from \"@lisn/widgets/widget\";\n\nimport debug from \"@lisn/debug/debug\";\n\n/**\n * Configures the given element, which must be scrollable, to use a\n * {@link Scrollbar}.\n *\n * The Scrollbar widget is a customizable alternative to the native\n * scrollbars (vertical and horizontal). You can position each of the two\n * scrollbars on any of the four sides of the element, make them automatically\n * hide after certain time of inactivity, style them as a traditional handle\n * scrollbar or a percentage fill progress bar and so on.\n *\n * It is also itself draggable/clickable so it _can_ be used to scroll the\n * element similar to the native scrollbar. The drag/click functionality can be\n * disabled too.\n *\n * **NOTE:** If you have disabled the {@link Widgets.PageLoader | PageLoader}\n * and have left {@link ScrollbarConfig.hideNative} ON, but are seeing the\n * native scrollbars just for a fraction of a second at the beginning of the\n * page load, you may want to manually add `lisn-hide-scroll` class on the\n * scrollable element to make sure the scrollbars are hidden as soon as\n * possible (before the scrollbar widget has time to initialize.\n *\n * **IMPORTANT:** If you are using the Scrollbar on an element other than the\n * main scrollable element, it's highly recommended to\n * {@link settings.contentWrappingAllowed | enable content wrapping} (it is\n * enabled by default). Otherwise, Scrollbar will rely on position: sticky. If\n * you want to instead manually create the wrappers yourself, ensure your\n * structure is as follows:\n * ```html\n * <div class=\"scrollable\"><!-- Element you instantiate as Scrollbar -->\n * <div class=\"lisn-scrollbar__content\"><!-- Optional wrapper to avoid relying on sticky -->\n * <div class=\"lisn-wrapper\"><!-- Optional wrapper to enable efficient scroll tracking -->\n * <!-- YOUR CONTENT -->\n * </div>\n * </div>\n * </div>\n * ```\n *\n * **IMPORTANT:** You should not instantiate more than one {@link Scrollbar}\n * widget on a given element. Use {@link Scrollbar.get} to get an existing\n * instance if any. If there is already a widget instance, it will be destroyed!\n *\n * -----\n *\n * You can use the following dynamic attributes or CSS properties in your\n * stylesheet:\n *\n * The following dynamic attributes are set on the element:\n * - `data-lisn-has-scrollbar-top`: `\"true\"` or `\"false\"`\n * - `data-lisn-has-scrollbar-bottom`: `\"true\"` or `\"false\"`\n * - `data-lisn-has-scrollbar-left`: `\"true\"` or `\"false\"`\n * - `data-lisn-has-scrollbar-right`: `\"true\"` or `\"false\"`\n *\n * The following dynamic attributes are set on each progressbar element:\n * - `data-lisn-orientation`: `\"horizontal\"` or `\"vertical\"`\n * - `data-lisn-place`: `\"top\"`, `\"bottom\"`, `\"left\"` or `\"right\"`\n * - `data-lisn-draggable`: `\"true\"` or `\"false\"`\n * - `data-lisn-clickable`: `\"true\"` or `\"false\"`\n *\n * -----\n *\n * To use with auto-widgets (HTML API) (see {@link settings.autoWidgets}), the\n * following CSS classes or data attributes are recognized:\n * - `lisn-scrollbar` class or `data-lisn-scrollbar` attribute set on the\n * scrollable element that you want to enable custom scrollbars for.\n *\n * See below examples for what values you can use set for the data attribute\n * in order to modify the configuration of the automatically created widget.\n *\n * @example\n * This will create custom scrollbars for\n * {@link settings.mainScrollableElementSelector | the main scrolling element}.\n *\n * This will work even if {@link settings.autoWidgets}) is false\n *\n * ```html\n * <!-- LISN should be loaded beforehand -->\n * <script>\n * // You can also just customise global default settings:\n * // LISN.settings.scrollbarPositionV = \"top\";\n * // LISN.settings.scrollbarAutoHide = 3000;\n * // LISN.settings.scrollbarUseHandle = true;\n *\n * LISN.widgets.Scrollbar.enableMain({\n * position: \"top\",\n * autoHide: 3000,\n * useHandle: true\n * });\n * </script>\n * ```\n *\n * @example\n * This will create custom scrollbars for a custom scrolling element (i.e. one\n * with overflow \"auto\" or \"scroll\").\n *\n * ```html\n * <div class=\"scrolling lisn-scrollbar\">\n * <!-- content here... -->\n * </div>\n * ```\n *\n * @example\n * As above but with custom settings.\n *\n * ```html\n * <div\n * class=\"scrolling\"\n * data-lisn-scrollbar=\"hide-native=false\n * | positionH=top\n * | positionV=left\n * | auto-hide=2000\n * | click-scroll=false\n * | drag-scroll=false\n * | use-handle=false\n * \">\n * <!-- content here... -->\n * </div>\n * ```\n */\nexport class Scrollbar extends Widget {\n /**\n * Returns the actual scrollable element us which, unless the scrollable you\n * passed to the constructor is the\n * {@link settings.mainScrollableElementSelector | the main scrolling element}\n * or unless\n * {@link settings.contentWrappingAllowed | you've disabled content wrapping},\n * this will be a new element created by us that is a descendant of the\n * original element you passed.\n */\n readonly getScrollable: () => Element;\n\n /**\n * If element is omitted, returns the instance created by {@link enableMain}\n * if any.\n */\n static get(scrollable?: Element): Scrollbar | null {\n if (!scrollable) {\n return mainWidget;\n }\n\n if (scrollable === MH.getDocElement()) {\n scrollable = MH.getBody();\n }\n\n const instance = super.get(scrollable, DUMMY_ID);\n if (MH.isInstanceOf(instance, Scrollbar)) {\n return instance;\n }\n return null;\n }\n\n /**\n * Enables scrollbars on the\n * {@link settings.mainScrollableElementSelector | the main scrolling element}.\n *\n * **NOTE:** It returns a Promise to a widget because it will wait for the\n * main scrollable element to be present in the DOM if not already.\n */\n static async enableMain(config?: ScrollbarConfig) {\n // [TODO v2]: enableMain should be synchronous and the constructor should\n // wait for the scrollable, allowing users who want to use the main\n // scrollable to just pass null/undefined/window. Then getScrollable should\n // return null or the actual scrollable if available + add fetchScrollable\n // to return a Promise.\n const scrollable = await ScrollWatcher.fetchMainScrollableElement();\n const widget = new Scrollbar(scrollable, config);\n widget.onDestroy(() => {\n if (mainWidget === widget) {\n mainWidget = null;\n }\n });\n\n mainWidget = widget;\n return widget;\n }\n\n static register() {\n registerWidget(\n WIDGET_NAME,\n (element, config) => {\n if (MH.isHTMLElement(element)) {\n if (!Scrollbar.get(element)) {\n return new Scrollbar(element, config);\n }\n } else {\n logError(\n MH.usageError(\"Only HTMLElement is supported for Scrollbar widget\"),\n );\n }\n return null;\n },\n configValidator,\n );\n }\n\n /**\n * Note that passing `document.body` is considered equivalent to\n * `document.documentElement`.\n */\n constructor(scrollable: HTMLElement, config?: ScrollbarConfig) {\n if (scrollable === MH.getDocElement()) {\n scrollable = MH.getBody();\n }\n\n const destroyPromise = Scrollbar.get(scrollable)?.destroy();\n super(scrollable, { id: DUMMY_ID });\n\n const props = getScrollableProps(scrollable);\n const ourScrollable = props.scrollable;\n\n (destroyPromise || MH.promiseResolve()).then(() => {\n if (this.isDestroyed()) {\n return;\n }\n\n init(this, scrollable, props, config);\n });\n\n this.getScrollable = () => ourScrollable;\n }\n}\n\n/**\n * @interface\n */\nexport type ScrollbarConfig = {\n /**\n * The DOM ID to set on the\n * {@link Scrollbar.getScrollable | scrollable element}. Will result in the\n * scrollable element getting this ID. This is useful if the scrollable is a\n * wrapper created by us and you want it to be assigned an ID.\n *\n * **IMPORTANT:** If the scrollable is the\n * {@link settings.mainScrollableElementSelector | the main scrolling element}\n * or {@link settings.contentWrappingAllowed | if you've disabled content wrapping},\n * then the scrollable element provided as the widget element will _not_ have\n * its content wrapped and will remain the actual scrollable. In this case,\n * its ID will be set to this, so if it already has an ID, it will be\n * overridden with this value.\n *\n * @defaultValue undefined\n */\n id?: string;\n\n /**\n * A class name or a list of class names to set on the\n * {@link Scrollbar.getScrollable | scrollable element}. Will result in the\n * scrollable element getting these classes. This is useful if the scrollable\n * is a wrapper created by us and you want it to be assigned classes.\n *\n * See explanation for {@link id}.\n *\n * @defaultValue undefined\n */\n className?: string[] | string;\n\n /**\n * Hide the native scroll bar.\n *\n * Note that the LISN scrollbar is itself draggable/clickable so it\n * _can_ be used to scroll the element similar to the native scrollbar.\n *\n * @defaultValue {@link settings.scrollbarHideNative}\n */\n hideNative?: boolean;\n\n /**\n * Whether to enable also on mobile and tablet devices. Detection is based on\n * user agent.\n *\n * @defaultValue {@link settings.scrollbarOnMobile}\n */\n onMobile?: boolean;\n\n /**\n * Where to place the scrollbar that tracks the horizontal scroll.\n *\n * It does not need to be a horizontal position; it can for example be \"left\"\n * or \"right\".\n *\n * @defaultValue {@link settings.scrollbarPositionH}\n */\n positionH?: Position;\n\n /**\n * Where to place the scrollbar that tracks the vertical scroll.\n *\n * It does not need to be a vertical position; it can for example be \"top\"\n * or \"bottom\".\n *\n * @defaultValue {@link settings.scrollbarPositionV}\n */\n positionV?: Position;\n\n /**\n * Auto-hide the scrollbar when there's no scrolling happening for the given\n * number of milliseconds.\n *\n * Set to 0 or a negative value to disable hiding.\n *\n * @defaultValue {@link settings.scrollbarAutoHide}\n */\n autoHide?: number;\n\n /**\n * Whether to scroll the element when a user clicks anywhere on the\n * scrollbar.\n *\n * @defaultValue {@link settings.scrollbarClickScroll}\n */\n clickScroll?: boolean;\n\n /**\n * Whether to scroll the element when a user drags the handle (if\n * {@link useHandle}) or drags along anywhere on the scrollbar (if _not_\n * {@link useHandle}).\n *\n * @defaultValue {@link settings.scrollbarDragScroll}\n */\n dragScroll?: boolean;\n\n /**\n * Whether to use a traditional fixed-length handle (like the native\n * scrollbar) to indicate the position or the default style of a fill (that\n * starts at the beginning and ends at the scroll fraction).\n *\n * @defaultValue {@link settings.scrollbarUseHandle}\n */\n useHandle?: boolean;\n};\n\n// --------------------\n\nconst WIDGET_NAME = \"scrollbar\";\nconst PREFIXED_NAME = MH.prefixName(WIDGET_NAME);\n// Only one Scrollbar widget per element is allowed, but Widget\n// requires a non-blank ID.\nconst DUMMY_ID = PREFIXED_NAME;\nconst PREFIX_ROOT = `${PREFIXED_NAME}__root`;\nconst PREFIX_CONTAINER = `${PREFIXED_NAME}__container`;\nconst PREFIX_CONTENT = `${PREFIXED_NAME}__content`;\nconst PREFIX_BAR = `${PREFIXED_NAME}__bar`;\nconst PREFIX_WRAPPER = `${PREFIXED_NAME}__wrapper`;\nconst PREFIX_FILL = `${PREFIXED_NAME}__fill`;\nconst PREFIX_SPACER = `${PREFIXED_NAME}__spacer`;\nconst PREFIX_HANDLE = `${PREFIXED_NAME}__handle`;\nconst PREFIX_DRAGGABLE = MH.prefixName(\"draggable\");\nconst PREFIX_CLICKABLE = MH.prefixName(\"clickable\");\nconst PREFIX_HAS_WRAPPER = MH.prefixName(\"has-wrapper\");\nconst PREFIX_ALLOW_COLLAPSE = MH.prefixName(\"allow-collapse\");\nconst PREFIX_HAS_V_SCROLL = MH.prefixName(\"has-v-scroll\");\nconst PREFIX_HAS_SCROLLBAR = MH.prefixName(\"has-scrollbar\");\nconst PREFIX_HIDE_SCROLL = MH.prefixName(\"hide-scroll\");\n\nconst S_SET_POINTER_CAPTURE = \"setPointerCapture\";\nconst S_RELEASE_POINTER_CAPTURE = \"releasePointerCapture\";\nconst S_ARIA_VALUENOW = MC.ARIA_PREFIX + \"valuenow\";\nconst S_SCROLLBAR = \"scrollbar\";\n\nlet mainWidget: Scrollbar | null = null;\n\nconst configValidator: WidgetConfigValidatorObject<ScrollbarConfig> = {\n id: validateString,\n className: validateStrList,\n hideNative: validateBoolean,\n onMobile: validateBoolean,\n positionH: validateString,\n positionV: validateString,\n autoHide: validateNumber,\n clickScroll: validateBoolean,\n dragScroll: validateBoolean,\n useHandle: validateBoolean,\n};\n\nconst getScrollableProps = (containerElement: HTMLElement) => {\n // If main scrollable element doesn't exist yet, then the containerElement\n // passed can't be it anyway, so no need to use fetchMainScrollableElement.\n const mainScrollableElement = tryGetMainScrollableElement();\n\n const body = MH.getBody();\n const defaultScrollable = getDefaultScrollingElement();\n\n const isBody = containerElement === body;\n const isMainScrollable =\n (isBody ? defaultScrollable : containerElement) === mainScrollableElement;\n\n const root: HTMLElement = isMainScrollable\n ? mainScrollableElement\n : isBody\n ? defaultScrollable\n : containerElement;\n\n // check if we're using body in quirks mode\n const isBodyInQuirks = isBody && isInQuirksMode();\n\n const allowedToWrap = isAllowedToWrap(containerElement);\n const barParent = isMainScrollable ? body : containerElement;\n const hasVScroll = isScrollable(root, { axis: \"y\" });\n\n let contentWrapper: HTMLElement | null = null;\n let supported = true;\n let hasExistingWrapper = true;\n\n if (!isMainScrollable && !isBody) {\n // we need to wrap if possible\n contentWrapper = getContentWrapper(containerElement, {\n _classNames: [PREFIX_CONTENT],\n });\n hasExistingWrapper = !MH.isNullish(contentWrapper);\n\n if (!contentWrapper) {\n const warnMsgPrefix =\n \"Scrollbar on elements other than \" +\n \"the main scrollable when content wrapping is \" +\n \"disabled relies on position: sticky\";\n\n if (allowedToWrap) {\n // we'll wrap later, but create the wrapper now as it will be the actual\n // scrollable\n contentWrapper = MH.createElement(\"div\");\n } else if (supportsSticky()) {\n logWarn(`${warnMsgPrefix}, is experimental and may not work properly.`);\n } else {\n logError(`${warnMsgPrefix}, but this browser does not support sticky.`);\n supported = false;\n }\n }\n }\n\n const needsSticky =\n !isMainScrollable && !allowedToWrap && !hasExistingWrapper;\n\n return {\n supported,\n isMainScrollable,\n isBody,\n isBodyInQuirks,\n root,\n scrollable: contentWrapper ?? root,\n barParent,\n contentWrapper,\n hasExistingWrapper,\n needsSticky,\n hasVScroll,\n };\n};\n\nconst init = (\n widget: Scrollbar,\n containerElement: HTMLElement,\n props: ReturnType<typeof getScrollableProps>,\n config: ScrollbarConfig | undefined,\n) => {\n const {\n supported,\n isMainScrollable,\n isBody,\n isBodyInQuirks,\n root,\n scrollable,\n barParent,\n contentWrapper,\n hasExistingWrapper,\n needsSticky,\n hasVScroll,\n } = props;\n\n const logger = debug\n ? new debug.Logger({\n name: `Scrollbar-${formatAsString(root)}`,\n logAtCreation: { props, config },\n })\n : null;\n\n // config\n const onMobile = config?.onMobile ?? settings.scrollbarOnMobile;\n const hideNative = config?.hideNative ?? settings.scrollbarHideNative;\n const positionH = config?.positionH || settings.scrollbarPositionH;\n const positionV = config?.positionV || settings.scrollbarPositionV;\n const autoHideDelay = config?.autoHide ?? settings.scrollbarAutoHide;\n const clickScroll = config?.clickScroll ?? settings.scrollbarClickScroll;\n const dragScroll = config?.dragScroll ?? settings.scrollbarDragScroll;\n const useHandle = config?.useHandle ?? settings.scrollbarUseHandle;\n\n if (isMobile() && !onMobile) {\n return;\n }\n\n // Ensure scroll tracking that will be setup on the original element uses the\n // new scrollable we create.\n // XXX TODO But this still breaks any existing scroll tracking\n mapScrollable(root, scrollable);\n\n // ----------\n\n const newScrollbar = (wrapper: Element, position: string) => {\n const barIsHorizontal = position === MC.S_TOP || position === MC.S_BOTTOM;\n\n const scrollbar = MH.createElement(\"div\");\n addClassesNow(scrollbar, PREFIX_BAR);\n setDataNow(\n scrollbar,\n MC.PREFIX_ORIENTATION,\n barIsHorizontal ? MC.S_HORIZONTAL : MC.S_VERTICAL,\n );\n setDataNow(scrollbar, MC.PREFIX_PLACE, position);\n\n if (clickScroll || dragScroll) {\n MH.setAttr(scrollbar, MC.S_ROLE, S_SCROLLBAR);\n MH.setAttr(scrollbar, MC.S_ARIA_CONTROLS, scrollDomID);\n }\n\n const fill = MH.createElement(\"div\");\n addClassesNow(fill, useHandle ? PREFIX_SPACER : PREFIX_FILL);\n\n let handle: Element | null = null;\n if (useHandle) {\n handle = MH.createElement(\"div\");\n addClassesNow(handle, PREFIX_HANDLE);\n setBooleanDataNow(handle, PREFIX_DRAGGABLE, dragScroll);\n }\n\n setBooleanDataNow(scrollbar, PREFIX_DRAGGABLE, dragScroll && !useHandle);\n setBooleanDataNow(scrollbar, PREFIX_CLICKABLE, clickScroll);\n\n moveElementNow(fill, { to: scrollbar });\n\n if (handle) {\n moveElementNow(handle, { to: scrollbar });\n }\n moveElementNow(scrollbar, { to: wrapper });\n\n return {\n _bar: scrollbar,\n _handle: handle,\n _fill: fill,\n };\n };\n\n // ----------\n\n const setProgress = (scrollData: ScrollData, tracksH: boolean) => {\n const scrollbar = tracksH ? scrollbarH : scrollbarV;\n const hasBarPrefix = `${PREFIX_HAS_SCROLLBAR}-${tracksH ? positionH : positionV}`;\n\n const completeFraction = tracksH\n ? scrollData[MC.S_SCROLL_LEFT_FRACTION]\n : scrollData[MC.S_SCROLL_TOP_FRACTION];\n\n const viewFraction = tracksH\n ? scrollData[MC.S_CLIENT_WIDTH] / scrollData[MC.S_SCROLL_WIDTH]\n : scrollData[MC.S_CLIENT_HEIGHT] / scrollData[MC.S_SCROLL_HEIGHT];\n\n debug: logger?.debug9(\"Updating progress\", {\n tracksH,\n completeFraction,\n viewFraction,\n });\n\n MH.setAttr(\n scrollbar,\n S_ARIA_VALUENOW,\n MH.round(completeFraction * 100) + \"\",\n );\n\n setNumericStyleJsVars(\n scrollbar,\n { viewFr: viewFraction, completeFr: completeFraction },\n { _numDecimal: 4 },\n );\n\n const scrollAxis = tracksH ? \"x\" : \"y\";\n // TODO When using content-box, reading scrollWidth/Height even on the\n // subsequent measure time still shows the \"old\" value that includes the\n // border width before it seems to adjust. So sometimes it gives false\n // positives for it being scrollable.\n const canScroll =\n viewFraction < 0.99 &&\n (completeFraction > 0 ||\n isScrollable(scrollable, {\n axis: scrollAxis,\n noCache: true,\n }));\n\n if (canScroll) {\n setBooleanData(containerElement, hasBarPrefix);\n displayElement(scrollbar);\n } else {\n delData(containerElement, hasBarPrefix);\n undisplayElement(scrollbar);\n }\n };\n\n // ----------\n\n const updateProgress = (target: Element, scrollData: ScrollData) => {\n if (!isMainScrollable && !isBody) {\n setBoxMeasureProps(containerElement);\n }\n\n setProgress(scrollData, true);\n setProgress(scrollData, false);\n\n if (autoHideDelay > 0) {\n showElement(wrapper).then(() => hideElement(wrapper, autoHideDelay));\n }\n };\n\n const updatePropsOnResize = (target: Element, sizeData: SizeData) => {\n setBoxMeasureProps(containerElement);\n setNumericStyleJsVars(\n containerElement,\n { barHeight: sizeData.border[MC.S_HEIGHT] },\n { _units: \"px\", _numDecimal: 2 },\n );\n };\n\n // ----------\n\n let isDragging = false;\n let lastOffset = 0;\n let lastTargetFraction = 0;\n let scrollAction: ScrollAction | null;\n\n const onClickOrDrag = async (event: Event, tracksH: boolean) => {\n MH.preventDefault(event);\n const scrollbar = tracksH ? scrollbarH : scrollbarV;\n const handle = tracksH ? handleH : handleV;\n\n const target = MH.targetOf(event);\n if (!MH.isMouseEvent(event) || !MH.isHTMLElement(target)) {\n return;\n }\n\n const eventType = event.type;\n\n const isClick =\n eventType === MC.S_POINTERDOWN || eventType === MC.S_MOUSEDOWN;\n const isHandleClick =\n isClick && useHandle && hasClass(target, PREFIX_HANDLE);\n const startsDrag = isClick && dragScroll && (isHandleClick || !useHandle);\n\n if (startsDrag) {\n isDragging = true;\n setOrReleasePointerCapture(event, scrollbar, S_SET_POINTER_CAPTURE);\n }\n\n debug: logger?.debug10(\"Click or drag\", {\n eventType,\n isClick,\n isHandleClick,\n isDragging,\n startsDrag,\n });\n\n if ((!isClick && !isDragging) || (isClick && !startsDrag && !clickScroll)) {\n // - Either moving pointer when no drag scroll has been started OR\n // - Clicking when no drag is allowed in the context of the click and no\n // click scroll is allowed either\n return;\n }\n\n await waitForMeasureTime();\n const barIsHorizontal = isHorizontal(scrollbar);\n\n const barLength = barIsHorizontal\n ? scrollbar[MC.S_CLIENT_WIDTH]\n : scrollbar[MC.S_CLIENT_HEIGHT];\n\n const currScrollOffset = tracksH\n ? scrollable[MC.S_SCROLL_LEFT]\n : scrollable[MC.S_SCROLL_TOP];\n\n const maxScrollOffset = tracksH\n ? scrollable[MC.S_SCROLL_WIDTH] - getClientWidthNow(scrollable)\n : scrollable[MC.S_SCROLL_HEIGHT] - getClientHeightNow(scrollable);\n\n // Get click offset relative to the scrollbar regardless of what the\n // event target is and what transforms is has applied.\n const rect = MH.getBoundingClientRect(scrollbar);\n const offset = barIsHorizontal\n ? event.clientX - rect.left\n : event.clientY - rect.top;\n\n debug: logger?.debug10(\"Pointer offset\", offset);\n\n if (offset === lastOffset) {\n return;\n }\n\n const deltaOffset = isClick ? offset : offset - lastOffset;\n lastOffset = offset;\n\n if (!isClick && useHandle) {\n // Dragging the handle\n const handleLength = handle\n ? MH.parseFloat(\n getComputedStylePropNow(\n handle,\n barIsHorizontal ? MC.S_WIDTH : MC.S_HEIGHT,\n ),\n )\n : 0;\n\n lastTargetFraction =\n lastTargetFraction + deltaOffset / (barLength - (handleLength || 0));\n } else if (isHandleClick) {\n // Starting a handle drag\n lastTargetFraction = currScrollOffset / maxScrollOffset;\n } else {\n // Clicking or dragging on the bar -> scroll to the offset under the pointer\n lastTargetFraction = offset / barLength;\n }\n\n if (isHandleClick || (isClick && !clickScroll)) {\n return;\n }\n\n const targetScrollOffset = lastTargetFraction * maxScrollOffset;\n const targetCoordinates = tracksH\n ? { left: targetScrollOffset }\n : { top: targetScrollOffset };\n\n debug: logger?.debug10(\"Scroll target offset\", {\n lastTargetFraction,\n targetCoordinates,\n });\n\n if (isClick) {\n // smooth scroll\n scrollAction = await scrollWatcher.scrollTo(targetCoordinates, {\n scrollable,\n weCanInterrupt: true,\n });\n } else {\n scrollAction?.cancel();\n scrollAction = null;\n MH.elScrollTo(scrollable, targetCoordinates);\n }\n };\n\n // ----------\n\n const onRelease = (event: Event, tracksH: boolean) => {\n const scrollbar = tracksH ? scrollbarH : scrollbarV;\n setOrReleasePointerCapture(event, scrollbar, S_RELEASE_POINTER_CAPTURE);\n\n isDragging = false;\n scrollAction = null;\n };\n\n const onClickOrDragH = (event: Event) => onClickOrDrag(event, true);\n const onClickOrDragV = (event: Event) => onClickOrDrag(event, false);\n const onReleaseH = (event: Event) => onRelease(event, true);\n const onReleaseV = (event: Event) => onRelease(event, false);\n\n // ----------\n\n const maybeSetNativeHidden = () => {\n if (hideNative) {\n addClasses(scrollable, PREFIX_HIDE_SCROLL);\n if (isBodyInQuirks) {\n addClasses(MH.getDocElement(), PREFIX_HIDE_SCROLL);\n }\n }\n };\n\n const setNativeShown = () => {\n removeClasses(scrollable, PREFIX_HIDE_SCROLL);\n if (isBodyInQuirks) {\n removeClasses(MH.getDocElement(), PREFIX_HIDE_SCROLL);\n }\n };\n\n // ----------\n\n const addWatchers = () => {\n // Track scroll in any direction as well as changes in border or content size\n // of the element and its contents.\n scrollWatcher.trackScroll(updateProgress, {\n threshold: 0,\n scrollable,\n });\n\n // Track changes in content or border size of the container element which\n // would also detect changes in its padding.\n sizeWatcher.onResize(updatePropsOnResize, {\n target: containerElement,\n threshold: 0,\n });\n };\n\n const removeWatchers = () => {\n scrollWatcher.noTrackScroll(updateProgress, scrollable);\n sizeWatcher.offResize(updatePropsOnResize, containerElement);\n };\n\n // SETUP ------------------------------\n\n if (!supported) {\n setNativeShown();\n return;\n }\n\n const scrollWatcher = ScrollWatcher.reuse({ [MC.S_DEBOUNCE_WINDOW]: 0 });\n const sizeWatcher = SizeWatcher.reuse({ [MC.S_DEBOUNCE_WINDOW]: 0 });\n\n if (!isMainScrollable && !isBody) {\n addClasses(containerElement, PREFIX_CONTAINER);\n }\n\n setBooleanData(containerElement, PREFIX_ALLOW_COLLAPSE, !isMobile());\n setBooleanData(containerElement, PREFIX_HAS_WRAPPER, !!contentWrapper);\n setBooleanData(\n containerElement,\n PREFIX_HAS_V_SCROLL,\n !!contentWrapper && hasVScroll,\n );\n\n // Wrap children if needed\n if (contentWrapper && !hasExistingWrapper) {\n wrapChildren(containerElement, {\n wrapper: contentWrapper,\n ignoreMove: true,\n }); // no need to await here\n addClasses(contentWrapper, PREFIX_CONTENT);\n }\n\n maybeSetNativeHidden();\n\n const origDomID = scrollable.id;\n if (config?.id) {\n scrollable.id = config.id;\n }\n\n if (config?.className) {\n addClasses(scrollable, ...toArrayIfSingle(config.className));\n }\n\n const scrollDomID = // for ARIA\n clickScroll || dragScroll ? getOrAssignID(scrollable, S_SCROLLBAR) : \"\";\n\n addClasses(barParent, PREFIX_ROOT);\n\n const wrapper = MH.createElement(\"div\");\n preventSelect(wrapper);\n addClasses(wrapper, MC.PREFIX_NO_TOUCH_ACTION);\n addClasses(wrapper, PREFIX_WRAPPER);\n\n if (isBody || isMainScrollable) {\n setData(wrapper, MC.PREFIX_POSITION, MC.S_FIXED);\n } else if (needsSticky) {\n setData(wrapper, MC.PREFIX_POSITION, MC.S_STICKY);\n }\n\n const { _bar: scrollbarH, _handle: handleH } = newScrollbar(\n wrapper,\n positionH,\n );\n const { _bar: scrollbarV, _handle: handleV } = newScrollbar(\n wrapper,\n positionV,\n );\n\n moveElement(wrapper, {\n to: barParent,\n position: \"prepend\",\n });\n\n addWatchers();\n\n // Track clicking and dragging on the two scrollbars\n if (dragScroll) {\n addEventListenerTo(scrollbarH, MC.S_POINTERMOVE, onClickOrDragH);\n addEventListenerTo(scrollbarV, MC.S_POINTERMOVE, onClickOrDragV);\n\n addEventListenerTo(scrollbarH, MC.S_POINTERUP, onReleaseH);\n addEventListenerTo(scrollbarV, MC.S_POINTERUP, onReleaseV);\n }\n\n if (dragScroll || clickScroll) {\n addEventListenerTo(scrollbarH, MC.S_POINTERDOWN, onClickOrDragH);\n addEventListenerTo(scrollbarV, MC.S_POINTERDOWN, onClickOrDragV);\n }\n\n widget.onDisable(() => {\n removeWatchers();\n undisplayElement(scrollbarH);\n undisplayElement(scrollbarV);\n setNativeShown();\n });\n\n widget.onEnable(() => {\n addWatchers();\n displayElement(scrollbarH);\n displayElement(scrollbarV);\n maybeSetNativeHidden();\n });\n\n widget.onDestroy(async () => {\n unmapScrollable(root);\n\n scrollable.id = origDomID;\n if (config?.className) {\n removeClasses(scrollable, ...toArrayIfSingle(config.className));\n }\n\n await waitForMutateTime();\n if (contentWrapper && !hasExistingWrapper) {\n unwrapContentNow(contentWrapper, [PREFIX_CONTENT]);\n }\n\n moveElementNow(wrapper); // remove\n\n if (dragScroll) {\n removeEventListenerFrom(scrollbarH, MC.S_POINTERMOVE, onClickOrDragH);\n removeEventListenerFrom(scrollbarV, MC.S_POINTERMOVE, onClickOrDragV);\n\n removeEventListenerFrom(scrollbarH, MC.S_POINTERUP, onReleaseH);\n removeEventListenerFrom(scrollbarV, MC.S_POINTERUP, onReleaseV);\n }\n\n if (dragScroll || clickScroll) {\n removeEventListenerFrom(scrollbarH, MC.S_POINTERDOWN, onClickOrDragH);\n removeEventListenerFrom(scrollbarV, MC.S_POINTERDOWN, onClickOrDragV);\n }\n\n removeClassesNow(barParent, PREFIX_ROOT);\n removeClassesNow(containerElement, PREFIX_CONTAINER);\n\n for (const position of [MC.S_TOP, MC.S_BOTTOM, MC.S_LEFT, MC.S_RIGHT]) {\n delDataNow(containerElement, `${PREFIX_HAS_SCROLLBAR}-${position}`);\n }\n\n delDataNow(containerElement, PREFIX_ALLOW_COLLAPSE);\n delDataNow(containerElement, PREFIX_HAS_WRAPPER);\n delDataNow(containerElement, PREFIX_HAS_V_SCROLL);\n });\n};\n\nconst isHorizontal = (scrollbar: Element) =>\n getData(scrollbar, MC.PREFIX_ORIENTATION) === MC.S_HORIZONTAL;\n\nconst setBoxMeasureProps = async (element: HTMLElement) => {\n for (const side of [MC.S_TOP, MC.S_RIGHT, MC.S_BOTTOM, MC.S_LEFT]) {\n for (const key of [`padding-${side}`, `border-${side}-width`]) {\n const value = await getComputedStyleProp(element, key);\n setStyleProp(element, MH.prefixCssJsVar(key), value);\n }\n }\n};\n\nconst setOrReleasePointerCapture = (\n event: Event,\n scrollbar: Element,\n method: \"setPointerCapture\" | \"releasePointerCapture\",\n) => {\n if (MH.isPointerEvent(event) && method in scrollbar) {\n scrollbar[method](event.pointerId);\n }\n};\n"],"mappings":"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