mirror of
https://github.com/ArthurDanjou/ui.git
synced 2026-01-21 15:31:46 +01:00
docs: integrate @nuxt/ui-pro (#739)
Co-authored-by: Pooya Parsa <pooya@pi0.io> Co-authored-by: Florent Delerue <florentdelerue@hotmail.com> Co-authored-by: Sébastien Chopin <seb@nuxt.com>
This commit is contained in:
@@ -1,22 +1,16 @@
|
||||
<template>
|
||||
<div v-if="$route.path !== '/playground'" class="w-full h-px bg-gray-200 dark:bg-gray-800 flex items-center justify-center">
|
||||
<div class="bg-white dark:bg-gray-900 px-4">
|
||||
<div class="w-full h-px bg-gray-200 dark:bg-gray-800 flex items-center justify-center">
|
||||
<div v-if="!['/playground', '/roadmap'].includes($route.path)" class="bg-white dark:bg-gray-900 px-4">
|
||||
<LogoOnly class="w-5 h-5" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<UFooter :links="[]" :ui="{ bottom: { container: 'lg:py-4' } }">
|
||||
<UFooter>
|
||||
<template #left>
|
||||
<div class="text-sm text-gray-500 dark:text-gray-400">
|
||||
Made by
|
||||
<NuxtLink to="https://nuxtlabs.com" aria-label="NuxtLabs" class="inline-block">
|
||||
<LogoLabs class="text-gray-900 dark:text-white h-4 w-auto" />
|
||||
</NuxtLink>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template #center>
|
||||
<span class="text-sm text-gray-500 dark:text-gray-400">
|
||||
<a v-if="$route.path.startsWith('/pro')" class="text-sm text-gray-500 dark:text-gray-400 hover:underline" href="https://ui.nuxt.com/pro/purchase" target="_blank">
|
||||
Purchase Nuxt UI Pro
|
||||
</a>
|
||||
<span v-else class="text-sm text-gray-500 dark:text-gray-400">
|
||||
Published under <NuxtLink to="https://github.com/nuxt/ui" target="_blank" class="text-gray-900 dark:text-white">
|
||||
MIT License
|
||||
</NuxtLink>
|
||||
|
||||
@@ -31,42 +31,35 @@
|
||||
</template>
|
||||
|
||||
<template #panel>
|
||||
<BranchSelect />
|
||||
<UAsideLinks :links="links" />
|
||||
|
||||
<UNavigationTree :links="mapContentNavigation(navigation)" />
|
||||
<UDivider type="dashed" class="mt-4 mb-3" />
|
||||
|
||||
<BranchSelect v-if="!route.path.startsWith('/pro')" />
|
||||
|
||||
<UNavigationTree :links="mapContentNavigation(navigation)" :multiple="false" default-open />
|
||||
</template>
|
||||
</UHeader>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import type { NavItem } from '@nuxt/content/dist/runtime/types'
|
||||
import type { Link } from '#ui-pro/types'
|
||||
|
||||
defineProps<{
|
||||
links: Link[]
|
||||
}>()
|
||||
|
||||
const route = useRoute()
|
||||
const { metaSymbol } = useShortcuts()
|
||||
|
||||
const navigation = inject<Ref<NavItem[]>>('navigation')
|
||||
const nav = inject<Ref<NavItem[]>>('navigation')
|
||||
|
||||
const links = computed(() => {
|
||||
return [{
|
||||
label: 'Documentation',
|
||||
icon: 'i-heroicons-book-open-solid',
|
||||
to: '/getting-started'
|
||||
}, {
|
||||
label: 'Examples',
|
||||
icon: 'i-heroicons-square-3-stack-3d',
|
||||
to: '/getting-started/examples'
|
||||
}, {
|
||||
label: 'Playground',
|
||||
icon: 'i-simple-icons-stackblitz',
|
||||
to: '/playground'
|
||||
}, {
|
||||
label: 'Pro',
|
||||
icon: 'i-heroicons-square-3-stack-3d',
|
||||
to: '/pro'
|
||||
}, {
|
||||
label: 'Releases',
|
||||
icon: 'i-heroicons-rocket-launch-solid',
|
||||
to: 'https://github.com/nuxt/ui/releases',
|
||||
target: '_blank'
|
||||
}]
|
||||
const navigation = computed(() => {
|
||||
if (route.path.startsWith('/pro')) {
|
||||
return nav.value.find(item => item._path === '/pro')?.children
|
||||
}
|
||||
|
||||
return nav.value.filter(item => !item._path.startsWith('/pro'))
|
||||
})
|
||||
</script>
|
||||
|
||||
@@ -36,8 +36,8 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex border border-b-0 border-gray-200 dark:border-gray-700 relative not-prose" :class="[{ 'p-4': padding }, propsToSelect.length ? 'border-t-0' : 'rounded-t-md', backgroundClass, overflowClass]">
|
||||
<component :is="name" v-model="vModel" v-bind="fullProps">
|
||||
<div class="flex border border-b-0 border-gray-200 dark:border-gray-700 relative not-prose" :class="[{ 'p-4': padding }, propsToSelect.length ? 'border-t-0' : 'rounded-t-md', backgroundClass, extraClass]">
|
||||
<component :is="name" v-model="vModel" v-bind="fullProps" :class="componentClass">
|
||||
<ContentSlot v-if="$slots.default" :use="$slots.default" />
|
||||
|
||||
<template v-for="slot in Object.keys(slots || {})" :key="slot" #[slot]>
|
||||
@@ -99,13 +99,17 @@ const props = defineProps({
|
||||
type: String,
|
||||
default: 'bg-white dark:bg-gray-900'
|
||||
},
|
||||
overflowClass: {
|
||||
extraClass: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
previewOnly: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
componentClass: {
|
||||
type: String,
|
||||
default: ''
|
||||
}
|
||||
})
|
||||
|
||||
@@ -116,10 +120,16 @@ const componentProps = reactive({ ...props.props })
|
||||
const { $prettier } = useNuxtApp()
|
||||
const appConfig = useAppConfig()
|
||||
const route = useRoute()
|
||||
// eslint-disable-next-line vue/no-dupe-keys
|
||||
const slug = props.slug || route.params.slug[route.params.slug.length - 1]
|
||||
const camelName = camelCase(slug)
|
||||
const name = `U${upperFirst(camelName)}`
|
||||
|
||||
let name = props.slug || `U${upperFirst(camelCase(route.params.slug[route.params.slug.length - 1]))}`
|
||||
|
||||
// TODO: Remove once merged on `main` branch
|
||||
if (['AvatarGroup', 'ButtonGroup', 'MeterGroup'].includes(name)) {
|
||||
name = `U${name}`
|
||||
}
|
||||
if (['avatar-group', 'button-group', 'radio'].includes(name)) {
|
||||
name = `U${upperFirst(camelCase(name))}`
|
||||
}
|
||||
|
||||
const meta = await fetchComponentMeta(name)
|
||||
|
||||
|
||||
@@ -1,10 +1,14 @@
|
||||
<template>
|
||||
<div class="[&>div>pre]:!rounded-t-none [&>div>pre]:!mt-0">
|
||||
<div
|
||||
class="flex border border-gray-200 dark:border-gray-700 relative not-prose rounded-t-md"
|
||||
:class="[{ 'p-4': padding, 'rounded-b-md': !hasCode, 'border-b-0': hasCode }, backgroundClass, overflowClass]"
|
||||
class="flex border border-gray-200 dark:border-gray-700 relative rounded-t-md"
|
||||
:class="[{ 'p-4': padding, 'rounded-b-md': !hasCode, 'border-b-0': hasCode, 'not-prose': !prose }, backgroundClass, extraClass]"
|
||||
>
|
||||
<component :is="camelName" v-if="component" v-bind="componentProps" />
|
||||
<template v-if="component">
|
||||
<iframe v-if="iframe" :src="`/examples/${component}`" v-bind="iframeProps" :class="backgroundClass" class="w-full" />
|
||||
<component :is="camelName" v-else v-bind="componentProps" :class="componentClass" />
|
||||
</template>
|
||||
|
||||
<ContentSlot v-if="$slots.default" :use="$slots.default" />
|
||||
</div>
|
||||
<template v-if="hasCode">
|
||||
@@ -43,18 +47,36 @@ const props = defineProps({
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
prose: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
iframe: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
iframeProps: {
|
||||
type: Object,
|
||||
default: () => ({})
|
||||
},
|
||||
backgroundClass: {
|
||||
type: String,
|
||||
default: 'bg-white dark:bg-gray-900'
|
||||
},
|
||||
overflowClass: {
|
||||
extraClass: {
|
||||
type: String,
|
||||
default: ''
|
||||
}
|
||||
})
|
||||
|
||||
let component = props.component
|
||||
// TODO: Remove once merged on `main` branch
|
||||
if (['command-palette-theme-algolia', 'command-palette-theme-raycast', 'vertical-navigation-theme-tailwind', 'pagination-theme-rounded'].includes(component)) {
|
||||
component = component.replace('-theme', '-example-theme')
|
||||
}
|
||||
|
||||
const instance = getCurrentInstance()
|
||||
const camelName = camelCase(props.component)
|
||||
const camelName = camelCase(component)
|
||||
const data = await fetchContentExampleCode(camelName)
|
||||
|
||||
const hasCode = computed(() => !props.hiddenCode && (data?.code || instance.slots.code))
|
||||
|
||||
@@ -17,10 +17,16 @@ const props = defineProps({
|
||||
})
|
||||
|
||||
const route = useRoute()
|
||||
// eslint-disable-next-line vue/no-dupe-keys
|
||||
const slug = props.slug || route.params.slug[route.params.slug.length - 1]
|
||||
const camelName = camelCase(slug)
|
||||
const name = `U${upperFirst(camelName)}`
|
||||
|
||||
let name = props.slug || `U${upperFirst(camelCase(route.params.slug[route.params.slug.length - 1]))}`
|
||||
|
||||
// TODO: Remove once merged on `main` branch
|
||||
if (['AvatarGroup', 'ButtonGroup', 'MeterGroup'].includes(name)) {
|
||||
name = `U${name}`
|
||||
}
|
||||
if (['avatar-group', 'button-group', 'radio'].includes(name)) {
|
||||
name = `U${upperFirst(camelCase(name))}`
|
||||
}
|
||||
|
||||
const meta = await fetchComponentMeta(name)
|
||||
</script>
|
||||
|
||||
@@ -1,21 +1,24 @@
|
||||
<template>
|
||||
<Field v-bind="prop">
|
||||
<code v-if="prop.default">{{ prop.default }}</code>
|
||||
<p v-if="prop.description">
|
||||
{{ prop.description }}
|
||||
</p>
|
||||
|
||||
<Collapsible v-if="prop.schema?.kind === 'array' && prop.schema?.schema?.filter(schema => schema.kind === 'object').length">
|
||||
<FieldGroup v-for="schema in prop.schema.schema" :key="schema.name" class="!mt-0">
|
||||
<FieldGroup v-for="schema in prop.schema.schema" :key="schema.name">
|
||||
<ComponentPropsField v-for="subProp in Object.values(schema.schema)" :key="(subProp as any).name" :prop="subProp" />
|
||||
</FieldGroup>
|
||||
</Collapsible>
|
||||
<Collapsible v-else-if="prop.schema?.kind === 'array' && prop.schema?.schema?.filter(schema => schema.kind === 'array').length">
|
||||
<FieldGroup v-for="schema in prop.schema.schema" :key="schema.name" class="!mt-0">
|
||||
<FieldGroup v-for="schema in prop.schema.schema" :key="schema.name">
|
||||
<template v-for="subSchema in schema.schema" :key="subSchema.name">
|
||||
<ComponentPropsField v-for="subProp in Object.values(subSchema.schema)" :key="(subProp as any).name" :prop="subProp" />
|
||||
</template>
|
||||
</FieldGroup>
|
||||
</Collapsible>
|
||||
<Collapsible v-else-if="prop.schema?.kind === 'object' && prop.schema.type !== 'Function' && Object.values(prop.schema.schema)?.length">
|
||||
<FieldGroup class="!mt-0">
|
||||
<FieldGroup>
|
||||
<ComponentPropsField v-for="subProp in Object.values(prop.schema.schema)" :key="(subProp as any).name" :prop="subProp" />
|
||||
</FieldGroup>
|
||||
</Collapsible>
|
||||
|
||||
@@ -1,19 +1,8 @@
|
||||
<template>
|
||||
<div>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Slot</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr v-for="slot in (meta.meta.slots as any[])" :key="slot.name">
|
||||
<td class="whitespace-nowrap">
|
||||
<code>{{ slot.name }}</code>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<FieldGroup>
|
||||
<Field v-for="slot in meta?.meta.slots" :key="slot.name" v-bind="slot" />
|
||||
</FieldGroup>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -28,10 +17,8 @@ const props = defineProps({
|
||||
})
|
||||
|
||||
const route = useRoute()
|
||||
// eslint-disable-next-line vue/no-dupe-keys
|
||||
const slug = props.slug || route.params.slug[route.params.slug.length - 1]
|
||||
const camelName = camelCase(slug)
|
||||
const name = `U${upperFirst(camelName)}`
|
||||
|
||||
const name = props.slug || `U${upperFirst(camelCase(route.params.slug[route.params.slug.length - 1]))}`
|
||||
|
||||
const meta = await fetchComponentMeta(name)
|
||||
</script>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<div class="relative overflow-hidden rounded border border-dashed border-gray-400 dark:border-gray-500 opacity-75">
|
||||
<div class="relative overflow-hidden rounded border border-dashed border-gray-400 dark:border-gray-500 opacity-75 px-4 flex items-center justify-center">
|
||||
<svg class="absolute inset-0 h-full w-full stroke-gray-900/10 dark:stroke-white/10" fill="none">
|
||||
<defs>
|
||||
<pattern
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
<template>
|
||||
<iframe :src="src" class="w-full min-h-[calc(100vh/1.5)] border border-gray-200 dark:border-gray-800 rounded-md" />
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
const props = defineProps({
|
||||
token: {
|
||||
type: String,
|
||||
required: true
|
||||
}
|
||||
})
|
||||
|
||||
const appConfig = useAppConfig()
|
||||
const colorMode = useColorMode()
|
||||
|
||||
const src = computed(() => `https://volta.net/embed/${props.token}?theme=${colorMode.value}&gray=${appConfig.ui.gray}&primary=${appConfig.ui.primary}`)
|
||||
</script>
|
||||
@@ -84,11 +84,11 @@ const pageFrom = computed(() => (page.value - 1) * pageCount.value + 1)
|
||||
const pageTo = computed(() => Math.min(page.value * pageCount.value, pageTotal.value))
|
||||
|
||||
// Data
|
||||
const { data: todos, pending } = await useLazyAsyncData('todos', () => $fetch<{
|
||||
const { data: todos, pending } = await useLazyAsyncData<{
|
||||
id: number
|
||||
title: string
|
||||
completed: string
|
||||
}[]>(`https://jsonplaceholder.typicode.com/todos${searchStatus.value}`, {
|
||||
}[]>('todos', () => ($fetch as any)(`https://jsonplaceholder.typicode.com/todos${searchStatus.value}`, {
|
||||
query: {
|
||||
q: search.value,
|
||||
'_page': page.value,
|
||||
|
||||
Reference in New Issue
Block a user