line_push/node_modules/vuetify/lib/mixins/activatable/index.js
2022-07-21 03:28:35 +00:00

192 lines
5.2 KiB
JavaScript

// Mixins
import Delayable from '../delayable';
import Toggleable from '../toggleable'; // Utilities
import mixins from '../../util/mixins';
import { getSlot, getSlotType } from '../../util/helpers';
import { consoleError } from '../../util/console';
const baseMixins = mixins(Delayable, Toggleable);
/* @vue/component */
export default baseMixins.extend({
name: 'activatable',
props: {
activator: {
default: null,
validator: val => {
return ['string', 'object'].includes(typeof val);
}
},
disabled: Boolean,
internalActivator: Boolean,
openOnHover: Boolean,
openOnFocus: Boolean
},
data: () => ({
// Do not use this directly, call getActivator() instead
activatorElement: null,
activatorNode: [],
events: ['click', 'mouseenter', 'mouseleave', 'focus'],
listeners: {}
}),
watch: {
activator: 'resetActivator',
openOnFocus: 'resetActivator',
openOnHover: 'resetActivator'
},
mounted() {
const slotType = getSlotType(this, 'activator', true);
if (slotType && ['v-slot', 'normal'].includes(slotType)) {
consoleError(`The activator slot must be bound, try '<template v-slot:activator="{ on }"><v-btn v-on="on">'`, this);
}
this.addActivatorEvents();
},
beforeDestroy() {
this.removeActivatorEvents();
},
methods: {
addActivatorEvents() {
if (!this.activator || this.disabled || !this.getActivator()) return;
this.listeners = this.genActivatorListeners();
const keys = Object.keys(this.listeners);
for (const key of keys) {
this.getActivator().addEventListener(key, this.listeners[key]);
}
},
genActivator() {
const node = getSlot(this, 'activator', Object.assign(this.getValueProxy(), {
on: this.genActivatorListeners(),
attrs: this.genActivatorAttributes()
})) || [];
this.activatorNode = node;
return node;
},
genActivatorAttributes() {
return {
role: 'button',
'aria-haspopup': true,
'aria-expanded': String(this.isActive)
};
},
genActivatorListeners() {
if (this.disabled) return {};
const listeners = {};
if (this.openOnHover) {
listeners.mouseenter = e => {
this.getActivator(e);
this.runDelay('open');
};
listeners.mouseleave = e => {
this.getActivator(e);
this.runDelay('close');
};
} else {
listeners.click = e => {
const activator = this.getActivator(e);
if (activator) activator.focus();
e.stopPropagation();
this.isActive = !this.isActive;
};
}
if (this.openOnFocus) {
listeners.focus = e => {
this.getActivator(e);
e.stopPropagation();
this.isActive = !this.isActive;
};
}
return listeners;
},
getActivator(e) {
// If we've already fetched the activator, re-use
if (this.activatorElement) return this.activatorElement;
let activator = null;
if (this.activator) {
const target = this.internalActivator ? this.$el : document;
if (typeof this.activator === 'string') {
// Selector
activator = target.querySelector(this.activator);
} else if (this.activator.$el) {
// Component (ref)
activator = this.activator.$el;
} else {
// HTMLElement | Element
activator = this.activator;
}
} else if (this.activatorNode.length === 1 || this.activatorNode.length && !e) {
// Use the contents of the activator slot
// There's either only one element in it or we
// don't have a click event to use as a last resort
const vm = this.activatorNode[0].componentInstance;
if (vm && vm.$options.mixins && // Activatable is indirectly used via Menuable
vm.$options.mixins.some(m => m.options && ['activatable', 'menuable'].includes(m.options.name))) {
// Activator is actually another activatible component, use its activator (#8846)
activator = vm.getActivator();
} else {
activator = this.activatorNode[0].elm;
}
} else if (e) {
// Activated by a click or focus event
activator = e.currentTarget || e.target;
}
this.activatorElement = activator;
return this.activatorElement;
},
getContentSlot() {
return getSlot(this, 'default', this.getValueProxy(), true);
},
getValueProxy() {
const self = this;
return {
get value() {
return self.isActive;
},
set value(isActive) {
self.isActive = isActive;
}
};
},
removeActivatorEvents() {
if (!this.activator || !this.activatorElement) return;
const keys = Object.keys(this.listeners);
for (const key of keys) {
this.activatorElement.removeEventListener(key, this.listeners[key]);
}
this.listeners = {};
},
resetActivator() {
this.removeActivatorEvents();
this.activatorElement = null;
this.getActivator();
this.addActivatorEvents();
}
}
});
//# sourceMappingURL=index.js.map