mirror of
https://github.com/ArthurDanjou/ui.git
synced 2026-01-14 20:19:34 +01:00
docs: improve ComponentCode and ComponentProps
This commit is contained in:
@@ -3,6 +3,7 @@ import { upperFirst, camelCase } from 'scule'
|
||||
import * as theme from '#build/ui'
|
||||
|
||||
const props = defineProps<{
|
||||
ignore?: string[]
|
||||
props?: { [key: string]: any }
|
||||
slots?: { [key: string]: any }
|
||||
}>()
|
||||
@@ -16,22 +17,24 @@ const name = `U${upperFirst(camelName)}`
|
||||
const componentProps = reactive({ ...(props.props || {}) })
|
||||
|
||||
const componentTheme = theme[camelName]
|
||||
// const meta = await fetchComponentMeta(name as any)
|
||||
const meta = await fetchComponentMeta(name as any)
|
||||
|
||||
const options = computed(() => Object.keys(props.props || {}).map((key) => {
|
||||
// const prop = meta?.meta?.props?.find((prop: any) => prop.name === key)
|
||||
const variants = componentTheme.variants?.[key]
|
||||
const items = variants
|
||||
? Object.keys(variants).map(variant => ({
|
||||
const options = computed(() => Object.keys(props.props || {}).filter((key) => {
|
||||
return !props.ignore?.includes(key)
|
||||
}).map((key) => {
|
||||
const prop = meta?.meta?.props?.find((prop: any) => prop.name === key)
|
||||
const variants = Object.keys(componentTheme.variants?.[key] || {})
|
||||
const items = prop?.type === 'boolean'
|
||||
? [{ value: true, label: 'true' }, { value: false, label: 'false' }]
|
||||
: variants.map(variant => ({
|
||||
value: variant,
|
||||
label: variant,
|
||||
chip: key === 'color' ? { color: variant } : undefined
|
||||
})).filter(variant => key === 'color' ? !['error'].includes(variant.value) : true)
|
||||
: []
|
||||
|
||||
return {
|
||||
name: key,
|
||||
label: camelCase(key),
|
||||
label: key,
|
||||
items
|
||||
}
|
||||
}))
|
||||
@@ -41,7 +44,29 @@ const code = computed(() => {
|
||||
<template>
|
||||
<${name}`
|
||||
for (const [key, value] of Object.entries(componentProps)) {
|
||||
code += ` ${key}="${value}"`
|
||||
if (value === undefined || value === null || value === '') {
|
||||
continue
|
||||
}
|
||||
|
||||
const prop = meta?.meta?.props?.find((prop: any) => prop.name === key)
|
||||
|
||||
if (typeof value === 'boolean') {
|
||||
if (value && prop?.default === 'true') {
|
||||
continue
|
||||
}
|
||||
if (!value && !prop?.default) {
|
||||
continue
|
||||
}
|
||||
|
||||
code += value ? ` ${key}` : ` :${key}="false"`
|
||||
} else {
|
||||
const propDefault = prop && (prop.default ?? prop.tags?.find(tag => tag.name === 'defaultValue')?.text ?? componentTheme?.defaultVariants?.[prop.name])
|
||||
if (propDefault === value) {
|
||||
continue
|
||||
}
|
||||
|
||||
code += ` ${key}="${value}"`
|
||||
}
|
||||
}
|
||||
|
||||
if (props.slots) {
|
||||
@@ -80,10 +105,10 @@ const { data: ast } = await useAsyncData(`${name}-code-${JSON.stringify({ props:
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<div v-if="options.length" class="flex items-center gap-3 border border-gray-300 dark:border-gray-700 border-b-0 relative rounded-t-md px-4 py-2.5">
|
||||
<div v-if="options.length" class="flex items-center gap-2.5 border border-gray-300 dark:border-gray-700 border-b-0 relative rounded-t-md px-4 py-2.5">
|
||||
<template v-for="option in options" :key="option.name">
|
||||
<UFormField
|
||||
:label="upperFirst(option.label)"
|
||||
:label="option.label"
|
||||
size="sm"
|
||||
class="inline-flex ring ring-gray-300 dark:ring-gray-700 rounded"
|
||||
:ui="{
|
||||
@@ -100,6 +125,9 @@ const { data: ast } = await useAsyncData(`${name}-code-${JSON.stringify({ props:
|
||||
color="gray"
|
||||
variant="soft"
|
||||
class="rounded rounded-l-none"
|
||||
:search="false"
|
||||
:class="[option.name === 'color' && 'pl-6']"
|
||||
:ui="{ itemLeadingChip: 'size-2' }"
|
||||
>
|
||||
<template v-if="option.name === 'color'" #leading="{ modelValue, ui }">
|
||||
<UChip
|
||||
@@ -108,7 +136,7 @@ const { data: ast } = await useAsyncData(`${name}-code-${JSON.stringify({ props:
|
||||
standalone
|
||||
:color="(modelValue as any)"
|
||||
:size="ui.itemLeadingChipSize()"
|
||||
:class="ui.itemLeadingChip()"
|
||||
class="size-2"
|
||||
/>
|
||||
</template>
|
||||
</USelectMenu>
|
||||
@@ -120,7 +148,9 @@ const { data: ast } = await useAsyncData(`${name}-code-${JSON.stringify({ props:
|
||||
<div class="flex border border-b-0 border-gray-300 dark:border-gray-700 relative p-4" :class="[!options.length && 'rounded-t-md']">
|
||||
<component :is="name" v-bind="componentProps">
|
||||
<template v-for="slot in Object.keys(slots || {})" :key="slot" #[slot]>
|
||||
<ContentSlot :name="slot" unwrap="p" />
|
||||
<ContentSlot :name="slot" unwrap="p">
|
||||
{{ slots[slot] }}
|
||||
</ContentSlot>
|
||||
</template>
|
||||
</component>
|
||||
</div>
|
||||
|
||||
@@ -3,6 +3,10 @@ import { upperFirst, camelCase } from 'scule'
|
||||
import type { ComponentMeta } from 'vue-component-meta'
|
||||
import * as theme from '#build/ui'
|
||||
|
||||
const props = defineProps<{
|
||||
ignore?: string[]
|
||||
}>()
|
||||
|
||||
const route = useRoute()
|
||||
|
||||
const camelName = camelCase(route.params.slug[route.params.slug.length - 1])
|
||||
@@ -16,7 +20,9 @@ const metaProps: ComputedRef<ComponentMeta['props']> = computed(() => {
|
||||
return []
|
||||
}
|
||||
|
||||
return meta.meta.props.map((prop) => {
|
||||
return meta.meta.props.filter((prop) => {
|
||||
return !props.ignore?.includes(prop.name)
|
||||
}).map((prop) => {
|
||||
prop.default = prop.default ?? prop.tags?.find(tag => tag.name === 'defaultValue')?.text ?? componentTheme?.defaultVariants?.[prop.name]
|
||||
return prop
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user