docs(ComponentCard): show all props for the code (#797)

Co-authored-by: Benjamin Canac <canacb1@gmail.com>
This commit is contained in:
KeJun
2023-10-15 23:52:20 +08:00
committed by GitHub
parent 9f4d88e0aa
commit 8867936e01
16 changed files with 157 additions and 99 deletions

View File

@@ -41,7 +41,7 @@
<ContentSlot v-if="$slots.default" :use="$slots.default" />
<template v-for="slot in Object.keys(slots || {})" :key="slot" #[slot]>
<ContentSlot :name="slot" />
<ContentSlot :name="slot" unwrap="p" />
</template>
</component>
</div>
@@ -113,6 +113,7 @@ const props = defineProps({
const baseProps = reactive({ ...props.baseProps })
const componentProps = reactive({ ...props.props })
const { $prettier } = useNuxtApp()
const appConfig = useAppConfig()
const route = useRoute()
// eslint-disable-next-line vue/no-dupe-keys
@@ -124,7 +125,7 @@ const meta = await fetchComponentMeta(name)
// Computed
const fullProps = computed(() => ({ ...baseProps, ...componentProps }))
const fullProps = computed(() => ({ ...componentProps, ...baseProps }))
const vModel = computed({
get: () => baseProps.modelValue,
set: (value) => {
@@ -186,7 +187,7 @@ const propsToSelect = computed(() => Object.keys(componentProps).map((key) => {
const code = computed(() => {
let code = `\`\`\`html
<${name}`
for (const [key, value] of Object.entries(componentProps)) {
for (const [key, value] of Object.entries(fullProps.value)) {
if (value === 'undefined' || value === null) {
continue
}
@@ -206,7 +207,7 @@ const code = computed(() => {
code += `>
${props.code}</${name}>`
} else {
code += `>${props.code}</${name}>`
code += `>${props.code.endsWith('>') ? `${props.code}\n` : props.code}</${name}>`
}
} else {
code += ' />'
@@ -235,16 +236,27 @@ function renderObject (obj: any) {
const shikiHighlighter = useShikiHighlighter({})
const codeHighlighter = async (code: string, lang: string, theme: any, highlights: number[]) => shikiHighlighter.getHighlightedAST(code, lang, theme, { highlights })
const { data: ast } = await useAsyncData(`${name}-ast-${JSON.stringify({ props: componentProps, slots: props.slots })}`, () => transformContent('content:_markdown.md', code.value, {
markdown: {
highlight: {
highlighter: codeHighlighter,
theme: {
light: 'material-theme-lighter',
default: 'material-theme',
dark: 'material-theme-palenight'
}
const { data: ast } = await useAsyncData(
`${name}-ast-${JSON.stringify({ props: componentProps, slots: props.slots })}`,
async () => {
let formatted = ''
try {
formatted = await $prettier.format(code.value) || code.value
} catch (error) {
formatted = code.value
}
}
}), { watch: [code] })
return transformContent('content:_markdown.md', formatted, {
markdown: {
highlight: {
highlighter: codeHighlighter,
theme: {
light: 'material-theme-lighter',
default: 'material-theme',
dark: 'material-theme-palenight'
}
}
}
})
}, { watch: [code] })
</script>

View File

@@ -5,8 +5,9 @@
</template>
<template #error="{ error }">
<UAlert v-if="error" icon="i-heroicons-exclamation-triangle-20-solid" :title="error" color="red" />
<UAlert v-else icon="i-heroicons-check-circle-20-solid" title="Your email is valid" color="green" />
<span :class="[error ? 'text-red-500 dark:text-red-400' : 'text-primary-500 dark:text-primary-400']">
{{ error ? error : 'Your email is valid' }}
</span>
</template>
</UFormGroup>
</template>

View File

@@ -38,6 +38,7 @@ Use the `color` and `variant` props to change the visual style of the Badge.
props:
color: 'primary'
variant: 'solid'
code: Badge
---
Badge
@@ -59,6 +60,7 @@ options:
- solid
excludedProps:
- color
code: Badge
---
Badge
@@ -78,6 +80,7 @@ options:
- solid
excludedProps:
- color
code: Badge
---
Badge
@@ -97,6 +100,7 @@ options:
- solid
excludedProps:
- color
code: Badge
---
Badge
@@ -110,6 +114,7 @@ Use the `size` prop to change the size of the Badge.
---
props:
size: 'sm'
code: Badge
---
Badge
@@ -126,6 +131,7 @@ props:
rounded: 'rounded-full'
excludedProps:
- ui
code: Badge
---
Badge

View File

@@ -36,6 +36,7 @@ Use the `color` and `variant` props to change the visual style of the Button.
props:
color: 'primary'
variant: 'solid'
code: Button
---
Button
@@ -56,9 +57,10 @@ options:
restriction: expected
values:
- solid
- ghost
- ghost
excludedProps:
- color
code: Button
---
Button
@@ -77,9 +79,10 @@ options:
values:
- solid
- ghost
- link
- link
excludedProps:
- color
code: Button
---
Button
@@ -97,9 +100,10 @@ options:
restriction: expected
values:
- solid
- link
- link
excludedProps:
- color
code: Button
---
Button
@@ -113,6 +117,7 @@ Use the `size` prop to change the size of the Button.
---
props:
size: 'sm'
code: Button
---
Button
@@ -129,6 +134,7 @@ props:
rounded: 'rounded-full'
excludedProps:
- ui
code: Button
---
Button
@@ -183,6 +189,7 @@ Use the `disabled` prop to disable the Button.
---
props:
disabled: true
code: Button
---
Button
@@ -198,6 +205,7 @@ Use the `loading-icon` prop to set a different icon or change it globally in `ui
---
props:
loading: true
code: Button
---
Button
@@ -211,6 +219,7 @@ Use the `block` prop to make the Button fill the width of its container.
---
props:
block: true
code: Button
---
Button
@@ -225,6 +234,7 @@ Use the `to` prop to make the Button a link.
props:
to: 'https://volta.net'
target: '_blank'
code: Button
---
Button

View File

@@ -19,7 +19,6 @@ Use the `color` and `variant` props to change the visual style of the Input.
::component-card
---
baseProps:
name: 'input'
placeholder: 'Search...'
props:
color: 'primary'
@@ -34,7 +33,6 @@ Besides all the colors from the `ui.colors` object, you can also use the `white`
::component-card
---
baseProps:
name: 'input'
placeholder: 'Search...'
props:
color: 'white'
@@ -49,7 +47,6 @@ excludedProps:
::component-card
---
baseProps:
name: 'input'
placeholder: 'Search...'
props:
color: 'gray'
@@ -65,8 +62,6 @@ Use the `size` prop to change the size of the Input.
::component-card
---
baseProps:
name: 'input'
props:
size: 'sm'
---
@@ -80,8 +75,6 @@ We have improved the implementation of certain types such as [Checkbox](/forms/c
::component-card
---
baseProps:
name: 'input'
props:
type: 'password'
---
@@ -93,8 +86,6 @@ Use the `placeholder` prop to set a placeholder text.
::component-card
---
baseProps:
name: 'input'
props:
placeholder: 'Search...'
---
@@ -109,7 +100,6 @@ Use the `leading` and `trailing` props to set the icon position or the `leading-
::component-card
---
baseProps:
name: 'input'
placeholder: 'Search...'
props:
icon: 'i-heroicons-magnifying-glass-20-solid'
@@ -134,7 +124,6 @@ Use the `disabled` prop to disable the Input.
::component-card
---
baseProps:
name: 'input'
placeholder: 'Search...'
props:
disabled: true
@@ -150,7 +139,6 @@ Use the `loading-icon` prop to set a different icon or change it globally in `ui
::component-card
---
baseProps:
name: 'input'
placeholder: 'Searching...'
props:
loading: true
@@ -171,7 +159,6 @@ Use the `#leading` slot to set the content of the leading icon.
slots:
leading: <UAvatar src="https://avatars.githubusercontent.com/u/739984?v=4" size="3xs" />
baseProps:
name: 'input'
placeholder: 'Search...'
---
@@ -188,7 +175,6 @@ Use the `#trailing` slot to set the content of the trailing icon.
slots:
trailing: <span class="text-gray-500 dark:text-gray-400 text-xs">EUR</span>
baseProps:
name: 'input'
placeholder: 'Search...'
---

View File

@@ -19,7 +19,6 @@ Use the `color` and `variant` props to change the visual style of the Textarea.
::component-card
---
baseProps:
name: 'textarea'
placeholder: 'Search...'
props:
color: 'primary'
@@ -34,7 +33,6 @@ Besides all the colors from the `ui.colors` object, you can also use the `white`
::component-card
---
baseProps:
name: 'textarea'
placeholder: 'Search...'
props:
color: 'white'
@@ -49,7 +47,6 @@ excludedProps:
::component-card
---
baseProps:
name: 'textarea'
placeholder: 'Search...'
props:
color: 'gray'
@@ -66,7 +63,6 @@ Use the `size` prop to change the size of the Textarea.
::component-card
---
baseProps:
name: 'textarea'
props:
size: 'sm'
---
@@ -78,8 +74,6 @@ Use the `placeholder` prop to set a placeholder text.
::component-card
---
baseProps:
name: 'textarea'
props:
placeholder: 'Search...'
---
@@ -92,7 +86,6 @@ Use the `rows` prop to set the number of rows of the Textarea.
::component-card
---
baseProps:
name: 'input'
placeholder: 'Search...'
props:
rows: 1
@@ -106,7 +99,6 @@ Use the `disabled` prop to disable the Textarea.
::component-card
---
baseProps:
name: 'input'
placeholder: 'Search...'
props:
disabled: true
@@ -120,7 +112,6 @@ Use the `autoresize` prop to enable the autoresize. Writing more lines than the
::component-card
---
baseProps:
name: 'input'
placeholder: 'Search...'
modelValue: 'Here is an autoresize Textarea, write new lines to make the Textarea grow up...'
props:
@@ -135,7 +126,6 @@ Use the `resize` prop to enable the resize control.
::component-card
---
baseProps:
name: 'input'
placeholder: 'Search...'
props:
resize: true

View File

@@ -27,7 +27,6 @@ Use the `color` and `variant` props to change the visual style of the Select.
::component-card
---
baseProps:
name: 'select'
options:
- 'United States'
- 'Canada'
@@ -45,7 +44,6 @@ Besides all the colors from the `ui.colors` object, you can also use the `white`
::component-card
---
baseProps:
name: 'select'
options:
- 'United States'
- 'Canada'
@@ -63,7 +61,6 @@ excludedProps:
::component-card
---
baseProps:
name: 'select'
options:
- 'United States'
- 'Canada'
@@ -83,7 +80,6 @@ Use the `size` prop to change the size of the Select.
::component-card
---
baseProps:
name: 'select'
options:
- 'United States'
- 'Canada'
@@ -100,7 +96,6 @@ Use the `placeholder` prop to set a placeholder text.
::component-card
---
baseProps:
name: 'select'
options:
- 'United States'
- 'Canada'
@@ -119,7 +114,6 @@ Use the `trailing-icon` prop to set a different icon or change it globally in `u
::component-card
---
baseProps:
name: 'select'
options:
- 'United States'
- 'Canada'
@@ -147,7 +141,6 @@ Use the `disabled` prop to disable the Select.
::component-card
---
baseProps:
name: 'select'
options:
- 'United States'
- 'Canada'
@@ -169,7 +162,6 @@ Use the `loading-icon` prop to set a different icon or change it globally in `ui
::component-card
---
baseProps:
name: 'select'
options:
- 'United States'
- 'Canada'
@@ -194,7 +186,6 @@ Use the `#leading` slot to set the content of the leading icon.
slots:
leading: <UAvatar src="https://avatars.githubusercontent.com/u/739984?v=4" size="3xs" />
baseProps:
name: 'select'
options:
- 'United States'
- 'Canada'
@@ -215,7 +206,6 @@ Use the `#trailing` slot to set the content of the trailing icon.
slots:
trailing: <UIcon name="i-heroicons-arrows-up-down-20-solid" />
baseProps:
name: 'input'
placeholder: 'Search...'
---

View File

@@ -18,8 +18,6 @@ Use the `label` prop to display a label on the right.
::component-card
---
baseProps:
name: 'checkbox1'
props:
label: 'Label'
---
@@ -32,7 +30,6 @@ Use the `color` prop to change the style of the Checkbox.
::component-card
---
baseProps:
name: 'checkbox2'
label: 'Label'
props:
color: 'primary'
@@ -45,8 +42,6 @@ Use the `required` prop to display a red star next to the label.
::component-card
---
baseProps:
name: 'checkbox3'
props:
label: 'Label'
required: true
@@ -59,8 +54,6 @@ Use the `help` prop to display some text under the Checkbox.
::component-card
---
baseProps:
name: 'checkbox4'
props:
label: 'Label'
help: 'Please check this box'
@@ -73,9 +66,6 @@ Use the `disabled` prop to disable the Checkbox.
::component-card
---
baseProps:
name: 'checkbox4'
modelValue: true
props:
disabled: true
---
@@ -91,8 +81,6 @@ Use the `#label` slot to override the content of the label.
---
slots:
label: <span class="italic">Label</span>
baseProps:
name: 'checkbox5'
---
#label

View File

@@ -18,8 +18,6 @@ Use the `label` prop to display a label on the right.
::component-card
---
baseProps:
name: 'radio1'
props:
label: 'Label'
---
@@ -32,7 +30,6 @@ Use the `color` prop to change the style of the Radio.
::component-card
---
baseProps:
name: 'radio2'
label: 'Label'
props:
color: 'primary'
@@ -45,8 +42,6 @@ Use the `required` prop to display a red star next to the label.
::component-card
---
baseProps:
name: 'radio3'
props:
label: 'Label'
required: true
@@ -59,8 +54,6 @@ Use the `help` prop to display some text under the Radio.
::component-card
---
baseProps:
name: 'radio4'
props:
label: 'Label'
help: 'Please choose one'
@@ -74,9 +67,7 @@ Use the `disabled` prop to disable the Radio.
::component-card
---
baseProps:
name: 'radio5'
label: 'Label'
value: true
props:
disabled: true
---
@@ -92,8 +83,6 @@ Use the `#label` slot to override the content of the label.
---
slots:
label: <span class="italic">Label</span>
baseProps:
name: 'radio6'
---
#label

View File

@@ -19,7 +19,6 @@ Use the `color` prop to change the visual style of the Range.
::component-card
---
baseProps:
name: range'
placeholder: 'Search...'
props:
color: 'primary'
@@ -32,8 +31,6 @@ Use the `size` prop to change the size of the Range.
::component-card
---
baseProps:
name: 'range'
props:
size: 'md'
---
@@ -45,8 +42,6 @@ Use the `disabled` prop to disable the Range.
::component-card
---
baseProps:
name: 'range'
props:
disabled: true
---
@@ -58,8 +53,6 @@ Use the `min` and `max` prop to configure the Range.
::component-card
---
baseProps:
name: 'range'
props:
min: 0
max: 100
@@ -72,8 +65,6 @@ Use the `step` prop to change the step increment.
::component-card
---
baseProps:
name: 'range'
props:
step: 20
---

View File

@@ -10,13 +10,12 @@ links:
## Usage
Use the FormGroup component around an [Input](/forms/input), [Textarea](/forms/textarea), [Select](/forms/select) or a [SelectMenu](/forms/select-menu) with the `name` prop to automatically associate a `<label>` element with the form element.
Use the FormGroup component around an [Input](/forms/input), [Textarea](/forms/textarea), [Select](/forms/select) or a [SelectMenu](/forms/select-menu) with a `label`. The `<label>` will automatically be associated with the form element so it gets focused on click.
::component-card
---
props:
label: 'Email'
name: 'email'
code: >-
<UInput placeholder="you@example.com" icon="i-heroicons-envelope" />
@@ -32,8 +31,6 @@ Use the `required` prop to indicate that the form element is required.
::component-card
---
baseProps:
name: 'group-required'
props:
label: 'Email'
required: true
@@ -52,8 +49,6 @@ Use the `description` prop to display a description below the label.
::component-card
---
baseProps:
name: 'group-description'
props:
label: 'Email'
description: "We'll only use this for spam."
@@ -72,8 +67,6 @@ Use the `hint` prop to display a hint above the form element.
::component-card
---
baseProps:
name: 'group-hint'
props:
label: 'Email'
hint: 'Optional'
@@ -92,8 +85,6 @@ Use the `help` prop to display an help message below the form element.
::component-card
---
baseProps:
name: 'group-help'
props:
label: 'Email'
help: 'We will never share your email with anyone else.'
@@ -122,8 +113,6 @@ You can also use the `error` prop as a boolean to mark the form element as inval
::component-card
---
baseProps:
name: 'group-error'
props:
label: 'Email'
error: true

View File

@@ -163,7 +163,7 @@ You can also highlight the matches in the command by setting the `fuse.fuseOptio
```
::callout{icon="i-heroicons-light-bulb"}
Try it yourself in this documentation's search by pressing :kbd{value="meta"} :kbd{value="K" class="ml-1"}.
Try it yourself in this documentation's search by pressing :shortcut{value="meta"} :shortcut{value="K" class="ml-1"}.
::
## Async search

View File

@@ -22,6 +22,7 @@
"nuxt-cloudflare-analytics": "^1.0.8",
"nuxt-component-meta": "^0.5.4",
"nuxt-og-image": "^2.1.2",
"prettier": "^3.0.3",
"typescript": "^5.2.2",
"ufo": "^1.3.1",
"v-calendar": "^3.1.1",

67
docs/plugins/prettier.ts Normal file
View File

@@ -0,0 +1,67 @@
import type { Options } from 'prettier'
import PrettierWorker from '@/workers/prettier.js?worker&inline'
export interface SimplePrettier {
format: (source: string, options?: Options) => Promise<string>;
}
function createPrettierWorkerApi (worker: Worker): SimplePrettier {
let counter = 0
const handlers = {}
worker.addEventListener('message', (event) => {
const { uid, message, error } = event.data
if (!handlers[uid]) {
return
}
const [resolve, reject] = handlers[uid]
delete handlers[uid]
if (error) {
reject(error)
} else {
resolve(message)
}
})
function postMessage<T> (message) {
const uid = ++counter
return new Promise<T>((resolve, reject) => {
handlers[uid] = [resolve, reject]
worker.postMessage({ uid, message })
})
}
return {
format (source: string, options?: Options) {
return postMessage({ type: 'format', source, options })
}
}
}
export default defineNuxtPlugin({
async setup () {
let prettier: SimplePrettier
if (process.server) {
const prettierModule = await import('prettier')
prettier = {
format (source, options = {
parser: 'markdown'
}) {
return prettierModule.format(source, options)
}
}
} else {
const worker = new PrettierWorker()
prettier = createPrettierWorkerApi(worker)
}
return {
provide: {
prettier
}
}
}
})

29
docs/workers/prettier.js Normal file
View File

@@ -0,0 +1,29 @@
/* eslint-disable no-undef */
import('https://unpkg.com/prettier@3.0.3/standalone.js')
import('https://unpkg.com/prettier@3.0.3/plugins/html.js')
import('https://unpkg.com/prettier@3.0.3/plugins/markdown.js')
self.onmessage = async function (event) {
self.postMessage({
uid: event.data.uid,
message: await handleMessage(event.data.message)
})
}
function handleMessage (message) {
switch (message.type) {
case 'format':
return handleFormatMessage(message)
}
}
async function handleFormatMessage (message) {
const { options, source } = message
const formatted = await prettier.format(source, {
parser: 'markdown',
plugins: prettierPlugins,
...options
})
return formatted
}

9
pnpm-lock.yaml generated
View File

@@ -172,6 +172,9 @@ importers:
nuxt-og-image:
specifier: ^2.1.2
version: 2.1.2(rollup@3.29.1)(vue@3.3.4)
prettier:
specifier: ^3.0.3
version: 3.0.3
typescript:
specifier: ^5.2.2
version: 5.2.2
@@ -9873,6 +9876,12 @@ packages:
engines: {node: '>= 0.8.0'}
dev: true
/prettier@3.0.3:
resolution: {integrity: sha512-L/4pUDMxcNa8R/EthV08Zt42WBO4h1rarVtK0K+QJG0X187OLo7l699jWw0GKuwzkPQ//jMFA/8Xm6Fh3J/DAg==}
engines: {node: '>=14'}
hasBin: true
dev: true
/pretty-bytes@6.1.1:
resolution: {integrity: sha512-mQUvGU6aUFQ+rNvTIAcZuWGRT9a6f6Yrg9bHs4ImKF+HZCEK+plBvnAZYSIQztknZF2qnzNtr6F8s0+IuptdlQ==}
engines: {node: ^14.13.1 || >=16.0.0}