mirror of
https://github.com/ArthurDanjou/ui.git
synced 2026-01-14 20:19:34 +01:00
docs(ComponentCode): add cast prop (#2773)
This commit is contained in:
@@ -3,9 +3,42 @@
|
||||
import json5 from 'json5'
|
||||
import { upperFirst, camelCase, kebabCase } from 'scule'
|
||||
import { hash } from 'ohash'
|
||||
import { CalendarDate } from '@internationalized/date'
|
||||
import * as theme from '#build/ui'
|
||||
import { get, set } from '#ui/utils'
|
||||
|
||||
interface Cast {
|
||||
get: (args: any) => any
|
||||
template: (args: any) => string
|
||||
}
|
||||
|
||||
type CastDateValue = [number, number, number]
|
||||
|
||||
const castMap: Record<string, Cast> = {
|
||||
'DateValue': {
|
||||
get: (args: CastDateValue) => new CalendarDate(...args),
|
||||
template: (value: CalendarDate) => {
|
||||
return value ? `new CalendarDate(${value.year}, ${value.month}, ${value.day})` : 'null'
|
||||
}
|
||||
},
|
||||
'DateValue[]': {
|
||||
get: (args: CastDateValue[]) => args.map(date => new CalendarDate(...date)),
|
||||
template: (value: CalendarDate[]) => {
|
||||
return value ? `[${value.map(date => `new CalendarDate(${date.year}, ${date.month}, ${date.day})`).join(', ')}]` : '[]'
|
||||
}
|
||||
},
|
||||
'DateRange': {
|
||||
get: (args: { start: CastDateValue, end: CastDateValue }) => ({ start: new CalendarDate(...args.start), end: new CalendarDate(...args.end) }),
|
||||
template: (value: { start: CalendarDate, end: CalendarDate }) => {
|
||||
if (!value.start || !value.end) {
|
||||
return `{ start: null, end: null }`
|
||||
}
|
||||
|
||||
return `{ start: new CalendarDate(${value.start.year}, ${value.start.month}, ${value.start.day}), end: new CalendarDate(${value.end.year}, ${value.end.month}, ${value.end.day}) }`
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const props = defineProps<{
|
||||
/** Override the slug taken from the route */
|
||||
slug?: string
|
||||
@@ -18,6 +51,8 @@ const props = defineProps<{
|
||||
external?: string[]
|
||||
/** List of props to use with `v-model` */
|
||||
model?: string[]
|
||||
/** List of props to cast from code and selection */
|
||||
cast?: { [key: string]: string }
|
||||
/** List of items for each prop */
|
||||
items?: { [key: string]: string[] }
|
||||
props?: { [key: string]: any }
|
||||
@@ -45,7 +80,17 @@ const camelName = camelCase(props.slug ?? route.params.slug?.[route.params.slug.
|
||||
const name = `U${upperFirst(camelName)}`
|
||||
const component = defineAsyncComponent(() => import(`#ui/components/${upperFirst(camelName)}.vue`))
|
||||
|
||||
const componentProps = reactive({ ...(props.props || {}) })
|
||||
const componentProps = reactive({
|
||||
...Object.fromEntries(Object.entries(props.props || {}).map(([key, value]) => {
|
||||
const cast = props.cast?.[key]
|
||||
|
||||
if (cast && !castMap[cast]) {
|
||||
throw new Error(`Unknown cast: ${cast}`)
|
||||
}
|
||||
|
||||
return [key, cast ? castMap[cast]!.get(value) : value]
|
||||
}))
|
||||
})
|
||||
const componentEvents = reactive({
|
||||
...Object.fromEntries((props.model || []).map(key => [`onUpdate:${key}`, (e: any) => setComponentProp(key, e)])),
|
||||
...(componentProps.modelValue ? { [`onUpdate:modelValue`]: (e: any) => setComponentProp('modelValue', e) } : {})
|
||||
@@ -93,12 +138,10 @@ const options = computed(() => {
|
||||
chip: key.toLowerCase().endsWith('color') ? { color: variant } : undefined
|
||||
}))
|
||||
|
||||
// TODO: process "undefined | Date | DateRange", https://github.com/nuxt/ui/issues/2651
|
||||
|
||||
return {
|
||||
name: key,
|
||||
label: key,
|
||||
type: prop?.type,
|
||||
type: props?.cast?.[key] ?? prop?.type,
|
||||
items
|
||||
}
|
||||
})
|
||||
@@ -119,7 +162,10 @@ const code = computed(() => {
|
||||
<script setup lang="ts">
|
||||
`
|
||||
for (const key of props.external) {
|
||||
code += `const ${key === 'modelValue' ? 'value' : key} = ref(${json5.stringify(componentProps[key], null, 2).replace(/,([ |\t\n]+[}|\]])/g, '$1')})
|
||||
const cast = props.cast?.[key]
|
||||
const value = cast ? castMap[cast]!.template(componentProps[key]) : json5.stringify(componentProps[key], null, 2).replace(/,([ |\t\n]+[}|\]])/g, '$1')
|
||||
|
||||
code += `const ${key === 'modelValue' ? 'value' : key} = ref(${value})
|
||||
`
|
||||
}
|
||||
code += `<\/script>
|
||||
|
||||
@@ -21,10 +21,31 @@ Use the `v-model` directive to control the selected date.
|
||||
|
||||
::component-code
|
||||
---
|
||||
cast:
|
||||
modelValue: DateValue
|
||||
ignore:
|
||||
- modelValue
|
||||
external:
|
||||
- modelValue
|
||||
props:
|
||||
modelValue: [2022, 2, 3]
|
||||
---
|
||||
::
|
||||
|
||||
<!-- TODO: Add example with default value -->
|
||||
Use the `default-value` prop to set the initial value when you do not need to control its state.
|
||||
|
||||
::component-code
|
||||
---
|
||||
cast:
|
||||
defaultValue: DateValue
|
||||
ignore:
|
||||
- defaultValue
|
||||
external:
|
||||
- defaultValue
|
||||
props:
|
||||
defaultValue: [2022, 2, 6]
|
||||
---
|
||||
::
|
||||
|
||||
### Multiple
|
||||
|
||||
@@ -32,10 +53,17 @@ Use the `multiple` prop to allow multiple selections.
|
||||
|
||||
::component-code
|
||||
---
|
||||
prettier: true
|
||||
cast:
|
||||
modelValue: DateValue[]
|
||||
ignore:
|
||||
- multiple
|
||||
- modelValue
|
||||
external:
|
||||
- modelValue
|
||||
props:
|
||||
multiple: true
|
||||
modelValue: [[2022, 2, 4], [2022, 2, 6], [2022, 2, 8]]
|
||||
---
|
||||
::
|
||||
|
||||
@@ -45,10 +73,20 @@ Use the `range` prop to select a range of dates.
|
||||
|
||||
::component-code
|
||||
---
|
||||
prettier: true
|
||||
cast:
|
||||
modelValue: DateRange
|
||||
ignore:
|
||||
- range
|
||||
- modelValue.start
|
||||
- modelValue.end
|
||||
external:
|
||||
- modelValue
|
||||
props:
|
||||
range: true
|
||||
modelValue:
|
||||
start: [2022, 2, 3]
|
||||
end: [2022, 2, 20]
|
||||
---
|
||||
::
|
||||
|
||||
|
||||
Reference in New Issue
Block a user