feat: create config sheet
This commit is contained in:
parent
c332ce1133
commit
e48c4dc2e9
|
|
@ -0,0 +1,98 @@
|
|||
<script lang="ts" setup>
|
||||
import { useForm } from 'vee-validate'
|
||||
import { toTypedSchema } from '@vee-validate/zod'
|
||||
import * as z from 'zod'
|
||||
import { useConfigStore } from '@/stores/config'
|
||||
import { Button } from '@/lib/registry/new-york/ui/button'
|
||||
import { Input } from '@/lib/registry/new-york/ui/input'
|
||||
import { FormControl, FormDescription, FormField, FormItem, FormLabel, FormMessage } from '@/lib/registry/new-york/ui/form'
|
||||
import { Sheet, SheetClose, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetTitle, SheetTrigger } from '@/lib/registry/new-york/ui/sheet'
|
||||
import RadixIconsGear from '~icons/radix-icons/gear'
|
||||
|
||||
const { codeConfig, setCodeConfig } = useConfigStore()
|
||||
|
||||
const formSchema = toTypedSchema(z.object({
|
||||
prefix: z.string().default(''),
|
||||
componentsPath: z.string().default('@/components'),
|
||||
utilsPath: z.string().default('@/utils'),
|
||||
}))
|
||||
|
||||
const { handleSubmit, setValues } = useForm({
|
||||
validationSchema: formSchema,
|
||||
initialValues: codeConfig.value,
|
||||
})
|
||||
|
||||
const onSubmit = handleSubmit((values) => {
|
||||
setCodeConfig(values)
|
||||
setValues(values)
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Sheet
|
||||
@update:open="(open) => {
|
||||
if (open) setValues(codeConfig)
|
||||
}"
|
||||
>
|
||||
<SheetTrigger as-child>
|
||||
<Button
|
||||
class="w-9 h-9"
|
||||
:variant="'ghost'"
|
||||
:size="'icon'"
|
||||
>
|
||||
<RadixIconsGear class="w-5 h-5" />
|
||||
</Button>
|
||||
</SheetTrigger>
|
||||
<SheetContent>
|
||||
<form @submit="onSubmit">
|
||||
<SheetHeader>
|
||||
<SheetTitle>Edit code config</SheetTitle>
|
||||
<SheetDescription>
|
||||
Configure how the CodeBlock should render on the site.
|
||||
</SheetDescription>
|
||||
</SheetHeader>
|
||||
|
||||
<div class="my-4">
|
||||
<!-- <FormField v-slot="{ componentField }" name="prefix">
|
||||
<FormItem>
|
||||
<FormLabel>Prefix</FormLabel>
|
||||
<FormControl>
|
||||
<Input placeholder="" v-bind="componentField" />
|
||||
</FormControl>
|
||||
<FormDescription />
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
</FormField> -->
|
||||
<FormField v-slot="{ componentField }" name="componentsPath">
|
||||
<FormItem>
|
||||
<FormLabel>Components Path</FormLabel>
|
||||
<FormControl>
|
||||
<Input placeholder="" v-bind="componentField" />
|
||||
</FormControl>
|
||||
<FormDescription />
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
</FormField>
|
||||
<FormField v-slot="{ componentField }" name="utilsPath">
|
||||
<FormItem>
|
||||
<FormLabel>Utils Path</FormLabel>
|
||||
<FormControl>
|
||||
<Input placeholder="" v-bind="componentField" />
|
||||
</FormControl>
|
||||
<FormDescription />
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
</FormField>
|
||||
</div>
|
||||
|
||||
<SheetFooter>
|
||||
<SheetClose as-child>
|
||||
<Button type="submit">
|
||||
Save changes
|
||||
</Button>
|
||||
</SheetClose>
|
||||
</SheetFooter>
|
||||
</form>
|
||||
</SheetContent>
|
||||
</Sheet>
|
||||
</template>
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
<script setup lang="ts">
|
||||
import { ref, watch } from 'vue'
|
||||
import { codeToHtml } from 'shiki'
|
||||
import MagicString from 'magic-string'
|
||||
import { cssVariables } from '../config/shiki'
|
||||
import StyleSwitcher from './StyleSwitcher.vue'
|
||||
import ComponentLoader from './ComponentLoader.vue'
|
||||
|
|
@ -19,19 +20,19 @@ const props = withDefaults(defineProps<{
|
|||
align?: 'center' | 'start' | 'end'
|
||||
}>(), { align: 'center' })
|
||||
|
||||
const { style } = useConfigStore()
|
||||
const { style, codeConfig } = useConfigStore()
|
||||
|
||||
const codeString = ref('')
|
||||
const codeHtml = ref('')
|
||||
|
||||
function transformImportPath(code: string) {
|
||||
let parsed = code
|
||||
parsed = parsed.replaceAll(`@/lib/registry/${style.value}`, '@/components')
|
||||
parsed = parsed.replaceAll('@/lib/utils', '@/utils')
|
||||
return parsed
|
||||
const s = new MagicString(code)
|
||||
s.replaceAll(`@/lib/registry/${style.value}`, codeConfig.value.componentsPath)
|
||||
s.replaceAll(`@/lib/utils`, codeConfig.value.utilsPath)
|
||||
return s.toString()
|
||||
}
|
||||
|
||||
watch(style, async () => {
|
||||
watch([style, codeConfig], async () => {
|
||||
try {
|
||||
codeString.value = await import(`../../../src/lib/registry/${style.value}/example/${props.name}.vue?raw`).then(res => transformImportPath(res.default.trim()))
|
||||
codeHtml.value = await codeToHtml(codeString.value, {
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import { Content, useData, useRoute, useRouter } from 'vitepress'
|
|||
import { type NavItem, docsConfig } from '../config/docs'
|
||||
import Logo from '../components/Logo.vue'
|
||||
import MobileNav from '../components/MobileNav.vue'
|
||||
import CodeConfigCustomizer from '../components/CodeConfigCustomizer.vue'
|
||||
|
||||
import Kbd from '../components/Kbd.vue'
|
||||
import { Command, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, CommandSeparator } from '@/lib/registry/default/ui/command'
|
||||
|
|
@ -126,27 +127,32 @@ watch(() => $route.path, (n) => {
|
|||
</Button>
|
||||
</div>
|
||||
|
||||
<nav class="flex items-center gap-x-1">
|
||||
<nav class="flex items-center">
|
||||
<CodeConfigCustomizer />
|
||||
|
||||
<Button
|
||||
v-for="link in links"
|
||||
:key="link.name"
|
||||
as="a"
|
||||
class="w-9 h-9"
|
||||
:href="link.href" target="_blank"
|
||||
:variant="'ghost'" :size="'icon'"
|
||||
:variant="'ghost'"
|
||||
:size="'icon'"
|
||||
>
|
||||
<component :is="link.icon" class="w-[20px] h-5" />
|
||||
<component :is="link.icon" class="w-5 h-5" />
|
||||
</Button>
|
||||
|
||||
<ClientOnly>
|
||||
<Button
|
||||
class="flex items-center justify-center"
|
||||
class="w-9 h-9"
|
||||
aria-label="Toggle dark mode"
|
||||
:variant="'ghost'"
|
||||
:size="'icon'" @click="toggleDark()"
|
||||
:size="'icon'"
|
||||
@click="toggleDark()"
|
||||
>
|
||||
<component
|
||||
:is="isDark ? RadixIconsSun : RadixIconsMoon"
|
||||
class="w-[20px] h-5 text-foreground"
|
||||
class="w-5 h-5 text-foreground"
|
||||
/>
|
||||
</Button>
|
||||
</ClientOnly>
|
||||
|
|
@ -292,4 +298,4 @@ watch(() => $route.path, (n) => {
|
|||
<NewYorkSonner :theme="'system'" />
|
||||
<NewYorkToaster />
|
||||
</div>
|
||||
</template>
|
||||
</template>../components/CodeConfigCustomizer.vue
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@
|
|||
"embla-carousel-autoplay": "^8.0.0",
|
||||
"embla-carousel-vue": "^8.0.0",
|
||||
"lucide-vue-next": "^0.350.0",
|
||||
"magic-string": "^0.30.8",
|
||||
"radix-vue": "^1.5.2",
|
||||
"tailwindcss-animate": "^1.0.7",
|
||||
"v-calendar": "^3.1.2",
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { computed } from 'vue'
|
||||
import { useSessionStorage } from '@vueuse/core'
|
||||
import { useSessionStorage, useStorage } from '@vueuse/core'
|
||||
import { useData } from 'vitepress'
|
||||
import { type Theme, themes } from './../lib/registry/themes'
|
||||
import { type Style, styles } from '@/lib/registry/styles'
|
||||
|
|
@ -10,6 +10,12 @@ interface Config {
|
|||
style: Style
|
||||
}
|
||||
|
||||
interface CodeConfig {
|
||||
prefix: string
|
||||
componentsPath: string
|
||||
utilsPath: string
|
||||
}
|
||||
|
||||
export const RADII = [0, 0.25, 0.5, 0.75, 1]
|
||||
|
||||
export function useConfigStore() {
|
||||
|
|
@ -18,6 +24,11 @@ export function useConfigStore() {
|
|||
radius: 0.5,
|
||||
style: styles[0].name,
|
||||
})
|
||||
const codeConfig = useStorage<CodeConfig>('code-config', {
|
||||
prefix: '',
|
||||
componentsPath: '@/components',
|
||||
utilsPath: '@/utils',
|
||||
})
|
||||
|
||||
const themeClass = computed(() => `theme-${config.value.theme}`)
|
||||
|
||||
|
|
@ -40,5 +51,21 @@ export function useConfigStore() {
|
|||
})`
|
||||
})
|
||||
|
||||
return { config, theme, setTheme, radius, setRadius, themeClass, style, themePrimary }
|
||||
const setCodeConfig = (payload: CodeConfig) => {
|
||||
codeConfig.value = payload
|
||||
}
|
||||
|
||||
return {
|
||||
config,
|
||||
theme,
|
||||
setTheme,
|
||||
radius,
|
||||
setRadius,
|
||||
themeClass,
|
||||
style,
|
||||
themePrimary,
|
||||
|
||||
codeConfig,
|
||||
setCodeConfig,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -89,6 +89,9 @@ importers:
|
|||
lucide-vue-next:
|
||||
specifier: ^0.350.0
|
||||
version: 0.350.0(vue@3.4.21)
|
||||
magic-string:
|
||||
specifier: ^0.30.8
|
||||
version: 0.30.8
|
||||
radix-vue:
|
||||
specifier: ^1.5.2
|
||||
version: 1.5.2(vue@3.4.21)
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user