UNPKG

quasar

Version:

Build high-performance VueJS user interfaces (SPA, PWA, SSR, Mobile and Desktop) in record time

283 lines (228 loc) 6.86 kB
import { h, ref, computed, watch, nextTick, getCurrentInstance, Transition, KeepAlive } from 'vue' import TouchSwipe from '../../directives/TouchSwipe.js' import useCache from '../../composables/private/use-cache.js' import { hSlot } from '../../utils/private/render.js' import { getNormalizedVNodes } from '../../utils/private/vm.js' export const usePanelChildProps = { name: { required: true }, disable: Boolean } const PanelWrapper = { setup (_, { slots }) { return () => h('div', { class: 'q-panel scroll', role: 'tabpanel' }, hSlot(slots.default)) } } export const usePanelProps = { modelValue: { required: true }, animated: Boolean, infinite: Boolean, swipeable: Boolean, vertical: Boolean, transitionPrev: String, transitionNext: String, transitionDuration: { type: [ String, Number ], default: 300 }, keepAlive: Boolean, keepAliveInclude: [ String, Array, RegExp ], keepAliveExclude: [ String, Array, RegExp ], keepAliveMax: Number } export const usePanelEmits = [ 'update:modelValue', 'beforeTransition', 'transition' ] export default function () { const { props, emit, proxy } = getCurrentInstance() const { getCacheWithFn } = useCache() let panels, forcedPanelTransition const panelIndex = ref(null) const panelTransition = ref(null) function onSwipe (evt) { const dir = props.vertical === true ? 'up' : 'left' goToPanelByOffset((proxy.$q.lang.rtl === true ? -1 : 1) * (evt.direction === dir ? 1 : -1)) } const panelDirectives = computed(() => { // if props.swipeable return [ [ TouchSwipe, onSwipe, void 0, { horizontal: props.vertical !== true, vertical: props.vertical, mouse: true } ] ] }) const transitionPrev = computed(() => props.transitionPrev || `slide-${ props.vertical === true ? 'down' : 'right' }` ) const transitionNext = computed(() => props.transitionNext || `slide-${ props.vertical === true ? 'up' : 'left' }` ) const transitionStyle = computed( () => `--q-transition-duration: ${ props.transitionDuration }ms` ) const contentKey = computed(() => ( typeof props.modelValue === 'string' || typeof props.modelValue === 'number' ? props.modelValue : String(props.modelValue) )) const keepAliveProps = computed(() => ({ include: props.keepAliveInclude, exclude: props.keepAliveExclude, max: props.keepAliveMax })) const needsUniqueKeepAliveWrapper = computed(() => props.keepAliveInclude !== void 0 || props.keepAliveExclude !== void 0 ) watch(() => props.modelValue, (newVal, oldVal) => { const index = isValidPanelName(newVal) === true ? getPanelIndex(newVal) : -1 if (forcedPanelTransition !== true) { updatePanelTransition( index === -1 ? 0 : (index < getPanelIndex(oldVal) ? -1 : 1) ) } if (panelIndex.value !== index) { panelIndex.value = index emit('beforeTransition', newVal, oldVal) nextTick(() => { emit('transition', newVal, oldVal) }) } }) function nextPanel () { goToPanelByOffset(1) } function previousPanel () { goToPanelByOffset(-1) } function goToPanel (name) { emit('update:modelValue', name) } function isValidPanelName (name) { return name !== void 0 && name !== null && name !== '' } function getPanelIndex (name) { return panels.findIndex(panel => { return panel.props.name === name && panel.props.disable !== '' && panel.props.disable !== true }) } function getEnabledPanels () { return panels.filter(panel => { return panel.props.disable !== '' && panel.props.disable !== true }) } function updatePanelTransition (direction) { const val = direction !== 0 && props.animated === true && panelIndex.value !== -1 ? 'q-transition--' + (direction === -1 ? transitionPrev.value : transitionNext.value) : null if (panelTransition.value !== val) { panelTransition.value = val } } function goToPanelByOffset (direction, startIndex = panelIndex.value) { let index = startIndex + direction while (index > -1 && index < panels.length) { const opt = panels[ index ] if ( opt !== void 0 && opt.props.disable !== '' && opt.props.disable !== true ) { updatePanelTransition(direction) forcedPanelTransition = true emit('update:modelValue', opt.props.name) setTimeout(() => { forcedPanelTransition = false }) return } index += direction } if (props.infinite === true && panels.length > 0 && startIndex !== -1 && startIndex !== panels.length) { goToPanelByOffset(direction, direction === -1 ? panels.length : -1) } } function updatePanelIndex () { const index = getPanelIndex(props.modelValue) if (panelIndex.value !== index) { panelIndex.value = index } return true } function getPanelContentChild () { const panel = isValidPanelName(props.modelValue) === true && updatePanelIndex() && panels[ panelIndex.value ] return props.keepAlive === true ? [ h(KeepAlive, keepAliveProps.value, [ h( needsUniqueKeepAliveWrapper.value === true ? getCacheWithFn(contentKey.value, () => ({ ...PanelWrapper, name: contentKey.value })) : PanelWrapper, { key: contentKey.value, style: transitionStyle.value }, () => panel ) ]) ] : [ h('div', { class: 'q-panel scroll', style: transitionStyle.value, key: contentKey.value, role: 'tabpanel' }, [ panel ]) ] } function getPanelContent () { if (panels.length === 0) { return } return props.animated === true ? [ h(Transition, { name: panelTransition.value }, getPanelContentChild) ] : getPanelContentChild() } function updatePanelsList (slots) { panels = getNormalizedVNodes( hSlot(slots.default, []) ).filter( panel => panel.props !== null && panel.props.slot === void 0 && isValidPanelName(panel.props.name) === true ) return panels.length } function getPanels () { return panels } // expose public methods Object.assign(proxy, { next: nextPanel, previous: previousPanel, goTo: goToPanel }) return { panelIndex, panelDirectives, updatePanelsList, updatePanelIndex, getPanelContent, getEnabledPanels, getPanels, isValidPanelName, keepAliveProps, needsUniqueKeepAliveWrapper, goToPanelByOffset, goToPanel, nextPanel, previousPanel } }