This repository has been archived by the owner on Aug 28, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 152
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: add description component demo (#327)
- Loading branch information
1 parent
daad5aa
commit 385e1c2
Showing
11 changed files
with
2,165 additions
and
1,285 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
<script lang="ts" setup> | ||
import { Description, DescItem, useDescription } from '@vben/components' | ||
const mockData: Recordable = { | ||
username: 'test', | ||
nickName: 'VB', | ||
age: '123', | ||
phone: '15695909xxx', | ||
email: '[email protected]', | ||
addr: '厦门市思明区', | ||
sex: '男', | ||
certy: '3504256199xxxxxxxxx', | ||
tag: 'orange', | ||
} | ||
const schema: DescItem[] = [ | ||
{ | ||
field: 'username', | ||
label: '用户名', | ||
}, | ||
{ | ||
field: 'nickName', | ||
label: '昵称', | ||
render: (curVal, data) => { | ||
return `${data.username}-${curVal}` | ||
}, | ||
}, | ||
{ | ||
field: 'phone', | ||
label: '联系电话', | ||
}, | ||
{ | ||
field: 'email', | ||
label: '邮箱', | ||
}, | ||
{ | ||
field: 'addr', | ||
label: '地址', | ||
}, | ||
] | ||
const [register] = useDescription({ | ||
title: 'useDescription', | ||
data: mockData, | ||
schema: schema, | ||
labelPlacement: 'left', | ||
}) | ||
const [register1] = useDescription({ | ||
title: '无边框', | ||
bordered: false, | ||
data: mockData, | ||
schema: schema, | ||
labelPlacement: 'left', | ||
}) | ||
</script> | ||
|
||
<template> | ||
<VbenCard title="详情组件示例"> | ||
<Description | ||
title="基础示例" | ||
:column="3" | ||
label-placement="left" | ||
:data="mockData" | ||
:schema="schema" | ||
/> | ||
|
||
<Description | ||
class="mt-4" | ||
title="垂直示例" | ||
:column="2" | ||
:data="mockData" | ||
:schema="schema" | ||
/> | ||
|
||
<Description @register="register" class="mt-4" /> | ||
<Description @register="register1" class="mt-4" /> | ||
</VbenCard> | ||
</template> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,174 @@ | ||
<script lang="tsx"> | ||
import type { DescriptionProps, DescInstance, DescItem } from './typing' | ||
import { | ||
type CSSProperties, | ||
type PropType, | ||
defineComponent, | ||
computed, | ||
ref, | ||
unref, | ||
toRefs, | ||
useAttrs, | ||
} from 'vue' | ||
import { getSlot, isFunction, get } from '@vben/utils' | ||
const props = { | ||
useContainer: { type: Boolean, default: true }, | ||
title: { type: String, default: '' }, | ||
size: { | ||
type: String, | ||
validator: (v: string) => | ||
['small', 'medium', 'large', undefined].includes(v), | ||
default: 'medium', | ||
}, | ||
bordered: { type: Boolean, default: true }, | ||
column: { | ||
type: Number, | ||
default: 3, | ||
}, | ||
schema: { | ||
type: Array as PropType<DescItem[]>, | ||
default: () => [], | ||
}, | ||
data: { type: Object }, | ||
} | ||
export default defineComponent({ | ||
name: 'Description', | ||
props, | ||
emits: ['register'], | ||
setup(props, { slots, emit }) { | ||
const propsRef = ref<Partial<DescriptionProps> | null>(null) | ||
const attrs = useAttrs() | ||
// Custom title component: get title | ||
const getMergeProps = computed(() => { | ||
return { | ||
...props, | ||
...(unref(propsRef) as any), | ||
} | ||
}) | ||
const getProps = computed(() => { | ||
const opt = { | ||
...unref(getMergeProps), | ||
title: undefined, | ||
} | ||
return opt as DescriptionProps | ||
}) | ||
/** | ||
* @description: Whether to setting title | ||
*/ | ||
const useWrapper = computed(() => !!unref(getMergeProps).title) | ||
const getDescriptionsProps = computed(() => { | ||
return { ...unref(attrs), ...unref(getProps) } | ||
}) | ||
/** | ||
* @description:设置desc | ||
*/ | ||
function setDescProps(descProps: Partial<DescriptionProps>): void { | ||
// Keep the last setDrawerProps | ||
propsRef.value = { | ||
...(unref(propsRef) as Record<string, any>), | ||
...descProps, | ||
} as Record<string, any> | ||
} | ||
// Prevent line breaks | ||
function renderLabel({ label, labelMinWidth, labelStyle }: DescItem) { | ||
if (!labelStyle && !labelMinWidth) { | ||
return label | ||
} | ||
const labelStyles: CSSProperties = { | ||
...labelStyle, | ||
minWidth: `${labelMinWidth}px `, | ||
} | ||
return <div style={labelStyles}>{label}</div> | ||
} | ||
function renderItem() { | ||
const { schema, data } = unref(getProps) | ||
return unref(schema) | ||
.map((item) => { | ||
const { render, field, span, show, contentMinWidth } = item | ||
if (show && isFunction(show) && !show(data)) { | ||
return null | ||
} | ||
const getContent = () => { | ||
const _data = unref(getProps)?.data | ||
if (!_data) { | ||
return null | ||
} | ||
const getField = get(_data, field) | ||
// eslint-disable-next-line | ||
if (getField && !_data.hasOwnProperty(field)) { | ||
return isFunction(render) ? render('', _data) : '' | ||
} | ||
return isFunction(render) ? render(getField, _data) : getField ?? '' | ||
} | ||
const width = contentMinWidth | ||
return ( | ||
<VbenDescItem label={renderLabel(item)} key={field} span={span}> | ||
{() => { | ||
if (!contentMinWidth) { | ||
return getContent() | ||
} | ||
const style: CSSProperties = { | ||
minWidth: `${width}px`, | ||
} | ||
return <div style={style}>{getContent()}</div> | ||
}} | ||
</VbenDescItem> | ||
) | ||
}) | ||
.filter((item) => !!item) | ||
} | ||
const renderDesc = () => { | ||
return ( | ||
<VbenDesc class="description" {...(unref(getDescriptionsProps) as any)}> | ||
{renderItem()} | ||
</VbenDesc> | ||
) | ||
} | ||
const renderContainer = () => { | ||
const content = props.useContainer ? ( | ||
renderDesc() | ||
) : ( | ||
<div>{renderDesc()}</div> | ||
) | ||
// Reduce the dom level | ||
if (!props.useContainer) { | ||
return content | ||
} | ||
const { title } = unref(getMergeProps) | ||
return ( | ||
<vben-card title={title}> | ||
{{ | ||
default: () => content, | ||
action: () => getSlot(slots, 'action'), | ||
}} | ||
</vben-card> | ||
) | ||
} | ||
const methods: DescInstance = { | ||
setDescProps, | ||
} | ||
emit('register', methods) | ||
return () => (unref(useWrapper) ? renderContainer() : renderDesc()) | ||
}, | ||
}) | ||
</script> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
import type { VNode, CSSProperties } from 'vue' | ||
|
||
declare type Recordable<T = any> = Record<string, T> | ||
|
||
export interface DescItem { | ||
labelMinWidth?: number | ||
contentMinWidth?: number | ||
labelStyle?: CSSProperties | ||
field: string | ||
label: string | VNode | JSX.Element | ||
// Merge column | ||
span?: number | ||
show?: (...arg: any) => boolean | ||
// render | ||
render?: ( | ||
val: any, | ||
data: Recordable, | ||
) => VNode | undefined | JSX.Element | Element | string | number | ||
} | ||
|
||
export interface DescriptionProps { | ||
useContainer?: boolean | ||
/** | ||
* item configuration | ||
* @type DescItem | ||
*/ | ||
schema: DescItem[] | ||
/** | ||
* 数据 | ||
* @type object | ||
*/ | ||
data: Recordable | ||
} | ||
|
||
export interface DescInstance { | ||
setDescProps(descProps: Partial<DescriptionProps>): void | ||
} | ||
|
||
export type Register = (descInstance: DescInstance) => void | ||
|
||
/** | ||
* @description: | ||
*/ | ||
export type UseDescReturnType = [Register, DescInstance] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
import type { | ||
DescriptionProps, | ||
DescInstance, | ||
UseDescReturnType, | ||
} from './typing' | ||
import { ref, getCurrentInstance, unref } from 'vue' | ||
import { isProdMode } from '@vben/utils' | ||
|
||
export function useDescription( | ||
props?: Partial<DescriptionProps>, | ||
): UseDescReturnType { | ||
if (!getCurrentInstance()) { | ||
throw new Error( | ||
'useDescription() can only be used inside setup() or functional components!', | ||
) | ||
} | ||
const desc = ref<Nullable<DescInstance>>(null) | ||
const loaded = ref(false) | ||
|
||
function register(instance: DescInstance) { | ||
if (unref(loaded) && isProdMode()) { | ||
return | ||
} | ||
desc.value = instance | ||
props && instance.setDescProps(props) | ||
loaded.value = true | ||
} | ||
|
||
const methods: DescInstance = { | ||
setDescProps: (descProps: Partial<DescriptionProps>): void => { | ||
unref(desc)?.setDescProps(descProps) | ||
}, | ||
} | ||
|
||
return [register, methods] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -96,5 +96,6 @@ export default { | |
steps: { | ||
page: 'Intro page', | ||
}, | ||
desc: 'Desc', | ||
}, | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -97,5 +97,6 @@ export default { | |
steps: { | ||
page: '引导页', | ||
}, | ||
desc: '详情组件', | ||
}, | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.