UNPKG

vuescroll

Version:

A beautiful scrollbar based on Vue.js for PC and mobile.

261 lines (258 loc) 7.39 kB
// begin importing import { getGutter, isSupportGivenStyle, isIE, insertChildrenIntoSlot, getRealParent } from '../../util'; import { createContent } from './vuescroll-content'; // vueScrollPanel export default { name: 'scrollPanel', props: { ops: { type: Object, required: true } }, methods: { // trigger scrollPanel options initialScrollX, // initialScrollY updateInitialScroll() { let x = 0; let y = 0; const parent = getRealParent(this); if (this.ops.initialScrollX) { x = this.ops.initialScrollX; } if (this.ops.initialScrollY) { y = this.ops.initialScrollY; } if (x || y) { parent.scrollTo({ x, y }); } } }, mounted() { setTimeout(() => { if (!this._isDestroyed) { this.updateInitialScroll(); } }, 0); }, render(h) { // eslint-disable-line let data = { class: ['vuescroll-panel'] }; const parent = getRealParent(this); const customPanel = parent.$slots['scroll-panel']; if (customPanel) { return insertChildrenIntoSlot(h, customPanel, this.$slots.default, data); } return <div {...data}>{[this.$slots.default]}</div>; } }; /** * create a scrollPanel * * @param {any} size * @param {any} vm * @returns */ export function createPanel(h, vm) { // scrollPanel data start const scrollPanelData = { ref: 'scrollPanel', style: {}, class: [], nativeOn: { scroll: vm.handleScroll }, props: { ops: vm.mergedOptions.scrollPanel } }; // set overflow only if the in native mode if (vm.mode == 'native') { scrollPanelData.class.push('__native'); // dynamic set overflow scroll // feat: #11 if (vm.mergedOptions.scrollPanel.scrollingY) { scrollPanelData.style['overflowY'] = vm.bar.vBar.state.size ? 'scroll' : ''; } else { scrollPanelData.style['overflowY'] = 'hidden'; } if (vm.mergedOptions.scrollPanel.scrollingX) { scrollPanelData.style['overflowX'] = vm.bar.hBar.state.size ? 'scroll' : ''; } else { scrollPanelData.style['overflowX'] = 'hidden'; } let gutter = getGutter(); /* istanbul ignore if */ if (!gutter && vm.mergedOptions.vuescroll.mode != 'pure-native') { scrollPanelData.class.push('__hidebar'); } else { // hide system bar by use a negative value px // gutter should be 0 when manually disable scrollingX #14 if (vm.bar.vBar.state.size && vm.mergedOptions.scrollPanel.scrollingY) { scrollPanelData.style.marginRight = `-${gutter}px`; } if (vm.bar.hBar.state.size && vm.mergedOptions.scrollPanel.scrollingX) { scrollPanelData.style.height = `calc(100% + ${gutter}px)`; } } // clear legency styles of slide mode... scrollPanelData.style.transformOrigin = ''; scrollPanelData.style.transform = ''; } else if (vm.mode == 'slide') { scrollPanelData.class.push('__slide'); let width = isSupportGivenStyle('width', 'fit-content'); if (width) { scrollPanelData.style['width'] = width; } /* istanbul ignore next */ else { // fallback to inline block while // doesn't support 'fit-content', // this may cause some issues, but this // can make `resize` event work... scrollPanelData['display'] = 'inline-block'; } } else if (vm.mode == 'pure-native') { scrollPanelData.class.push('__pure-native'); if (vm.mergedOptions.scrollPanel.scrollingY) { scrollPanelData.style['overflowY'] = 'auto'; } else { scrollPanelData.style['overflowY'] = 'hidden'; } if (vm.mergedOptions.scrollPanel.scrollingX) { scrollPanelData.style['overflowX'] = 'auto'; } else { scrollPanelData.style['overflowX'] = 'hidden'; } } return ( <scrollPanel {...scrollPanelData}>{createPanelChildren(vm, h)}</scrollPanel> ); } function createPanelChildren(vm, h) { if (vm.mode == 'native') { return [createContent(h, vm)]; } else if (vm.mode == 'slide') { let renderChildren = [vm.$slots.default]; // handle for refresh if (vm.mergedOptions.vuescroll.pullRefresh.enable) { // use default refresh dom let refreshDom = null; refreshDom = createTipDom(h, vm, 'refresh'); renderChildren.unshift( <div class="vuescroll-refresh" ref="refreshDom" key="refshDom"> {[refreshDom, vm.pullRefreshTip]} </div> ); } // handle for load if (vm.mergedOptions.vuescroll.pushLoad.enable) { let loadDom = null; loadDom = createTipDom(h, vm, 'load'); // no slot load elm, use default renderChildren.push( <div class="vuescroll-load" ref="loadDom" key="loadDom"> {[loadDom, vm.pushLoadTip]} </div> ); } return renderChildren; } else if (vm.mode == 'pure-native') { return [vm.$slots.default]; } } // create load or refresh tip dom function createTipDom(h, vm, type) { const stage = vm.vuescroll.state[`${type}Stage`]; let dom = null; /* istanbul ignore if */ if ((dom = vm.$slots[`${type}-${stage}`])) { return dom[0]; } switch (stage) { case 'deactive': dom = ( <svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlnsXlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 1000 1000" enable-background="new 0 0 1000 1000" xmlSpace="preserve" > <metadata> Svg Vector Icons : http://www.sfont.cn </metadata> <g> <g transform="matrix(1 0 0 -1 0 1008)"> <path d="M10,543l490,455l490-455L885,438L570,735.5V18H430v717.5L115,438L10,543z" /> </g> </g> </svg> ); break; case 'start': // IE seems not supporting animateTransform /* istanbul ignore if */ if (isIE()) { dom = null; break; } dom = ( <svg version="1.1" id="loader-1" xmlns="http://www.w3.org/2000/svg" xmlnsXlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 50 50" style="enable-background:new 0 0 50 50;" xmlSpace="preserve" > <path fill="#000" d="M43.935,25.145c0-10.318-8.364-18.683-18.683-18.683c-10.318,0-18.683,8.365-18.683,18.683h4.068c0-8.071,6.543-14.615,14.615-14.615c8.072,0,14.615,6.543,14.615,14.615H43.935z" > <animateTransform attributeType="xml" attributeName="transform" type="rotate" from="0 25 25" to="360 25 25" dur="0.6s" repeatCount="indefinite" /> </path> </svg> ); break; case 'active': dom = ( <svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlnsXlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 1000 1000" enable-background="new 0 0 1000 1000" xmlSpace="preserve" > <metadata> Svg Vector Icons : http://www.sfont.cn </metadata> <g> <g transform="matrix(1 0 0 -1 0 1008)"> <path d="M500,18L10,473l105,105l315-297.5V998h140V280.5L885,578l105-105L500,18z" /> </g> </g> </svg> ); break; } return dom; }