@movk/nuxt-docs 1.14.1 → 1.15.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/README.md +1 -1
- package/app/app.config.ts +5 -32
- package/app/app.vue +54 -32
- package/app/components/DocsAsideRightBottom.vue +1 -1
- package/app/components/OgImage/OgImageDocs.takumi.vue +90 -0
- package/app/components/PageHeaderLinks.vue +6 -16
- package/app/components/content/CommitChangelog.vue +1 -0
- package/app/components/content/Mermaid.vue +3 -1
- package/app/components/header/HeaderCTA.vue +1 -10
- package/app/components/theme-picker/ThemePicker.vue +22 -33
- package/app/composables/useTheme.ts +64 -84
- package/app/composables/useToolCall.ts +5 -8
- package/app/error.vue +1 -1
- package/app/pages/docs/[...slug].vue +6 -6
- package/app/plugins/theme.ts +39 -68
- package/app/templates/landing.vue +5 -2
- package/app/templates/releases.vue +5 -2
- package/app/types/index.d.ts +8 -57
- package/content.config.ts +1 -0
- package/modules/ai-chat/index.ts +16 -26
- package/modules/ai-chat/runtime/components/AiChat.vue +3 -3
- package/modules/ai-chat/runtime/components/AiChatFloatingInput.vue +8 -8
- package/modules/ai-chat/runtime/components/AiChatPanel.vue +216 -231
- package/modules/ai-chat/runtime/components/AiChatPreStream.vue +0 -14
- package/modules/ai-chat/runtime/composables/useAIChat.ts +25 -73
- package/modules/ai-chat/runtime/composables/useModels.ts +0 -19
- package/modules/ai-chat/runtime/server/api/ai-chat.ts +74 -48
- package/modules/ai-chat/runtime/server/utils/getModel.ts +1 -9
- package/modules/ai-chat/runtime/types.ts +5 -0
- package/nuxt.config.ts +42 -36
- package/nuxt.schema.ts +14 -99
- package/package.json +25 -29
- package/server/mcp/tools/get-page.ts +5 -47
- package/server/mcp/tools/list-getting-started-guides.ts +1 -3
- package/server/mcp/tools/list-pages.ts +9 -44
- package/utils/git.ts +26 -79
- package/app/components/OgImage/Nuxt.vue +0 -247
- package/app/composables/useAnalytics.ts +0 -7
- package/modules/ai-chat/runtime/components/AiChatReasoning.vue +0 -49
- package/modules/ai-chat/runtime/components/AiChatSlideoverFaq.vue +0 -38
- package/modules/ai-chat/runtime/components/AiChatToolCall.vue +0 -31
- package/modules/ai-chat/runtime/server/utils/docs_agent.ts +0 -54
package/README.md
CHANGED
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
<img src="https://docs.mhaibaraai.cn/ai/AiChat.png" alt="AiChat" width="400">
|
|
25
25
|
</div>
|
|
26
26
|
|
|
27
|
-
- **AI 聊天助手** - 内置智能文档助手,基于 Vercel AI SDK 支持多种 LLM
|
|
27
|
+
- **AI 聊天助手** - 内置智能文档助手,基于 Vercel AI SDK 支持多种 LLM 模型
|
|
28
28
|
- **MCP Server 支持** - 集成 Model Context Protocol 服务器,为 AI 助手提供结构化的文档访问能力
|
|
29
29
|
- **LLM 优化** - 通过 `nuxt-llms` 模块自动生成 `llms.txt` 和 `llms-full.txt`,为 AI 工具提供优化的文档索引
|
|
30
30
|
- **流式响应** - 支持 AI 响应流式输出和代码高亮,配合 `shiki-stream` 实现实时语法高亮渲染
|
package/app/app.config.ts
CHANGED
|
@@ -17,26 +17,8 @@ export default defineAppConfig({
|
|
|
17
17
|
colors: {
|
|
18
18
|
primary: 'green',
|
|
19
19
|
neutral: 'slate'
|
|
20
|
-
},
|
|
21
|
-
contentNavigation: {
|
|
22
|
-
slots: {
|
|
23
|
-
linkLeadingIcon: 'size-4 mr-1',
|
|
24
|
-
linkTrailing: 'hidden'
|
|
25
|
-
},
|
|
26
|
-
defaultVariants: {
|
|
27
|
-
variant: 'link'
|
|
28
|
-
}
|
|
29
|
-
},
|
|
30
|
-
pageLinks: {
|
|
31
|
-
slots: {
|
|
32
|
-
linkLeadingIcon: 'size-4',
|
|
33
|
-
linkLabelExternalIcon: 'size-2.5'
|
|
34
|
-
}
|
|
35
20
|
}
|
|
36
|
-
|
|
37
|
-
vercelAnalytics: {
|
|
38
|
-
enable: false,
|
|
39
|
-
debug: false
|
|
21
|
+
|
|
40
22
|
},
|
|
41
23
|
header: {
|
|
42
24
|
avatar: 'https://docs.mhaibaraai.cn/avatar.png',
|
|
@@ -79,28 +61,19 @@ export default defineAppConfig({
|
|
|
79
61
|
},
|
|
80
62
|
texts: {
|
|
81
63
|
title: 'AI 助手',
|
|
82
|
-
collapse: '折叠',
|
|
83
|
-
expand: '展开',
|
|
84
64
|
clearChat: '清除聊天记录',
|
|
85
65
|
close: '关闭',
|
|
86
|
-
loading: 'Loading...',
|
|
87
|
-
askAnything: '问我任何事情...',
|
|
88
|
-
askMeAnythingDescription: '我可以帮助您浏览文档、解释概念并回答您的问题。',
|
|
89
|
-
faq: 'FAQ 建议',
|
|
90
66
|
placeholder: '输入你的问题...',
|
|
91
67
|
lineBreak: '换行',
|
|
92
68
|
trigger: '与 AI 聊天',
|
|
93
|
-
streaming: '思考中...',
|
|
94
|
-
streamed: '思考过程',
|
|
95
69
|
explainWithAi: '用 AI 解释此页面'
|
|
96
70
|
},
|
|
97
71
|
icons: {
|
|
98
|
-
loading: 'i-lucide-loader',
|
|
99
72
|
trigger: 'i-custom-ai',
|
|
100
|
-
explain: 'i-lucide-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
73
|
+
explain: 'i-lucide-bot-message-square',
|
|
74
|
+
reasoning: 'i-lucide-brain',
|
|
75
|
+
close: 'i-lucide-panel-right-close',
|
|
76
|
+
clearChat: 'i-lucide-list-x',
|
|
104
77
|
providers: {
|
|
105
78
|
deepseek: 'i-hugeicons:deepseek',
|
|
106
79
|
alibaba: 'i-hugeicons:qwen',
|
package/app/app.vue
CHANGED
|
@@ -1,33 +1,39 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
import colors from 'tailwindcss/colors'
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
3
|
+
import { withoutTrailingSlash } from 'ufo'
|
|
4
|
+
import { zh_cn } from '@nuxt/ui/locale'
|
|
5
5
|
|
|
6
6
|
const site = useSiteConfig()
|
|
7
7
|
const appConfig = useAppConfig()
|
|
8
8
|
const colorMode = useColorMode()
|
|
9
9
|
const route = useRoute()
|
|
10
|
-
const {
|
|
10
|
+
const { style, link } = useTheme()
|
|
11
|
+
const { isEnabled: isAiChatEnabled } = useAIChat()
|
|
11
12
|
|
|
12
13
|
const { data: navigation } = await useAsyncData('navigation', () => queryCollectionNavigation('docs', ['category', 'description']))
|
|
13
|
-
const { data: files } = useLazyAsyncData('search', () => queryCollectionSearchSections('docs'
|
|
14
|
+
const { data: files } = useLazyAsyncData('search', () => queryCollectionSearchSections('docs', {
|
|
15
|
+
ignoredTags: ['style']
|
|
16
|
+
}), {
|
|
14
17
|
server: false
|
|
15
18
|
})
|
|
19
|
+
|
|
16
20
|
const color = computed(() => colorMode.value === 'dark' ? (colors as any)[appConfig.ui.colors.neutral][900] : 'white')
|
|
17
|
-
const radius = computed(() => `:root { --ui-radius: ${appConfig.theme.radius}rem; }`)
|
|
18
|
-
const blackAsPrimary = computed(() => appConfig.theme.blackAsPrimary ? `:root { --ui-primary: black; } .dark { --ui-primary: white; }` : ':root {}')
|
|
19
|
-
const font = computed(() => `:root { --font-sans: '${appConfig.theme.font}', sans-serif; }`)
|
|
20
21
|
|
|
21
22
|
useHead({
|
|
22
23
|
meta: [
|
|
23
24
|
{ name: 'viewport', content: 'width=device-width, initial-scale=1' },
|
|
24
25
|
{ key: 'theme-color', name: 'theme-color', content: color }
|
|
25
26
|
],
|
|
26
|
-
|
|
27
|
-
{
|
|
28
|
-
{
|
|
29
|
-
|
|
30
|
-
]
|
|
27
|
+
link: [
|
|
28
|
+
{ rel: 'icon', href: '/favicon.ico' },
|
|
29
|
+
{ rel: 'canonical', href: `${site.url}${withoutTrailingSlash(route.path)}` },
|
|
30
|
+
...link.value
|
|
31
|
+
],
|
|
32
|
+
htmlAttrs: {
|
|
33
|
+
lang: 'zh-CN',
|
|
34
|
+
dir: 'ltr'
|
|
35
|
+
},
|
|
36
|
+
style
|
|
31
37
|
})
|
|
32
38
|
|
|
33
39
|
useSeoMeta({
|
|
@@ -44,32 +50,48 @@ provide('navigation', rootNavigation)
|
|
|
44
50
|
</script>
|
|
45
51
|
|
|
46
52
|
<template>
|
|
47
|
-
<UApp :toaster="appConfig.toaster">
|
|
53
|
+
<UApp :toaster="appConfig.toaster" :locale="zh_cn">
|
|
48
54
|
<NuxtLoadingIndicator color="var(--ui-primary)" :height="2" />
|
|
49
|
-
<Analytics v-if="appConfig.vercelAnalytics" :debug="appConfig.vercelAnalytics?.debug" />
|
|
50
|
-
<SpeedInsights v-if="appConfig.vercelAnalytics" :debug="appConfig.vercelAnalytics?.debug" />
|
|
51
55
|
|
|
52
|
-
<
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
+
<UTheme
|
|
57
|
+
:ui="{
|
|
58
|
+
contentNavigation: {
|
|
59
|
+
linkLeadingIcon: 'size-4 mr-1',
|
|
60
|
+
linkTrailing: 'hidden'
|
|
61
|
+
},
|
|
62
|
+
pageLinks: {
|
|
63
|
+
linkLeadingIcon: 'size-4',
|
|
64
|
+
linkLabelExternalIcon: 'size-2.5'
|
|
65
|
+
}
|
|
66
|
+
}"
|
|
67
|
+
>
|
|
68
|
+
<div class="flex">
|
|
69
|
+
<div class="flex-1 min-w-0" :class="[route.path.startsWith('/docs/') && 'root']">
|
|
70
|
+
<template v-if="!route.path.startsWith('/examples')">
|
|
71
|
+
<Header v-if="$route.meta.header !== false" />
|
|
72
|
+
</template>
|
|
56
73
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
74
|
+
<NuxtLayout>
|
|
75
|
+
<NuxtPage />
|
|
76
|
+
</NuxtLayout>
|
|
60
77
|
|
|
61
|
-
|
|
62
|
-
|
|
78
|
+
<template v-if="!route.path.startsWith('/examples')">
|
|
79
|
+
<Footer v-if="$route.meta.footer !== false" />
|
|
63
80
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
<LazyAiChatPanel />
|
|
68
|
-
<LazyAiChatFloatingInput />
|
|
81
|
+
<ClientOnly>
|
|
82
|
+
<UContentSearch :files="files" :navigation="rootNavigation" :fuse="{ resultLimit: 500 }" />
|
|
83
|
+
</ClientOnly>
|
|
69
84
|
</template>
|
|
70
|
-
</
|
|
71
|
-
|
|
72
|
-
|
|
85
|
+
</div>
|
|
86
|
+
|
|
87
|
+
<template v-if="!route.path.startsWith('/examples') && isAiChatEnabled">
|
|
88
|
+
<ClientOnly>
|
|
89
|
+
<AiChatPanel />
|
|
90
|
+
<AiChatFloatingInput />
|
|
91
|
+
</ClientOnly>
|
|
92
|
+
</template>
|
|
93
|
+
</div>
|
|
94
|
+
</UTheme>
|
|
73
95
|
</UApp>
|
|
74
96
|
</template>
|
|
75
97
|
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
withDefaults(defineProps<{
|
|
3
|
+
title?: string
|
|
4
|
+
description?: string
|
|
5
|
+
siteName?: string
|
|
6
|
+
}>(), {
|
|
7
|
+
title: '文档',
|
|
8
|
+
description: '使用 Nuxt Content 构建的文档站点',
|
|
9
|
+
siteName: 'Movk Nuxt Docs'
|
|
10
|
+
})
|
|
11
|
+
</script>
|
|
12
|
+
|
|
13
|
+
<template>
|
|
14
|
+
<div
|
|
15
|
+
style="font-family: 'Public Sans', 'Noto Sans SC', system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;"
|
|
16
|
+
class="w-full h-full flex flex-col justify-center items-center relative p-10 lg:p-15 bg-white text-neutral-900 dark:bg-neutral-900 dark:text-neutral-50"
|
|
17
|
+
>
|
|
18
|
+
<div
|
|
19
|
+
class="absolute top-0 left-0 right-0 bottom-0"
|
|
20
|
+
:style="{
|
|
21
|
+
backgroundImage: `radial-gradient(at 100% 100%, rgba(34, 197, 94, 0.15), transparent)`
|
|
22
|
+
}"
|
|
23
|
+
/>
|
|
24
|
+
<div
|
|
25
|
+
class="absolute top-0 left-0 right-0 bottom-0"
|
|
26
|
+
:style="{
|
|
27
|
+
backgroundImage: `radial-gradient(at 0% 0%, rgba(34, 197, 94, 0.1), transparent)`
|
|
28
|
+
}"
|
|
29
|
+
/>
|
|
30
|
+
|
|
31
|
+
<div class="relative flex flex-col items-center text-center gap-5 lg:gap-8">
|
|
32
|
+
<div class="flex items-center gap-3">
|
|
33
|
+
<svg viewBox="0 0 64 64" class="w-10 h-10 lg:w-16 lg:h-16">
|
|
34
|
+
<defs>
|
|
35
|
+
<linearGradient
|
|
36
|
+
id="nsLine1"
|
|
37
|
+
x1="0%"
|
|
38
|
+
y1="100%"
|
|
39
|
+
x2="100%"
|
|
40
|
+
y2="0%"
|
|
41
|
+
>
|
|
42
|
+
<stop offset="0%" stop-color="#22c55e" />
|
|
43
|
+
<stop offset="100%" stop-color="#86efac" />
|
|
44
|
+
</linearGradient>
|
|
45
|
+
<linearGradient
|
|
46
|
+
id="nsFill1"
|
|
47
|
+
x1="0%"
|
|
48
|
+
y1="0%"
|
|
49
|
+
x2="0%"
|
|
50
|
+
y2="100%"
|
|
51
|
+
>
|
|
52
|
+
<stop offset="0%" stop-color="#22c55e" stop-opacity="0.6" />
|
|
53
|
+
<stop offset="100%" stop-color="#22c55e" stop-opacity="0" />
|
|
54
|
+
</linearGradient>
|
|
55
|
+
</defs>
|
|
56
|
+
<path d="M8 52 Q20 48 24 36 T40 20 T56 12 L56 56 L8 56 Z" fill="url(#nsFill1)" />
|
|
57
|
+
<path
|
|
58
|
+
d="M8 52 Q20 48 24 36 T40 20 T56 12"
|
|
59
|
+
fill="none"
|
|
60
|
+
stroke="url(#nsLine1)"
|
|
61
|
+
stroke-width="4"
|
|
62
|
+
stroke-linecap="round"
|
|
63
|
+
/>
|
|
64
|
+
<circle
|
|
65
|
+
cx="56"
|
|
66
|
+
cy="12"
|
|
67
|
+
r="6"
|
|
68
|
+
fill="url(#nsLine1)"
|
|
69
|
+
/>
|
|
70
|
+
</svg>
|
|
71
|
+
<span class="text-[32px] font-medium lg:text-[42px] text-green-500">
|
|
72
|
+
{{ siteName }}
|
|
73
|
+
</span>
|
|
74
|
+
</div>
|
|
75
|
+
|
|
76
|
+
<div class="items-center justify-center w-full">
|
|
77
|
+
<h1
|
|
78
|
+
class="text-[48px] lg:text-[72px] leading-tight text-pretty font-normal text-slate-900 max-w-175 lg:max-w-250"
|
|
79
|
+
style="display: block; line-clamp: 3; text-overflow: ellipsis; text-wrap: balance;"
|
|
80
|
+
>
|
|
81
|
+
{{ title }}
|
|
82
|
+
</h1>
|
|
83
|
+
</div>
|
|
84
|
+
|
|
85
|
+
<p v-if="description" class="text-slate-500 text-[24px] lg:text-[32px] opacity-70 max-w-162.5 lg:max-w-225 leading-normal">
|
|
86
|
+
{{ description }}
|
|
87
|
+
</p>
|
|
88
|
+
</div>
|
|
89
|
+
</div>
|
|
90
|
+
</template>
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
+
import { useClipboard } from '@vueuse/core'
|
|
3
|
+
|
|
2
4
|
const route = useRoute()
|
|
3
5
|
const toast = useToast()
|
|
4
6
|
const { copy, copied } = useClipboard()
|
|
5
7
|
const site = useSiteConfig()
|
|
6
|
-
const {
|
|
7
|
-
const { track } = useAnalytics()
|
|
8
|
+
const { ui } = useAppConfig()
|
|
8
9
|
|
|
9
10
|
const appBaseURL = useRuntimeConfig().app?.baseURL || '/'
|
|
10
11
|
|
|
@@ -15,7 +16,6 @@ const items = [[
|
|
|
15
16
|
label: 'Copy Markdown link',
|
|
16
17
|
icon: 'i-lucide-link',
|
|
17
18
|
onSelect() {
|
|
18
|
-
if (vercelAnalytics?.debug) track('Page Action', { action: 'Copy Markdown Link' })
|
|
19
19
|
copy(mdPath.value)
|
|
20
20
|
toast.add({
|
|
21
21
|
title: 'Copied to clipboard',
|
|
@@ -27,28 +27,19 @@ const items = [[
|
|
|
27
27
|
label: 'View as Markdown',
|
|
28
28
|
icon: 'i-simple-icons-markdown',
|
|
29
29
|
target: '_blank',
|
|
30
|
-
to: `/raw${route.path}.md
|
|
31
|
-
onSelect() {
|
|
32
|
-
if (vercelAnalytics?.debug) track('Page Action', { action: 'View as Markdown' })
|
|
33
|
-
}
|
|
30
|
+
to: `/raw${route.path}.md`
|
|
34
31
|
},
|
|
35
32
|
{
|
|
36
33
|
label: 'Open in ChatGPT',
|
|
37
34
|
icon: 'i-simple-icons-openai',
|
|
38
35
|
target: '_blank',
|
|
39
|
-
to: `https://chatgpt.com/?hints=search&q=${encodeURIComponent(`Read ${mdPath.value} so I can ask questions about it.`)}
|
|
40
|
-
onSelect() {
|
|
41
|
-
if (vercelAnalytics?.debug) track('Page Action', { action: 'Open in ChatGPT' })
|
|
42
|
-
}
|
|
36
|
+
to: `https://chatgpt.com/?hints=search&q=${encodeURIComponent(`Read ${mdPath.value} so I can ask questions about it.`)}`
|
|
43
37
|
},
|
|
44
38
|
{
|
|
45
39
|
label: 'Open in Claude',
|
|
46
40
|
icon: 'i-simple-icons-anthropic',
|
|
47
41
|
target: '_blank',
|
|
48
|
-
to: `https://claude.ai/new?q=${encodeURIComponent(`Read ${mdPath.value} so I can ask questions about it.`)}
|
|
49
|
-
onSelect() {
|
|
50
|
-
if (vercelAnalytics?.debug) track('Page Action', { action: 'Open in Claude' })
|
|
51
|
-
}
|
|
42
|
+
to: `https://claude.ai/new?q=${encodeURIComponent(`Read ${mdPath.value} so I can ask questions about it.`)}`
|
|
52
43
|
}
|
|
53
44
|
], [
|
|
54
45
|
{
|
|
@@ -77,7 +68,6 @@ const items = [[
|
|
|
77
68
|
]]
|
|
78
69
|
|
|
79
70
|
async function copyPage() {
|
|
80
|
-
if (vercelAnalytics?.debug) track('Page Action', { action: 'Copy Page Content' })
|
|
81
71
|
copy(await $fetch<string>(`/raw${route.path}.md`))
|
|
82
72
|
}
|
|
83
73
|
</script>
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
import { hash } from 'ohash'
|
|
3
3
|
import type { IconProps } from '@nuxt/ui'
|
|
4
|
-
import type { ClassNameValue } from 'tailwind-merge'
|
|
5
4
|
import {
|
|
6
5
|
useClipboard,
|
|
7
6
|
useElementVisibility,
|
|
@@ -10,6 +9,9 @@ import {
|
|
|
10
9
|
} from '@vueuse/core'
|
|
11
10
|
import { tv } from '@nuxt/ui/utils/tv'
|
|
12
11
|
|
|
12
|
+
type ClassNameValue = ClassNameArray | string | null | undefined | 0 | 0n | false
|
|
13
|
+
type ClassNameArray = ClassNameValue[]
|
|
14
|
+
|
|
13
15
|
const theme = {
|
|
14
16
|
slots: {
|
|
15
17
|
root: 'relative my-5 group border border-muted rounded-md overflow-hidden',
|
|
@@ -1,18 +1,9 @@
|
|
|
1
1
|
<script lang="ts" setup>
|
|
2
|
-
const route = useRoute()
|
|
3
2
|
const { isEnabled: isAiChatEnabled } = useAIChat()
|
|
4
3
|
</script>
|
|
5
4
|
|
|
6
5
|
<template>
|
|
7
6
|
<div v-if="isAiChatEnabled" class="hidden md:block">
|
|
8
|
-
<
|
|
9
|
-
v-if="route.path === '/'"
|
|
10
|
-
to="/docs"
|
|
11
|
-
label="Get Started"
|
|
12
|
-
variant="ghost"
|
|
13
|
-
trailing
|
|
14
|
-
icon="i-lucide-arrow-right"
|
|
15
|
-
/>
|
|
16
|
-
<AiChat v-else />
|
|
7
|
+
<AiChat />
|
|
17
8
|
</div>
|
|
18
9
|
</template>
|
|
@@ -1,19 +1,10 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
import { useClipboard } from '@vueuse/core'
|
|
3
3
|
|
|
4
|
-
const appConfig = useAppConfig()
|
|
5
4
|
const colorMode = useColorMode()
|
|
6
5
|
|
|
7
|
-
const { track } = useAnalytics()
|
|
8
|
-
|
|
9
6
|
const open = ref(false)
|
|
10
7
|
|
|
11
|
-
watch(open, (isOpen) => {
|
|
12
|
-
if (isOpen && appConfig.vercelAnalytics?.debug) {
|
|
13
|
-
track('Theme Picker Opened')
|
|
14
|
-
}
|
|
15
|
-
})
|
|
16
|
-
|
|
17
8
|
const { copy: copyCSS, copied: copiedCSS } = useClipboard()
|
|
18
9
|
const { copy: copyAppConfig, copied: copiedAppConfig } = useClipboard()
|
|
19
10
|
|
|
@@ -22,7 +13,7 @@ const {
|
|
|
22
13
|
neutral,
|
|
23
14
|
primaryColors,
|
|
24
15
|
primary,
|
|
25
|
-
|
|
16
|
+
blackAsPrimary,
|
|
26
17
|
radiuses,
|
|
27
18
|
radius,
|
|
28
19
|
fonts,
|
|
@@ -58,21 +49,24 @@ const {
|
|
|
58
49
|
Primary
|
|
59
50
|
|
|
60
51
|
<UButton
|
|
61
|
-
to="
|
|
52
|
+
to="/docs/getting-started/theme/css-variables#colors"
|
|
62
53
|
size="xs"
|
|
63
54
|
color="neutral"
|
|
64
55
|
variant="link"
|
|
65
|
-
|
|
66
|
-
icon="i-lucide-circle-help"
|
|
56
|
+
icon="i-lucide-help-circle"
|
|
67
57
|
class="p-0 -my-0.5"
|
|
68
58
|
:ui="{ leadingIcon: 'size-3' }"
|
|
69
59
|
/>
|
|
70
60
|
</legend>
|
|
71
61
|
|
|
72
62
|
<div class="grid grid-cols-3 gap-1 -mx-2">
|
|
73
|
-
<ThemePickerButton
|
|
63
|
+
<ThemePickerButton
|
|
64
|
+
label="Black"
|
|
65
|
+
:selected="blackAsPrimary"
|
|
66
|
+
@click="blackAsPrimary = true"
|
|
67
|
+
>
|
|
74
68
|
<template #leading>
|
|
75
|
-
<span class="inline-block
|
|
69
|
+
<span class="inline-block size-2 rounded-full bg-black dark:bg-white" />
|
|
76
70
|
</template>
|
|
77
71
|
</ThemePickerButton>
|
|
78
72
|
|
|
@@ -81,7 +75,7 @@ const {
|
|
|
81
75
|
:key="color"
|
|
82
76
|
:label="color"
|
|
83
77
|
:chip="color"
|
|
84
|
-
:selected="!
|
|
78
|
+
:selected="!blackAsPrimary && primary === color"
|
|
85
79
|
@click="primary = color"
|
|
86
80
|
/>
|
|
87
81
|
</div>
|
|
@@ -92,12 +86,11 @@ const {
|
|
|
92
86
|
Neutral
|
|
93
87
|
|
|
94
88
|
<UButton
|
|
95
|
-
to="
|
|
89
|
+
to="/docs/getting-started/theme/css-variables#text"
|
|
96
90
|
size="xs"
|
|
97
91
|
color="neutral"
|
|
98
92
|
variant="link"
|
|
99
|
-
|
|
100
|
-
icon="i-lucide-circle-help"
|
|
93
|
+
icon="i-lucide-help-circle"
|
|
101
94
|
class="p-0 -my-0.5"
|
|
102
95
|
:ui="{ leadingIcon: 'size-3' }"
|
|
103
96
|
/>
|
|
@@ -120,12 +113,11 @@ const {
|
|
|
120
113
|
Radius
|
|
121
114
|
|
|
122
115
|
<UButton
|
|
123
|
-
to="
|
|
116
|
+
to="/docs/getting-started/theme/css-variables#radius"
|
|
124
117
|
size="xs"
|
|
125
118
|
color="neutral"
|
|
126
119
|
variant="link"
|
|
127
|
-
|
|
128
|
-
icon="i-lucide-circle-help"
|
|
120
|
+
icon="i-lucide-help-circle"
|
|
129
121
|
class="p-0 -my-0.5"
|
|
130
122
|
:ui="{ leadingIcon: 'size-3' }"
|
|
131
123
|
/>
|
|
@@ -148,12 +140,11 @@ const {
|
|
|
148
140
|
Font
|
|
149
141
|
|
|
150
142
|
<UButton
|
|
151
|
-
to="
|
|
143
|
+
to="/docs/getting-started/integrations/fonts"
|
|
152
144
|
size="xs"
|
|
153
145
|
color="neutral"
|
|
154
146
|
variant="link"
|
|
155
|
-
|
|
156
|
-
icon="i-lucide-circle-help"
|
|
147
|
+
icon="i-lucide-help-circle"
|
|
157
148
|
class="p-0 -my-0.5"
|
|
158
149
|
:ui="{ leadingIcon: 'size-3' }"
|
|
159
150
|
/>
|
|
@@ -177,12 +168,11 @@ const {
|
|
|
177
168
|
Icons
|
|
178
169
|
|
|
179
170
|
<UButton
|
|
180
|
-
to="
|
|
171
|
+
to="/docs/getting-started/integrations/icons"
|
|
181
172
|
size="xs"
|
|
182
173
|
color="neutral"
|
|
183
174
|
variant="link"
|
|
184
|
-
|
|
185
|
-
icon="i-lucide-circle-help"
|
|
175
|
+
icon="i-lucide-help-circle"
|
|
186
176
|
class="p-0 -my-0.5"
|
|
187
177
|
:ui="{ leadingIcon: 'size-3' }"
|
|
188
178
|
/>
|
|
@@ -206,12 +196,11 @@ const {
|
|
|
206
196
|
Color Mode
|
|
207
197
|
|
|
208
198
|
<UButton
|
|
209
|
-
to="
|
|
199
|
+
to="/docs/getting-started/integrations/color-mode"
|
|
210
200
|
size="xs"
|
|
211
201
|
color="neutral"
|
|
212
202
|
variant="link"
|
|
213
|
-
|
|
214
|
-
icon="i-lucide-circle-help"
|
|
203
|
+
icon="i-lucide-help-circle"
|
|
215
204
|
class="p-0 -my-0.5"
|
|
216
205
|
:ui="{ leadingIcon: 'size-3' }"
|
|
217
206
|
/>
|
|
@@ -241,7 +230,7 @@ const {
|
|
|
241
230
|
size="sm"
|
|
242
231
|
label="main.css"
|
|
243
232
|
class="flex-1 text-[11px]"
|
|
244
|
-
:icon="copiedCSS ?
|
|
233
|
+
:icon="copiedCSS ? 'i-lucide-copy-check' : 'i-lucide-copy'"
|
|
245
234
|
@click="copyCSS(exportCSS())"
|
|
246
235
|
/>
|
|
247
236
|
<UButton
|
|
@@ -250,7 +239,7 @@ const {
|
|
|
250
239
|
variant="soft"
|
|
251
240
|
size="sm"
|
|
252
241
|
label="app.config.ts"
|
|
253
|
-
:icon="copiedAppConfig ?
|
|
242
|
+
:icon="copiedAppConfig ? 'i-lucide-copy-check' : 'i-lucide-copy'"
|
|
254
243
|
class="flex-1 text-[11px]"
|
|
255
244
|
@click="copyAppConfig(exportAppConfig())"
|
|
256
245
|
/>
|