返回 slidev
Tweet.vue
根目录 / packages / client / builtin / Tweet.vue
1 <!--
2 A simple wrapper for embedded Tweet
3
4 Usage:
5
6 <Tweet id="20" />
7 -->
8
9 <script setup lang="ts">
10 import { onMounted, ref } from 'vue'
11 import { isDark } from '../logic/dark'
12
13 const props = defineProps<{
14 id: string | number
15 scale?: string | number
16 conversation?: string
17 cards?: 'hidden' | 'visible'
18 }>()
19
20 const tweet = ref<HTMLElement | null>()
21
22 const loaded = ref(false)
23 const tweetNotFound = ref(false)
24
25 async function create(retries = 10) {
26 // @ts-expect-error global
27 if (!window.twttr?.widgets?.createTweet) {
28 if (retries <= 0)
29 return console.error('Failed to load Twitter widget after 10 retries.')
30 setTimeout(create, 1000, retries - 1)
31 return
32 }
33 // @ts-expect-error global
34 const element = await window.twttr.widgets.createTweet(
35 props.id.toString(),
36 tweet.value,
37 {
38 theme: isDark.value ? 'dark' : 'light',
39 conversation: props.conversation || 'none',
40 cards: props.cards,
41 },
42 )
43 loaded.value = true
44 if (element === undefined)
45 tweetNotFound.value = true
46 }
47
48 onMounted(() => {
49 create()
50 })
51 </script>
52
53 <template>
54 <Transform :scale="scale || 1">
55 <div ref="tweet" class="tweet slidev-tweet">
56 <div v-if="!loaded || tweetNotFound" class="w-30 h-30 my-10px bg-gray-400 bg-opacity-10 rounded-lg flex opacity-50">
57 <div class="m-auto animate-pulse text-4xl">
58 <div class="i-carbon:logo-twitter" />
59 <span v-if="tweetNotFound">Could not load tweet with id="{{ props.id }}"</span>
60 </div>
61 </div>
62 </div>
63 </Transform>
64 </template>
65
66 <style>
67 .slidev-tweet iframe {
68 border-radius: 12px;
69 overflow: hidden;
70 }
71 </style>
72
72 lines Plain Text