113 lines
3.0 KiB
JavaScript
113 lines
3.0 KiB
JavaScript
import _extends from "@babel/runtime/helpers/esm/extends";
|
|
import ResizeObserver from 'resize-observer-polyfill';
|
|
import { defineComponent, getCurrentInstance, onMounted, onUnmounted, onUpdated, reactive, watch } from 'vue';
|
|
import { findDOMNode } from '../_util/props-util';
|
|
export default defineComponent({
|
|
compatConfig: {
|
|
MODE: 3
|
|
},
|
|
name: 'ResizeObserver',
|
|
props: {
|
|
disabled: Boolean,
|
|
onResize: Function
|
|
},
|
|
emits: ['resize'],
|
|
setup(props, _ref) {
|
|
let {
|
|
slots
|
|
} = _ref;
|
|
const state = reactive({
|
|
width: 0,
|
|
height: 0,
|
|
offsetHeight: 0,
|
|
offsetWidth: 0
|
|
});
|
|
let currentElement = null;
|
|
let resizeObserver = null;
|
|
const destroyObserver = () => {
|
|
if (resizeObserver) {
|
|
resizeObserver.disconnect();
|
|
resizeObserver = null;
|
|
}
|
|
};
|
|
const onResize = entries => {
|
|
const {
|
|
onResize
|
|
} = props;
|
|
const target = entries[0].target;
|
|
const {
|
|
width,
|
|
height
|
|
} = target.getBoundingClientRect();
|
|
const {
|
|
offsetWidth,
|
|
offsetHeight
|
|
} = target;
|
|
/**
|
|
* Resize observer trigger when content size changed.
|
|
* In most case we just care about element size,
|
|
* let's use `boundary` instead of `contentRect` here to avoid shaking.
|
|
*/
|
|
const fixedWidth = Math.floor(width);
|
|
const fixedHeight = Math.floor(height);
|
|
if (state.width !== fixedWidth || state.height !== fixedHeight || state.offsetWidth !== offsetWidth || state.offsetHeight !== offsetHeight) {
|
|
const size = {
|
|
width: fixedWidth,
|
|
height: fixedHeight,
|
|
offsetWidth,
|
|
offsetHeight
|
|
};
|
|
_extends(state, size);
|
|
if (onResize) {
|
|
// defer the callback but not defer to next frame
|
|
Promise.resolve().then(() => {
|
|
onResize(_extends(_extends({}, size), {
|
|
offsetWidth,
|
|
offsetHeight
|
|
}), target);
|
|
});
|
|
}
|
|
}
|
|
};
|
|
const instance = getCurrentInstance();
|
|
const registerObserver = () => {
|
|
const {
|
|
disabled
|
|
} = props;
|
|
// Unregister if disabled
|
|
if (disabled) {
|
|
destroyObserver();
|
|
return;
|
|
}
|
|
// Unregister if element changed
|
|
const element = findDOMNode(instance);
|
|
const elementChanged = element !== currentElement;
|
|
if (elementChanged) {
|
|
destroyObserver();
|
|
currentElement = element;
|
|
}
|
|
if (!resizeObserver && element) {
|
|
resizeObserver = new ResizeObserver(onResize);
|
|
resizeObserver.observe(element);
|
|
}
|
|
};
|
|
onMounted(() => {
|
|
registerObserver();
|
|
});
|
|
onUpdated(() => {
|
|
registerObserver();
|
|
});
|
|
onUnmounted(() => {
|
|
destroyObserver();
|
|
});
|
|
watch(() => props.disabled, () => {
|
|
registerObserver();
|
|
}, {
|
|
flush: 'post'
|
|
});
|
|
return () => {
|
|
var _a;
|
|
return (_a = slots.default) === null || _a === void 0 ? void 0 : _a.call(slots)[0];
|
|
};
|
|
}
|
|
}); |