reinerBa / Vue-Responsive

A plugin for responsive handling with vue.js
https://reinerba.github.io/Vue-Responsive/dist/
MIT License
99 stars 6 forks source link

Vue 3? #16

Open hykilpikonna opened 2 years ago

hykilpikonna commented 2 years ago

When will this update to vue 3? And for typescript support?

reinerBa commented 2 years ago

You can code a pull request :)

reinerBa commented 2 years ago

@hykilpikonna I am working on it. Why do you don't tell me that i only need on script for ts support... like described here https://stackoverflow.com/a/58066522/6355502 with some addition from the help site https://www.typescriptlang.org/docs/handbook/compiler-options.html

hykilpikonna commented 2 years ago

@hykilpikonna I am working on it. Why do you don't tell me that i only need on script for ts support... like described here https://stackoverflow.com/a/58066522/6355502 with some addition from the help site https://www.typescriptlang.org/docs/handbook/compiler-options.html

Thank you so much!

Sorry, I didn't know you can generate TS declarations with a script.

reinerBa commented 2 years ago

The IDE gives warnings only because there is no d.ts file. Now i have generated a d.ts file which exports a function full of any-types and the warning pasts away lol .

The most plugins authors create new repositories for there plugins when they change them to be vu3-compatible. I want to serve both versions with one package. That makes the thing so complex.

reinerBa commented 2 years ago

@hykilpikonna Here is the first prototype that works with vue3 https://github.com/reinerBa/Vue-Responsive/commit/54e18ee424ce4e6b27778b5836d42d3e78ec2511

trajano commented 1 year ago

I did a simplistic one based on your code, except I had more complicated logic for determining the size so I made it a function

import { App, ObjectDirective } from "vue";
import { RectToClass } from "./RectToClass";
import { PluginOptions } from "./PluginOptions";
export type { RectToClass };
const updateClassesForElement = (
  element: Element,
  rect: DOMRect,
  elToFunctionMap: Map<Element, RectToClass>,
  possibleClasses: string[]
) => {
  const fn = elToFunctionMap.get(element);
  if (!fn) {
    throw new Error(
      `The element id=${element.id} does not have a rect to class function asssociated.`
    );
  }
  const responsiveClass = fn(rect);
  if (responsiveClass !== null) {
    element.classList.add(responsiveClass);
  }
  possibleClasses
    .filter((c) => c !== responsiveClass)
    .forEach((c) => element.classList.remove(c));
};
export default {
  install: (app: App, options: PluginOptions) => {
    const elToFunctionMap = new Map<Element, RectToClass>();

    const resizeObserver = new ResizeObserver((entries) => {
      entries
        .filter((entry) => elToFunctionMap.has(entry.target))
        .forEach((entry) => {
          const element = entry.target;
          const rect = entry.contentRect;
          updateClassesForElement(
            element,
            rect,
            elToFunctionMap,
            options.classes
          );
        });
    });
    const vResponsive: ObjectDirective<Element, RectToClass> = {
      mounted: (el, binding) => {
        // reregister hook after update
        elToFunctionMap.set(el, binding.value);
        updateClassesForElement(
          el,
          el.getBoundingClientRect(),
          elToFunctionMap,
          options.classes
        );
        resizeObserver.observe(el);
      },
      beforeUpdate: (el) => {
        // deregister the element before update
        resizeObserver.unobserve(el);
      },
      updated: (el, binding) => {
        // reregister hook after update
        elToFunctionMap.set(el, binding.value);
        updateClassesForElement(
          el,
          el.getBoundingClientRect(),
          elToFunctionMap,
          options.classes
        );
        resizeObserver.observe(el);
      },
      beforeUnmount: (el) => {
        // deregister the element before unmount
        resizeObserver.unobserve(el);
        elToFunctionMap.delete(el);
      },
    };

    app.directive("responsive", vResponsive);
    app.mixin({
      beforeUnmount: () => {
        resizeObserver.disconnect();
      },
    });
  },
};
export interface PluginOptions {
    /**
     * List of classes that would be applied.
     */
    classes: string[];
}
export type RectToClass = (rect: DOMRect) => string | null;