diff --git a/packages/element/docs/demos/guide/checkbox/template.vue b/packages/element/docs/demos/guide/checkbox/template.vue index 42e1c51daf8..ac657da5df5 100644 --- a/packages/element/docs/demos/guide/checkbox/template.vue +++ b/packages/element/docs/demos/guide/checkbox/template.vue @@ -14,8 +14,12 @@ { label: '选项2', value: 2 }, ]" :decorator="[FormItem]" - :component="[Checkbox.Group]" - /> + :component="[Checkbox.Group, { optionType: 'button' }]" + > + + 提交 diff --git a/packages/element/docs/demos/guide/form-item/size.vue b/packages/element/docs/demos/guide/form-item/size.vue index bb1982b3258..485ec8ba7d3 100644 --- a/packages/element/docs/demos/guide/form-item/size.vue +++ b/packages/element/docs/demos/guide/form-item/size.vue @@ -5,7 +5,7 @@ name="size" title="Radio.Group" x-decorator="FormItem" - x-component="RadioGroup" + x-component="Radio.Group" :enum="[ { value: 'small', label: 'Small' }, { value: 'default', label: 'Default' }, @@ -106,7 +106,7 @@ import { DatePicker, Switch, InputNumber, - RadioGroup, + Radio, } from '@formily/element' const Div = { @@ -139,7 +139,7 @@ const fields = createSchemaField({ DatePicker, Switch, InputNumber, - RadioGroup, + Radio, Div, }, }) diff --git a/packages/element/docs/demos/guide/form-step/markup-schema.vue b/packages/element/docs/demos/guide/form-step/markup-schema.vue index 0dcee315251..04fa7af2cfc 100644 --- a/packages/element/docs/demos/guide/form-step/markup-schema.vue +++ b/packages/element/docs/demos/guide/form-step/markup-schema.vue @@ -88,7 +88,7 @@ const SchemaField = createSchemaField({ Input, }, }) -const formStep = FormStep.createFormStep +const formStep = FormStep.createFormStep() export default { components: { diff --git a/packages/element/docs/demos/guide/radio/json-schema.vue b/packages/element/docs/demos/guide/radio/json-schema.vue index 4fa15ae7a6d..107f21c8c33 100644 --- a/packages/element/docs/demos/guide/radio/json-schema.vue +++ b/packages/element/docs/demos/guide/radio/json-schema.vue @@ -38,6 +38,9 @@ export default { ], 'x-decorator': 'FormItem', 'x-component': 'Radio.Group', + 'x-component-props': { + optionType: 'button', + }, }, }, } diff --git a/packages/element/docs/demos/guide/space/json-schema.vue b/packages/element/docs/demos/guide/space/json-schema.vue index ebaf0b3da62..d1dba313134 100644 --- a/packages/element/docs/demos/guide/space/json-schema.vue +++ b/packages/element/docs/demos/guide/space/json-schema.vue @@ -17,7 +17,6 @@ import { FormLayout, FormItem, Input, - TextArea, Submit, Space, } from '@formily/element' @@ -27,7 +26,6 @@ const { SchemaField } = createSchemaField({ FormLayout, FormItem, Input, - TextArea, Space, }, }) @@ -112,7 +110,7 @@ export default { type: 'string', title: '文本框', 'x-decorator': 'FormItem', - 'x-component': 'TextArea', + 'x-component': 'Input.TextArea', 'x-component-props': { style: { width: 400, diff --git a/packages/element/docs/guide/checkbox.md b/packages/element/docs/guide/checkbox.md index 435e263a8f1..a6a36d59236 100644 --- a/packages/element/docs/guide/checkbox.md +++ b/packages/element/docs/guide/checkbox.md @@ -20,6 +20,7 @@ ### 扩展属性 -| 属性名 | 类型 | 描述 | 默认值 | -| ------- | ------------------------------------------------------------------------------------------ | ---- | ------ | -| options | [CheckboxProps](https://element.eleme.io/#/zh-CN/component/checkbox#checkbox-attributes)[] | 选项 | [] | +| 属性名 | 类型 | 描述 | 默认值 | +| ---------- | ------------------------------------------------------------------------------------------ | -------- | ------- | +| options | [CheckboxProps](https://element.eleme.io/#/zh-CN/component/checkbox#checkbox-attributes)[] | 选项 | [] | +| optionType | default/button | 样式类型 | default | diff --git a/packages/element/docs/guide/radio.md b/packages/element/docs/guide/radio.md index b9dc537cd1b..fff7df3b7c5 100644 --- a/packages/element/docs/guide/radio.md +++ b/packages/element/docs/guide/radio.md @@ -20,6 +20,7 @@ ### 扩展属性 -| 属性名 | 类型 | 描述 | 默认值 | -| ------- | --------------------------------------------------------------------------------- | ---- | ------ | -| options | [RadioProps](https://element.eleme.io/#/zh-CN/component/radio#radio-attributes)[] | 选项 | [] | +| 属性名 | 类型 | 描述 | 默认值 | +| ---------- | --------------------------------------------------------------------------------- | -------- | ------- | +| options | [RadioProps](https://element.eleme.io/#/zh-CN/component/radio#radio-attributes)[] | 选项 | [] | +| optionType | default/button | 样式类型 | default | diff --git a/packages/element/src/__builtins__/shared/index.ts b/packages/element/src/__builtins__/shared/index.ts index 113e5b0c72e..d7b9d7e4ddd 100644 --- a/packages/element/src/__builtins__/shared/index.ts +++ b/packages/element/src/__builtins__/shared/index.ts @@ -4,3 +4,4 @@ export * from './create-context' export * from './utils' export * from './portal' export * from './loading' +export * from './types' diff --git a/packages/element/src/__builtins__/shared/resolve-component.ts b/packages/element/src/__builtins__/shared/resolve-component.ts index ea4e99d6001..9eec7b3b0b4 100644 --- a/packages/element/src/__builtins__/shared/resolve-component.ts +++ b/packages/element/src/__builtins__/shared/resolve-component.ts @@ -2,11 +2,20 @@ import { h, toRaw } from '@vue/composition-api' import { Component, VNode } from 'vue' export const resolveComponent = ( - child?: Component | string | number | ((...args: any[]) => VNode[] | VNode), + child?: + | Component + | string + | number + | boolean + | ((...args: any[]) => VNode[] | VNode), props?: Record ) => { if (child) { - if (typeof child === 'string' || typeof child === 'number') { + if ( + typeof child === 'string' || + typeof child === 'number' || + typeof child === 'boolean' + ) { return child } else if (typeof child === 'function') { return (child as Function)(props) diff --git a/packages/element/src/__builtins__/shared/types.ts b/packages/element/src/__builtins__/shared/types.ts new file mode 100644 index 00000000000..2daff0509a4 --- /dev/null +++ b/packages/element/src/__builtins__/shared/types.ts @@ -0,0 +1,8 @@ +import { Component, VNode } from 'vue' + +export type SlotTypes = + | Component + | string + | number + | ((props: Record) => VNode[] | VNode) + | VNode diff --git a/packages/element/src/checkbox/index.ts b/packages/element/src/checkbox/index.ts index c83d93d08b5..da22fa269de 100644 --- a/packages/element/src/checkbox/index.ts +++ b/packages/element/src/checkbox/index.ts @@ -1,6 +1,11 @@ import { connect, mapProps, h, mapReadPretty } from '@formily/vue' -import { defineComponent } from '@vue/composition-api' -import { composeExport, getComponentByTag } from '../__builtins__/shared' +import { defineComponent, PropType } from '@vue/composition-api' +import { + composeExport, + getComponentByTag, + resolveComponent, + SlotTypes, +} from '../__builtins__/shared' import type { Checkbox as _ElCheckboxProps, CheckboxGroup as ElCheckboxGroupProps, @@ -8,6 +13,7 @@ import type { import { Checkbox as ElCheckbox, CheckboxGroup as ElCheckboxGroup, + CheckboxButton as ElCheckboxButton, } from 'element-ui' import { PreviewText } from '../preview-text' @@ -18,12 +24,13 @@ type ElCheckboxProps = Omit<_ElCheckboxProps, 'value'> & { export interface CheckboxProps extends ElCheckboxProps { option: Omit<_ElCheckboxProps, 'value'> & { value: ElCheckboxProps['label'] - label: string + label: SlotTypes } } const CheckboxOption = defineComponent({ name: 'Checkbox', + inheritAttrs: false, props: { option: { type: Object, @@ -35,16 +42,18 @@ const CheckboxOption = defineComponent({ const props = attrs as unknown as CheckboxProps const option = curtomProps?.option if (option) { - const children = option.label - ? { default: () => [option.label] } - : slots + const children = { + default: () => [ + resolveComponent(slots.default ?? option.label, { option }), + ], + } const newProps = {} as Partial Object.assign(newProps, option) newProps.label = option.value delete newProps.value return h( - ElCheckbox, + attrs.optionType === 'button' ? ElCheckboxButton : ElCheckbox, { attrs: { ...newProps, @@ -71,6 +80,7 @@ const CheckboxOption = defineComponent({ export type CheckboxGroupProps = ElCheckboxGroupProps & { value: any[] options?: Array + optionType: 'default' | 'button' } const TransformElCheckboxGroup = getComponentByTag(ElCheckboxGroup, { @@ -84,6 +94,10 @@ const CheckboxGroupOption = defineComponent({ type: Array, default: () => [], }, + optionType: { + type: String as PropType, + default: 'default', + }, }, setup(customProps, { attrs, slots, listeners }) { return () => { @@ -96,11 +110,36 @@ const CheckboxGroupOption = defineComponent({ if (typeof option === 'string') { return h( Checkbox, - { props: { option: { label: option, value: option } } }, - {} + { + props: { + option: { + label: option, + value: option, + }, + }, + attrs: { + optionType: customProps.optionType, + }, + }, + slots?.option + ? { default: () => slots.option({ option }) } + : {} ) } else { - return h(Checkbox, { props: { option } }, {}) + return h( + Checkbox, + { + props: { + option, + }, + attrs: { + optionType: customProps.optionType, + }, + }, + slots?.option + ? { default: () => slots.option({ option }) } + : {} + ) } }), } diff --git a/packages/element/src/form-item/index.ts b/packages/element/src/form-item/index.ts index 98ecb799ee5..98b7f7e3823 100644 --- a/packages/element/src/form-item/index.ts +++ b/packages/element/src/form-item/index.ts @@ -107,17 +107,17 @@ export const FormBaseItem = defineComponent({ className: {}, required: {}, label: {}, - colon: { default: true }, + colon: {}, layout: {}, tooltip: {}, labelStyle: {}, labelAlign: {}, - labelWrap: { default: false }, + labelWrap: {}, labelWidth: {}, wrapperWidth: {}, labelCol: {}, wrapperCol: {}, - wrapperAlign: { default: 'left' }, + wrapperAlign: {}, wrapperWrap: {}, wrapperStyle: {}, fullness: {}, @@ -151,16 +151,16 @@ export const FormBaseItem = defineComponent({ return () => { const { label, - colon, + colon = deepLayout.colon ?? true, layout = deepLayout.layout ?? 'horizontal', tooltip, labelStyle = {}, - labelWrap = deepLayout.labelWrap, + labelWrap = deepLayout.labelWrap ?? false, labelWidth = deepLayout.labelWidth, wrapperWidth = deepLayout.wrapperWidth, labelCol = deepLayout.labelCol, wrapperCol = deepLayout.wrapperCol, - wrapperAlign = deepLayout.wrapperAlign, + wrapperAlign = deepLayout.wrapperAlign ?? 'left', wrapperWrap = deepLayout.wrapperWrap, wrapperStyle = {}, fullness = deepLayout.fullness, diff --git a/packages/element/src/form-item/style.scss b/packages/element/src/form-item/style.scss index 2962eb7199f..a1c73d64b22 100644 --- a/packages/element/src/form-item/style.scss +++ b/packages/element/src/form-item/style.scss @@ -316,7 +316,7 @@ } .#{$form-item-prefix}-colon { - margin-left: 4px / 2; + margin-left: 2px; margin-right: 8px; } diff --git a/packages/element/src/radio/index.ts b/packages/element/src/radio/index.ts index 55cb99b660f..fcf498ca2e2 100644 --- a/packages/element/src/radio/index.ts +++ b/packages/element/src/radio/index.ts @@ -1,19 +1,32 @@ import { connect, mapProps, h, mapReadPretty } from '@formily/vue' -import { defineComponent } from '@vue/composition-api' -import { composeExport, getComponentByTag } from '../__builtins__/shared' +import { defineComponent, PropType } from '@vue/composition-api' +import { + composeExport, + getComponentByTag, + resolveComponent, + SlotTypes, +} from '../__builtins__/shared' import { PreviewText } from '../preview-text' import type { Radio as ElRadioProps, RadioGroup as ElRadioGroupProps, } from 'element-ui' -import { Radio as ElRadio, RadioGroup as ElRadioGroup } from 'element-ui' +import { + Radio as ElRadio, + RadioGroup as ElRadioGroup, + RadioButton, +} from 'element-ui' export type RadioGroupProps = ElRadioGroupProps & { value: any - options?: (Omit & { - value: ElRadioProps['label'] - label: string - })[] + options?: ( + | (Omit & { + value: ElRadioProps['label'] + label: SlotTypes + }) + | string + )[] + optionType: 'defalt' | 'button' } export type RadioProps = ElRadioProps @@ -26,13 +39,19 @@ const RadioGroupOption = defineComponent({ name: 'FRadioGroup', props: { options: { - type: Array, + type: Array as PropType, default: () => [], }, + optionType: { + type: String as PropType, + default: 'default', + }, }, setup(customProps, { attrs, slots, listeners }) { return () => { const options = customProps.options || [] + const OptionType = + customProps.optionType === 'button' ? RadioButton : ElRadio const children = options.length !== 0 ? { @@ -40,13 +59,17 @@ const RadioGroupOption = defineComponent({ options.map((option) => { if (typeof option === 'string') { return h( - ElRadio, + OptionType, { props: { label: option } }, - { default: () => [option] } + { + default: () => [ + resolveComponent(slots?.option ?? option, { option }), + ], + } ) } else { return h( - ElRadio, + OptionType, { props: { ...option, @@ -54,7 +77,13 @@ const RadioGroupOption = defineComponent({ label: option.value, }, }, - { default: () => [option.label] } + { + default: () => [ + resolveComponent(slots?.option ?? option.label, { + option, + }), + ], + } ) } }),