docs: fix block preview
This commit is contained in:
parent
96800c4c44
commit
64c0371280
237
apps/www/.vitepress/theme/components/BlockContainer.vue
Normal file
237
apps/www/.vitepress/theme/components/BlockContainer.vue
Normal file
|
|
@ -0,0 +1,237 @@
|
|||
<script setup lang="ts">
|
||||
import { useConfigStore } from '@/stores/config'
|
||||
import { CircleHelp, Info, Monitor, Smartphone, Tablet } from 'lucide-vue-next'
|
||||
import MagicString from 'magic-string'
|
||||
import { codeToHtml } from 'shiki'
|
||||
import { reactive, ref, watch } from 'vue'
|
||||
import { compileScript, parse, walk } from 'vue/compiler-sfc'
|
||||
import { cssVariables } from '../config/shiki'
|
||||
import BlockCopyButton from './BlockCopyButton.vue'
|
||||
import StyleSwitcher from './StyleSwitcher.vue'
|
||||
|
||||
// import { V0Button } from '@/components/v0-button'
|
||||
import { Badge } from '@/lib/registry/new-york/ui/badge'
|
||||
import { Popover, PopoverContent, PopoverTrigger } from '@/lib/registry/new-york/ui/popover'
|
||||
import { ResizableHandle, ResizablePanel, ResizablePanelGroup } from '@/lib/registry/new-york/ui/resizable'
|
||||
import { Separator } from '@/lib/registry/new-york/ui/separator'
|
||||
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/lib/registry/new-york/ui/tabs'
|
||||
import { ToggleGroup, ToggleGroupItem } from '@/lib/registry/new-york/ui/toggle-group'
|
||||
import BlockPreview from './BlockPreview.vue'
|
||||
|
||||
const props = defineProps<{
|
||||
name: string
|
||||
}>()
|
||||
|
||||
const { style, codeConfig } = useConfigStore()
|
||||
|
||||
const isLoading = ref(true)
|
||||
const tabValue = ref('preview')
|
||||
const resizableRef = ref<InstanceType<typeof ResizablePanel>>()
|
||||
|
||||
const rawString = ref('')
|
||||
const codeHtml = ref('')
|
||||
const metadata = reactive({
|
||||
description: null as string | null,
|
||||
iframeHeight: null as string | null,
|
||||
containerClass: null as string | null,
|
||||
})
|
||||
|
||||
function removeScript(code: string) {
|
||||
const s = new MagicString(code)
|
||||
const scriptTagRegex = /<script\s+lang="ts"\s*>[\s\S]+?<\/script>/g
|
||||
let match
|
||||
// eslint-disable-next-line no-cond-assign
|
||||
while ((match = scriptTagRegex.exec(code)) !== null) {
|
||||
const start = match.index
|
||||
const end = match.index + match[0].length
|
||||
s.overwrite(start, end, '') // Replace the script tag with an empty string
|
||||
}
|
||||
return s.trimStart().toString()
|
||||
}
|
||||
|
||||
function transformImportPath(code: string) {
|
||||
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, codeConfig], async () => {
|
||||
try {
|
||||
const baseRawString = await import(`../../../src/lib/registry/${style.value}/block/${props.name}.vue?raw`).then(res => res.default.trim())
|
||||
rawString.value = transformImportPath(removeScript(baseRawString))
|
||||
|
||||
if (!metadata.description) {
|
||||
const { descriptor } = parse(baseRawString)
|
||||
const ast = compileScript(descriptor, { id: '' })
|
||||
walk(ast.scriptAst, {
|
||||
enter(node: any) {
|
||||
const declaration = node.declaration
|
||||
// Check if the declaration is a variable declaration
|
||||
if (declaration?.type === 'VariableDeclaration') {
|
||||
// Extract variable names and their values
|
||||
declaration.declarations.forEach((decl: any) => {
|
||||
// @ts-expect-error ignore missing type
|
||||
metadata[decl.id.name] = decl.init ? decl.init.value : null
|
||||
})
|
||||
}
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
codeHtml.value = await codeToHtml(rawString.value, {
|
||||
lang: 'vue',
|
||||
theme: cssVariables,
|
||||
})
|
||||
}
|
||||
catch (err) {
|
||||
console.error(err)
|
||||
}
|
||||
}, { immediate: true, deep: true })
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Tabs
|
||||
:id="name"
|
||||
v-model="tabValue"
|
||||
class="relative grid w-full scroll-m-20 gap-4"
|
||||
:style=" {
|
||||
'--container-height': metadata.iframeHeight ?? '600px',
|
||||
}"
|
||||
>
|
||||
<div class="flex flex-col items-center gap-4 sm:flex-row">
|
||||
<div class="flex items-center gap-2">
|
||||
<TabsList class="hidden sm:flex">
|
||||
<TabsTrigger value="preview">
|
||||
Preview
|
||||
</TabsTrigger>
|
||||
<TabsTrigger value="code">
|
||||
Code
|
||||
</TabsTrigger>
|
||||
</TabsList>
|
||||
<div class="hidden items-center gap-2 sm:flex">
|
||||
<Separator
|
||||
orientation="vertical"
|
||||
class="mx-2 hidden h-4 md:flex"
|
||||
/>
|
||||
<div class="flex items-center gap-2">
|
||||
<a :href="`#${name}`">
|
||||
<Badge variant="outline">{{ name }}</Badge>
|
||||
</a>
|
||||
<Popover>
|
||||
<PopoverTrigger class="hidden text-muted-foreground hover:text-foreground sm:flex">
|
||||
<Info class="h-3.5 w-3.5" />
|
||||
<span class="sr-only">Block description</span>
|
||||
</PopoverTrigger>
|
||||
<PopoverContent
|
||||
side="right"
|
||||
:side-offset="10"
|
||||
class="text-sm"
|
||||
>
|
||||
{{ metadata.description }}
|
||||
</PopoverContent>
|
||||
</Popover>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex items-center gap-2 pr-[14px] sm:ml-auto">
|
||||
<div class="hidden h-[28px] items-center gap-1.5 rounded-md border p-[2px] shadow-sm md:flex">
|
||||
<ToggleGroup
|
||||
type="single"
|
||||
default-value="100"
|
||||
@update:model-value="(value) => {
|
||||
resizableRef?.resize(parseInt(value as string))
|
||||
}"
|
||||
>
|
||||
<ToggleGroupItem
|
||||
value="100"
|
||||
class="h-[22px] w-[22px] rounded-sm p-0"
|
||||
>
|
||||
<Monitor class="h-3.5 w-3.5" />
|
||||
</ToggleGroupItem>
|
||||
<ToggleGroupItem
|
||||
value="60"
|
||||
class="h-[22px] w-[22px] rounded-sm p-0"
|
||||
>
|
||||
<Tablet class="h-3.5 w-3.5" />
|
||||
</ToggleGroupItem>
|
||||
<ToggleGroupItem
|
||||
value="30"
|
||||
class="h-[22px] w-[22px] rounded-sm p-0"
|
||||
>
|
||||
<Smartphone class="h-3.5 w-3.5" />
|
||||
</ToggleGroupItem>
|
||||
</ToggleGroup>
|
||||
</div>
|
||||
<Separator
|
||||
orientation="vertical"
|
||||
class="mx-2 hidden h-4 md:flex"
|
||||
/>
|
||||
<StyleSwitcher class="h-7" />
|
||||
<Popover>
|
||||
<PopoverTrigger class="hidden text-muted-foreground hover:text-foreground sm:flex">
|
||||
<CircleHelp class="h-3.5 w-3.5" />
|
||||
<span class="sr-only">Block description</span>
|
||||
</PopoverTrigger>
|
||||
<PopoverContent
|
||||
side="top"
|
||||
:side-offset="20"
|
||||
class="space-y-3 rounded-[0.5rem] text-sm"
|
||||
>
|
||||
<p class="font-medium">
|
||||
What is the difference between the New York and Default style?
|
||||
</p>
|
||||
<p>
|
||||
A style comes with its own set of components, animations,
|
||||
icons and more.
|
||||
</p>
|
||||
<p>
|
||||
The <span class="font-medium">Default</span> style has
|
||||
larger inputs, uses lucide-vue-next for icons and
|
||||
tailwindcss-animate for animations.
|
||||
</p>
|
||||
<p>
|
||||
The <span class="font-medium">New York</span> style ships
|
||||
with smaller buttons and inputs. It also uses shadows on cards
|
||||
and buttons.
|
||||
</p>
|
||||
</PopoverContent>
|
||||
</Popover>
|
||||
<Separator orientation="vertical" class="mx-2 h-4" />
|
||||
<BlockCopyButton :code="rawString" />
|
||||
<!-- <V0Button
|
||||
name="{block.name}"
|
||||
description="{block.description" || "Edit in v0"}
|
||||
code="{block.code}"
|
||||
style="{block.style}"
|
||||
/> -->
|
||||
</div>
|
||||
</div>
|
||||
<TabsContent
|
||||
v-show="tabValue === 'preview'"
|
||||
force-mount
|
||||
value="preview"
|
||||
class="relative after:absolute after:inset-0 after:right-3 after:z-0 after:rounded-lg after:bg-muted h-[--container-height] px-0"
|
||||
>
|
||||
<ResizablePanelGroup id="block-resizable" direction="horizontal" class="relative z-10">
|
||||
<ResizablePanel
|
||||
id="block-resizable-panel-1"
|
||||
ref="resizableRef"
|
||||
:default-size="100"
|
||||
:min-size="30"
|
||||
:as-child="true"
|
||||
>
|
||||
<BlockPreview :name="name" styles="default" :container-class="metadata.containerClass ?? ''" container />
|
||||
</ResizablePanel>
|
||||
<ResizableHandle id="block-resizable-handle" class="relative hidden w-3 bg-transparent p-0 after:absolute after:right-0 after:top-1/2 after:h-8 after:w-[6px] after:-translate-y-1/2 after:translate-x-[-1px] after:rounded-full after:bg-border after:transition-all after:hover:h-10 sm:block" />
|
||||
<ResizablePanel id="block-resizable-panel-2" :default-size="0" :min-size="0" />
|
||||
</ResizablePanelGroup>
|
||||
</TabsContent>
|
||||
<TabsContent value="code" class="h-[--container-height]">
|
||||
<div
|
||||
class="language-vue !h-full !max-h-[none] !mt-0"
|
||||
v-html="codeHtml"
|
||||
/>
|
||||
</TabsContent>
|
||||
</Tabs>
|
||||
</template>
|
||||
|
|
@ -2,11 +2,11 @@
|
|||
import { useUrlSearchParams } from '@vueuse/core'
|
||||
import ComponentLoader from './ComponentLoader.vue'
|
||||
|
||||
const params = useUrlSearchParams('hash-params')
|
||||
const params = useUrlSearchParams('history')
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div v-if="params.name && params.style" :class="params.containerClass">
|
||||
<div v-if="params.name" :class="params.containerClass">
|
||||
<ComponentLoader :key="params.style?.toString()" :name="params.name?.toString()" :type-name="'block'" />
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
|||
|
|
@ -1,245 +1,40 @@
|
|||
<script setup lang="ts">
|
||||
import { useConfigStore } from '@/stores/config'
|
||||
import { CircleHelp, Info, Monitor, Smartphone, Tablet } from 'lucide-vue-next'
|
||||
import MagicString from 'magic-string'
|
||||
import { codeToHtml } from 'shiki'
|
||||
import { reactive, ref, watch } from 'vue'
|
||||
import { compileScript, parse, walk } from 'vue/compiler-sfc'
|
||||
import { cssVariables } from '../config/shiki'
|
||||
import BlockCopyButton from './BlockCopyButton.vue'
|
||||
import { computed, ref } from 'vue'
|
||||
import Spinner from './Spinner.vue'
|
||||
import StyleSwitcher from './StyleSwitcher.vue'
|
||||
|
||||
// import { V0Button } from '@/components/v0-button'
|
||||
import { Badge } from '@/lib/registry/new-york/ui/badge'
|
||||
import { Popover, PopoverContent, PopoverTrigger } from '@/lib/registry/new-york/ui/popover'
|
||||
import { ResizableHandle, ResizablePanel, ResizablePanelGroup } from '@/lib/registry/new-york/ui/resizable'
|
||||
import { Separator } from '@/lib/registry/new-york/ui/separator'
|
||||
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/lib/registry/new-york/ui/tabs'
|
||||
import { ToggleGroup, ToggleGroupItem } from '@/lib/registry/new-york/ui/toggle-group'
|
||||
|
||||
const props = defineProps<{
|
||||
name: string
|
||||
styles?: string
|
||||
containerClass?: string
|
||||
container?: boolean
|
||||
}>()
|
||||
|
||||
const { style, codeConfig } = useConfigStore()
|
||||
|
||||
const isLoading = ref(true)
|
||||
const tabValue = ref('preview')
|
||||
const resizableRef = ref<InstanceType<typeof ResizablePanel>>()
|
||||
|
||||
const rawString = ref('')
|
||||
const codeHtml = ref('')
|
||||
const metadata = reactive({
|
||||
description: null as string | null,
|
||||
iframeHeight: null as string | null,
|
||||
containerClass: null as string | null,
|
||||
const iframeURL = computed(() => {
|
||||
const url = new URL(`${window.location.origin}/blocks/renderer`)
|
||||
Object.entries(props).forEach(([key, value]) => {
|
||||
if (value)
|
||||
url.searchParams.append(key, value as string)
|
||||
})
|
||||
return url.href
|
||||
})
|
||||
|
||||
function removeScript(code: string) {
|
||||
const s = new MagicString(code)
|
||||
const scriptTagRegex = /<script\s+lang="ts"\s*>[\s\S]+?<\/script>/g
|
||||
let match
|
||||
// eslint-disable-next-line no-cond-assign
|
||||
while ((match = scriptTagRegex.exec(code)) !== null) {
|
||||
const start = match.index
|
||||
const end = match.index + match[0].length
|
||||
s.overwrite(start, end, '') // Replace the script tag with an empty string
|
||||
}
|
||||
return s.trimStart().toString()
|
||||
}
|
||||
|
||||
function transformImportPath(code: string) {
|
||||
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, codeConfig], async () => {
|
||||
try {
|
||||
const baseRawString = await import(`../../../src/lib/registry/${style.value}/block/${props.name}.vue?raw`).then(res => res.default.trim())
|
||||
rawString.value = transformImportPath(removeScript(baseRawString))
|
||||
|
||||
if (!metadata.description) {
|
||||
const { descriptor } = parse(baseRawString)
|
||||
const ast = compileScript(descriptor, { id: '' })
|
||||
walk(ast.scriptAst, {
|
||||
enter(node: any) {
|
||||
const declaration = node.declaration
|
||||
// Check if the declaration is a variable declaration
|
||||
if (declaration?.type === 'VariableDeclaration') {
|
||||
// Extract variable names and their values
|
||||
declaration.declarations.forEach((decl: any) => {
|
||||
// @ts-expect-error ignore missing type
|
||||
metadata[decl.id.name] = decl.init ? decl.init.value : null
|
||||
})
|
||||
}
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
codeHtml.value = await codeToHtml(rawString.value, {
|
||||
lang: 'vue',
|
||||
theme: cssVariables,
|
||||
})
|
||||
}
|
||||
catch (err) {
|
||||
console.error(err)
|
||||
}
|
||||
}, { immediate: true, deep: true })
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Tabs
|
||||
:id="name"
|
||||
v-model="tabValue"
|
||||
class="relative grid w-full scroll-m-20 gap-4"
|
||||
:style=" {
|
||||
'--container-height': metadata.iframeHeight ?? '600px',
|
||||
}"
|
||||
>
|
||||
<div class="flex flex-col items-center gap-4 sm:flex-row">
|
||||
<div class="flex items-center gap-2">
|
||||
<TabsList class="hidden sm:flex">
|
||||
<TabsTrigger value="preview">
|
||||
Preview
|
||||
</TabsTrigger>
|
||||
<TabsTrigger value="code">
|
||||
Code
|
||||
</TabsTrigger>
|
||||
</TabsList>
|
||||
<div class="hidden items-center gap-2 sm:flex">
|
||||
<Separator
|
||||
orientation="vertical"
|
||||
class="mx-2 hidden h-4 md:flex"
|
||||
/>
|
||||
<div class="flex items-center gap-2">
|
||||
<a :href="`#${name}`">
|
||||
<Badge variant="outline">{{ name }}</Badge>
|
||||
</a>
|
||||
<Popover>
|
||||
<PopoverTrigger class="hidden text-muted-foreground hover:text-foreground sm:flex">
|
||||
<Info class="h-3.5 w-3.5" />
|
||||
<span class="sr-only">Block description</span>
|
||||
</PopoverTrigger>
|
||||
<PopoverContent
|
||||
side="right"
|
||||
:side-offset="10"
|
||||
class="text-sm"
|
||||
>
|
||||
{{ metadata.description }}
|
||||
</PopoverContent>
|
||||
</Popover>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex items-center gap-2 pr-[14px] sm:ml-auto">
|
||||
<div class="hidden h-[28px] items-center gap-1.5 rounded-md border p-[2px] shadow-sm md:flex">
|
||||
<ToggleGroup
|
||||
type="single"
|
||||
default-value="100"
|
||||
@update:model-value="(value) => {
|
||||
resizableRef?.resize(parseInt(value))
|
||||
}"
|
||||
>
|
||||
<ToggleGroupItem
|
||||
value="100"
|
||||
class="h-[22px] w-[22px] rounded-sm p-0"
|
||||
>
|
||||
<Monitor class="h-3.5 w-3.5" />
|
||||
</ToggleGroupItem>
|
||||
<ToggleGroupItem
|
||||
value="60"
|
||||
class="h-[22px] w-[22px] rounded-sm p-0"
|
||||
>
|
||||
<Tablet class="h-3.5 w-3.5" />
|
||||
</ToggleGroupItem>
|
||||
<ToggleGroupItem
|
||||
value="30"
|
||||
class="h-[22px] w-[22px] rounded-sm p-0"
|
||||
>
|
||||
<Smartphone class="h-3.5 w-3.5" />
|
||||
</ToggleGroupItem>
|
||||
</ToggleGroup>
|
||||
</div>
|
||||
<Separator
|
||||
orientation="vertical"
|
||||
class="mx-2 hidden h-4 md:flex"
|
||||
/>
|
||||
<StyleSwitcher class="h-7" />
|
||||
<Popover>
|
||||
<PopoverTrigger class="hidden text-muted-foreground hover:text-foreground sm:flex">
|
||||
<CircleHelp class="h-3.5 w-3.5" />
|
||||
<span class="sr-only">Block description</span>
|
||||
</PopoverTrigger>
|
||||
<PopoverContent
|
||||
side="top"
|
||||
:side-offset="20"
|
||||
class="space-y-3 rounded-[0.5rem] text-sm"
|
||||
>
|
||||
<p class="font-medium">
|
||||
What is the difference between the New York and Default style?
|
||||
</p>
|
||||
<p>
|
||||
A style comes with its own set of components, animations,
|
||||
icons and more.
|
||||
</p>
|
||||
<p>
|
||||
The <span class="font-medium">Default</span> style has
|
||||
larger inputs, uses lucide-vue-next for icons and
|
||||
tailwindcss-animate for animations.
|
||||
</p>
|
||||
<p>
|
||||
The <span class="font-medium">New York</span> style ships
|
||||
with smaller buttons and inputs. It also uses shadows on cards
|
||||
and buttons.
|
||||
</p>
|
||||
</PopoverContent>
|
||||
</Popover>
|
||||
<Separator orientation="vertical" class="mx-2 h-4" />
|
||||
<BlockCopyButton :code="rawString" />
|
||||
<!-- <V0Button
|
||||
name="{block.name}"
|
||||
description="{block.description" || "Edit in v0"}
|
||||
code="{block.code}"
|
||||
style="{block.style}"
|
||||
/> -->
|
||||
</div>
|
||||
<div class="relative rounded-lg border overflow-hidden bg-background" :class="[container ? '' : 'aspect-[4/2.5]']">
|
||||
<div v-if="isLoading" class="flex items-center justify-center h-full">
|
||||
<Spinner />
|
||||
</div>
|
||||
<TabsContent
|
||||
v-show="tabValue === 'preview'"
|
||||
force-mount
|
||||
value="preview"
|
||||
class="relative after:absolute after:inset-0 after:right-3 after:z-0 after:rounded-lg after:bg-muted h-[--container-height] px-0"
|
||||
<div
|
||||
:class="[container ? 'w-full' : 'absolute inset-0 hidden w-[1600px] bg-background md:block']"
|
||||
>
|
||||
<ResizablePanelGroup id="block-resizable" direction="horizontal" class="relative z-10">
|
||||
<ResizablePanel
|
||||
id="block-resizable-panel-1"
|
||||
ref="resizableRef"
|
||||
class="relative rounded-lg border bg-background transition-all "
|
||||
:default-size="100"
|
||||
:min-size="30"
|
||||
>
|
||||
<div v-if="isLoading" class="flex items-center justify-center h-full">
|
||||
<Spinner />
|
||||
</div>
|
||||
<iframe
|
||||
v-show="!isLoading"
|
||||
:src="`/blocks/renderer#name=${name}&style=${style}&containerClass=${encodeURIComponent(metadata.containerClass ?? '')}`"
|
||||
class="relative z-20 w-full bg-background h-[--container-height]"
|
||||
@load="isLoading = false"
|
||||
/>
|
||||
</ResizablePanel>
|
||||
<ResizableHandle id="block-resizable-handle" class="relative hidden w-3 bg-transparent p-0 after:absolute after:right-0 after:top-1/2 after:h-8 after:w-[6px] after:-translate-y-1/2 after:translate-x-[-1px] after:rounded-full after:bg-border after:transition-all after:hover:h-10 sm:block" />
|
||||
<ResizablePanel id="block-resizable-panel-2" :default-size="0" :min-size="0" />
|
||||
</ResizablePanelGroup>
|
||||
</TabsContent>
|
||||
<TabsContent value="code" class="h-[--container-height]">
|
||||
<div
|
||||
class="language-vue !h-full !max-h-[none] !mt-0"
|
||||
v-html="codeHtml"
|
||||
<iframe
|
||||
v-show="!isLoading"
|
||||
:src="iframeURL"
|
||||
class="relative z-20 w-full bg-background" :class="[container ? 'h-[--container-height]' : 'size-full']"
|
||||
@load="isLoading = false"
|
||||
/>
|
||||
</TabsContent>
|
||||
</Tabs>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ import PageHeader from '../components/PageHeader.vue'
|
|||
import PageHeaderDescription from '../components/PageHeaderDescription.vue'
|
||||
|
||||
import PageHeaderHeading from '../components/PageHeaderHeading.vue'
|
||||
import BlockPreview from './BlockPreview.vue'
|
||||
import BlockContainer from './BlockContainer.vue'
|
||||
|
||||
const blocks = ref<string[]>([])
|
||||
|
||||
|
|
@ -48,6 +48,6 @@ import('../../../__registry__/index').then((res) => {
|
|||
</PageHeader>
|
||||
|
||||
<section id="blocks" class="grid scroll-mt-24 gap-24 lg:gap-48">
|
||||
<BlockPreview v-for="block in blocks" :key="block" :name="block" />
|
||||
<BlockContainer v-for="block in blocks" :key="block" :name="block" />
|
||||
</section>
|
||||
</template>
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
export { default as APITable } from './APITable.vue'
|
||||
export { default as BlockPreview } from './BlockPreview.vue'
|
||||
export { default as Callout } from './Callout.vue'
|
||||
export { default as CodeWrapper } from './CodeWrapper'
|
||||
export { default as ComponentPreview } from './ComponentPreview.vue'
|
||||
|
|
|
|||
|
|
@ -28,6 +28,16 @@
|
|||
--ring: 240 5% 64.9%;
|
||||
--radius: 0.5rem;
|
||||
|
||||
--sidebar-background: 0 0% 98%;
|
||||
--sidebar-foreground: 240 5.3% 26.1%;
|
||||
--sidebar-primary: 240 5.9% 10%;
|
||||
--sidebar-primary-foreground: 0 0% 98%;
|
||||
--sidebar-accent: 240 4.8% 95.9%;
|
||||
--sidebar-accent-foreground: 240 5.9% 10%;
|
||||
--sidebar-border: 220 13% 91%;
|
||||
--sidebar-ring: 217.2 91.2% 59.8%;
|
||||
|
||||
|
||||
--vis-primary-color: var(--primary);
|
||||
--vis-secondary-color: 160 81% 40%;
|
||||
--vis-text-color: var(--muted-foreground);
|
||||
|
|
@ -64,6 +74,15 @@
|
|||
--border: 240 3.7% 15.9%;
|
||||
--input: 240 3.7% 15.9%;
|
||||
--ring: 240 4.9% 83.9%;
|
||||
|
||||
--sidebar-background: 240 5.9% 10%;
|
||||
--sidebar-foreground: 240 4.8% 95.9%;
|
||||
--sidebar-primary: 224.3 76.3% 48%;
|
||||
--sidebar-primary-foreground: 0 0% 100%;
|
||||
--sidebar-accent: 240 3.7% 15.9%;
|
||||
--sidebar-accent-foreground: 240 4.8% 95.9%;
|
||||
--sidebar-border: 240 3.7% 15.9%;
|
||||
--sidebar-ring: 217.2 91.2% 59.8%;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -97,19 +116,6 @@
|
|||
src: url("/fonts/Geist/GeistVariableVF.woff2") format("woff2");
|
||||
}
|
||||
|
||||
/* === Scrollbars === */
|
||||
|
||||
::-webkit-scrollbar {
|
||||
@apply w-2;
|
||||
@apply h-2;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-track {
|
||||
@apply !bg-muted;
|
||||
}
|
||||
::-webkit-scrollbar-thumb {
|
||||
@apply rounded-sm !bg-muted-foreground/30;
|
||||
}
|
||||
|
||||
/* Firefox */
|
||||
/* https://developer.mozilla.org/en-US/docs/Web/CSS/scrollbar-color#browser_compatibility */
|
||||
|
|
@ -121,15 +127,6 @@
|
|||
scrollbar-color: hsl(215.4 16.3% 56.9% / 0.3);
|
||||
}
|
||||
|
||||
.hide-scrollbar::-webkit-scrollbar {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.hide-scrollbar {
|
||||
-ms-overflow-style: none;
|
||||
scrollbar-width: none;
|
||||
}
|
||||
|
||||
.antialised {
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
|
|
|
|||
|
|
@ -1501,6 +1501,20 @@ export const Index = {
|
|||
component: () => import("../src/lib/registry/default/block/Dashboard07.vue").then((m) => m.default),
|
||||
files: ["../src/lib/registry/default/block/Dashboard07.vue"],
|
||||
},
|
||||
"Sidebar01": {
|
||||
name: "Sidebar01",
|
||||
type: "components:block",
|
||||
registryDependencies: ["breadcrumb","dropdown-menu","label","separator","sidebar"],
|
||||
component: () => import("../src/lib/registry/default/block/Sidebar01.vue").then((m) => m.default),
|
||||
files: ["../src/lib/registry/default/block/Sidebar01.vue"],
|
||||
},
|
||||
"Sidebar07": {
|
||||
name: "Sidebar07",
|
||||
type: "components:block",
|
||||
registryDependencies: ["avatar","breadcrumb","collapsible","dropdown-menu","separator","sidebar"],
|
||||
component: () => import("../src/lib/registry/default/block/Sidebar07.vue").then((m) => m.default),
|
||||
files: ["../src/lib/registry/default/block/Sidebar07.vue"],
|
||||
},
|
||||
}, "new-york": {
|
||||
"AccordionDemo": {
|
||||
name: "AccordionDemo",
|
||||
|
|
@ -3000,5 +3014,19 @@ export const Index = {
|
|||
component: () => import("../src/lib/registry/new-york/block/Dashboard07.vue").then((m) => m.default),
|
||||
files: ["../src/lib/registry/new-york/block/Dashboard07.vue"],
|
||||
},
|
||||
"Sidebar01": {
|
||||
name: "Sidebar01",
|
||||
type: "components:block",
|
||||
registryDependencies: ["breadcrumb","dropdown-menu","label","separator","sidebar"],
|
||||
component: () => import("../src/lib/registry/new-york/block/Sidebar01.vue").then((m) => m.default),
|
||||
files: ["../src/lib/registry/new-york/block/Sidebar01.vue"],
|
||||
},
|
||||
"Sidebar07": {
|
||||
name: "Sidebar07",
|
||||
type: "components:block",
|
||||
registryDependencies: ["avatar","breadcrumb","collapsible","dropdown-menu","separator","sidebar"],
|
||||
component: () => import("../src/lib/registry/new-york/block/Sidebar07.vue").then((m) => m.default),
|
||||
files: ["../src/lib/registry/new-york/block/Sidebar07.vue"],
|
||||
},
|
||||
},
|
||||
}
|
||||
|
|
|
|||
|
|
@ -80,10 +80,17 @@ for (const style of styles) {
|
|||
continue
|
||||
|
||||
const files = item.files?.map((file) => {
|
||||
let content = fs.readFileSync(
|
||||
path.join(process.cwd(), 'src/lib/registry', style.name, file),
|
||||
'utf8',
|
||||
)
|
||||
let content: string = ''
|
||||
|
||||
try {
|
||||
content = fs.readFileSync(
|
||||
path.join(process.cwd(), 'src/lib/registry', style.name, file),
|
||||
'utf8',
|
||||
)
|
||||
}
|
||||
catch (err) {
|
||||
console.log(`'${file}' is missing`)
|
||||
}
|
||||
|
||||
// Replace Windows-style newlines with Unix-style newlines
|
||||
content = content.replace(/\r\n/g, newLine)
|
||||
|
|
@ -99,7 +106,7 @@ for (const style of styles) {
|
|||
files,
|
||||
}
|
||||
|
||||
const payloadStr = JSON.stringify(payload, null, 2).replace(/\r\n/g, newLine)
|
||||
const payloadStr = `${JSON.stringify(payload, null, 2).replace(/\r\n/g, newLine)}\n`
|
||||
|
||||
fs.writeFileSync(
|
||||
path.join(targetPath, `${item.name}.json`),
|
||||
|
|
|
|||
|
|
@ -51,6 +51,16 @@ export default {
|
|||
DEFAULT: 'hsl(var(--card))',
|
||||
foreground: 'hsl(var(--card-foreground))',
|
||||
},
|
||||
sidebar: {
|
||||
'DEFAULT': 'hsl(var(--sidebar-background))',
|
||||
'foreground': 'hsl(var(--sidebar-foreground))',
|
||||
'primary': 'hsl(var(--sidebar-primary))',
|
||||
'primary-foreground': 'hsl(var(--sidebar-primary-foreground))',
|
||||
'accent': 'hsl(var(--sidebar-accent))',
|
||||
'accent-foreground': 'hsl(var(--sidebar-accent-foreground))',
|
||||
'border': 'hsl(var(--sidebar-border))',
|
||||
'ring': 'hsl(var(--sidebar-ring))',
|
||||
},
|
||||
},
|
||||
borderRadius: {
|
||||
xl: 'calc(var(--radius) + 4px)',
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user