vuepress-theme-aurora
Version:
A vuepress-based animation blog theme, simple, beautiful, multi-color, multiple custom functions, providing article poster sharing, talk, photo album, comment and other features 一个基于vuepress的动漫类博客主题,简洁,漂亮,多色彩,多种自定义功能,提供文章海报分享,说说,相册,评论等特色功�?
103 lines (102 loc) • 4.17 kB
JavaScript
import { defineComponent, h, ref } from 'vue';
export default defineComponent({
name: 'CodeGroup',
setup(_, { slots }) {
// index of current active item
const activeIndex = ref(-1);
// refs of the tab buttons
const tabRefs = ref([]);
// activate next tab
const activateNext = (i = activeIndex.value) => {
if (i < tabRefs.value.length - 1) {
activeIndex.value = i + 1;
}
else {
activeIndex.value = 0;
}
tabRefs.value[activeIndex.value].focus();
};
// activate previous tab
const activatePrev = (i = activeIndex.value) => {
if (i > 0) {
activeIndex.value = i - 1;
}
else {
activeIndex.value = tabRefs.value.length - 1;
}
tabRefs.value[activeIndex.value].focus();
};
// handle keyboard event
const keyboardHandler = (event, i) => {
if (event.key === ' ' || event.key === 'Enter') {
event.preventDefault();
activeIndex.value = i;
}
else if (event.key === 'ArrowRight') {
event.preventDefault();
activateNext(i);
}
else if (event.key === 'ArrowLeft') {
event.preventDefault();
activatePrev(i);
}
};
return () => {
// NOTICE: here we put the `slots.default()` inside the render function to make
// the slots reactive, otherwise the slot content won't be changed once the
// `setup()` function of current component is called
var _a;
// get children code-group-item
const items = (((_a = slots.default) === null || _a === void 0 ? void 0 : _a.call(slots)) || [])
.filter((vnode) => vnode.type.name === 'CodeGroupItem')
.map((vnode) => {
if (vnode.props === null) {
vnode.props = {};
}
return vnode;
});
// clear tabRefs for HMR
tabRefs.value = [];
// do not render anything if there is no code-group-item
if (items.length === 0) {
return null;
}
if (activeIndex.value < 0 || activeIndex.value > items.length - 1) {
// if `activeIndex` is invalid
// find the index of the code-group-item with `active` props
activeIndex.value = items.findIndex((vnode) => vnode.props.active === '' || vnode.props.active === true);
// if there is no `active` props on code-group-item, set the first item active
if (activeIndex.value === -1) {
activeIndex.value = 0;
}
}
else {
// set the active item
items.forEach((vnode, i) => {
vnode.props.active = i === activeIndex.value;
});
}
return h('div', { class: 'code-group' }, [
h('div', { class: 'code-group__nav' }, h('ul', { class: 'code-group__ul' }, items.map((vnode, i) => {
const isActive = i === activeIndex.value;
return h('li', { class: 'code-group__li' }, h('button', {
ref: (element) => {
if (element) {
tabRefs.value[i] = element;
}
},
class: {
'code-group__nav-tab': true,
'code-group__nav-tab-active': isActive,
},
ariaPressed: isActive,
ariaExpanded: isActive,
onClick: () => (activeIndex.value = i),
onKeydown: (e) => keyboardHandler(e, i),
}, vnode.props.title));
}))),
items,
]);
};
},
});