From 15ca2f5701fd51de94282022dc7bc0fc3c1705da Mon Sep 17 00:00:00 2001 From: Alex Date: Tue, 26 Nov 2024 20:13:47 +0500 Subject: [PATCH] docs(ComponentCode): add `cast` prop (#2773) --- docs/app/components/content/ComponentCode.vue | 56 +++++++++++++++++-- docs/content/3.components/calendar.md | 40 ++++++++++++- 2 files changed, 90 insertions(+), 6 deletions(-) diff --git a/docs/app/components/content/ComponentCode.vue b/docs/app/components/content/ComponentCode.vue index 08746c80..614acf65 100644 --- a/docs/app/components/content/ComponentCode.vue +++ b/docs/app/components/content/ComponentCode.vue @@ -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 = { + '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(() => {