primevue
Version:
PrimeVue is a premium UI library for Vue featuring a rich set of 90+ components, a theme designer, various theme alternatives such as Material, Bootstrap, Tailwind, premium templates and professional support. In addition, it integrates with PrimeBlock, wh
403 lines (397 loc) • 14.8 kB
JavaScript
import { isElement } from '@primeuix/utils/dom';
import { mergeProps, openBlock, createBlock, resolveDynamicComponent, withCtx, renderSlot, normalizeClass } from 'vue';
import BaseComponent from '@primevue/core/basecomponent';
import ScrollAreaStyle from 'primevue/scrollarea/style';
var script$1 = {
name: 'BaseScrollArea',
"extends": BaseComponent,
props: {
variant: {
type: String,
"default": 'auto'
},
mask: {
type: Boolean,
"default": false
},
as: {
type: [String, Object],
"default": 'DIV'
},
asChild: {
type: Boolean,
"default": false
},
tabIndex: {
type: Number,
"default": 0
}
},
style: ScrollAreaStyle,
provide: function provide() {
return {
$pcScrollArea: this,
$parentInstance: this
};
}
};
var SCROLL_TIMEOUT = 500;
var MIN_HANDLE_SIZE = 20;
var script = {
name: 'ScrollArea',
"extends": script$1,
inheritAttrs: false,
resizeObserver: null,
resizeObserverRaf: null,
rafId: null,
scrollXTimeout: null,
scrollYTimeout: null,
isDragging: false,
dragOrientation: null,
dragStart: {
pointerPos: 0,
scrollPos: 0
},
prevScroll: {
top: 0,
left: 0
},
data: function data() {
return {
viewportEl: null,
scrollbarYEl: null,
scrollbarXEl: null,
hovering: false,
scrollingX: false,
scrollingY: false,
scrollMeta: {
hiddenX: true,
hiddenY: true,
cornerWidth: 0,
cornerHeight: 0,
xBefore: false,
xAfter: false,
yBefore: false,
yAfter: false
}
};
},
watch: {
viewportEl: function viewportEl(newEl, oldEl) {
if (oldEl && oldEl !== newEl) {
this.unbindResizeObserver();
}
if (newEl) {
this.bindResizeObserver();
this.$nextTick(this.computeHandle);
} else {
this.unbindResizeObserver();
}
}
},
beforeUnmount: function beforeUnmount() {
this.unbindResizeObserver();
if (this.scrollXTimeout) {
clearTimeout(this.scrollXTimeout);
this.scrollXTimeout = null;
}
if (this.scrollYTimeout) {
clearTimeout(this.scrollYTimeout);
this.scrollYTimeout = null;
}
if (this.rafId) {
cancelAnimationFrame(this.rafId);
this.rafId = null;
}
},
methods: {
setViewportEl: function setViewportEl(el) {
this.viewportEl = isElement(el) ? el : null;
},
setScrollbarEl: function setScrollbarEl(el, orientation) {
var value = isElement(el) ? el : null;
if (orientation === 'vertical') this.scrollbarYEl = value;else this.scrollbarXEl = value;
if (this.viewportEl) {
this.$nextTick(this.computeHandle);
}
},
getHandleSize: function getHandleSize(scrollbar, isVertical) {
if (!scrollbar) return 0;
var value = scrollbar.style.getPropertyValue(isVertical ? '--px-handle-height' : '--px-handle-width');
return parseFloat(value) || 0;
},
bindResizeObserver: function bindResizeObserver() {
var _this = this;
if (!this.viewportEl || typeof ResizeObserver === 'undefined') return;
this.unbindResizeObserver();
this.resizeObserver = new ResizeObserver(function () {
if (_this.resizeObserverRaf) return;
_this.resizeObserverRaf = requestAnimationFrame(function () {
_this.resizeObserverRaf = null;
_this.computeHandle();
});
});
this.resizeObserver.observe(this.viewportEl);
if (this.viewportEl.firstElementChild) {
this.resizeObserver.observe(this.viewportEl.firstElementChild);
}
},
unbindResizeObserver: function unbindResizeObserver() {
if (this.resizeObserverRaf) {
cancelAnimationFrame(this.resizeObserverRaf);
this.resizeObserverRaf = null;
}
if (this.resizeObserver) {
this.resizeObserver.disconnect();
this.resizeObserver = null;
}
},
computeHandle: function computeHandle() {
var vp = this.viewportEl;
if (!vp) return;
var scrollHeight = vp.scrollHeight,
scrollWidth = vp.scrollWidth,
clientHeight = vp.clientHeight,
clientWidth = vp.clientWidth,
scrollTop = vp.scrollTop,
scrollLeft = vp.scrollLeft;
var yHidden = clientHeight >= scrollHeight;
var xHidden = clientWidth >= scrollWidth;
var scrollbarY = this.scrollbarYEl;
var scrollbarX = this.scrollbarXEl;
var cw = !yHidden && !xHidden && scrollbarY ? scrollbarY.offsetWidth : 0;
var ch = !yHidden && !xHidden && scrollbarX ? scrollbarX.offsetHeight : 0;
var scrollbarYHeight = scrollbarY && !yHidden ? scrollbarY.offsetHeight : 0;
var scrollbarXWidth = scrollbarX && !xHidden ? scrollbarX.offsetWidth : 0;
var next = {
hiddenX: xHidden,
hiddenY: yHidden,
cornerWidth: cw,
cornerHeight: ch,
xBefore: !xHidden && scrollLeft > 0,
xAfter: !xHidden && scrollWidth - clientWidth - scrollLeft > 1,
yBefore: !yHidden && scrollTop > 0,
yAfter: !yHidden && scrollHeight - clientHeight - scrollTop > 1
};
var prev = this.scrollMeta;
var changed = prev.hiddenX !== next.hiddenX || prev.hiddenY !== next.hiddenY || prev.cornerWidth !== next.cornerWidth || prev.cornerHeight !== next.cornerHeight || prev.xBefore !== next.xBefore || prev.xAfter !== next.xAfter || prev.yBefore !== next.yBefore || prev.yAfter !== next.yAfter;
if (changed) {
this.scrollMeta = next;
if (prev.hiddenX !== next.hiddenX || prev.hiddenY !== next.hiddenY) {
this.$nextTick(this.computeHandle);
}
}
if (scrollbarY && !yHidden && scrollbarYHeight > 0) {
var handleRatio = clientHeight / scrollHeight;
var handleHeight = Math.max(handleRatio * scrollbarYHeight, MIN_HANDLE_SIZE);
var availableTrack = scrollbarYHeight - handleHeight;
var maxScrollTop = scrollHeight - clientHeight;
var scrollRatio = maxScrollTop > 0 ? scrollTop / maxScrollTop : 0;
var offsetPx = scrollRatio * availableTrack;
scrollbarY.style.setProperty('--px-handle-height', "".concat(handleHeight, "px"));
scrollbarY.style.setProperty('--px-handle-offset', "".concat(offsetPx, "px"));
} else if (scrollbarY) {
scrollbarY.style.removeProperty('--px-handle-height');
scrollbarY.style.removeProperty('--px-handle-offset');
}
if (scrollbarX && !xHidden && scrollbarXWidth > 0) {
var _handleRatio = clientWidth / scrollWidth;
var handleWidth = Math.max(_handleRatio * scrollbarXWidth, MIN_HANDLE_SIZE);
var _availableTrack = scrollbarXWidth - handleWidth;
var maxScrollLeft = scrollWidth - clientWidth;
var _scrollRatio = maxScrollLeft > 0 ? scrollLeft / maxScrollLeft : 0;
var _offsetPx = _scrollRatio * _availableTrack;
scrollbarX.style.setProperty('--px-handle-width', "".concat(handleWidth, "px"));
scrollbarX.style.setProperty('--px-handle-offset', "".concat(_offsetPx, "px"));
} else if (scrollbarX) {
scrollbarX.style.removeProperty('--px-handle-width');
scrollbarX.style.removeProperty('--px-handle-offset');
}
},
onScroll: function onScroll() {
var _this2 = this;
if (!this.rafId) {
this.rafId = requestAnimationFrame(function () {
_this2.rafId = null;
_this2.computeHandle();
});
}
var vp = this.viewportEl;
if (!vp) return;
var scrollTop = vp.scrollTop,
scrollLeft = vp.scrollLeft;
if (!this.prevScroll) this.prevScroll = {
top: 0,
left: 0
};
var prev = this.prevScroll;
if (scrollTop !== prev.top) {
this.scrollingY = true;
if (this.scrollYTimeout) clearTimeout(this.scrollYTimeout);
this.scrollYTimeout = setTimeout(function () {
_this2.scrollingY = false;
}, SCROLL_TIMEOUT);
}
if (scrollLeft !== prev.left) {
this.scrollingX = true;
if (this.scrollXTimeout) clearTimeout(this.scrollXTimeout);
this.scrollXTimeout = setTimeout(function () {
_this2.scrollingX = false;
}, SCROLL_TIMEOUT);
}
prev.top = scrollTop;
prev.left = scrollLeft;
},
onPointerEnter: function onPointerEnter(event) {
if (event.pointerType !== 'touch') {
this.hovering = true;
}
},
onPointerLeave: function onPointerLeave() {
this.hovering = false;
},
onScrollbarPointerDown: function onScrollbarPointerDown(event, orientation) {
if (event.pointerType === 'mouse' && event.button !== 0) return;
event.preventDefault();
var isVertical = orientation === 'vertical';
var scrollbar = isVertical ? this.scrollbarYEl : this.scrollbarXEl;
var vp = this.viewportEl;
if (!scrollbar || !vp) return;
if (scrollbar.setPointerCapture && event.pointerId != null) {
scrollbar.setPointerCapture(event.pointerId);
}
this.isDragging = true;
this.dragOrientation = orientation;
var rect = scrollbar.getBoundingClientRect();
var handleSize = this.getHandleSize(scrollbar, isVertical);
var trackSize = isVertical ? rect.height : rect.width;
var effectiveTrack = trackSize - handleSize;
if (effectiveTrack > 0) {
var clickPos = (isVertical ? event.clientY - rect.top : event.clientX - rect.left) - handleSize / 2;
var ratio = Math.max(0, Math.min(1, clickPos / effectiveTrack));
var maxScroll = isVertical ? vp.scrollHeight - vp.clientHeight : vp.scrollWidth - vp.clientWidth;
if (isVertical) {
vp.scrollTop = ratio * maxScroll;
} else {
vp.scrollLeft = ratio * maxScroll;
}
}
this.dragStart = {
pointerPos: isVertical ? event.clientY : event.clientX,
scrollPos: isVertical ? vp.scrollTop : vp.scrollLeft
};
},
onScrollbarPointerMove: function onScrollbarPointerMove(event) {
if (!this.isDragging) return;
event.preventDefault();
var isVertical = this.dragOrientation === 'vertical';
var vp = this.viewportEl;
var scrollbar = isVertical ? this.scrollbarYEl : this.scrollbarXEl;
if (!vp || !scrollbar) return;
var rect = scrollbar.getBoundingClientRect();
var handleSize = this.getHandleSize(scrollbar, isVertical);
var trackSize = isVertical ? rect.height : rect.width;
var effectiveTrack = trackSize - handleSize;
if (effectiveTrack <= 0) return;
var currentPos = isVertical ? event.clientY : event.clientX;
var delta = currentPos - this.dragStart.pointerPos;
var maxScroll = isVertical ? vp.scrollHeight - vp.clientHeight : vp.scrollWidth - vp.clientWidth;
var scrollDelta = delta / effectiveTrack * maxScroll;
if (isVertical) {
vp.scrollTop = this.dragStart.scrollPos + scrollDelta;
} else {
vp.scrollLeft = this.dragStart.scrollPos + scrollDelta;
}
},
onScrollbarPointerUp: function onScrollbarPointerUp(event) {
var _event$currentTarget, _event$currentTarget$;
if (!this.isDragging) return;
event.preventDefault();
if ((_event$currentTarget = event.currentTarget) !== null && _event$currentTarget !== void 0 && (_event$currentTarget$ = _event$currentTarget.hasPointerCapture) !== null && _event$currentTarget$ !== void 0 && _event$currentTarget$.call(_event$currentTarget, event.pointerId)) {
event.currentTarget.releasePointerCapture(event.pointerId);
}
this.isDragging = false;
this.dragOrientation = null;
},
onScrollbarWheel: function onScrollbarWheel(event, orientation) {
var vp = this.viewportEl;
if (!vp || event.ctrlKey) return;
event.preventDefault();
if (orientation === 'vertical') {
vp.scrollTop += event.deltaY;
} else {
vp.scrollLeft += event.deltaX || event.deltaY;
}
},
onHandlePointerDown: function onHandlePointerDown(event, orientation) {
if (event.pointerType === 'mouse' && event.button !== 0) return;
event.preventDefault();
event.stopPropagation();
var isVertical = orientation === 'vertical';
var scrollbar = isVertical ? this.scrollbarYEl : this.scrollbarXEl;
var vp = this.viewportEl;
if (!scrollbar || !vp) return;
if (scrollbar.setPointerCapture && event.pointerId != null) {
scrollbar.setPointerCapture(event.pointerId);
}
this.isDragging = true;
this.dragOrientation = orientation;
this.dragStart = {
pointerPos: isVertical ? event.clientY : event.clientX,
scrollPos: isVertical ? vp.scrollTop : vp.scrollLeft
};
}
},
computed: {
rootStyle: function rootStyle() {
return {
'--px-corner-height': "".concat(this.scrollMeta.cornerHeight, "px"),
'--px-corner-width': "".concat(this.scrollMeta.cornerWidth, "px")
};
},
hasOverflowX: function hasOverflowX() {
return !this.scrollMeta.hiddenX;
},
hasOverflowY: function hasOverflowY() {
return !this.scrollMeta.hiddenY;
},
attrs: function attrs() {
return mergeProps(this.a11yAttrs, this.ptmi('root'));
},
a11yAttrs: function a11yAttrs() {
return {
'data-variant': this.variant,
'data-mask': this.mask ? '' : undefined,
'data-scrolling': this.scrollingX || this.scrollingY ? '' : undefined,
'data-has-overflow-x': this.hasOverflowX ? '' : undefined,
'data-has-overflow-y': this.hasOverflowY ? '' : undefined,
'data-scroll-x-before': this.scrollMeta.xBefore ? '' : undefined,
'data-scroll-x-after': this.scrollMeta.xAfter ? '' : undefined,
'data-scroll-y-before': this.scrollMeta.yBefore ? '' : undefined,
'data-scroll-y-after': this.scrollMeta.yAfter ? '' : undefined,
role: 'presentation',
style: this.rootStyle,
onPointerenter: this.onPointerEnter,
onPointerleave: this.onPointerLeave
};
}
}
};
function render(_ctx, _cache, $props, $setup, $data, $options) {
return !_ctx.asChild ? (openBlock(), createBlock(resolveDynamicComponent(_ctx.as), mergeProps({
key: 0,
"class": _ctx.cx('root'),
style: _ctx.sx('root')
}, $options.attrs), {
"default": withCtx(function () {
return [renderSlot(_ctx.$slots, "default")];
}),
_: 3
}, 16, ["class", "style"])) : renderSlot(_ctx.$slots, "default", {
key: 1,
"class": normalizeClass(_ctx.cx('root')),
a11yAttrs: $options.a11yAttrs
});
}
script.render = render;
export { script as default };