1
0
Fork 0
mirror of https://github.com/FrankerFaceZ/FrankerFaceZ.git synced 2025-06-27 21:05:53 +00:00
FrankerFaceZ/src/std-components/tab-container.vue

241 lines
4.7 KiB
Vue
Raw Normal View History

2017-11-13 01:23:39 -05:00
<template lang="html">
<div
v-if="item.tabs"
class="ffz--tab-container"
@keyup.alt.page-up.stop="focusPrevTab"
@keyup.alt.page-down.stop="focusNextTab"
2017-11-13 01:23:39 -05:00
>
<header
class="tw-flex"
tabindex="0"
role="tablist"
@keyup.home="firstTab"
@keyup.end="lastTab"
@keyup.page-up="prevTab"
@keyup.up="prevTab"
@keyup.left="prevTab"
@keyup.page-down="nextTab"
@keyup.right="nextTab"
@keyup.down="nextTab"
2017-11-13 01:23:39 -05:00
>
<div
v-for="(i, idx) in visibleTabs"
:id="'tab-for-' + i.full_key"
:key="i.full_key"
:aria-selected="selected === idx"
:aria-controls="'tab-panel-' + i.full_key"
:class="{'active': selected === idx, 'ffz-unmatched-item': showing && ! shouldShow(i)}"
role="tab"
class="tab tw-pd-y-05 tw-pd-x-1"
@click="select(idx)"
>
{{ t(i.i18n_key, i.title) }}
<span v-if="filter" class="ffz-pill ffz-pill--overlay">{{ countMatches(i) }}</span>
<span v-else-if="i.unseen" class="ffz-pill ffz-pill--overlay">{{ i.unseen }}</span>
</div>
</header>
<section
:id="'tab-panel-' + tab.full_key"
:aria-labelledby="'tab-for-' + tab.full_key"
class="tw-border"
role="tabpanel"
aria-hidden="false"
aria-expanded="true"
>
<section v-if="tab.description" class="tw-pd-b-1">
{{ t(tab.desc_i18n_key, tab.description) }}
</section>
<div
v-for="i in visibleContents"
:key="i.full_key"
:class="{'ffz-unmatched-item': showing && ! shouldShow(i)}"
>
<component
:is="i.component"
:current-profile="currentProfile"
:profiles="profiles"
:context="context"
:item="i"
:filter="filter"
/>
</div>
</section>
</div>
2017-11-13 01:23:39 -05:00
</template>
<script>
export default {
props: ['item', 'profiles', 'currentProfile', 'context', 'filter'],
2017-11-13 01:23:39 -05:00
data() {
return {
selected: 0
}
},
computed: {
showing() {
return this.shouldShow(this.item)
},
2017-11-13 01:23:39 -05:00
tab() {
return this.item.tabs[this.selected];
},
visibleTabs() {
if ( ! this.item || ! this.item.tabs )
return [];
//if ( ! this.context.matches_only )
2025-06-07 16:09:55 -06:00
return this.item.tabs;
//return this.item.tabs.filter(tab => this.shouldShow(tab));
},
visibleContents() {
if ( ! this.tab || ! this.tab.contents )
return [];
if ( ! this.context.matches_only )
return this.tab.contents;
return this.tab.contents.filter(item => this.shouldShow(item));
2017-11-13 01:23:39 -05:00
}
},
created() {
if ( ! this.item._component )
this.item._component = this;
},
mounted() {
this.markSeen()
},
destroyed() {
if ( this.item._component === this )
this.item._component = null;
},
2017-11-13 01:23:39 -05:00
methods: {
countMatches(item, seen) {
if ( ! this.filter || ! item )
return 0;
if ( seen && seen.has(item) )
return 0;
if ( ! seen )
seen = new Set;
seen.add(item);
let count = 0;
for(const key of ['tabs', 'contents', 'items'])
if ( item[key] )
for(const thing of item[key])
count += this.countMatches(thing, seen);
if ( item.setting && this.shouldShow(item, true) )
count++;
return count;
},
2017-11-13 01:23:39 -05:00
focus() {
this.$el.querySelector('header').focus();
},
focusNextTab() {
this.focus();
this.nextTab();
},
focusPrevTab() {
this.focus();
this.prevTab();
},
focusFirstTab() {
this.focus();
this.firstTab();
},
focusLastTab() {
this.focus();
this.lastTab();
},
markSeen() {
this.$emit('mark-seen', this.item.tabs[this.selected]);
},
2017-11-13 01:23:39 -05:00
firstTab() {
this.selected = 0;
this.markSeen();
2017-11-13 01:23:39 -05:00
},
lastTab() {
this.selected = this.item.tabs.length - 1;
this.markSeen();
2017-11-13 01:23:39 -05:00
},
prevTab() {
if ( this.selected > 0 ) {
2017-11-13 01:23:39 -05:00
this.selected--;
this.markSeen();
}
},
select(idx) {
/*const selected = this.visibleTabs[idx];
if ( this.item.tabs[idx] !== selected )
for(let i = 0; i < this.item.tabs.length; i++) {
if ( selected === this.item.tabs[i] ) {
idx = i;
break;
}
}*/
this.selected = idx;
this.markSeen();
2017-11-13 01:23:39 -05:00
},
nextTab() {
if ( this.selected + 1 < this.item.tabs.length ) {
2017-11-13 01:23:39 -05:00
this.selected++;
this.markSeen();
}
},
shouldShow(item, is_walking = false) {
if ( ! this.filter || item.no_filter )
return true;
if ( this.filter.flags ) {
if ( this.filter.flags.has('modified') ) {
// We need to tree walk for this one.
if ( ! is_walking ) {
for(const key of ['tabs', 'contents', 'items'])
if ( item[key] )
for(const thing of item[key])
if ( this.shouldShow(thing) )
return true;
}
if ( ! item.setting || ! this.context.currentProfile.has(item.setting) )
return false;
}
}
if ( this.filter.query ) {
if ( ! item.search_terms || ! item.search_terms.includes(this.filter.query) )
return false;
}
return true;
2017-11-13 01:23:39 -05:00
}
}
}
</script>