vuestic-ui
Version:
Vue 3 UI Framework
85 lines (84 loc) • 2.95 kB
JavaScript
import { computed, ref } from "vue";
import { offset, flip, shift, size, useFloating, autoUpdate } from "@floating-ui/vue";
import { u as usePlacementAliases } from "../../../composables/usePlacementAliases.js";
const useDropdown = (anchorComputed, floating, target, options) => {
const placementComputed = computed(() => {
const { position, align } = usePlacementAliases({ placement: options.value.placement });
return `${position.value}-${align.value}`;
});
const offsetComputed = computed(() => {
const dropdownOffset = options.value.offset;
const result = { mainAxis: 0, crossAxis: 0 };
if (Array.isArray(dropdownOffset)) {
result.mainAxis = dropdownOffset[0];
result.crossAxis = dropdownOffset[1];
}
if (typeof dropdownOffset === "number") {
result.mainAxis = dropdownOffset;
}
return result;
});
const middlewareComputed = computed(() => {
const { autoPlacement, stickToEdges, keepAnchorWidth, verticalScrollOnOverflow } = options.value;
const result = [
offset(offsetComputed.value)
];
if (autoPlacement) {
result.push(
// boundary doesn't work with ssr (trying to access document)
flip({
boundary: target.value
})
);
}
if (stickToEdges) {
result.push(
shift()
);
}
if (keepAnchorWidth || verticalScrollOnOverflow) {
result.push(size({
apply({ elements, availableHeight }) {
if (keepAnchorWidth) {
const reference = elements.reference;
const availableWidth = reference.getBoundingClientRect().width;
Object.assign(elements.floating.style, {
// Don't set width here, because some plugin applies width 100% and it breaks layout
maxWidth: `${availableWidth}px`,
minWidth: `${availableWidth}px`
});
}
if (verticalScrollOnOverflow) {
Object.assign(elements.floating.style, {
maxHeight: `${availableHeight}px`
});
}
}
}));
}
return result;
});
const { floatingStyles, isPositioned } = typeof document === "undefined" ? { floatingStyles: {}, isPositioned: ref(false) } : useFloating(anchorComputed, floating, {
placement: placementComputed,
whileElementsMounted: autoUpdate,
middleware: middlewareComputed,
transform: true
});
return {
// Because floating ui by default set top and left to 0 before position calculated, dropdown jumps to the left top corner
// If user wants to make focus on el as soon as Dropdown is opened, page will be scrolled on the left top corner
floatingStyles: computed(() => {
if (!isPositioned.value) {
return {
position: "fixed"
};
}
return floatingStyles.value;
}),
isPositioned
};
};
export {
useDropdown as u
};
//# sourceMappingURL=useDropdown.js.map