mirror of
https://gitee.com/baidu/amis.git
synced 2024-11-29 18:48:45 +08:00
feat: checkbox\radios支持外观配置 (#11095)
Co-authored-by: qinhaoyan <30946345+qinhaoyan@users.noreply.github.com>
This commit is contained in:
parent
dc8dcc6828
commit
75b3e03b29
@ -21,6 +21,7 @@ import {ValidatorTag} from '../../validator';
|
||||
import {RendererPluginAction, RendererPluginEvent} from 'amis-editor-core';
|
||||
import {getEventControlConfig} from '../../renderer/event-control/helper';
|
||||
import omit from 'lodash/omit';
|
||||
import {inputStateTpl} from '../../renderer/style-control/helper';
|
||||
|
||||
setSchemaTpl('option', {
|
||||
name: 'option',
|
||||
@ -45,7 +46,8 @@ export class CheckboxControlPlugin extends BasePlugin {
|
||||
scaffold = {
|
||||
type: 'checkbox',
|
||||
option: '勾选框',
|
||||
name: 'checkbox'
|
||||
name: 'checkbox',
|
||||
label: '勾选框'
|
||||
};
|
||||
previewSchema: any = {
|
||||
type: 'form',
|
||||
@ -227,7 +229,70 @@ export class CheckboxControlPlugin extends BasePlugin {
|
||||
title: '外观',
|
||||
body: [
|
||||
getSchemaTpl('collapseGroup', [
|
||||
getSchemaTpl('style:formItem', {renderer: context.info.renderer}),
|
||||
getSchemaTpl('theme:formItem', {hidSize: true}),
|
||||
getSchemaTpl('theme:form-label'),
|
||||
getSchemaTpl('theme:form-description'),
|
||||
{
|
||||
title: '勾选框样式',
|
||||
body: [
|
||||
...inputStateTpl('themeCss.checkboxClassName', '--checkbox', {
|
||||
hideFont: true,
|
||||
hideMargin: true,
|
||||
hidePadding: true,
|
||||
state: [
|
||||
{
|
||||
label: '常规',
|
||||
value: 'checkbox-default'
|
||||
},
|
||||
{
|
||||
label: '悬浮',
|
||||
value: 'checkbox-hover'
|
||||
},
|
||||
{
|
||||
label: '禁用',
|
||||
value: 'checkbox-disabled'
|
||||
},
|
||||
{
|
||||
label: '选中',
|
||||
value: 'checked-default'
|
||||
},
|
||||
{
|
||||
label: '选中态悬浮',
|
||||
value: 'checked-hover'
|
||||
},
|
||||
{
|
||||
label: '选中禁用',
|
||||
value: 'checked-disabled'
|
||||
}
|
||||
]
|
||||
})
|
||||
]
|
||||
},
|
||||
{
|
||||
title: '选项说明样式',
|
||||
body: [
|
||||
...inputStateTpl('themeCss.checkboxLabelClassName', '', {
|
||||
hidePadding: true,
|
||||
hideRadius: true,
|
||||
hideBorder: true,
|
||||
state: [
|
||||
{
|
||||
label: '常规',
|
||||
value: 'default'
|
||||
},
|
||||
{
|
||||
label: '悬浮',
|
||||
value: 'hover'
|
||||
},
|
||||
{
|
||||
label: '禁用',
|
||||
value: 'disabled'
|
||||
}
|
||||
]
|
||||
})
|
||||
]
|
||||
},
|
||||
getSchemaTpl('theme:cssCode'),
|
||||
getSchemaTpl('style:classNames')
|
||||
])
|
||||
]
|
||||
|
@ -13,6 +13,7 @@ import {getEventControlConfig} from '../../renderer/event-control/helper';
|
||||
import {RendererPluginAction, RendererPluginEvent} from 'amis-editor-core';
|
||||
import {resolveOptionEventDataSchame, resolveOptionType} from '../../util';
|
||||
import type {Schema, SchemaType} from 'amis';
|
||||
import {inputStateTpl} from '../../renderer/style-control/helper';
|
||||
|
||||
export class RadiosControlPlugin extends BasePlugin {
|
||||
static id = 'RadiosControlPlugin';
|
||||
@ -157,8 +158,8 @@ export class RadiosControlPlugin extends BasePlugin {
|
||||
title: '外观',
|
||||
body: [
|
||||
getSchemaTpl('collapseGroup', [
|
||||
getSchemaTpl('style:formItem', {
|
||||
renderer: context.info.renderer,
|
||||
getSchemaTpl('theme:formItem', {
|
||||
hidSize: true,
|
||||
schema: [
|
||||
getSchemaTpl('switch', {
|
||||
label: '一行选项显示',
|
||||
@ -177,6 +178,92 @@ export class RadiosControlPlugin extends BasePlugin {
|
||||
}
|
||||
]
|
||||
}),
|
||||
getSchemaTpl('theme:form-label'),
|
||||
getSchemaTpl('theme:form-description'),
|
||||
{
|
||||
title: '单选框样式',
|
||||
body: [
|
||||
...inputStateTpl('themeCss.radiosClassName', '--radio', {
|
||||
hideFont: true,
|
||||
hideMargin: true,
|
||||
hidePadding: true,
|
||||
state: [
|
||||
{
|
||||
label: '常规',
|
||||
value: 'radios-default'
|
||||
},
|
||||
{
|
||||
label: '悬浮',
|
||||
value: 'radios-hover'
|
||||
},
|
||||
{
|
||||
label: '禁用',
|
||||
value: 'radios-disabled'
|
||||
},
|
||||
{
|
||||
label: '选中',
|
||||
value: 'checked-default'
|
||||
},
|
||||
{
|
||||
label: '选中态悬浮',
|
||||
value: 'checked-hover'
|
||||
},
|
||||
{
|
||||
label: '选中禁用',
|
||||
value: 'checked-disabled'
|
||||
}
|
||||
],
|
||||
schema: [
|
||||
getSchemaTpl('theme:colorPicker', {
|
||||
name: 'themeCss.radiosCheckedInnerClassName.background:default',
|
||||
labelMode: 'input',
|
||||
label: '圆点颜色',
|
||||
visibleOn:
|
||||
"${__editorStatethemeCss.radiosClassName == 'checked-default'}"
|
||||
}),
|
||||
getSchemaTpl('theme:colorPicker', {
|
||||
name: 'themeCss.radiosCheckedInnerClassName.background:hover',
|
||||
labelMode: 'input',
|
||||
label: '圆点颜色',
|
||||
visibleOn:
|
||||
"${__editorStatethemeCss.radiosClassName == 'checked-hover'}"
|
||||
}),
|
||||
getSchemaTpl('theme:colorPicker', {
|
||||
name: 'themeCss.radiosCheckedInnerClassName.background:disabled',
|
||||
labelMode: 'input',
|
||||
label: '圆点颜色',
|
||||
visibleOn:
|
||||
"${__editorStatethemeCss.radiosClassName == 'checked-disabled'}"
|
||||
})
|
||||
]
|
||||
})
|
||||
]
|
||||
},
|
||||
{
|
||||
title: '选项说明样式',
|
||||
body: [
|
||||
...inputStateTpl('themeCss.radiosLabelClassName', '', {
|
||||
hidePadding: true,
|
||||
hideRadius: true,
|
||||
hideBorder: true,
|
||||
state: [
|
||||
{
|
||||
label: '常规',
|
||||
value: 'default'
|
||||
},
|
||||
{
|
||||
label: '悬浮',
|
||||
value: 'hover'
|
||||
},
|
||||
{
|
||||
label: '禁用',
|
||||
value: 'disabled'
|
||||
}
|
||||
]
|
||||
})
|
||||
]
|
||||
},
|
||||
getSchemaTpl('theme:cssCode'),
|
||||
getSchemaTpl('style:classNames', {
|
||||
schema: [
|
||||
getSchemaTpl('className', {
|
||||
|
@ -1,21 +1,23 @@
|
||||
import {getSchemaTpl} from 'amis-editor-core';
|
||||
interface InputStateOptions {
|
||||
state?: {
|
||||
label: string;
|
||||
value: string;
|
||||
token?: string;
|
||||
}[];
|
||||
hideFont?: boolean;
|
||||
hidePadding?: boolean;
|
||||
hideMargin?: boolean;
|
||||
hideRadius?: boolean;
|
||||
hideBackground?: boolean;
|
||||
hideBorder?: boolean;
|
||||
schema?: any[];
|
||||
}
|
||||
|
||||
export const inputStateTpl = (
|
||||
className: string,
|
||||
token: string = '',
|
||||
options?: {
|
||||
state?: {
|
||||
label: string;
|
||||
value: string;
|
||||
token?: string;
|
||||
}[];
|
||||
hideFont?: boolean;
|
||||
hidePadding?: boolean;
|
||||
hideMargin?: boolean;
|
||||
hideRadius?: boolean;
|
||||
hideBackground?: boolean;
|
||||
hideBorder?: boolean;
|
||||
}
|
||||
options?: InputStateOptions
|
||||
) => {
|
||||
const stateOptions = options?.state || [
|
||||
{
|
||||
@ -67,7 +69,7 @@ export const inputStateFunc = (
|
||||
state: string,
|
||||
className: string,
|
||||
token: string,
|
||||
options: any
|
||||
options?: InputStateOptions
|
||||
) => {
|
||||
const cssTokenState = state === 'focused' ? 'active' : state;
|
||||
|
||||
|
@ -127,6 +127,13 @@
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
&--flex {
|
||||
margin: calc(var(--Form-item-gap) / 2);
|
||||
&:last-child {
|
||||
margin-bottom: calc(var(--Form-item-gap) / 2);
|
||||
}
|
||||
}
|
||||
|
||||
&--inline {
|
||||
margin-right: var(--Form-mode-inline-item-gap);
|
||||
}
|
||||
@ -428,7 +435,6 @@
|
||||
flex-basis: 0;
|
||||
flex-grow: 1;
|
||||
flex-shrink: 1;
|
||||
padding: calc(var(--Form-item-gap) / 2);
|
||||
min-width: 0;
|
||||
min-height: 0;
|
||||
}
|
||||
|
@ -4,7 +4,9 @@ import {
|
||||
FormControlProps,
|
||||
FormBaseControl,
|
||||
resolveEventData,
|
||||
getVariable
|
||||
getVariable,
|
||||
setThemeClassName,
|
||||
CustomStyle
|
||||
} from 'amis-core';
|
||||
import cx from 'classnames';
|
||||
import {Checkbox} from 'amis-ui';
|
||||
@ -128,6 +130,29 @@ export default class CheckboxControl extends React.Component<
|
||||
);
|
||||
}
|
||||
|
||||
formateThemeCss(themeCss: any) {
|
||||
if (!themeCss) {
|
||||
return {};
|
||||
}
|
||||
const {checkboxClassName = {}} = themeCss;
|
||||
const defaultThemeCss: any = {};
|
||||
const checkedThemeCss: any = {};
|
||||
Object.keys(checkboxClassName).forEach(key => {
|
||||
if (key.includes('checked-')) {
|
||||
const newKey = key.replace('checked-', '');
|
||||
checkedThemeCss[newKey] = checkboxClassName[key];
|
||||
} else if (key.includes('checkbox-')) {
|
||||
const newKey = key.replace('checkbox-', '');
|
||||
defaultThemeCss[newKey] = checkboxClassName[key];
|
||||
}
|
||||
});
|
||||
return {
|
||||
...themeCss,
|
||||
checkboxClassName: defaultThemeCss,
|
||||
checkboxCheckedClassName: checkedThemeCss
|
||||
};
|
||||
}
|
||||
|
||||
@supportStatic()
|
||||
render() {
|
||||
const {
|
||||
@ -145,11 +170,39 @@ export default class CheckboxControl extends React.Component<
|
||||
checked,
|
||||
labelClassName,
|
||||
testIdBuilder,
|
||||
classPrefix: ns
|
||||
classPrefix: ns,
|
||||
id,
|
||||
env,
|
||||
themeCss
|
||||
} = this.props;
|
||||
|
||||
const css = this.formateThemeCss(themeCss);
|
||||
|
||||
return (
|
||||
<div className={cx(`${ns}CheckboxControl`, className)}>
|
||||
<div
|
||||
className={cx(
|
||||
`${ns}CheckboxControl`,
|
||||
className,
|
||||
setThemeClassName({
|
||||
...this.props,
|
||||
name: 'checkboxClassName',
|
||||
id,
|
||||
themeCss: css
|
||||
}),
|
||||
setThemeClassName({
|
||||
...this.props,
|
||||
name: 'checkboxCheckedClassName',
|
||||
id,
|
||||
themeCss: css
|
||||
}),
|
||||
setThemeClassName({
|
||||
...this.props,
|
||||
name: 'checkboxLabelClassName',
|
||||
id,
|
||||
themeCss: css
|
||||
})
|
||||
)}
|
||||
>
|
||||
<Checkbox
|
||||
inline
|
||||
value={value || ''}
|
||||
@ -165,6 +218,64 @@ export default class CheckboxControl extends React.Component<
|
||||
>
|
||||
{option ? render('option', option) : null}
|
||||
</Checkbox>
|
||||
|
||||
<CustomStyle
|
||||
{...this.props}
|
||||
config={{
|
||||
themeCss: this.formateThemeCss(themeCss),
|
||||
classNames: [
|
||||
{
|
||||
key: 'checkboxClassName',
|
||||
weights: {
|
||||
default: {
|
||||
suf: ' label',
|
||||
inner: 'i'
|
||||
},
|
||||
hover: {
|
||||
suf: ' label',
|
||||
inner: 'i'
|
||||
},
|
||||
disabled: {
|
||||
inner: `.${ns}Checkbox--checkbox input[disabled] + i`
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
key: 'checkboxCheckedClassName',
|
||||
weights: {
|
||||
default: {
|
||||
inner: `.${ns}Checkbox--checkbox input:checked + i`
|
||||
},
|
||||
hover: {
|
||||
suf: ` .${ns}Checkbox--checkbox`,
|
||||
inner: 'input:checked + i'
|
||||
},
|
||||
disabled: {
|
||||
inner: `.${ns}Checkbox--checkbox input:checked[disabled] + i`
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
key: 'checkboxLabelClassName',
|
||||
weights: {
|
||||
default: {
|
||||
suf: ' label',
|
||||
inner: 'span'
|
||||
},
|
||||
hover: {
|
||||
suf: ' label',
|
||||
inner: 'span'
|
||||
},
|
||||
disabled: {
|
||||
inner: `.${ns}Checkbox--checkbox input[disabled] + i + span`
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
id: id
|
||||
}}
|
||||
env={env}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -343,7 +343,7 @@ export default class CheckboxesControl extends React.Component<
|
||||
if (!themeCss) {
|
||||
return {};
|
||||
}
|
||||
const {checkboxesClassName} = themeCss;
|
||||
const {checkboxesClassName = {}} = themeCss;
|
||||
const defaultThemeCss: any = {};
|
||||
const checkedThemeCss: any = {};
|
||||
Object.keys(checkboxesClassName).forEach(key => {
|
||||
|
@ -8,7 +8,9 @@ import {
|
||||
FormOptionsControl,
|
||||
resolveEventData,
|
||||
TestIdBuilder,
|
||||
getVariable
|
||||
getVariable,
|
||||
setThemeClassName,
|
||||
CustomStyle
|
||||
} from 'amis-core';
|
||||
import {autobind, isEmpty, createObject} from 'amis-core';
|
||||
import {ActionObject} from 'amis-core';
|
||||
@ -105,6 +107,30 @@ export default class RadiosControl extends React.Component<RadiosProps, any> {
|
||||
return <>{typeof label === 'string' ? filter(label, data) : `${label}`}</>;
|
||||
}
|
||||
|
||||
formateThemeCss(themeCss: any) {
|
||||
if (!themeCss) {
|
||||
return {};
|
||||
}
|
||||
const {radiosClassName = {}} = themeCss;
|
||||
const defaultThemeCss: any = {};
|
||||
const checkedThemeCss: any = {};
|
||||
Object.keys(radiosClassName).forEach(key => {
|
||||
if (key.includes('checked-')) {
|
||||
const newKey = key.replace('checked-', '');
|
||||
checkedThemeCss[newKey] = radiosClassName[key];
|
||||
} else if (key.includes('radios-')) {
|
||||
const newKey = key.replace('radios-', '');
|
||||
defaultThemeCss[newKey] = radiosClassName[key];
|
||||
}
|
||||
});
|
||||
|
||||
return {
|
||||
...themeCss,
|
||||
radiosClassName: defaultThemeCss,
|
||||
radiosCheckedClassName: checkedThemeCss
|
||||
};
|
||||
}
|
||||
|
||||
@supportStatic()
|
||||
render() {
|
||||
const {
|
||||
@ -132,33 +158,139 @@ export default class RadiosControl extends React.Component<RadiosProps, any> {
|
||||
translate: __,
|
||||
optionType,
|
||||
level,
|
||||
testIdBuilder
|
||||
testIdBuilder,
|
||||
themeCss,
|
||||
id,
|
||||
env
|
||||
} = this.props;
|
||||
|
||||
const css = this.formateThemeCss(themeCss);
|
||||
|
||||
return (
|
||||
<Radios
|
||||
inline={inline || formMode === 'inline'}
|
||||
className={cx(`${ns}RadiosControl`, className)}
|
||||
value={typeof value === 'undefined' || value === null ? '' : value}
|
||||
disabled={disabled}
|
||||
onChange={this.handleChange}
|
||||
joinValues={joinValues}
|
||||
extractValue={extractValue!}
|
||||
delimiter={delimiter!}
|
||||
/** 兼容一下错误的用法 */
|
||||
labelClassName={optionClassName ?? labelClassName}
|
||||
labelField={labelField}
|
||||
valueField={valueField}
|
||||
placeholder={__(placeholder)}
|
||||
options={options}
|
||||
renderLabel={this.renderLabel}
|
||||
columnsCount={columnsCount}
|
||||
classPrefix={classPrefix}
|
||||
itemClassName={itemClassName}
|
||||
optionType={optionType}
|
||||
level={level}
|
||||
testIdBuilder={testIdBuilder}
|
||||
/>
|
||||
<>
|
||||
<Radios
|
||||
inline={inline || formMode === 'inline'}
|
||||
className={cx(
|
||||
`${ns}RadiosControl`,
|
||||
className,
|
||||
setThemeClassName({
|
||||
...this.props,
|
||||
name: 'radiosClassName',
|
||||
id,
|
||||
themeCss: css
|
||||
}),
|
||||
setThemeClassName({
|
||||
...this.props,
|
||||
name: 'radiosCheckedInnerClassName',
|
||||
id,
|
||||
themeCss: css
|
||||
}),
|
||||
setThemeClassName({
|
||||
...this.props,
|
||||
name: 'radiosCheckedClassName',
|
||||
id,
|
||||
themeCss: css
|
||||
}),
|
||||
setThemeClassName({
|
||||
...this.props,
|
||||
name: 'radiosLabelClassName',
|
||||
id,
|
||||
themeCss: css
|
||||
})
|
||||
)}
|
||||
value={typeof value === 'undefined' || value === null ? '' : value}
|
||||
disabled={disabled}
|
||||
onChange={this.handleChange}
|
||||
joinValues={joinValues}
|
||||
extractValue={extractValue!}
|
||||
delimiter={delimiter!}
|
||||
/** 兼容一下错误的用法 */
|
||||
labelClassName={optionClassName ?? labelClassName}
|
||||
labelField={labelField}
|
||||
valueField={valueField}
|
||||
placeholder={__(placeholder)}
|
||||
options={options}
|
||||
renderLabel={this.renderLabel}
|
||||
columnsCount={columnsCount}
|
||||
classPrefix={classPrefix}
|
||||
itemClassName={itemClassName}
|
||||
optionType={optionType}
|
||||
level={level}
|
||||
testIdBuilder={testIdBuilder}
|
||||
/>
|
||||
<CustomStyle
|
||||
{...this.props}
|
||||
config={{
|
||||
themeCss: this.formateThemeCss(themeCss),
|
||||
classNames: [
|
||||
{
|
||||
key: 'radiosClassName',
|
||||
weights: {
|
||||
default: {
|
||||
suf: ' label',
|
||||
inner: 'i'
|
||||
},
|
||||
hover: {
|
||||
suf: ' label',
|
||||
inner: 'i'
|
||||
},
|
||||
disabled: {
|
||||
inner: `.${ns}Checkbox--radio input[disabled] + i`
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
key: 'radiosCheckedClassName',
|
||||
weights: {
|
||||
default: {
|
||||
inner: `.${ns}Checkbox--radio input:checked + i`
|
||||
},
|
||||
hover: {
|
||||
suf: ` .${ns}Checkbox--radio`,
|
||||
inner: 'input:checked + i'
|
||||
},
|
||||
disabled: {
|
||||
inner: `.${ns}Checkbox--radio input:checked[disabled] + i`
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
key: 'radiosCheckedInnerClassName',
|
||||
weights: {
|
||||
default: {
|
||||
inner: `.${ns}Checkbox--radio input:checked + i:before`
|
||||
},
|
||||
hover: {
|
||||
suf: ` .${ns}Checkbox--radio`,
|
||||
inner: 'input:checked + i:before'
|
||||
},
|
||||
disabled: {
|
||||
inner: `.${ns}Checkbox--radio input:checked[disabled] + i:before`
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
key: 'radiosLabelClassName',
|
||||
weights: {
|
||||
default: {
|
||||
suf: ' label',
|
||||
inner: 'span'
|
||||
},
|
||||
hover: {
|
||||
suf: ' label',
|
||||
inner: 'span'
|
||||
},
|
||||
disabled: {
|
||||
inner: `.${ns}Checkbox--radio input[disabled] + i + span`
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
id: id
|
||||
}}
|
||||
env={env}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user