Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
package.lib.components.VOverlay.useActivator.mjs Maven / Gradle / Ivy
// Components
import { VMenuSymbol } from "../VMenu/shared.mjs"; // Composables
import { makeDelayProps, useDelay } from "../../composables/delay.mjs"; // Utilities
import { computed, effectScope, inject, mergeProps, nextTick, onScopeDispose, ref, watch, watchEffect } from 'vue';
import { bindProps, getCurrentInstance, IN_BROWSER, matchesSelector, propsFactory, templateRef, unbindProps } from "../../util/index.mjs"; // Types
export const makeActivatorProps = propsFactory({
target: [String, Object],
activator: [String, Object],
activatorProps: {
type: Object,
default: () => ({})
},
openOnClick: {
type: Boolean,
default: undefined
},
openOnHover: Boolean,
openOnFocus: {
type: Boolean,
default: undefined
},
closeOnContentClick: Boolean,
...makeDelayProps()
}, 'VOverlay-activator');
export function useActivator(props, _ref) {
let {
isActive,
isTop
} = _ref;
const vm = getCurrentInstance('useActivator');
const activatorEl = ref();
let isHovered = false;
let isFocused = false;
let firstEnter = true;
const openOnFocus = computed(() => props.openOnFocus || props.openOnFocus == null && props.openOnHover);
const openOnClick = computed(() => props.openOnClick || props.openOnClick == null && !props.openOnHover && !openOnFocus.value);
const {
runOpenDelay,
runCloseDelay
} = useDelay(props, value => {
if (value === (props.openOnHover && isHovered || openOnFocus.value && isFocused) && !(props.openOnHover && isActive.value && !isTop.value)) {
if (isActive.value !== value) {
firstEnter = true;
}
isActive.value = value;
}
});
const cursorTarget = ref();
const availableEvents = {
onClick: e => {
e.stopPropagation();
activatorEl.value = e.currentTarget || e.target;
if (!isActive.value) {
cursorTarget.value = [e.clientX, e.clientY];
}
isActive.value = !isActive.value;
},
onMouseenter: e => {
if (e.sourceCapabilities?.firesTouchEvents) return;
isHovered = true;
activatorEl.value = e.currentTarget || e.target;
runOpenDelay();
},
onMouseleave: e => {
isHovered = false;
runCloseDelay();
},
onFocus: e => {
if (matchesSelector(e.target, ':focus-visible') === false) return;
isFocused = true;
e.stopPropagation();
activatorEl.value = e.currentTarget || e.target;
runOpenDelay();
},
onBlur: e => {
isFocused = false;
e.stopPropagation();
runCloseDelay();
}
};
const activatorEvents = computed(() => {
const events = {};
if (openOnClick.value) {
events.onClick = availableEvents.onClick;
}
if (props.openOnHover) {
events.onMouseenter = availableEvents.onMouseenter;
events.onMouseleave = availableEvents.onMouseleave;
}
if (openOnFocus.value) {
events.onFocus = availableEvents.onFocus;
events.onBlur = availableEvents.onBlur;
}
return events;
});
const contentEvents = computed(() => {
const events = {};
if (props.openOnHover) {
events.onMouseenter = () => {
isHovered = true;
runOpenDelay();
};
events.onMouseleave = () => {
isHovered = false;
runCloseDelay();
};
}
if (openOnFocus.value) {
events.onFocusin = () => {
isFocused = true;
runOpenDelay();
};
events.onFocusout = () => {
isFocused = false;
runCloseDelay();
};
}
if (props.closeOnContentClick) {
const menu = inject(VMenuSymbol, null);
events.onClick = () => {
isActive.value = false;
menu?.closeParents();
};
}
return events;
});
const scrimEvents = computed(() => {
const events = {};
if (props.openOnHover) {
events.onMouseenter = () => {
if (firstEnter) {
isHovered = true;
firstEnter = false;
runOpenDelay();
}
};
events.onMouseleave = () => {
isHovered = false;
runCloseDelay();
};
}
return events;
});
watch(isTop, val => {
if (val && (props.openOnHover && !isHovered && (!openOnFocus.value || !isFocused) || openOnFocus.value && !isFocused && (!props.openOnHover || !isHovered))) {
isActive.value = false;
}
});
watch(isActive, val => {
if (!val) {
setTimeout(() => {
cursorTarget.value = undefined;
});
}
}, {
flush: 'post'
});
const activatorRef = templateRef();
watchEffect(() => {
if (!activatorRef.value) return;
nextTick(() => {
activatorEl.value = activatorRef.el;
});
});
const targetRef = templateRef();
const target = computed(() => {
if (props.target === 'cursor' && cursorTarget.value) return cursorTarget.value;
if (targetRef.value) return targetRef.el;
return getTarget(props.target, vm) || activatorEl.value;
});
const targetEl = computed(() => {
return Array.isArray(target.value) ? undefined : target.value;
});
let scope;
watch(() => !!props.activator, val => {
if (val && IN_BROWSER) {
scope = effectScope();
scope.run(() => {
_useActivator(props, vm, {
activatorEl,
activatorEvents
});
});
} else if (scope) {
scope.stop();
}
}, {
flush: 'post',
immediate: true
});
onScopeDispose(() => {
scope?.stop();
});
return {
activatorEl,
activatorRef,
target,
targetEl,
targetRef,
activatorEvents,
contentEvents,
scrimEvents
};
}
function _useActivator(props, vm, _ref2) {
let {
activatorEl,
activatorEvents
} = _ref2;
watch(() => props.activator, (val, oldVal) => {
if (oldVal && val !== oldVal) {
const activator = getActivator(oldVal);
activator && unbindActivatorProps(activator);
}
if (val) {
nextTick(() => bindActivatorProps());
}
}, {
immediate: true
});
watch(() => props.activatorProps, () => {
bindActivatorProps();
});
onScopeDispose(() => {
unbindActivatorProps();
});
function bindActivatorProps() {
let el = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : getActivator();
let _props = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : props.activatorProps;
if (!el) return;
bindProps(el, mergeProps(activatorEvents.value, _props));
}
function unbindActivatorProps() {
let el = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : getActivator();
let _props = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : props.activatorProps;
if (!el) return;
unbindProps(el, mergeProps(activatorEvents.value, _props));
}
function getActivator() {
let selector = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : props.activator;
const activator = getTarget(selector, vm);
// The activator should only be a valid element (Ignore comments and text nodes)
activatorEl.value = activator?.nodeType === Node.ELEMENT_NODE ? activator : undefined;
return activatorEl.value;
}
}
function getTarget(selector, vm) {
if (!selector) return;
let target;
if (selector === 'parent') {
let el = vm?.proxy?.$el?.parentNode;
while (el?.hasAttribute('data-no-activator')) {
el = el.parentNode;
}
target = el;
} else if (typeof selector === 'string') {
// Selector
target = document.querySelector(selector);
} else if ('$el' in selector) {
// Component (ref)
target = selector.$el;
} else {
// HTMLElement | Element | [x, y]
target = selector;
}
return target;
}
//# sourceMappingURL=useActivator.mjs.map