167 lines
5.4 KiB
Vue
167 lines
5.4 KiB
Vue
|
<template>
|
||
|
<component v-if="!asChild" :is="as" v-ripple :class="cx('root')" @click="onClick" v-bind="attrs">
|
||
|
<slot></slot>
|
||
|
</component>
|
||
|
<slot v-else :class="cx('root')" :active="active" :a11yAttrs="a11yAttrs" :onClick="onClick"></slot>
|
||
|
</template>
|
||
|
|
||
|
<script>
|
||
|
import Ripple from 'primevue/ripple';
|
||
|
import { DomHandler, ObjectUtils } from 'primevue/utils';
|
||
|
import { mergeProps } from 'vue';
|
||
|
import BaseTab from './BaseTab.vue';
|
||
|
|
||
|
export default {
|
||
|
name: 'Tab',
|
||
|
extends: BaseTab,
|
||
|
inheritAttrs: false,
|
||
|
inject: ['$pcTabs', '$pcTabList'],
|
||
|
methods: {
|
||
|
onFocus() {
|
||
|
this.$pcTabs.selectOnFocus && this.changeActiveValue();
|
||
|
},
|
||
|
onClick() {
|
||
|
this.changeActiveValue();
|
||
|
},
|
||
|
onKeydown(event) {
|
||
|
switch (event.code) {
|
||
|
case 'ArrowRight':
|
||
|
this.onArrowRightKey(event);
|
||
|
break;
|
||
|
|
||
|
case 'ArrowLeft':
|
||
|
this.onArrowLeftKey(event);
|
||
|
break;
|
||
|
|
||
|
case 'Home':
|
||
|
this.onHomeKey(event);
|
||
|
break;
|
||
|
|
||
|
case 'End':
|
||
|
this.onEndKey(event);
|
||
|
break;
|
||
|
|
||
|
case 'PageDown':
|
||
|
this.onPageDownKey(event);
|
||
|
break;
|
||
|
|
||
|
case 'PageUp':
|
||
|
this.onPageUpKey(event);
|
||
|
break;
|
||
|
|
||
|
case 'Enter':
|
||
|
case 'NumpadEnter':
|
||
|
case 'Space':
|
||
|
this.onEnterKey(event);
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
},
|
||
|
onArrowRightKey(event) {
|
||
|
const nextTab = this.findNextTab(event.currentTarget);
|
||
|
|
||
|
nextTab ? this.changeFocusedTab(event, nextTab) : this.onHomeKey(event);
|
||
|
event.preventDefault();
|
||
|
},
|
||
|
onArrowLeftKey(event) {
|
||
|
const prevTab = this.findPrevTab(event.currentTarget);
|
||
|
|
||
|
prevTab ? this.changeFocusedTab(event, prevTab) : this.onEndKey(event);
|
||
|
event.preventDefault();
|
||
|
},
|
||
|
onHomeKey(event) {
|
||
|
const firstTab = this.findFirstTab();
|
||
|
|
||
|
this.changeFocusedTab(event, firstTab);
|
||
|
event.preventDefault();
|
||
|
},
|
||
|
onEndKey(event) {
|
||
|
const lastTab = this.findLastTab();
|
||
|
|
||
|
this.changeFocusedTab(event, lastTab);
|
||
|
event.preventDefault();
|
||
|
},
|
||
|
onPageDownKey(event) {
|
||
|
this.scrollInView(this.findLastTab());
|
||
|
event.preventDefault();
|
||
|
},
|
||
|
onPageUpKey(event) {
|
||
|
this.scrollInView(this.findFirstTab());
|
||
|
event.preventDefault();
|
||
|
},
|
||
|
onEnterKey() {
|
||
|
this.changeActiveValue();
|
||
|
},
|
||
|
findNextTab(tabElement, selfCheck = false) {
|
||
|
const element = selfCheck ? tabElement : tabElement.nextElementSibling;
|
||
|
|
||
|
return element ? (DomHandler.getAttribute(element, 'data-p-disabled') || DomHandler.getAttribute(element, 'data-pc-section') === 'inkbar' ? this.findNextTab(element) : DomHandler.findSingle(element, '[data-pc-name="tab"]')) : null;
|
||
|
},
|
||
|
findPrevTab(tabElement, selfCheck = false) {
|
||
|
const element = selfCheck ? tabElement : tabElement.previousElementSibling;
|
||
|
|
||
|
return element ? (DomHandler.getAttribute(element, 'data-p-disabled') || DomHandler.getAttribute(element, 'data-pc-section') === 'inkbar' ? this.findPrevTab(element) : DomHandler.findSingle(element, '[data-pc-name="tab"]')) : null;
|
||
|
},
|
||
|
findFirstTab() {
|
||
|
return this.findNextTab(this.$pcTabList.$refs.content.firstElementChild, true);
|
||
|
},
|
||
|
findLastTab() {
|
||
|
return this.findPrevTab(this.$pcTabList.$refs.content.lastElementChild, true);
|
||
|
},
|
||
|
changeActiveValue() {
|
||
|
this.$pcTabs.updateValue(this.value);
|
||
|
},
|
||
|
changeFocusedTab(event, element) {
|
||
|
DomHandler.focus(element);
|
||
|
this.scrollInView(element);
|
||
|
},
|
||
|
scrollInView(element) {
|
||
|
element?.scrollIntoView?.({ block: 'nearest' });
|
||
|
}
|
||
|
},
|
||
|
computed: {
|
||
|
active() {
|
||
|
return ObjectUtils.equals(this.$pcTabs?.d_value, this.value);
|
||
|
},
|
||
|
id() {
|
||
|
return `${this.$pcTabs?.id}_tab_${this.value}`;
|
||
|
},
|
||
|
ariaControls() {
|
||
|
return `${this.$pcTabs?.id}_tabpanel_${this.value}`;
|
||
|
},
|
||
|
attrs() {
|
||
|
return mergeProps(this.asAttrs, this.a11yAttrs, this.ptmi('root', this.ptParams));
|
||
|
},
|
||
|
asAttrs() {
|
||
|
return this.as === 'BUTTON' ? { type: 'button', disabled: this.disabled } : undefined;
|
||
|
},
|
||
|
a11yAttrs() {
|
||
|
return {
|
||
|
id: this.id,
|
||
|
tabindex: this.active ? this.$pcTabs.tabindex : -1,
|
||
|
role: 'tab',
|
||
|
'aria-selected': this.active,
|
||
|
'aria-controls': this.ariaControls,
|
||
|
'data-pc-name': 'tab',
|
||
|
'data-p-disabled': this.disabled,
|
||
|
'data-p-active': this.active,
|
||
|
onFocus: this.onFocus,
|
||
|
onKeydown: this.onKeydown
|
||
|
};
|
||
|
},
|
||
|
ptParams() {
|
||
|
return {
|
||
|
context: {
|
||
|
active: this.active
|
||
|
}
|
||
|
};
|
||
|
}
|
||
|
},
|
||
|
directives: {
|
||
|
ripple: Ripple
|
||
|
}
|
||
|
};
|
||
|
</script>
|