naive-ui
Version:
A Vue 3 Component Library. Fairly Complete, Theme Customizable, Uses TypeScript, Fast
193 lines (192 loc) • 7.87 kB
JavaScript
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.affixPropKeys = exports.affixProps = void 0;
const vue_1 = require("vue");
const seemly_1 = require("seemly");
const _mixins_1 = require("../../_mixins");
const _utils_1 = require("../../_utils");
const utils_1 = require("./utils");
const index_cssr_1 = __importDefault(require("./styles/index.cssr"));
exports.affixProps = {
listenTo: [String, Object, Function],
top: Number,
bottom: Number,
triggerTop: Number,
triggerBottom: Number,
position: {
type: String,
default: 'fixed'
},
// deprecated
offsetTop: {
type: Number,
validator: () => {
if (process.env.NODE_ENV !== 'production') {
(0, _utils_1.warn)('affix', '`offset-top` is deprecated, please use `trigger-top` instead.');
}
return true;
},
default: undefined
},
offsetBottom: {
type: Number,
validator: () => {
if (process.env.NODE_ENV !== 'production') {
(0, _utils_1.warn)('affix', '`offset-bottom` is deprecated, please use `trigger-bottom` instead.');
}
return true;
},
default: undefined
},
target: {
type: Function,
validator: () => {
if (process.env.NODE_ENV !== 'production') {
(0, _utils_1.warn)('affix', '`target` is deprecated, please use `listen-to` instead.');
}
return true;
},
default: undefined
}
};
exports.affixPropKeys = (0, _utils_1.keysOf)(exports.affixProps);
exports.default = (0, vue_1.defineComponent)({
name: 'Affix',
props: exports.affixProps,
setup(props) {
const { mergedClsPrefixRef } = (0, _mixins_1.useConfig)(props);
(0, _mixins_1.useStyle)('-affix', index_cssr_1.default, mergedClsPrefixRef);
let scrollTarget = null;
const stickToTopRef = (0, vue_1.ref)(false);
const stickToBottomRef = (0, vue_1.ref)(false);
const bottomAffixedTriggerScrollTopRef = (0, vue_1.ref)(null);
const topAffixedTriggerScrollTopRef = (0, vue_1.ref)(null);
const affixedRef = (0, vue_1.computed)(() => {
return stickToBottomRef.value || stickToTopRef.value;
});
const mergedOffsetTopRef = (0, vue_1.computed)(() => {
var _a, _b;
return (_b = (_a = props.triggerTop) !== null && _a !== void 0 ? _a : props.offsetTop) !== null && _b !== void 0 ? _b : props.top;
});
const mergedTopRef = (0, vue_1.computed)(() => {
var _a, _b;
return (_b = (_a = props.top) !== null && _a !== void 0 ? _a : props.triggerTop) !== null && _b !== void 0 ? _b : props.offsetTop;
});
const mergedBottomRef = (0, vue_1.computed)(() => {
var _a, _b;
return (_b = (_a = props.bottom) !== null && _a !== void 0 ? _a : props.triggerBottom) !== null && _b !== void 0 ? _b : props.offsetBottom;
});
const mergedOffsetBottomRef = (0, vue_1.computed)(() => {
var _a, _b;
return (_b = (_a = props.triggerBottom) !== null && _a !== void 0 ? _a : props.offsetBottom) !== null && _b !== void 0 ? _b : props.bottom;
});
const selfRef = (0, vue_1.ref)(null);
const init = () => {
const { target: getScrollTarget, listenTo } = props;
if (getScrollTarget) {
// deprecated
scrollTarget = getScrollTarget();
}
else if (listenTo) {
scrollTarget = (0, seemly_1.unwrapElement)(listenTo);
}
else {
scrollTarget = document;
}
if (scrollTarget) {
scrollTarget.addEventListener('scroll', handleScroll);
handleScroll();
}
else if (process.env.NODE_ENV !== 'production') {
(0, _utils_1.warn)('affix', 'Target to be listened to is not valid.');
}
};
function handleScroll() {
(0, seemly_1.beforeNextFrameOnce)(_handleScroll);
}
function _handleScroll() {
const { value: selfEl } = selfRef;
if (!scrollTarget || !selfEl)
return;
const scrollTop = (0, utils_1.getScrollTop)(scrollTarget);
if (affixedRef.value) {
if (topAffixedTriggerScrollTopRef.value !== null
&& scrollTop < topAffixedTriggerScrollTopRef.value) {
stickToTopRef.value = false;
topAffixedTriggerScrollTopRef.value = null;
}
if (bottomAffixedTriggerScrollTopRef.value !== null
&& scrollTop > bottomAffixedTriggerScrollTopRef.value) {
stickToBottomRef.value = false;
bottomAffixedTriggerScrollTopRef.value = null;
}
return;
}
const containerRect = (0, utils_1.getRect)(scrollTarget);
const affixRect = selfEl.getBoundingClientRect();
const pxToTop = affixRect.top - containerRect.top;
const pxToBottom = containerRect.bottom - affixRect.bottom;
const mergedOffsetTop = mergedOffsetTopRef.value;
const mergedOffsetBottom = mergedOffsetBottomRef.value;
if (mergedOffsetTop !== undefined && pxToTop <= mergedOffsetTop) {
stickToTopRef.value = true;
topAffixedTriggerScrollTopRef.value
= scrollTop - (mergedOffsetTop - pxToTop);
}
else {
stickToTopRef.value = false;
topAffixedTriggerScrollTopRef.value = null;
}
if (mergedOffsetBottom !== undefined
&& pxToBottom <= mergedOffsetBottom) {
stickToBottomRef.value = true;
bottomAffixedTriggerScrollTopRef.value
= scrollTop + mergedOffsetBottom - pxToBottom;
}
else {
stickToBottomRef.value = false;
bottomAffixedTriggerScrollTopRef.value = null;
}
}
(0, vue_1.onMounted)(() => {
init();
});
(0, vue_1.onBeforeUnmount)(() => {
if (!scrollTarget)
return;
scrollTarget.removeEventListener('scroll', handleScroll);
});
return {
selfRef,
affixed: affixedRef,
mergedClsPrefix: mergedClsPrefixRef,
mergedstyle: (0, vue_1.computed)(() => {
const style = {};
if (stickToTopRef.value
&& mergedOffsetTopRef.value !== undefined
&& mergedTopRef.value !== undefined) {
style.top = `${mergedTopRef.value}px`;
}
if (stickToBottomRef.value
&& mergedOffsetBottomRef.value !== undefined
&& mergedBottomRef.value !== undefined) {
style.bottom = `${mergedBottomRef.value}px`;
}
return style;
})
};
},
render() {
const { mergedClsPrefix } = this;
return ((0, vue_1.h)("div", { ref: "selfRef", class: [
`${mergedClsPrefix}-affix`,
{
[`${mergedClsPrefix}-affix--affixed`]: this.affixed,
[`${mergedClsPrefix}-affix--absolute-positioned`]: this.position === 'absolute'
}
], style: this.mergedstyle }, this.$slots));
}
});
;