useScroll.js 2.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071
  1. import { unref } from "vue";
  2. const resolveElement = (reference) => {
  3. const value = unref(reference);
  4. return value?.$el ?? value;
  5. };
  6. export const useScroll = () => {
  7. /**
  8. * Scrolls to a specific component within a scroll container
  9. * @param {Ref<Component>} targetRef - Reference to the component to scroll to
  10. * @param {Ref<Component>} containerRef - Reference to the Quasar ScrollArea component
  11. * @param {Object} options - Scroll options
  12. * @param {number} options.offset - Offset from the top in pixels (default: 50)
  13. * @param {number} options.duration - Animation duration in milliseconds (default: 150)
  14. * @returns {boolean} - Whether the scroll was successful
  15. */
  16. const scrollToComponent = (targetRef, containerRef, options = {}) => {
  17. const { offset = 50, duration = 150 } = options;
  18. const targetElement = resolveElement(targetRef);
  19. const container = unref(containerRef);
  20. const containerElement = resolveElement(containerRef);
  21. if (
  22. !targetElement?.getBoundingClientRect ||
  23. !containerElement?.getBoundingClientRect
  24. ) {
  25. console.warn("useScroll: Target or container element not found");
  26. return false;
  27. }
  28. try {
  29. if (!containerElement.contains(targetElement)) {
  30. console.warn("useScroll: Target is not a child of the container");
  31. return false;
  32. }
  33. const currentPosition =
  34. container?.getScrollPosition?.().top ?? containerElement.scrollTop ?? 0;
  35. const targetPosition = Math.max(
  36. 0,
  37. currentPosition +
  38. targetElement.getBoundingClientRect().top -
  39. containerElement.getBoundingClientRect().top -
  40. offset,
  41. );
  42. if (typeof container?.setScrollPosition === "function") {
  43. container.setScrollPosition("vertical", targetPosition, duration);
  44. } else if (typeof containerElement.scrollTo === "function") {
  45. containerElement.scrollTo({
  46. top: targetPosition,
  47. behavior: duration > 0 ? "smooth" : "auto",
  48. });
  49. } else {
  50. containerElement.scrollTop = targetPosition;
  51. }
  52. return true;
  53. } catch (error) {
  54. console.error("useScroll: Error while scrolling", error);
  55. return false;
  56. }
  57. };
  58. return {
  59. scrollToComponent,
  60. };
  61. };