docus 3.0.0-beta.8 → 3.0.0
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/LICENSE +21 -0
- package/README.md +31 -9
- package/app/app/app.config.ts +33 -0
- package/app/app/app.vue +54 -0
- package/app/app/assets/css/main.css +5 -0
- package/app/app/components/IconMenuToggle.vue +81 -0
- package/app/app/components/OgImage/OgImageDocs.vue +76 -0
- package/app/app/components/OgImage/OgImageLanding.vue +73 -0
- package/app/app/components/app/AppFooter.vue +40 -0
- package/app/app/components/app/AppHeader.vue +57 -0
- package/app/app/components/app/AppHeaderBody.vue +13 -0
- package/{theme/components/globals/Logo.vue → app/app/components/app/AppHeaderCTA.vue} +1 -1
- package/app/app/components/app/AppHeaderCenter.vue +6 -0
- package/app/app/components/app/AppHeaderLogo.vue +16 -0
- package/app/app/components/docs/DocsAsideLeftTop.vue +3 -0
- package/app/app/components/docs/DocsAsideRightBottom.vue +17 -0
- package/app/app/components/docs/DocsPageHeaderLinks.vue +91 -0
- package/app/app/error.vue +42 -0
- package/app/app/layouts/docs.vue +25 -0
- package/app/app/pages/[...slug].vue +111 -0
- package/app/app/pages/index.vue +37 -0
- package/app/content.config.ts +31 -0
- package/app/nuxt.config.ts +41 -0
- package/app/nuxt.schema.ts +255 -0
- package/app/server/routes/raw/[...slug].md.get.ts +24 -0
- package/dist/main.mjs +242 -0
- package/package.json +66 -39
- package/theme/app/router.options.ts +0 -18
- package/theme/assets/css/fonts.css +0 -84
- package/theme/assets/css/main.css +0 -104
- package/theme/components/app/Container.vue +0 -25
- package/theme/components/app/Footer.vue +0 -40
- package/theme/components/app/MobileNav.vue +0 -85
- package/theme/components/app/Navbar.vue +0 -37
- package/theme/components/app/NavbarLogo.vue +0 -33
- package/theme/components/app/Page.vue +0 -7
- package/theme/components/app/PoweredByDocus.vue +0 -11
- package/theme/components/content/Alert.vue +0 -124
- package/theme/components/content/BlockHero.vue +0 -54
- package/theme/components/content/ButtonLink.vue +0 -45
- package/theme/components/content/Card.vue +0 -46
- package/theme/components/content/CardGrid.vue +0 -23
- package/theme/components/content/CodeBlock.vue +0 -47
- package/theme/components/content/CodeGroup.vue +0 -135
- package/theme/components/content/CopyButton.vue +0 -49
- package/theme/components/content/List.vue +0 -5
- package/theme/components/content/NeedContribution.vue +0 -23
- package/theme/components/content/ReadMore.vue +0 -25
- package/theme/components/content/Sandbox.vue +0 -102
- package/theme/components/content/TabsHeader.vue +0 -44
- package/theme/components/content/Terminal.vue +0 -64
- package/theme/components/content/VideoPlayer.vue +0 -115
- package/theme/components/dev/Debug.vue +0 -66
- package/theme/components/docs/DocsAside.vue +0 -21
- package/theme/components/docs/DocsAsideTree.vue +0 -104
- package/theme/components/docs/DocsHero.vue +0 -39
- package/theme/components/docs/DocsPage.vue +0 -21
- package/theme/components/docs/DocsPageContent.vue +0 -32
- package/theme/components/docs/DocsToc.vue +0 -77
- package/theme/components/globals/Icon.vue +0 -24
- package/theme/components/globals/NuxtImg.vue +0 -45
- package/theme/components/globals/SocialIcons.vue +0 -45
- package/theme/components/globals/ThemeSelect.vue +0 -35
- package/theme/components/icons/IconAlgolia.vue +0 -8
- package/theme/components/icons/IconArrowLeft.vue +0 -10
- package/theme/components/icons/IconArrowRight.vue +0 -10
- package/theme/components/icons/IconBadgeCheck.vue +0 -14
- package/theme/components/icons/IconCheck.vue +0 -10
- package/theme/components/icons/IconCheckCircle.vue +0 -10
- package/theme/components/icons/IconChevronRight.vue +0 -12
- package/theme/components/icons/IconClipboardCheck.vue +0 -14
- package/theme/components/icons/IconClipboardCopy.vue +0 -14
- package/theme/components/icons/IconCodeSandbox.vue +0 -8
- package/theme/components/icons/IconCopy.vue +0 -17
- package/theme/components/icons/IconDots.vue +0 -10
- package/theme/components/icons/IconEdit.vue +0 -18
- package/theme/components/icons/IconExclamationCircle.vue +0 -12
- package/theme/components/icons/IconExclamationTriangle.vue +0 -10
- package/theme/components/icons/IconExternalLink.vue +0 -12
- package/theme/components/icons/IconGit.vue +0 -7
- package/theme/components/icons/IconGitHub.vue +0 -10
- package/theme/components/icons/IconHeart.vue +0 -9
- package/theme/components/icons/IconInformationCircle.vue +0 -10
- package/theme/components/icons/IconLighthouse.vue +0 -83
- package/theme/components/icons/IconLine.vue +0 -10
- package/theme/components/icons/IconMarkdown.vue +0 -13
- package/theme/components/icons/IconMenu.vue +0 -12
- package/theme/components/icons/IconMenuAlt.vue +0 -10
- package/theme/components/icons/IconMinus.vue +0 -10
- package/theme/components/icons/IconMoon.vue +0 -10
- package/theme/components/icons/IconNuxt.vue +0 -14
- package/theme/components/icons/IconNuxtContent.vue +0 -20
- package/theme/components/icons/IconNuxtLabs.vue +0 -21
- package/theme/components/icons/IconPlus.vue +0 -10
- package/theme/components/icons/IconPuzzle.vue +0 -8
- package/theme/components/icons/IconSSG.vue +0 -7
- package/theme/components/icons/IconSearch.vue +0 -12
- package/theme/components/icons/IconSun.vue +0 -10
- package/theme/components/icons/IconTailwind.vue +0 -3
- package/theme/components/icons/IconTocBack.vue +0 -21
- package/theme/components/icons/IconTocCurrent.vue +0 -21
- package/theme/components/icons/IconTocNext.vue +0 -8
- package/theme/components/icons/IconTranslate.vue +0 -14
- package/theme/components/icons/IconTwitter.vue +0 -8
- package/theme/components/icons/IconVite.vue +0 -30
- package/theme/components/icons/IconVue.vue +0 -6
- package/theme/components/icons/IconVueTelescope.vue +0 -11
- package/theme/components/icons/IconWindi.vue +0 -17
- package/theme/components/icons/IconX.vue +0 -12
- package/theme/components/icons/IconXCircle.vue +0 -10
- package/theme/components/icons/IconZap.vue +0 -8
- package/theme/components/prose/ProseA.vue +0 -66
- package/theme/components/prose/ProseBlockquote.vue +0 -21
- package/theme/components/prose/ProseCode.vue +0 -67
- package/theme/components/prose/ProseCodeInline.vue +0 -38
- package/theme/components/prose/ProseEm.vue +0 -11
- package/theme/components/prose/ProseH1.vue +0 -22
- package/theme/components/prose/ProseH2.vue +0 -22
- package/theme/components/prose/ProseH3.vue +0 -24
- package/theme/components/prose/ProseH4.vue +0 -24
- package/theme/components/prose/ProseHr.vue +0 -13
- package/theme/components/prose/ProseImg.vue +0 -30
- package/theme/components/prose/ProseLi.vue +0 -31
- package/theme/components/prose/ProseOl.vue +0 -16
- package/theme/components/prose/ProseP.vue +0 -14
- package/theme/components/prose/ProseStrong.vue +0 -14
- package/theme/components/prose/ProseTable.vue +0 -13
- package/theme/components/prose/ProseTbody.vue +0 -5
- package/theme/components/prose/ProseTd.vue +0 -11
- package/theme/components/prose/ProseTh.vue +0 -11
- package/theme/components/prose/ProseThead.vue +0 -11
- package/theme/components/prose/ProseTr.vue +0 -11
- package/theme/components/prose/ProseUl.vue +0 -15
- package/theme/composables/useDocus.ts +0 -43
- package/theme/composables/useMenu.ts +0 -7
- package/theme/composables/useScrollToHeading.ts +0 -35
- package/theme/composables/useScrollspy.ts +0 -46
- package/theme/composables/useUserAgent.ts +0 -7
- package/theme/composables/utils.ts +0 -4
- package/theme/layouts/default.vue +0 -29
- package/theme/layouts/page.vue +0 -19
- package/theme/middleware/components.ts +0 -26
- package/theme/middleware/navigation.global.ts +0 -12
- package/theme/middleware/page.ts +0 -8
- package/theme/middleware/theme.global.ts +0 -12
- package/theme/nuxt.config.ts +0 -171
- package/theme/pages/[...slug].vue +0 -64
- package/theme/plugins/menu.ts +0 -67
- package/theme/plugins/user-agent.ts +0 -27
- package/theme/utils/components.ts +0 -25
- package/theme/utils/navigation.ts +0 -49
- package/theme/utils/plugin.ts +0 -21
- package/theme/utils/queries.ts +0 -68
- package/theme/utils/state.ts +0 -32
- package/theme/utils/theme.ts +0 -66
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
<script setup lang="ts">
|
|
2
|
-
import Clipboard from 'clipboard'
|
|
3
|
-
import { onMounted, ref } from '#imports'
|
|
4
|
-
|
|
5
|
-
const copy = ref()
|
|
6
|
-
const state = ref('init')
|
|
7
|
-
|
|
8
|
-
onMounted(() => {
|
|
9
|
-
const copyCode = new Clipboard(copy.value, {
|
|
10
|
-
target(trigger) {
|
|
11
|
-
return trigger.previousElementSibling
|
|
12
|
-
},
|
|
13
|
-
})
|
|
14
|
-
|
|
15
|
-
copyCode.on('success', (event) => {
|
|
16
|
-
event.clearSelection()
|
|
17
|
-
state.value = 'copied'
|
|
18
|
-
window.setTimeout(() => {
|
|
19
|
-
state.value = 'init'
|
|
20
|
-
}, 1000)
|
|
21
|
-
})
|
|
22
|
-
})
|
|
23
|
-
</script>
|
|
24
|
-
|
|
25
|
-
<template>
|
|
26
|
-
<button
|
|
27
|
-
ref="copy"
|
|
28
|
-
class="
|
|
29
|
-
copy
|
|
30
|
-
focus:outline-none
|
|
31
|
-
absolute
|
|
32
|
-
right-1
|
|
33
|
-
bottom-1
|
|
34
|
-
px-2
|
|
35
|
-
py-2
|
|
36
|
-
m-1
|
|
37
|
-
text-gray-400
|
|
38
|
-
bg-gray-900
|
|
39
|
-
text-xs
|
|
40
|
-
leading-none
|
|
41
|
-
rounded-lg
|
|
42
|
-
font-mono
|
|
43
|
-
font-semibold
|
|
44
|
-
"
|
|
45
|
-
>
|
|
46
|
-
<Icon v-if="state === 'copied'" name="fa-check" class="w-4 h-4" />
|
|
47
|
-
<Icon v-else name="fa-copy" class="w-4 h-4" />
|
|
48
|
-
</button>
|
|
49
|
-
</template>
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
<script setup lang="ts">
|
|
2
|
-
defineProps({
|
|
3
|
-
to: {
|
|
4
|
-
type: String,
|
|
5
|
-
required: true,
|
|
6
|
-
default: '/community/contribution#documentation-guide',
|
|
7
|
-
},
|
|
8
|
-
icon: {
|
|
9
|
-
type: String,
|
|
10
|
-
required: true,
|
|
11
|
-
default: '🚧',
|
|
12
|
-
},
|
|
13
|
-
})
|
|
14
|
-
</script>
|
|
15
|
-
|
|
16
|
-
<template>
|
|
17
|
-
<Alert type="warning" :icon="icon">
|
|
18
|
-
Documentation for this section is not yet complete. You can
|
|
19
|
-
<NuxtLink :to="to">
|
|
20
|
-
contribute to the documentation.
|
|
21
|
-
</NuxtLink>
|
|
22
|
-
</Alert>
|
|
23
|
-
</template>
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
<script setup lang="ts">
|
|
2
|
-
import { splitByCase, upperFirst } from 'scule'
|
|
3
|
-
import { computed } from '#imports'
|
|
4
|
-
|
|
5
|
-
const props = defineProps({
|
|
6
|
-
link: {
|
|
7
|
-
type: String,
|
|
8
|
-
required: true,
|
|
9
|
-
},
|
|
10
|
-
title: {
|
|
11
|
-
type: String,
|
|
12
|
-
required: false,
|
|
13
|
-
default: '',
|
|
14
|
-
},
|
|
15
|
-
})
|
|
16
|
-
|
|
17
|
-
// Guess title from link!
|
|
18
|
-
const computedTitle = computed(() => (props.title || props.link).split('/').filter(Boolean).map(part => splitByCase(part).map(p => upperFirst(p)).join(' ')).join(' > '))
|
|
19
|
-
</script>
|
|
20
|
-
|
|
21
|
-
<template>
|
|
22
|
-
<Alert icon="👉">
|
|
23
|
-
Read more in <NuxtLink :to="link" v-html="computedTitle" />.
|
|
24
|
-
</Alert>
|
|
25
|
-
</template>
|
|
@@ -1,102 +0,0 @@
|
|
|
1
|
-
<script setup lang="ts">
|
|
2
|
-
import { computed, onMounted, ref, useColorMode } from '#imports'
|
|
3
|
-
|
|
4
|
-
const props = defineProps({
|
|
5
|
-
src: {
|
|
6
|
-
type: String,
|
|
7
|
-
default: '',
|
|
8
|
-
},
|
|
9
|
-
repo: {
|
|
10
|
-
type: String,
|
|
11
|
-
default: '',
|
|
12
|
-
},
|
|
13
|
-
branch: {
|
|
14
|
-
type: String,
|
|
15
|
-
default: '',
|
|
16
|
-
},
|
|
17
|
-
dir: {
|
|
18
|
-
type: String,
|
|
19
|
-
default: '',
|
|
20
|
-
},
|
|
21
|
-
file: {
|
|
22
|
-
type: String,
|
|
23
|
-
default: 'app.vue',
|
|
24
|
-
},
|
|
25
|
-
})
|
|
26
|
-
|
|
27
|
-
const colorMode = useColorMode()
|
|
28
|
-
|
|
29
|
-
const providers = {
|
|
30
|
-
CodeSandBox: () => `https://codesandbox.io/embed/github/${props.repo}/tree/${props.branch}/${props.dir}?hidenavigation=1&theme=${colorMode.value}`,
|
|
31
|
-
StackBlitz: () => `https://stackblitz.com/github/${props.repo}/tree/${props.branch}/${props.dir}?embed=1&file=${props.file}&theme=${colorMode.value}`,
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
const providersTabs = Object.keys(providers).map(p => ({ label: p }))
|
|
35
|
-
const activeTabIndex = ref(-1)
|
|
36
|
-
const tabs = ref()
|
|
37
|
-
const url = ref('')
|
|
38
|
-
const provider = ref('')
|
|
39
|
-
|
|
40
|
-
const changeProvider = (value) => {
|
|
41
|
-
provider.value = value
|
|
42
|
-
url.value = props.src || providers[provider.value]()
|
|
43
|
-
localStorage.setItem('docus_sandbox', value)
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
const sandBoxUrl = computed(() => url.value?.replace('?embed=1&', '?').replace('/embed/', '/s/'))
|
|
47
|
-
|
|
48
|
-
const updateTab = (i: number) => {
|
|
49
|
-
activeTabIndex.value = i
|
|
50
|
-
changeProvider(providersTabs[i].label)
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
onMounted(() => {
|
|
54
|
-
// TODO: if Safari, use CodeSandBox by default: const defaultSandbox = ...
|
|
55
|
-
provider.value = window.localStorage.getItem('docus_sandbox') || 'CodeSandBox'
|
|
56
|
-
|
|
57
|
-
url.value = props.src || providers[provider.value]()
|
|
58
|
-
|
|
59
|
-
// Set active tab
|
|
60
|
-
activeTabIndex.value = Object.keys(providers).indexOf(provider.value)
|
|
61
|
-
|
|
62
|
-
setTimeout(() => tabs.value.updateTabs(activeTabIndex.value), 100)
|
|
63
|
-
})
|
|
64
|
-
</script>
|
|
65
|
-
|
|
66
|
-
<template>
|
|
67
|
-
<div class="w-full min-h-[500px] mx-auto mb-6 overflow-hidden text-3xl rounded-lg sandbox mt-4">
|
|
68
|
-
<TabsHeader
|
|
69
|
-
v-if="!src"
|
|
70
|
-
ref="tabs"
|
|
71
|
-
:active-tab-index="activeTabIndex"
|
|
72
|
-
:tabs="providersTabs"
|
|
73
|
-
@update:active-tab-index="updateTab"
|
|
74
|
-
>
|
|
75
|
-
<template #footer>
|
|
76
|
-
<div class="absolute top-1/2 transform -translate-y-1/2 right-0 px-2">
|
|
77
|
-
<Link class="flex items-center text-gray-500 dark:text-gray-400" :to="sandBoxUrl" blank>
|
|
78
|
-
<IconExternalLink class="h-5 w-5" />
|
|
79
|
-
</Link>
|
|
80
|
-
</div>
|
|
81
|
-
</template>
|
|
82
|
-
</TabsHeader>
|
|
83
|
-
|
|
84
|
-
<iframe
|
|
85
|
-
v-if="url"
|
|
86
|
-
:src="url"
|
|
87
|
-
title="Sandbox editor"
|
|
88
|
-
sandbox="allow-modals allow-forms allow-popups allow-scripts allow-same-origin"
|
|
89
|
-
class="w-full h-full min-h-[700px] overflow-hidden bg-gray-100 dark:bg-gray-800"
|
|
90
|
-
/>
|
|
91
|
-
|
|
92
|
-
<span v-else class="text-white flex-1">Loading Sandbox...</span>
|
|
93
|
-
</div>
|
|
94
|
-
</template>
|
|
95
|
-
|
|
96
|
-
<style lang="postcss" scoped>
|
|
97
|
-
.sandbox,
|
|
98
|
-
.sandbox iframe {
|
|
99
|
-
@apply w-full rounded-lg rounded-tl-none rounded-tr-none overflow-hidden h-64;
|
|
100
|
-
height: 700px;
|
|
101
|
-
}
|
|
102
|
-
</style>
|
|
@@ -1,44 +0,0 @@
|
|
|
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>
|
|
@@ -1,64 +0,0 @@
|
|
|
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>
|
|
@@ -1,115 +0,0 @@
|
|
|
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>
|
|
@@ -1,66 +0,0 @@
|
|
|
1
|
-
<script setup lang="ts">
|
|
2
|
-
import type { PropType } from 'vue'
|
|
3
|
-
import type { ParsedContent } from '@nuxt/content/dist/runtime/types'
|
|
4
|
-
import type { ThemeDebugConfig } from '../../utils/theme'
|
|
5
|
-
import { useDocus } from '#imports'
|
|
6
|
-
|
|
7
|
-
const { page, navigation, theme } = useDocus()
|
|
8
|
-
|
|
9
|
-
const defaultConfig = {
|
|
10
|
-
page: true,
|
|
11
|
-
navigation: true,
|
|
12
|
-
theme: true,
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
const config = computed(
|
|
16
|
-
() => {
|
|
17
|
-
const _config = theme.value?.debug
|
|
18
|
-
|
|
19
|
-
if (typeof _config === 'object')
|
|
20
|
-
return Object.assign(defaultConfig, _config)
|
|
21
|
-
|
|
22
|
-
if (_config === true)
|
|
23
|
-
return defaultConfig
|
|
24
|
-
|
|
25
|
-
if (_config === false)
|
|
26
|
-
return _config
|
|
27
|
-
},
|
|
28
|
-
)
|
|
29
|
-
|
|
30
|
-
const icons = {
|
|
31
|
-
page: '📃',
|
|
32
|
-
navigation: '🔖',
|
|
33
|
-
theme: '🎨',
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
Object.entries({
|
|
37
|
-
page,
|
|
38
|
-
navigation,
|
|
39
|
-
theme,
|
|
40
|
-
}).forEach(([key, reference]) => {
|
|
41
|
-
if (!config.value || !config.value?.[key])
|
|
42
|
-
return
|
|
43
|
-
|
|
44
|
-
watchDebounced(
|
|
45
|
-
reference,
|
|
46
|
-
() => {
|
|
47
|
-
if (key === 'page')
|
|
48
|
-
// eslint-disable-next-line no-console
|
|
49
|
-
console.log(`[${icons[key]}] Page updates detected! ${`(${(reference.value as ParsedContent)?.title})` || `(${(reference.value as ParsedContent)?.id})` || ''}`)
|
|
50
|
-
else
|
|
51
|
-
// eslint-disable-next-line no-console
|
|
52
|
-
console.log(`[${icons[key]}] ${key[0].toUpperCase() + key.slice(1, key.length)} updates detected!`)
|
|
53
|
-
|
|
54
|
-
// eslint-disable-next-line no-console
|
|
55
|
-
console.dir({ ...reference.value })
|
|
56
|
-
},
|
|
57
|
-
{
|
|
58
|
-
debounce: 100,
|
|
59
|
-
},
|
|
60
|
-
)
|
|
61
|
-
})
|
|
62
|
-
</script>
|
|
63
|
-
|
|
64
|
-
<template>
|
|
65
|
-
<div class="hidden" />
|
|
66
|
-
</template>
|
|
@@ -1,21 +0,0 @@
|
|
|
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>
|
|
@@ -1,104 +0,0 @@
|
|
|
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>
|
|
@@ -1,39 +0,0 @@
|
|
|
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>
|
|
@@ -1,21 +0,0 @@
|
|
|
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>
|