primevue-mirror/components/lib/tab/Tab.vue

168 lines
5.4 KiB
Vue
Raw Normal View History

2024-04-19 13:51:57 +00:00
<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();
},
2024-04-24 22:43:32 +00:00
onEnterKey(event) {
2024-04-19 13:51:57 +00:00
this.changeActiveValue();
2024-04-24 22:43:32 +00:00
event.preventDefault();
2024-04-19 13:51:57 +00:00
},
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>