@inkline/inkline
Version:
Inkline is the Vue.js UI/UX Library built for creating your next design system
132 lines • 4.11 kB
JavaScript
import { defineComponent } from 'vue';
import { on, off, focusFirstDescendant } from '../helpers/index.mjs';
export default defineComponent({
props: {
disabled: {
type: Boolean,
default: false
},
modelValue: {
type: Boolean,
default: undefined
},
trigger: {
type: Array,
default: () => ['hover', 'click', 'focus']
}
},
emits: ['update:modelValue'],
data() {
return {
visible: this.modelValue,
triggerStack: 0
};
},
watch: {
modelValue(value) {
if (value) {
this.show();
}
else {
this.hide();
}
}
},
mounted() {
if (!this.$slots.default) {
throw new Error('Popup components require one child element to be used as trigger.');
}
this.addEventListeners();
},
beforeUnmount() {
this.removeEventListeners();
},
methods: {
show() {
if (this.disabled || this.visible) {
return;
}
this.triggerStack += 1;
this.visible = true;
this.createPopper();
this.$emit('update:modelValue', true);
},
hide() {
if (this.disabled || !this.visible) {
return;
}
this.triggerStack -= 1;
if (this.triggerStack <= 0) {
this.triggerStack = 0;
this.visible = false;
// Destroyed by <transition> component after transition is finished
// this.destroyPopper();
this.$emit('update:modelValue', false);
}
},
onClick() {
if (this.visible) {
this.hide();
}
else {
this.show();
}
},
onClickOutside() {
if (this.modelValue)
return;
this.hide();
},
addEventListeners() {
[].concat(this.trigger).forEach((trigger) => {
switch (trigger) {
case 'hover':
on(this.$refs.trigger, 'mouseenter', this.show);
on(this.$refs.trigger, 'mouseleave', this.hide);
break;
case 'click':
on(this.$refs.trigger, 'click', this.onClick);
break;
case 'focus':
for (const child of this.$refs.trigger.children) {
on(child, 'focus', this.show);
on(child, 'blur', this.hide);
}
break;
default:
break;
}
});
},
removeEventListeners() {
[].concat(this.trigger).forEach((trigger) => {
switch (trigger) {
case 'hover':
off(this.$refs.trigger, 'mouseenter', this.show);
off(this.$refs.trigger, 'mouseleave', this.hide);
break;
case 'click':
off(this.$refs.trigger, 'click', this.onClick);
break;
case 'focus':
for (const child of this.$refs.trigger.children) {
off(child, 'focus', this.show);
off(child, 'blur', this.hide);
}
break;
default:
break;
}
});
},
focusTrigger() {
for (const child of this.$refs.trigger.children) {
if (focusFirstDescendant(child)) {
child.focus();
break;
}
}
}
}
});
//# sourceMappingURL=PopupControlsMixin.mjs.map