feat: checkbox\radios支持外观配置 (#11095)

Co-authored-by: qinhaoyan <30946345+qinhaoyan@users.noreply.github.com>
This commit is contained in:
qkiroc 2024-10-28 14:42:04 +08:00 committed by GitHub
parent dc8dcc6828
commit 75b3e03b29
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 451 additions and 48 deletions

View File

@ -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')
])
]

View File

@ -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', {

View File

@ -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;

View File

@ -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;
}

View File

@ -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>
);
}

View File

@ -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 => {

View File

@ -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}
/>
</>
);
}
}