@aplus-frontend/antdv
Version:
Vue basic component library maintained based on ant-design-vue
85 lines (84 loc) • 2.77 kB
JavaScript
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = useTarget;
var _vue = require("vue");
var _util = require("../util");
var _useState = _interopRequireDefault(require("../../_util/hooks/useState"));
function useTarget(target, open, gap, scrollIntoViewOptions) {
// ========================= Target =========================
// We trade `undefined` as not get target by function yet.
// `null` as empty target.
const [targetElement, setTargetElement] = (0, _useState.default)(undefined);
(0, _vue.watchEffect)(() => {
const nextElement = typeof target.value === 'function' ? target.value() : target.value;
setTargetElement(nextElement || null);
}, {
flush: 'post'
});
// ========================= Align ==========================
const [posInfo, setPosInfo] = (0, _useState.default)(null);
const updatePos = () => {
if (!open.value) {
setPosInfo(null);
return;
}
if (targetElement.value) {
// Exist target element. We should scroll and get target position
if (!(0, _util.isInViewPort)(targetElement.value) && open.value) {
targetElement.value.scrollIntoView(scrollIntoViewOptions.value);
}
const {
left,
top,
width,
height
} = targetElement.value.getBoundingClientRect();
const nextPosInfo = {
left,
top,
width,
height,
radius: 0
};
if (JSON.stringify(posInfo.value) !== JSON.stringify(nextPosInfo)) {
setPosInfo(nextPosInfo);
}
} else {
// Not exist target which means we just show in center
setPosInfo(null);
}
};
(0, _vue.onMounted)(() => {
(0, _vue.watch)([open, targetElement], () => {
updatePos();
}, {
flush: 'post',
immediate: true
});
// update when window resize
window.addEventListener('resize', updatePos);
});
(0, _vue.onBeforeUnmount)(() => {
window.removeEventListener('resize', updatePos);
});
// ======================== PosInfo =========================
const mergedPosInfo = (0, _vue.computed)(() => {
var _a, _b;
if (!posInfo.value) {
return posInfo.value;
}
const gapOffset = ((_a = gap.value) === null || _a === void 0 ? void 0 : _a.offset) || 6;
const gapRadius = ((_b = gap.value) === null || _b === void 0 ? void 0 : _b.radius) || 2;
return {
left: posInfo.value.left - gapOffset,
top: posInfo.value.top - gapOffset,
width: posInfo.value.width + gapOffset * 2,
height: posInfo.value.height + gapOffset * 2,
radius: gapRadius
};
});
return [mergedPosInfo, targetElement];
}
;