docus 2.1.0 → 3.0.0-beta.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -4
- package/package.json +39 -83
- package/theme/app/router.options.ts +18 -0
- package/theme/assets/css/fonts.css +84 -0
- package/theme/assets/css/main.css +104 -0
- package/theme/components/app/Container.vue +25 -0
- package/theme/components/app/Footer.vue +40 -0
- package/theme/components/app/MobileNav.vue +85 -0
- package/theme/components/app/Navbar.vue +37 -0
- package/theme/components/app/NavbarLogo.vue +33 -0
- package/theme/components/app/Page.vue +7 -0
- package/theme/components/app/PoweredByDocus.vue +11 -0
- package/theme/components/content/Alert.vue +124 -0
- package/theme/components/content/BlockHero.vue +54 -0
- package/theme/components/content/ButtonLink.vue +45 -0
- package/theme/components/content/Card.vue +46 -0
- package/theme/components/content/CardGrid.vue +23 -0
- package/theme/components/content/CodeBlock.vue +47 -0
- package/theme/components/content/CodeGroup.vue +135 -0
- package/theme/components/content/CopyButton.vue +49 -0
- package/{dist/runtime/app/components/prose/ProseOl.vue → theme/components/content/List.vue} +2 -2
- package/theme/components/content/NeedContribution.vue +23 -0
- package/theme/components/content/ReadMore.vue +25 -0
- package/theme/components/content/Sandbox.vue +102 -0
- package/theme/components/content/TabsHeader.vue +44 -0
- package/theme/components/content/Terminal.vue +64 -0
- package/theme/components/content/VideoPlayer.vue +115 -0
- package/theme/components/dev/Debug.vue +65 -0
- package/theme/components/docs/DocsAside.vue +21 -0
- package/theme/components/docs/DocsAsideTree.vue +104 -0
- package/theme/components/docs/DocsHero.vue +39 -0
- package/theme/components/docs/DocsPage.vue +21 -0
- package/theme/components/docs/DocsPageContent.vue +32 -0
- package/theme/components/docs/DocsToc.vue +77 -0
- package/theme/components/globals/Icon.vue +24 -0
- package/{dist/runtime/app/components/prose/ProseHr.vue → theme/components/globals/Logo.vue} +1 -1
- package/theme/components/globals/NuxtImg.vue +45 -0
- package/theme/components/globals/SocialIcons.vue +45 -0
- package/theme/components/globals/ThemeSelect.vue +35 -0
- package/theme/components/icons/IconAlgolia.vue +8 -0
- package/theme/components/icons/IconArrowLeft.vue +10 -0
- package/theme/components/icons/IconArrowRight.vue +10 -0
- package/theme/components/icons/IconBadgeCheck.vue +14 -0
- package/theme/components/icons/IconCheck.vue +10 -0
- package/theme/components/icons/IconCheckCircle.vue +10 -0
- package/theme/components/icons/IconChevronRight.vue +12 -0
- package/theme/components/icons/IconClipboardCheck.vue +14 -0
- package/theme/components/icons/IconClipboardCopy.vue +14 -0
- package/theme/components/icons/IconCodeSandbox.vue +8 -0
- package/theme/components/icons/IconCopy.vue +17 -0
- package/theme/components/icons/IconDots.vue +10 -0
- package/theme/components/icons/IconEdit.vue +18 -0
- package/theme/components/icons/IconExclamationCircle.vue +12 -0
- package/theme/components/icons/IconExclamationTriangle.vue +10 -0
- package/theme/components/icons/IconExternalLink.vue +12 -0
- package/theme/components/icons/IconGit.vue +7 -0
- package/theme/components/icons/IconGitHub.vue +10 -0
- package/theme/components/icons/IconHeart.vue +9 -0
- package/theme/components/icons/IconInformationCircle.vue +10 -0
- package/theme/components/icons/IconLighthouse.vue +83 -0
- package/theme/components/icons/IconLine.vue +10 -0
- package/theme/components/icons/IconMarkdown.vue +13 -0
- package/theme/components/icons/IconMenu.vue +12 -0
- package/theme/components/icons/IconMenuAlt.vue +10 -0
- package/theme/components/icons/IconMinus.vue +10 -0
- package/theme/components/icons/IconMoon.vue +10 -0
- package/theme/components/icons/IconNuxt.vue +14 -0
- package/theme/components/icons/IconNuxtContent.vue +20 -0
- package/theme/components/icons/IconNuxtLabs.vue +21 -0
- package/theme/components/icons/IconPlus.vue +10 -0
- package/theme/components/icons/IconPuzzle.vue +8 -0
- package/theme/components/icons/IconSSG.vue +7 -0
- package/theme/components/icons/IconSearch.vue +12 -0
- package/theme/components/icons/IconSun.vue +10 -0
- package/theme/components/icons/IconTailwind.vue +3 -0
- package/theme/components/icons/IconTocBack.vue +21 -0
- package/theme/components/icons/IconTocCurrent.vue +21 -0
- package/theme/components/icons/IconTocNext.vue +8 -0
- package/theme/components/icons/IconTranslate.vue +14 -0
- package/theme/components/icons/IconTwitter.vue +8 -0
- package/theme/components/icons/IconVite.vue +30 -0
- package/theme/components/icons/IconVue.vue +6 -0
- package/theme/components/icons/IconVueTelescope.vue +11 -0
- package/theme/components/icons/IconWindi.vue +17 -0
- package/theme/components/icons/IconX.vue +12 -0
- package/theme/components/icons/IconXCircle.vue +10 -0
- package/theme/components/icons/IconZap.vue +8 -0
- package/theme/components/prose/ProseA.vue +66 -0
- package/theme/components/prose/ProseBlockquote.vue +21 -0
- package/theme/components/prose/ProseCode.vue +67 -0
- package/theme/components/prose/ProseCodeInline.vue +38 -0
- package/theme/components/prose/ProseEm.vue +11 -0
- package/theme/components/prose/ProseH1.vue +22 -0
- package/theme/components/prose/ProseH2.vue +22 -0
- package/theme/components/prose/ProseH3.vue +24 -0
- package/theme/components/prose/ProseH4.vue +24 -0
- package/theme/components/prose/ProseHr.vue +13 -0
- package/theme/components/prose/ProseImg.vue +30 -0
- package/theme/components/prose/ProseLi.vue +31 -0
- package/theme/components/prose/ProseOl.vue +16 -0
- package/theme/components/prose/ProseP.vue +14 -0
- package/theme/components/prose/ProseStrong.vue +14 -0
- package/theme/components/prose/ProseTable.vue +13 -0
- package/{dist/runtime/app → theme}/components/prose/ProseTbody.vue +0 -0
- package/theme/components/prose/ProseTd.vue +11 -0
- package/theme/components/prose/ProseTh.vue +11 -0
- package/theme/components/prose/ProseThead.vue +11 -0
- package/theme/components/prose/ProseTr.vue +11 -0
- package/theme/components/prose/ProseUl.vue +15 -0
- package/theme/composables/useDocus.ts +43 -0
- package/theme/composables/useMenu.ts +7 -0
- package/theme/composables/useScrollToHeading.ts +35 -0
- package/theme/composables/useScrollspy.ts +46 -0
- package/theme/composables/useUserAgent.ts +7 -0
- package/theme/composables/utils.ts +4 -0
- package/theme/layouts/default.vue +29 -0
- package/theme/layouts/page.vue +19 -0
- package/theme/middleware/components.ts +26 -0
- package/theme/middleware/navigation.global.ts +12 -0
- package/theme/middleware/page.ts +8 -0
- package/theme/middleware/theme.global.ts +12 -0
- package/theme/nuxt.config.ts +171 -0
- package/theme/pages/[...slug].vue +64 -0
- package/theme/plugins/menu.ts +67 -0
- package/theme/plugins/user-agent.ts +27 -0
- package/theme/utils/components.ts +25 -0
- package/theme/utils/navigation.ts +49 -0
- package/theme/utils/plugin.ts +21 -0
- package/theme/utils/queries.ts +68 -0
- package/theme/utils/state.ts +33 -0
- package/theme/utils/theme.ts +66 -0
- package/LICENSE +0 -21
- package/dist/index.cjs +0 -549
- package/dist/index.d.ts +0 -25
- package/dist/index.mjs +0 -523
- package/dist/runtime/app/components/DocusContent.vue +0 -215
- package/dist/runtime/app/components/DocusContent.vue.d.ts +0 -25
- package/dist/runtime/app/components/Error.vue +0 -19
- package/dist/runtime/app/components/Error.vue.d.ts +0 -9
- package/dist/runtime/app/components/Markdown.vue +0 -56
- package/dist/runtime/app/components/Markdown.vue.d.ts +0 -25
- package/dist/runtime/app/components/Page.vue +0 -29
- package/dist/runtime/app/components/Page.vue.d.ts +0 -2
- package/dist/runtime/app/components/Props.vue +0 -130
- package/dist/runtime/app/components/Props.vue.d.ts +0 -80
- package/dist/runtime/app/components/prose/ProseA.vue +0 -41
- package/dist/runtime/app/components/prose/ProseA.vue.d.ts +0 -23
- package/dist/runtime/app/components/prose/ProseBlockquote.vue +0 -5
- package/dist/runtime/app/components/prose/ProseCode.vue +0 -5
- package/dist/runtime/app/components/prose/ProseCodeInline.vue +0 -5
- package/dist/runtime/app/components/prose/ProseEm.vue +0 -5
- package/dist/runtime/app/components/prose/ProseH1.vue +0 -3
- package/dist/runtime/app/components/prose/ProseH2.vue +0 -3
- package/dist/runtime/app/components/prose/ProseH3.vue +0 -3
- package/dist/runtime/app/components/prose/ProseH4.vue +0 -3
- package/dist/runtime/app/components/prose/ProseH5.vue +0 -3
- package/dist/runtime/app/components/prose/ProseH6.vue +0 -3
- package/dist/runtime/app/components/prose/ProseImg.vue +0 -32
- package/dist/runtime/app/components/prose/ProseImg.vue.d.ts +0 -21
- package/dist/runtime/app/components/prose/ProseLi.vue +0 -3
- package/dist/runtime/app/components/prose/ProseParagraph.vue +0 -3
- package/dist/runtime/app/components/prose/ProseStrong.vue +0 -5
- package/dist/runtime/app/components/prose/ProseTable.vue +0 -5
- package/dist/runtime/app/components/prose/ProseTd.vue +0 -5
- package/dist/runtime/app/components/prose/ProseTh.vue +0 -5
- package/dist/runtime/app/components/prose/ProseThead.vue +0 -5
- package/dist/runtime/app/components/prose/ProseTr.vue +0 -5
- package/dist/runtime/app/components/prose/ProseUl.vue +0 -5
- package/dist/runtime/app/composables/helpers.d.ts +0 -4
- package/dist/runtime/app/composables/helpers.js +0 -66
- package/dist/runtime/app/composables/helpers.mjs +0 -40
- package/dist/runtime/app/composables/index.d.ts +0 -90
- package/dist/runtime/app/composables/index.js +0 -108
- package/dist/runtime/app/composables/index.mjs +0 -63
- package/dist/runtime/app/composables/navigation.d.ts +0 -37
- package/dist/runtime/app/composables/navigation.js +0 -227
- package/dist/runtime/app/composables/navigation.mjs +0 -148
- package/dist/runtime/app/composables/store.d.ts +0 -7
- package/dist/runtime/app/composables/store.js +0 -52
- package/dist/runtime/app/composables/store.mjs +0 -35
- package/dist/runtime/app/composables/style.d.ts +0 -11
- package/dist/runtime/app/composables/style.js +0 -117
- package/dist/runtime/app/composables/style.mjs +0 -71
- package/dist/runtime/app/composables/theme-colors.d.ts +0 -30
- package/dist/runtime/app/composables/theme-colors.js +0 -80
- package/dist/runtime/app/composables/theme-colors.mjs +0 -48
- package/dist/runtime/app/composables/websocket.d.ts +0 -3
- package/dist/runtime/app/composables/websocket.js +0 -79
- package/dist/runtime/app/composables/websocket.mjs +0 -63
- package/dist/runtime/app/layouts/default.vue +0 -5
- package/dist/runtime/app/layouts/error.vue +0 -33
- package/dist/runtime/app/layouts/error.vue.d.ts +0 -21
- package/dist/runtime/app/pages/_.vue +0 -222
- package/dist/runtime/app/pages/_.vue.d.ts +0 -2
- package/dist/runtime/context.d.ts +0 -1
- package/dist/runtime/context.js +0 -17
- package/dist/runtime/context.mjs +0 -5
- package/dist/runtime/database/Query.d.ts +0 -18
- package/dist/runtime/database/Query.js +0 -68
- package/dist/runtime/database/Query.mjs +0 -49
- package/dist/runtime/database/index.d.ts +0 -4
- package/dist/runtime/database/index.js +0 -45
- package/dist/runtime/database/index.mjs +0 -25
- package/dist/runtime/database/providers/local/Query.d.ts +0 -14
- package/dist/runtime/database/providers/local/Query.js +0 -85
- package/dist/runtime/database/providers/local/Query.mjs +0 -60
- package/dist/runtime/database/providers/local/index.d.ts +0 -3
- package/dist/runtime/database/providers/local/index.js +0 -63
- package/dist/runtime/database/providers/local/index.mjs +0 -39
- package/dist/runtime/database/providers/local/operations.d.ts +0 -2
- package/dist/runtime/database/providers/local/operations.js +0 -83
- package/dist/runtime/database/providers/local/operations.mjs +0 -53
- package/dist/runtime/database/providers/local/utils.d.ts +0 -8
- package/dist/runtime/database/providers/local/utils.js +0 -28
- package/dist/runtime/database/providers/local/utils.mjs +0 -17
- package/dist/runtime/index.d.ts +0 -3
- package/dist/runtime/index.js +0 -44
- package/dist/runtime/index.mjs +0 -3
- package/dist/runtime/navigation.d.ts +0 -4
- package/dist/runtime/navigation.js +0 -176
- package/dist/runtime/navigation.mjs +0 -137
- package/dist/runtime/server/api/get.d.ts +0 -10
- package/dist/runtime/server/api/get.js +0 -24
- package/dist/runtime/server/api/get.mjs +0 -13
- package/dist/runtime/server/api/list.d.ts +0 -9
- package/dist/runtime/server/api/list.js +0 -34
- package/dist/runtime/server/api/list.mjs +0 -18
- package/dist/runtime/server/api/navigation.d.ts +0 -7
- package/dist/runtime/server/api/navigation.js +0 -20
- package/dist/runtime/server/api/navigation.mjs +0 -10
- package/dist/runtime/server/api/preview.d.ts +0 -3
- package/dist/runtime/server/api/preview.js +0 -54
- package/dist/runtime/server/api/preview.mjs +0 -31
- package/dist/runtime/server/api/reload.d.ts +0 -6
- package/dist/runtime/server/api/reload.js +0 -27
- package/dist/runtime/server/api/reload.mjs +0 -11
- package/dist/runtime/server/api/search.d.ts +0 -6
- package/dist/runtime/server/api/search.js +0 -27
- package/dist/runtime/server/api/search.mjs +0 -13
- package/dist/runtime/server/content.d.ts +0 -46
- package/dist/runtime/server/content.js +0 -175
- package/dist/runtime/server/content.mjs +0 -114
- package/dist/runtime/server/socket.d.ts +0 -9
- package/dist/runtime/server/socket.js +0 -33
- package/dist/runtime/server/socket.mjs +0 -20
- package/dist/runtime/server/utils/cache.d.ts +0 -19
- package/dist/runtime/server/utils/cache.js +0 -110
- package/dist/runtime/server/utils/cache.mjs +0 -75
- package/dist/runtime/server/utils/index.d.ts +0 -4
- package/dist/runtime/server/utils/index.js +0 -18
- package/dist/runtime/server/utils/index.mjs +0 -8
- package/dist/runtime/transformers/index.d.ts +0 -1
- package/dist/runtime/transformers/index.js +0 -26
- package/dist/runtime/transformers/index.mjs +0 -11
- package/dist/runtime/transformers/json.d.ts +0 -3
- package/dist/runtime/transformers/json.js +0 -15
- package/dist/runtime/transformers/json.mjs +0 -5
- package/dist/runtime/transformers/markdown/index.d.ts +0 -8
- package/dist/runtime/transformers/markdown/index.js +0 -25
- package/dist/runtime/transformers/markdown/index.mjs +0 -16
- package/dist/runtime/transformers/utils/index.d.ts +0 -1
- package/dist/runtime/transformers/utils/index.js +0 -18
- package/dist/runtime/transformers/utils/index.mjs +0 -1
- package/dist/runtime/transformers/utils/path.d.ts +0 -26
- package/dist/runtime/transformers/utils/path.js +0 -88
- package/dist/runtime/transformers/utils/path.mjs +0 -56
- package/dist/runtime/utils/index.d.ts +0 -1
- package/dist/runtime/utils/index.js +0 -18
- package/dist/runtime/utils/index.mjs +0 -1
- package/dist/runtime/utils/log.d.ts +0 -1
- package/dist/runtime/utils/log.js +0 -14
- package/dist/runtime/utils/log.mjs +0 -2
- package/dist/runtime/utils/object.d.ts +0 -9
- package/dist/runtime/utils/object.js +0 -22
- package/dist/runtime/utils/object.mjs +0 -4
- package/dist/templates/content.mjs +0 -50
- package/dist/templates/docus.mjs +0 -13
- package/dist/templates/hot.mjs +0 -16
- package/dist/templates/i18n.mjs +0 -23
- package/dist/templates/options.mjs +0 -46
- package/shims.d.ts +0 -24
- package/types.d.ts +0 -397
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import type { PropType } from 'vue'
|
|
3
|
+
|
|
4
|
+
defineProps({
|
|
5
|
+
tabs: {
|
|
6
|
+
type: Array as PropType<{ label: string }[]>,
|
|
7
|
+
required: true,
|
|
8
|
+
},
|
|
9
|
+
activeTabIndex: {
|
|
10
|
+
type: Number,
|
|
11
|
+
required: true,
|
|
12
|
+
},
|
|
13
|
+
})
|
|
14
|
+
|
|
15
|
+
defineEmits(['update:activeTabIndex'])
|
|
16
|
+
</script>
|
|
17
|
+
|
|
18
|
+
<template>
|
|
19
|
+
<div class="relative text-white bg-gray-200 dark:bg-gray-700">
|
|
20
|
+
<div v-if="tabs" class="relative z-0 px-2">
|
|
21
|
+
<button
|
|
22
|
+
v-for="({ label }, i) in tabs"
|
|
23
|
+
ref="tabs"
|
|
24
|
+
:key="`${i}${label}`"
|
|
25
|
+
class="relative px-3 py-1.5 xs:py-3 my-1.5 xs:my-0 text-sm font-mono font-medium tracking-tight focus:outline-none font-bold"
|
|
26
|
+
:class="[activeTabIndex === i ? 'active text-gray-800 dark:text-white' : 'text-gray-600 dark:text-gray-400']"
|
|
27
|
+
@click="$emit('update:activeTabIndex', i)"
|
|
28
|
+
>
|
|
29
|
+
{{ label }}
|
|
30
|
+
</button>
|
|
31
|
+
<span ref="highlight-underline" class="absolute -z-[1] highlight-underline h-full xs:py-1.5">
|
|
32
|
+
<span class="flex w-full h-full bg-gray-300 dark:bg-gray-600 rounded-lg" />
|
|
33
|
+
</span>
|
|
34
|
+
</div>
|
|
35
|
+
</div>
|
|
36
|
+
</template>
|
|
37
|
+
|
|
38
|
+
<style scoped>
|
|
39
|
+
.highlight-underline {
|
|
40
|
+
/* bottom: -2px; */
|
|
41
|
+
/* height: 2px; */
|
|
42
|
+
transition: left 150ms, top 150ms, width 150ms, height 150ms;
|
|
43
|
+
}
|
|
44
|
+
</style>
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import Clipboard from 'clipboard'
|
|
3
|
+
import { nextTick, onMounted, ref } from '#imports'
|
|
4
|
+
|
|
5
|
+
const props = defineProps({
|
|
6
|
+
snippet: {
|
|
7
|
+
type: String,
|
|
8
|
+
required: true,
|
|
9
|
+
},
|
|
10
|
+
})
|
|
11
|
+
|
|
12
|
+
const copyInstall = ref()
|
|
13
|
+
const copied = ref(false)
|
|
14
|
+
|
|
15
|
+
const setupCopyInstall = () => {
|
|
16
|
+
if (!copyInstall.value)
|
|
17
|
+
return nextTick(setupCopyInstall)
|
|
18
|
+
|
|
19
|
+
const instance = new Clipboard(copyInstall.value)
|
|
20
|
+
|
|
21
|
+
instance.on('success', () => {
|
|
22
|
+
copied.value = true
|
|
23
|
+
|
|
24
|
+
setTimeout(() => {
|
|
25
|
+
copied.value = false
|
|
26
|
+
}, 1000)
|
|
27
|
+
})
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
onMounted(() => setupCopyInstall())
|
|
31
|
+
|
|
32
|
+
</script>
|
|
33
|
+
|
|
34
|
+
<template>
|
|
35
|
+
<div
|
|
36
|
+
ref="copyInstall"
|
|
37
|
+
:data-clipboard-text="snippet"
|
|
38
|
+
class="relative flex flex-col w-full h-64 overflow-hidden text-gray-600 bg-gray-800 rounded-lg cursor-pointer group"
|
|
39
|
+
>
|
|
40
|
+
<div v-if="copied" class="absolute top-0 left-0 z-10 flex items-center justify-center w-full h-full">
|
|
41
|
+
<div class="absolute top-0 left-0 w-full h-full bg-gray-900 opacity-75" />
|
|
42
|
+
<div class="z-10 text-lg font-medium text-gray-100">
|
|
43
|
+
Copied!
|
|
44
|
+
</div>
|
|
45
|
+
</div>
|
|
46
|
+
<div class="relative flex items-center w-full h-12 border-b border-gray-700">
|
|
47
|
+
<div class="flex ml-4">
|
|
48
|
+
<div class="w-3 h-3 bg-red-400 rounded-full" />
|
|
49
|
+
<div class="w-3 h-3 ml-2 bg-yellow-400 rounded-full" />
|
|
50
|
+
<div class="w-3 h-3 ml-2 bg-green-400 rounded-full" />
|
|
51
|
+
</div>
|
|
52
|
+
<div class="absolute top-0 left-0 flex items-center justify-center w-full h-full">
|
|
53
|
+
Bash
|
|
54
|
+
</div>
|
|
55
|
+
</div>
|
|
56
|
+
<div class="flex flex-1 p-4 font-mono">
|
|
57
|
+
<span class="inline-block mr-2 font-bold select-none">$</span>
|
|
58
|
+
<span class="inline-block text-gray-200">{{ snippet }}</span>
|
|
59
|
+
</div>
|
|
60
|
+
<div class="py-2 text-center transition-opacity opacity-0 group-hover:opacity-100">
|
|
61
|
+
Click to copy
|
|
62
|
+
</div>
|
|
63
|
+
</div>
|
|
64
|
+
</template>
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
<script lang="ts" setup>
|
|
2
|
+
import { ref } from '#imports'
|
|
3
|
+
|
|
4
|
+
const props = defineProps({
|
|
5
|
+
poster: {
|
|
6
|
+
type: String,
|
|
7
|
+
default: '',
|
|
8
|
+
},
|
|
9
|
+
src: {
|
|
10
|
+
type: String,
|
|
11
|
+
default: '',
|
|
12
|
+
},
|
|
13
|
+
sources: {
|
|
14
|
+
type: Array,
|
|
15
|
+
default: () => [],
|
|
16
|
+
},
|
|
17
|
+
})
|
|
18
|
+
|
|
19
|
+
const provider = ref(null)
|
|
20
|
+
const loaded = ref(false)
|
|
21
|
+
|
|
22
|
+
if (!props.src && !props.sources.length)
|
|
23
|
+
throw new Error('VideoPlayer: you need to provide either `src` or `sources` props')
|
|
24
|
+
|
|
25
|
+
const src = props.src || props.sources[0].src
|
|
26
|
+
|
|
27
|
+
if (src && src.includes('youtube.com/watch')) {
|
|
28
|
+
const match = src.match(/\?v=([^&]*)/)
|
|
29
|
+
|
|
30
|
+
provider.value = {
|
|
31
|
+
name: 'youtube',
|
|
32
|
+
src: `https://www.youtube-nocookie.com/embed/${match[1]}?autoplay=1`,
|
|
33
|
+
poster: props.poster || `https://i3.ytimg.com/vi/${match[1]}/hqdefault.jpg`,
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
</script>
|
|
37
|
+
|
|
38
|
+
<template>
|
|
39
|
+
<div class="video-player relative my-4 bg-black bg-opacity-25 rounded-sm overflow-hidden" :class="{ loaded }">
|
|
40
|
+
<NuxtImg
|
|
41
|
+
v-if="provider ? provider.poster : poster"
|
|
42
|
+
class="video absolute top-0 left-0 w-full h-full object-cover"
|
|
43
|
+
:src="provider ? provider.poster : poster"
|
|
44
|
+
:width="670"
|
|
45
|
+
:height="377"
|
|
46
|
+
/>
|
|
47
|
+
<div v-if="loaded" class="video absolute top-0 left-0 w-full h-full">
|
|
48
|
+
<!-- remote videos -->
|
|
49
|
+
<video v-if="!provider" :poster="poster" controls autoplay>
|
|
50
|
+
<source v-if="src" :src="src">
|
|
51
|
+
<source v-for="source in sources" :key="source.src || source" :src="source.src || source" :type="source.type">
|
|
52
|
+
</video>
|
|
53
|
+
<!-- youtube -->
|
|
54
|
+
<iframe
|
|
55
|
+
v-else-if="provider.name === 'youtube'"
|
|
56
|
+
width="560"
|
|
57
|
+
height="377"
|
|
58
|
+
allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture"
|
|
59
|
+
allowfullscreen=""
|
|
60
|
+
class="w-full h-full"
|
|
61
|
+
:src="provider.src"
|
|
62
|
+
/>
|
|
63
|
+
</div>
|
|
64
|
+
<div v-if="!loaded" class="overlay absolute top-0 left-0 w-full h-full cursor-pointer" @click="loaded = true">
|
|
65
|
+
<button class="play" />
|
|
66
|
+
</div>
|
|
67
|
+
</div>
|
|
68
|
+
</template>
|
|
69
|
+
|
|
70
|
+
<style scoped lang="postcss">
|
|
71
|
+
.video-player {
|
|
72
|
+
&:not(.loaded):before {
|
|
73
|
+
content: ' ';
|
|
74
|
+
display: block;
|
|
75
|
+
position: absolute;
|
|
76
|
+
top: 0;
|
|
77
|
+
background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAADGCAYAAAAT+OqFAAAAdklEQVQoz42QQQ7AIAgEF/T/D+kbq/RWAlnQyyazA4aoAB4FsBSA/bFjuF1EOL7VbrIrBuusmrt4ZZORfb6ehbWdnRHEIiITaEUKa5EJqUakRSaEYBJSCY2dEstQY7AuxahwXFrvZmWl2rh4JZ07z9dLtesfNj5q0FU3A5ObbwAAAABJRU5ErkJggg==');
|
|
78
|
+
background-position: top;
|
|
79
|
+
background-repeat: repeat-x;
|
|
80
|
+
height: 60px;
|
|
81
|
+
padding-bottom: 50px;
|
|
82
|
+
width: 100%;
|
|
83
|
+
transition: all 0.2s cubic-bezier(0, 0, 0.2, 1);
|
|
84
|
+
z-index: 1;
|
|
85
|
+
}
|
|
86
|
+
&:after {
|
|
87
|
+
content: ' ';
|
|
88
|
+
display: block;
|
|
89
|
+
padding-bottom: 56.25%;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
.play {
|
|
93
|
+
width: 68px;
|
|
94
|
+
height: 48px;
|
|
95
|
+
position: absolute;
|
|
96
|
+
cursor: pointer;
|
|
97
|
+
transform: translate3d(-50%, -50%, 0);
|
|
98
|
+
top: 50%;
|
|
99
|
+
left: 50%;
|
|
100
|
+
z-index: 1;
|
|
101
|
+
background-color: transparent;
|
|
102
|
+
background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 68 48"><path fill="%23f00" fill-opacity="0.8" d="M66.52,7.74c-0.78-2.93-2.49-5.41-5.42-6.19C55.79,.13,34,0,34,0S12.21,.13,6.9,1.55 C3.97,2.33,2.27,4.81,1.48,7.74C0.06,13.05,0,24,0,24s0.06,10.95,1.48,16.26c0.78,2.93,2.49,5.41,5.42,6.19 C12.21,47.87,34,48,34,48s21.79-0.13,27.1-1.55c2.93-0.78,4.64-3.26,5.42-6.19C67.94,34.95,68,24,68,24S67.94,13.05,66.52,7.74z"></path><path d="M 45,24 27,14 27,34" fill="%23fff"></path></svg>');
|
|
103
|
+
filter: grayscale(100%);
|
|
104
|
+
transition: filter 0.1s cubic-bezier(0, 0, 0.2, 1);
|
|
105
|
+
border: none;
|
|
106
|
+
}
|
|
107
|
+
&:hover .play {
|
|
108
|
+
filter: none;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
video {
|
|
113
|
+
@apply w-full;
|
|
114
|
+
}
|
|
115
|
+
</style>
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import type { ParsedContent } from '@nuxt/content/dist/runtime/types'
|
|
3
|
+
import type { ThemeDebugConfig } from '../../utils/theme'
|
|
4
|
+
import { computed, useDocus, watchDebounced } from '#imports'
|
|
5
|
+
|
|
6
|
+
const { page, navigation, theme } = useDocus()
|
|
7
|
+
|
|
8
|
+
const defaultConfig: ThemeDebugConfig = {
|
|
9
|
+
page: true,
|
|
10
|
+
navigation: true,
|
|
11
|
+
theme: true,
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const config = computed(
|
|
15
|
+
() => {
|
|
16
|
+
const _config = theme.value?.debug
|
|
17
|
+
|
|
18
|
+
if (typeof _config === 'object')
|
|
19
|
+
return Object.assign(defaultConfig, _config)
|
|
20
|
+
|
|
21
|
+
if (_config === true)
|
|
22
|
+
return defaultConfig
|
|
23
|
+
|
|
24
|
+
if (_config === false)
|
|
25
|
+
return _config
|
|
26
|
+
},
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
const icons = {
|
|
30
|
+
page: '📃',
|
|
31
|
+
navigation: '🔖',
|
|
32
|
+
theme: '🎨',
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
Object.entries({
|
|
36
|
+
page,
|
|
37
|
+
navigation,
|
|
38
|
+
theme,
|
|
39
|
+
}).forEach(([key, reference]) => {
|
|
40
|
+
if (!config.value || !config.value?.[key])
|
|
41
|
+
return
|
|
42
|
+
|
|
43
|
+
watchDebounced(
|
|
44
|
+
reference,
|
|
45
|
+
() => {
|
|
46
|
+
if (key === 'page')
|
|
47
|
+
// eslint-disable-next-line no-console
|
|
48
|
+
console.log(`[${icons[key]}] Page updates detected! ${`(${(reference.value as ParsedContent)?.title})` || `(${(reference.value as ParsedContent)?.id})` || ''}`)
|
|
49
|
+
else
|
|
50
|
+
// eslint-disable-next-line no-console
|
|
51
|
+
console.log(`[${icons[key]}] ${key[0].toUpperCase() + key.slice(1, key.length)} updates detected!`)
|
|
52
|
+
|
|
53
|
+
// eslint-disable-next-line no-console
|
|
54
|
+
console.dir({ ...reference.value })
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
debounce: 100,
|
|
58
|
+
},
|
|
59
|
+
)
|
|
60
|
+
})
|
|
61
|
+
</script>
|
|
62
|
+
|
|
63
|
+
<template>
|
|
64
|
+
<div class="hidden" />
|
|
65
|
+
</template>
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { computed, useDocus } from '#imports'
|
|
3
|
+
|
|
4
|
+
const { navigation } = useDocus()
|
|
5
|
+
|
|
6
|
+
const tree = computed(() => {
|
|
7
|
+
return navigation.value.filter(
|
|
8
|
+
(item) => {
|
|
9
|
+
if (item.slug === '/' || item.slug === '/templates')
|
|
10
|
+
return false
|
|
11
|
+
return true
|
|
12
|
+
},
|
|
13
|
+
)
|
|
14
|
+
})
|
|
15
|
+
</script>
|
|
16
|
+
|
|
17
|
+
<template>
|
|
18
|
+
<nav>
|
|
19
|
+
<DocsAsideTree :tree="tree" />
|
|
20
|
+
</nav>
|
|
21
|
+
</template>
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import type { PropType } from 'vue'
|
|
3
|
+
import { reactive, useRoute, useRouter, watch } from '#imports'
|
|
4
|
+
|
|
5
|
+
const props = defineProps({
|
|
6
|
+
tree: {
|
|
7
|
+
type: Array as PropType<any>,
|
|
8
|
+
default: () => [],
|
|
9
|
+
},
|
|
10
|
+
level: {
|
|
11
|
+
type: Number,
|
|
12
|
+
default: 0,
|
|
13
|
+
},
|
|
14
|
+
max: {
|
|
15
|
+
type: Number,
|
|
16
|
+
default: null,
|
|
17
|
+
},
|
|
18
|
+
})
|
|
19
|
+
const emit = defineEmits(['close', 'select'])
|
|
20
|
+
|
|
21
|
+
const route = useRoute()
|
|
22
|
+
const router = useRouter()
|
|
23
|
+
|
|
24
|
+
const isChildOpen = reactive({})
|
|
25
|
+
|
|
26
|
+
function isActive(link) {
|
|
27
|
+
return link.exact ? route.path === link.slug : route.path.startsWith(link.slug)
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function onClick(link) {
|
|
31
|
+
if (link.children?.length) {
|
|
32
|
+
// Open dir when element is collapsible
|
|
33
|
+
toggleDir(link.slug)
|
|
34
|
+
|
|
35
|
+
// Select element for mobile nav
|
|
36
|
+
if (props.max !== null && props.level + 1 === props.max)
|
|
37
|
+
emit('select', link)
|
|
38
|
+
}
|
|
39
|
+
else {
|
|
40
|
+
router.push(link.slug)
|
|
41
|
+
emit('close')
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function toggleDir(slug, force?) {
|
|
46
|
+
isChildOpen[slug] = force ? true : !isChildOpen[slug]
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
watch(
|
|
50
|
+
() => route.path,
|
|
51
|
+
() => {
|
|
52
|
+
const paths = route.path.split('/')
|
|
53
|
+
for (let i = paths.length; i > 1; i--) {
|
|
54
|
+
paths.pop()
|
|
55
|
+
toggleDir(paths.join('/'), true)
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
toggleDir(route.path, true)
|
|
59
|
+
},
|
|
60
|
+
{ immediate: true },
|
|
61
|
+
)
|
|
62
|
+
</script>
|
|
63
|
+
|
|
64
|
+
<template>
|
|
65
|
+
<ul :class="{ 'pl-4': level > 1 }">
|
|
66
|
+
<li
|
|
67
|
+
v-for="(link, index) in tree"
|
|
68
|
+
:key="link.slug"
|
|
69
|
+
:class="{
|
|
70
|
+
'border-l-2': level > 0,
|
|
71
|
+
'border-primary-600': isActive(link),
|
|
72
|
+
'border-primary-300 hover:border-primary-300': !isActive(link)
|
|
73
|
+
}"
|
|
74
|
+
>
|
|
75
|
+
<NuxtLink
|
|
76
|
+
class="block py-1.5 flex items-center justify-between focus:outline-none cursor-pointer"
|
|
77
|
+
:exact="link.exact"
|
|
78
|
+
:class="{
|
|
79
|
+
'pl-4': level > 0,
|
|
80
|
+
'text-xl !text-primary font-bold': level === 0,
|
|
81
|
+
'!pt-0': level === 0 && index === 0,
|
|
82
|
+
'text-secondary-active': isActive(link),
|
|
83
|
+
'text-secondary text-secondary-hover': !isActive(link)
|
|
84
|
+
}"
|
|
85
|
+
@click.stop.prevent="onClick(link)"
|
|
86
|
+
>
|
|
87
|
+
<span>{{ link.title }}</span>
|
|
88
|
+
|
|
89
|
+
<Icon v-if="link.icon" :name="link.icon" class="w-5 h-5 u-text-gray-500" />
|
|
90
|
+
</NuxtLink>
|
|
91
|
+
|
|
92
|
+
<DocsAsideTree
|
|
93
|
+
v-if="link.children?.length && (max === null || ((level + 1) < max))"
|
|
94
|
+
v-show="isChildOpen[link.slug]"
|
|
95
|
+
:tree="link.children"
|
|
96
|
+
:level="level + 1"
|
|
97
|
+
:max="max"
|
|
98
|
+
class="py-2"
|
|
99
|
+
@select="link => $emit('select', link)"
|
|
100
|
+
@close="$emit('close')"
|
|
101
|
+
/>
|
|
102
|
+
</li>
|
|
103
|
+
</ul>
|
|
104
|
+
</template>
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import type { PropType } from 'vue'
|
|
3
|
+
|
|
4
|
+
defineProps({
|
|
5
|
+
buttons: {
|
|
6
|
+
type: Array as PropType<{ label?: string; variant?: string; to?: string; size?: string; icon?: string }[]>,
|
|
7
|
+
default: () => [],
|
|
8
|
+
},
|
|
9
|
+
})
|
|
10
|
+
</script>
|
|
11
|
+
|
|
12
|
+
<template>
|
|
13
|
+
<div class="flex flex-col items-center justify-center pb-48 gap-y-8 pt-36 md:pt-44 lg:pb-56 lg:pt-36 ">
|
|
14
|
+
<div v-if="$slots.badge" class="flex gap-x-2">
|
|
15
|
+
<UBadge rounded label="Warning" />
|
|
16
|
+
|
|
17
|
+
<span class="u-text-gray-500">
|
|
18
|
+
<Markdown unwrap="p" :use="$slots.badge" />
|
|
19
|
+
</span>
|
|
20
|
+
</div>
|
|
21
|
+
<h1 v-if="$slots.title" class="font-bold text-7xl text-center mb-0 u-text-gray-900">
|
|
22
|
+
<Markdown unwrap="p" :use="$slots.title" />
|
|
23
|
+
</h1>
|
|
24
|
+
<p v-if="$slots.description" class="w-1/2 text-lg text-center u-text-gray-500">
|
|
25
|
+
<Markdown unwrap="p" :use="$slots.description" />
|
|
26
|
+
</p>
|
|
27
|
+
<div class="flex gap-x-8">
|
|
28
|
+
<UButton
|
|
29
|
+
v-for="button of buttons"
|
|
30
|
+
:key="button.label"
|
|
31
|
+
:size="button.size || 'xl'"
|
|
32
|
+
:variant="button.variant || 'transparent'"
|
|
33
|
+
:icon="button.icon || undefined"
|
|
34
|
+
:label="button.label || ''"
|
|
35
|
+
:to="button.to || '#'"
|
|
36
|
+
/>
|
|
37
|
+
</div>
|
|
38
|
+
</div>
|
|
39
|
+
</template>
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="relative flex-1">
|
|
3
|
+
<slot name="header" />
|
|
4
|
+
|
|
5
|
+
<main class="relative pb-4 sm:pb-6 lg:py-8">
|
|
6
|
+
<Container padded>
|
|
7
|
+
<div class="grid grid-cols-10 gap-8 relative">
|
|
8
|
+
<aside
|
|
9
|
+
class="pb-8 overflow-x-hidden overflow-y-auto lg:pb-0 hidden lg:block lg:sticky lg:top-16 lg:pt-8 lg:-mt-8 lg:self-start col-span-2 lg:max-h-[calc(100vh-64px)]"
|
|
10
|
+
>
|
|
11
|
+
<slot name="aside" />
|
|
12
|
+
</aside>
|
|
13
|
+
|
|
14
|
+
<div class="relative" :class="{ 'col-span-10 lg:col-span-8': !!$slots.aside, 'col-span-10': !$slots.aside }">
|
|
15
|
+
<slot />
|
|
16
|
+
</div>
|
|
17
|
+
</div>
|
|
18
|
+
</Container>
|
|
19
|
+
</main>
|
|
20
|
+
</div>
|
|
21
|
+
</template>
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { ref } from '#imports'
|
|
3
|
+
|
|
4
|
+
const isOpen = ref(false)
|
|
5
|
+
</script>
|
|
6
|
+
|
|
7
|
+
<template>
|
|
8
|
+
<div class="flex flex-col-reverse lg:grid lg:grid-cols-10 gap-8 relative">
|
|
9
|
+
<div
|
|
10
|
+
class="col-span-10 lg:col-span-8"
|
|
11
|
+
>
|
|
12
|
+
<slot />
|
|
13
|
+
</div>
|
|
14
|
+
|
|
15
|
+
<div
|
|
16
|
+
:class="{
|
|
17
|
+
'flex items-center lg:block': !isOpen
|
|
18
|
+
}"
|
|
19
|
+
class="lg:col-span-2 top-16 flex items-center lg:self-start overflow-x-hidden surface surface-blurry sticky -mx-4 sm:-mx-6 px-4 sm:px-6 lg:mx-0 lg:px-0 lg:pt-8 lg:-mt-8 lg:max-h-[calc(100vh-var(--header-height))] border-b lg:border-none border-gray-200 dark:border-gray-800"
|
|
20
|
+
>
|
|
21
|
+
<div class="py-4 lg:py-0">
|
|
22
|
+
<button class="flex lg:hidden items-center gap-3" @click="isOpen = !isOpen">
|
|
23
|
+
<span class="font-semibold">Table of Contents</span>
|
|
24
|
+
|
|
25
|
+
<Icon name="heroicons-outline:chevron-right" class="w-6 h-6 transition-transform duration-100 transform" :class="[isOpen ? 'rotate-90' : 'rotate-0']" />
|
|
26
|
+
</button>
|
|
27
|
+
|
|
28
|
+
<DocsToc class="mt-4 lg:mt-0" :class="[isOpen ? 'lg:block' : 'hidden lg:block']" @move="isOpen = false" />
|
|
29
|
+
</div>
|
|
30
|
+
</div>
|
|
31
|
+
</div>
|
|
32
|
+
</template>
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { useDocus, useRoute, useScrollToHeading, useScrollspy, watch } from '#imports'
|
|
3
|
+
|
|
4
|
+
const emit = defineEmits(['move'])
|
|
5
|
+
|
|
6
|
+
const route = useRoute()
|
|
7
|
+
|
|
8
|
+
const { activeHeadings, updateHeadings } = useScrollspy()
|
|
9
|
+
|
|
10
|
+
const { toc, prev, next } = useDocus()
|
|
11
|
+
|
|
12
|
+
watch(
|
|
13
|
+
() => route.path,
|
|
14
|
+
() => {
|
|
15
|
+
if (process.client) {
|
|
16
|
+
setTimeout(() => {
|
|
17
|
+
updateHeadings([
|
|
18
|
+
...document.querySelectorAll('.content h1'),
|
|
19
|
+
...document.querySelectorAll('.content h2'),
|
|
20
|
+
...document.querySelectorAll('.content h3'),
|
|
21
|
+
])
|
|
22
|
+
}, 100)
|
|
23
|
+
}
|
|
24
|
+
}, {
|
|
25
|
+
immediate: true,
|
|
26
|
+
})
|
|
27
|
+
|
|
28
|
+
function scrollToHeading(id: string, scrollMarginCssVar: string) {
|
|
29
|
+
useScrollToHeading(id, scrollMarginCssVar)
|
|
30
|
+
emit('move', id)
|
|
31
|
+
}
|
|
32
|
+
</script>
|
|
33
|
+
|
|
34
|
+
<template>
|
|
35
|
+
<div class="space-y-2">
|
|
36
|
+
<NuxtLink v-if="prev" :to="prev.slug" class="flex lg:flex-row-reverse items-center text-primary font-semibold group gap-x-3">
|
|
37
|
+
<div class="flex-shrink-0 p-1 rounded-lg text-secondary-group-hover transition-base">
|
|
38
|
+
<Icon name="heroicons-solid:chevron-double-left" class="w-6 h-6" />
|
|
39
|
+
</div>
|
|
40
|
+
|
|
41
|
+
<span>Previous page</span>
|
|
42
|
+
</NuxtLink>
|
|
43
|
+
|
|
44
|
+
<template v-if="toc?.links?.length">
|
|
45
|
+
<div class="flex lg:flex-row-reverse items-center font-semibold gap-x-3">
|
|
46
|
+
<div class="flex-shrink-0 p-1 rounded-lg">
|
|
47
|
+
<Icon name="heroicons-outline:view-grid" class="w-6 h-6" />
|
|
48
|
+
</div>
|
|
49
|
+
|
|
50
|
+
<span>On this page</span>
|
|
51
|
+
</div>
|
|
52
|
+
|
|
53
|
+
<ul class="pl-3 lg:pr-3 mr-1 border-gray-500">
|
|
54
|
+
<li v-for="link in toc.links" :key="link.text" class="group border-l-2 lg:border-r-2 lg:border-l-0 min-w-0 lg:text-right" :class="activeHeadings.includes(link.id) ? 'border-primary-600' : 'border-primary-600'">
|
|
55
|
+
<a
|
|
56
|
+
:href="`#${link.id}`"
|
|
57
|
+
class="text-secondary text-secondary-group-hover py-1 pl-3 lg:pr-3 block truncate"
|
|
58
|
+
:class="{
|
|
59
|
+
'text-primary-500 dark:text-primary-400': activeHeadings.includes(link.id),
|
|
60
|
+
}"
|
|
61
|
+
@click.prevent="scrollToHeading(link.id, '--docs-scroll-margin-block')"
|
|
62
|
+
>
|
|
63
|
+
{{ link.text }}
|
|
64
|
+
</a>
|
|
65
|
+
</li>
|
|
66
|
+
</ul>
|
|
67
|
+
</template>
|
|
68
|
+
|
|
69
|
+
<NuxtLink v-if="next" :to="next.slug" class="flex lg:flex-row-reverse items-center text-primary font-semibold group gap-x-3">
|
|
70
|
+
<div class="flex-shrink-0 p-1 rounded-lg text-secondary-group-hover transition-base">
|
|
71
|
+
<Icon name="heroicons-solid:chevron-double-right" class="w-6 h-6" />
|
|
72
|
+
</div>
|
|
73
|
+
|
|
74
|
+
<span>Next page</span>
|
|
75
|
+
</NuxtLink>
|
|
76
|
+
</div>
|
|
77
|
+
</template>
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
<script setup>
|
|
2
|
+
import { Icon } from '@iconify/vue/dist/offline'
|
|
3
|
+
import { loadIcon } from '@iconify/vue'
|
|
4
|
+
import { ref, watch } from '#imports'
|
|
5
|
+
|
|
6
|
+
const props = defineProps({
|
|
7
|
+
name: {
|
|
8
|
+
type: [String, Object],
|
|
9
|
+
required: true,
|
|
10
|
+
},
|
|
11
|
+
})
|
|
12
|
+
|
|
13
|
+
const icon = ref(null)
|
|
14
|
+
|
|
15
|
+
icon.value = await loadIcon(props.name)
|
|
16
|
+
|
|
17
|
+
watch(() => props.name, async () => {
|
|
18
|
+
icon.value = await loadIcon(props.name)
|
|
19
|
+
})
|
|
20
|
+
</script>
|
|
21
|
+
|
|
22
|
+
<template>
|
|
23
|
+
<Icon :icon="icon" />
|
|
24
|
+
</template>
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import type { PropType } from 'vue'
|
|
3
|
+
|
|
4
|
+
import { computed, useColorMode } from '#imports'
|
|
5
|
+
|
|
6
|
+
export interface NuxtImg {
|
|
7
|
+
light: string
|
|
8
|
+
dark: string
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
const props = defineProps({
|
|
12
|
+
src: {
|
|
13
|
+
type: [String, Object] as PropType<NuxtImg>,
|
|
14
|
+
default: null,
|
|
15
|
+
},
|
|
16
|
+
})
|
|
17
|
+
|
|
18
|
+
const colorMode = useColorMode()
|
|
19
|
+
|
|
20
|
+
const src = computed(
|
|
21
|
+
() => {
|
|
22
|
+
let src = props.src
|
|
23
|
+
|
|
24
|
+
try {
|
|
25
|
+
src = JSON.parse(src as any)
|
|
26
|
+
}
|
|
27
|
+
catch (e) {
|
|
28
|
+
src = props.src
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
if (typeof src === 'string')
|
|
32
|
+
return props.src
|
|
33
|
+
|
|
34
|
+
if (colorMode.value === 'dark')
|
|
35
|
+
return props.src.dark || props.src.light
|
|
36
|
+
|
|
37
|
+
if (colorMode.value === 'light')
|
|
38
|
+
return props.src.light || props.src.light
|
|
39
|
+
},
|
|
40
|
+
)
|
|
41
|
+
</script>
|
|
42
|
+
|
|
43
|
+
<template>
|
|
44
|
+
<img :src="src">
|
|
45
|
+
</template>
|