index.js 1.7 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12
import Vue from 'vue';
import Tooltips from './components/tooltips.vue';

let app;

const EVENTS_MAP = {
  hover: 'mouseenter',
  click: 'click',
  focus: 'focus',
};

const DEFAULT_TRIGGER = 'hover focus';
13
const APP_ELEMENT_ID = 'gl-tooltips-app';
14 15 16

const tooltipsApp = () => {
  if (!app) {
17 18 19 20 21
    const container = document.createElement('div');

    container.setAttribute('id', APP_ELEMENT_ID);
    document.body.appendChild(container);

22 23 24 25 26 27 28 29 30
    app = new Vue({
      render(h) {
        return h(Tooltips, {
          props: {
            elements: this.elements,
          },
          ref: 'tooltips',
        });
      },
31
    }).$mount(container);
32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
  }

  return app;
};

const isTooltip = (node, selector) => node.matches && node.matches(selector);

const addTooltips = (elements, config) => {
  tooltipsApp().$refs.tooltips.addTooltips(Array.from(elements), config);
};

const handleTooltipEvent = (rootTarget, e, selector, config = {}) => {
  for (let { target } = e; target && target !== rootTarget; target = target.parentNode) {
    if (isTooltip(target, selector)) {
      addTooltips([target], {
        show: true,
        ...config,
      });
      break;
    }
  }
};

export const initTooltips = (selector, config = {}) => {
  const triggers = config?.triggers || DEFAULT_TRIGGER;
  const events = triggers.split(' ').map(trigger => EVENTS_MAP[trigger]);

  events.forEach(event => {
    document.addEventListener(event, e => handleTooltipEvent(document, e, selector, config), true);
  });

  return tooltipsApp();
};
65 66 67 68 69 70 71 72 73

export const dispose = elements => {
  return tooltipsApp().$refs.tooltips.dispose(elements);
};

export const destroy = () => {
  tooltipsApp().$destroy();
  app = null;
};