| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081 |
- import { unref } from "vue";
- export const useScroll = () => {
- /**
- * Scrolls to a target element within a scroll container.
- * The function is agnostic to whether the container is a QScrollArea or a native DOM element.
- *
- * @param {Ref<Component|HTMLElement>} targetRef - Ref to the target component or DOM element.
- * @param {Ref<Component|HTMLElement>} containerRef - Ref to the container (QScrollArea or a scrollable DOM element like body).
- * @param {Object} options - Scroll options.
- * @param {number} options.offset - Offset from the top in pixels (default: 50).
- * @param {number} options.duration - Animation duration for QScrollArea (default: 150). Note: duration is not supported for native scrolling.
- * @returns {boolean} - Whether the scroll was successful.
- */
- const scrollToComponent = (targetRef, containerRef, options = {}) => {
- const { offset = 150, duration = 150 } = options;
- const targetInstance = unref(targetRef);
- const containerInstance = unref(containerRef);
- const targetElement = targetInstance?.$el ?? targetInstance;
- const containerElement = containerInstance?.$el ?? containerInstance;
- if (!targetElement || !containerElement) {
- console.warn("useScroll: Target or container element not found");
- return false;
- }
- try {
- let currentElement = targetElement;
- let offsetTop = 0;
- while (currentElement && currentElement !== containerElement) {
- offsetTop += currentElement.offsetTop;
- if (
- containerElement.contains(currentElement.offsetParent) ||
- containerElement === document.body
- ) {
- currentElement = currentElement.offsetParent;
- } else {
- currentElement = null;
- }
- }
- if (
- containerElement !== document.body &&
- !containerElement.contains(targetElement)
- ) {
- console.warn("useScroll: Target is not a child of the container");
- return false;
- }
- const targetPosition = Math.max(0, offsetTop - offset);
- if (typeof containerInstance.setScrollPosition === "function") {
- containerInstance.setScrollPosition(
- "vertical",
- targetPosition,
- duration,
- );
- } else {
- const scrollable =
- containerElement === document.body ? window : containerElement;
- scrollable.scrollTo({
- top: targetPosition,
- behavior: "smooth",
- });
- }
- return true;
- } catch (error) {
- console.error("useScroll: Error while scrolling", error);
- return false;
- }
- };
- return {
- scrollToComponent,
- };
- };
|