| 1 | <script setup lang="ts"> |
| 2 | import { onMounted, provide, ref, useTemplateRef } from 'vue' |
| 3 | import TitleIcon from '../internals/TitleIcon.vue' |
| 4 | |
| 5 | const codeGroupBlocksRef = useTemplateRef('codeGroupBlocksRef') |
| 6 | const activeTitle = ref('') |
| 7 | |
| 8 | provide('activeTitle', activeTitle) |
| 9 | const tabs = ref<string[]>([]) |
| 10 | |
| 11 | onMounted(() => { |
| 12 | const codeGroupBlocks = codeGroupBlocksRef.value |
| 13 | let isActiveSet = false |
| 14 | |
| 15 | codeGroupBlocks?.querySelectorAll('.slidev-code-wrapper')?.forEach((block) => { |
| 16 | const title = block.getAttribute('data-title') || '' |
| 17 | if (title) { |
| 18 | if (!isActiveSet) { |
| 19 | activeTitle.value = title |
| 20 | isActiveSet = true |
| 21 | } |
| 22 | tabs.value.push(title) |
| 23 | } |
| 24 | }) |
| 25 | }) |
| 26 | </script> |
| 27 | |
| 28 | <template> |
| 29 | <div class="slidev-code-group"> |
| 30 | <div class="slidev-code-group-tabs"> |
| 31 | <div v-for="tab in tabs" :key="tab" class="flex items-center"> |
| 32 | <div |
| 33 | class="slidev-code-tab" |
| 34 | :style="{ |
| 35 | borderColor: activeTitle === tab ? 'var(--slidev-theme-primary)' : 'transparent', |
| 36 | color: activeTitle === tab ? 'var(--slidev-code-tab-active-text-color)' : 'var(--slidev-code-tab-text-color)', |
| 37 | }" |
| 38 | @click="activeTitle = tab" |
| 39 | > |
| 40 | <TitleIcon :title="tab" /> |
| 41 | |
| 42 | <div> |
| 43 | {{ tab.replace(/~([^~]+)~/g, '').trim() }} |
| 44 | </div> |
| 45 | </div> |
| 46 | </div> |
| 47 | </div> |
| 48 | <div ref="codeGroupBlocksRef" class="slidev-code-group-blocks"> |
| 49 | <slot /> |
| 50 | </div> |
| 51 | </div> |
| 52 | </template> |
| 53 |