-
-
Notifications
You must be signed in to change notification settings - Fork 425
Expand file tree
/
Copy pathBadgeGenerator.vue
More file actions
94 lines (86 loc) · 3.54 KB
/
BadgeGenerator.vue
File metadata and controls
94 lines (86 loc) · 3.54 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
<script lang="ts" setup>
import { useClipboard } from '@vueuse/core'
const pkg = useState('badge-pkg', () => 'nuxt')
const type = useState<BadgeType>('badge-type', () => 'version')
const isValid = ref(true)
const { copy, copied } = useClipboard({ copiedDuring: 2000 })
watch([pkg, type], () => {
isValid.value = true
})
const copyToClipboard = async () => {
const markdown = `[](https://npmx.dev/package/${pkg.value})`
copy(markdown)
}
</script>
<template>
<div
class="my-8 p-5 rounded-xl border border-gray-200/60 dark:border-white/5 bg-gray-50/50 dark:bg-white/2 flex flex-col sm:flex-row items-end gap-4"
>
<div class="flex flex-col gap-1.5 flex-1 w-full">
<label class="text-2xs font-bold uppercase tracking-wider text-gray-400 ms-1"
>Package Name</label
>
<input
v-model="pkg"
type="text"
spellcheck="false"
class="w-full h-10.5 px-4 py-2 rounded-lg border border-gray-200 dark:border-white/10 bg-white dark:bg-black/20 focus:ring-2 focus:ring-emerald-500/20 focus:border-emerald-500 outline-none text-sm transition-all"
:class="{ 'border-red-500/50 focus:ring-red-500/10 focus:border-red-500': !isValid }"
placeholder="e.g. nuxt"
/>
</div>
<div class="flex flex-col gap-1.5 flex-1 w-full">
<label class="text-2xs font-bold uppercase tracking-wider text-gray-400 ms-1"
>Badge Type</label
>
<div class="relative">
<select
v-model="type"
class="w-full h-10.5 px-4 py-2 rounded-lg border border-gray-200 dark:border-white/10 bg-white dark:bg-black/20 focus:ring-2 focus:ring-emerald-500/20 focus:border-emerald-500 outline-none text-sm transition-all appearance-none cursor-pointer"
>
<option v-for="t in BADGE_TYPES" :key="t" :value="t" class="dark:bg-gray-900">
{{ titleCase(t) }}
</option>
</select>
<span
class="absolute inset-ie-3 top-1/2 -translate-y-1/2 i-lucide-chevron-down w-4 h-4 text-gray-400 pointer-events-none"
/>
</div>
</div>
<div class="flex flex-col gap-1.5 flex-2 w-full">
<label class="text-2xs font-bold uppercase tracking-wider text-gray-400 ms-1"
>Preview & Action</label
>
<div
class="flex items-center bg-white dark:bg-black/20 border border-gray-200 dark:border-white/10 rounded-lg h-10.5 overflow-hidden"
>
<div
class="flex-1 flex items-center justify-center px-3 border-ie border-gray-200 dark:border-white/10 h-full bg-gray-50/50 dark:bg-transparent"
>
<img
v-if="isValid"
:src="`https://npmx.dev/api/registry/badge/${type}/${pkg}`"
class="h-5"
alt="Badge Preview"
@error="isValid = false"
/>
<span v-else class="text-3xs font-bold text-red-500 uppercase tracking-tighter"
>Invalid</span
>
</div>
<button
@click="copyToClipboard"
:disabled="!isValid || !pkg"
class="px-4 h-full text-2xs font-bold uppercase tracking-widest transition-all disabled:opacity-20 disabled:cursor-not-allowed min-w-21.25 hover:bg-gray-50 dark:hover:bg-white/5"
:class="
copied
? 'text-emerald-500 bg-emerald-50/50 dark:bg-emerald-500/10'
: 'text-gray-500 dark:text-gray-400'
"
>
{{ copied ? 'Done!' : 'Copy' }}
</button>
</div>
</div>
</div>
</template>