Files
vue-tippy/src/components/Tippy.ts
T
2021-12-16 14:59:49 +01:00

113 lines
2.5 KiB
TypeScript

import { defineComponent, ref, h, ComponentObjectPropsOptions, onMounted } from 'vue'
import { TippyOptions } from '../types'
import { useTippy } from '../composables'
import tippy, { DefaultProps } from 'tippy.js'
declare module '@vue/runtime-core' {
interface ComponentCustomProps extends TippyOptions { }
}
// const pluginProps = [
// 'animateFill',
// 'followCursor',
// 'inlinePositioning',
// 'sticky',
// ]
const booleanProps = [
'a11y',
'allowHTML',
'arrow',
'flip',
'flipOnUpdate',
'hideOnClick',
'ignoreAttributes',
'inertia',
'interactive',
'lazy',
'multiple',
'showOnInit',
'touch',
'touchHold',
]
let props: ComponentObjectPropsOptions = {}
Object.keys(tippy.defaultProps).forEach((prop: string) => {
if (booleanProps.includes(prop)) {
props[prop] = {
type: Boolean,
default: function () {
return tippy.defaultProps[prop as keyof DefaultProps] as Boolean
},
}
} else {
props[prop] = {
default: function () {
return tippy.defaultProps[prop as keyof DefaultProps]
},
}
}
})
props['to'] = {}
props['tag'] = {
default: 'span'
}
props['contentTag'] = {
default: 'span'
}
props['contentClass'] = {
default: null
}
const TippyComponent = defineComponent({
props,
setup(props, { slots }) {
const elem = ref<Element>()
const contentElem = ref<Element>()
const mounted = ref(false)
let options = { ...props } as TippyOptions;
for (const prop of ['to', 'tag', 'contentTag', 'contentClass']) {
if (options.hasOwnProperty(prop)) {
// @ts-ignore
delete options[prop];
}
}
let target: any = elem
if (props.to) {
if (props.to instanceof Element) {
target = () => props.to
} else if (typeof props.to === 'string' || props.to instanceof String) {
target = () => document.querySelector(props.to)
}
}
const tippy = useTippy(target, options)
onMounted(() => {
mounted.value = true
if (slots.content)
tippy.setContent(() => contentElem.value)
})
return { elem, contentElem, mounted, ...tippy }
},
render() {
let slot = this.$slots.default ? this.$slots.default(this) : []
return h(this.tag, { ref: 'elem', 'data-v-tippy': '' }, this.$slots.content ? [
slot,
this.mounted ? h(this.contentTag, { ref: 'contentElem', class: this.contentClass }, this.$slots.content(this)) : undefined,
] : slot)
},
})
export default TippyComponent