import { computed, defineComponent, getCurrentInstance, h, inject, onUnmounted, ref, type Ref } from 'vue';
|
|
import { off, on } from '@jnpf/utils';
|
|
import { BAR_MAP, renderThumbStyle } from './util';
|
|
export default defineComponent({
|
name: 'Bar',
|
|
props: {
|
move: Number,
|
size: String,
|
vertical: Boolean,
|
},
|
|
setup(props) {
|
const instance = getCurrentInstance();
|
const thumb = ref();
|
const wrap = inject('scroll-bar-wrap', {} as Ref<Nullable<HTMLElement>>) as any;
|
const bar = computed(() => {
|
return BAR_MAP[props.vertical ? 'vertical' : 'horizontal'];
|
});
|
const barStore = ref<Recordable>({});
|
const cursorDown = ref();
|
|
const mouseMoveDocumentHandler = (e: any) => {
|
if (cursorDown.value === false) return;
|
const prevPage = barStore.value[bar.value.axis];
|
|
if (!prevPage) return;
|
|
const offset = (instance?.vnode.el?.getBoundingClientRect()[bar.value.direction] - e[bar.value.client]) * -1;
|
const thumbClickPosition = thumb.value[bar.value.offset] - prevPage;
|
const thumbPositionPercentage = ((offset - thumbClickPosition) * 100) / instance?.vnode.el?.[bar.value.offset];
|
wrap.value[bar.value.scroll] = (thumbPositionPercentage * wrap.value[bar.value.scrollSize]) / 100;
|
};
|
|
function mouseUpDocumentHandler() {
|
cursorDown.value = false;
|
barStore.value[bar.value.axis] = 0;
|
off(document, 'mousemove', mouseMoveDocumentHandler);
|
// eslint-disable-next-line unicorn/prefer-add-event-listener
|
document.onselectstart = null;
|
}
|
const startDrag = (e: any) => {
|
e.stopImmediatePropagation();
|
cursorDown.value = true;
|
on(document, 'mousemove', mouseMoveDocumentHandler);
|
on(document, 'mouseup', mouseUpDocumentHandler);
|
document.addEventListener('selectstart', () => false);
|
};
|
const clickThumbHandler = (e: any) => {
|
// prevent click event of right button
|
if (e.ctrlKey || e.button === 2) {
|
return;
|
}
|
window.getSelection()?.removeAllRanges();
|
startDrag(e);
|
barStore.value[bar.value.axis] = e.currentTarget[bar.value.offset] - (e[bar.value.client] - e.currentTarget.getBoundingClientRect()[bar.value.direction]);
|
};
|
|
const clickTrackHandler = (e: any) => {
|
const offset = Math.abs(e.target.getBoundingClientRect()[bar.value.direction] - e[bar.value.client]);
|
const thumbHalf = thumb.value[bar.value.offset] / 2;
|
const thumbPositionPercentage = ((offset - thumbHalf) * 100) / instance?.vnode.el?.[bar.value.offset];
|
|
wrap.value[bar.value.scroll] = (thumbPositionPercentage * wrap.value[bar.value.scrollSize]) / 100;
|
};
|
|
onUnmounted(() => {
|
off(document, 'mouseup', mouseUpDocumentHandler);
|
});
|
|
return () =>
|
h(
|
'div',
|
{
|
class: ['scrollbar__bar', `is-${bar.value.key}`],
|
onMousedown: clickTrackHandler,
|
},
|
h('div', {
|
class: 'scrollbar__thumb',
|
onMousedown: clickThumbHandler,
|
ref: thumb,
|
style: renderThumbStyle({
|
bar: bar.value,
|
move: props.move,
|
size: props.size,
|
}),
|
}),
|
);
|
},
|
});
|