feat: 复选框支持新版外观配置 (#11066)

Co-authored-by: qinhaoyan <30946345+qinhaoyan@users.noreply.github.com>
This commit is contained in:
qkiroc 2024-10-17 16:53:48 +08:00 committed by GitHub
parent 0e2d2de60d
commit 1e5b057988
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 309 additions and 119 deletions

View File

@ -417,7 +417,7 @@ export function insertEditCustomStyle(params: {
} else if (key === 'root') { } else if (key === 'root') {
const res = map( const res = map(
styles[key], styles[key],
(value, key) => (value: any, key) =>
`${key}: ${ `${key}: ${
resolveVariableAndFilter( resolveVariableAndFilter(
value.replace(/['|"]/g, ''), value.replace(/['|"]/g, ''),
@ -430,7 +430,7 @@ export function insertEditCustomStyle(params: {
} else if (/^root:/.test(key)) { } else if (/^root:/.test(key)) {
const res = map( const res = map(
styles[key], styles[key],
(value, key) => (value: any, key) =>
`${key}: ${ `${key}: ${
resolveVariableAndFilter( resolveVariableAndFilter(
value.replace(/['|"]/g, ''), value.replace(/['|"]/g, ''),
@ -444,7 +444,7 @@ export function insertEditCustomStyle(params: {
} else { } else {
const res = map( const res = map(
styles[key], styles[key],
(value, key) => (value: any, key) =>
`${key}: ${ `${key}: ${
resolveVariableAndFilter( resolveVariableAndFilter(
value.replace(/['|"]/g, ''), value.replace(/['|"]/g, ''),

View File

@ -219,7 +219,7 @@ export class ChainedSelectControlPlugin extends BasePlugin {
body: [ body: [
...inputStateTpl( ...inputStateTpl(
'themeCss.chainedSelectControlClassName', 'themeCss.chainedSelectControlClassName',
'--chained-select' '--select-base'
) )
] ]
}, },
@ -228,9 +228,13 @@ export class ChainedSelectControlPlugin extends BasePlugin {
body: [ body: [
...inputStateTpl( ...inputStateTpl(
'themeCss.chainedSelectPopoverClassName', 'themeCss.chainedSelectPopoverClassName',
'--chained-select', '--select-base-${state}-option',
{ {
state: ['default', 'hover', 'focused'] state: [
{label: '常规', value: 'default'},
{label: '悬浮', value: 'hover'},
{label: '选中', value: 'focused'}
]
} }
) )
] ]

View File

@ -25,6 +25,7 @@ import {
resolveOptionEventDataSchame, resolveOptionEventDataSchame,
resolveOptionType resolveOptionType
} from '../../util'; } from '../../util';
import {inputStateTpl} from '../../renderer/style-control/helper';
export class CheckboxesControlPlugin extends BasePlugin { export class CheckboxesControlPlugin extends BasePlugin {
static id = 'CheckboxesControlPlugin'; static id = 'CheckboxesControlPlugin';
@ -230,7 +231,70 @@ export class CheckboxesControlPlugin extends BasePlugin {
title: '外观', title: '外观',
body: [ body: [
getSchemaTpl('collapseGroup', [ getSchemaTpl('collapseGroup', [
getSchemaTpl('style:formItem', {renderer}), getSchemaTpl('theme:formItem', {hidSize: true}),
getSchemaTpl('theme:form-label'),
getSchemaTpl('theme:form-description'),
{
title: '勾选框样式',
body: [
...inputStateTpl('themeCss.checkboxesClassName', '--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.checkboxesLabelClassName', '', {
hidePadding: true,
hideRadius: true,
hideBorder: true,
state: [
{
label: '常规',
value: 'default'
},
{
label: '悬浮',
value: 'hover'
},
{
label: '禁用',
value: 'disabled'
}
]
})
]
},
getSchemaTpl('theme:cssCode'),
getSchemaTpl('style:classNames') getSchemaTpl('style:classNames')
]) ])
] ]

View File

@ -3,7 +3,6 @@ import {registerEditorPlugin} from 'amis-editor-core';
import {BasePlugin, BaseEventContext} from 'amis-editor-core'; import {BasePlugin, BaseEventContext} from 'amis-editor-core';
import {RendererPluginAction, RendererPluginEvent} from 'amis-editor-core'; import {RendererPluginAction, RendererPluginEvent} from 'amis-editor-core';
import {getEventControlConfig} from '../../renderer/event-control/helper'; import {getEventControlConfig} from '../../renderer/event-control/helper';
import {inputStateTpl} from '../../renderer/style-control/helper';
import {ValidatorTag} from '../../validator'; import {ValidatorTag} from '../../validator';
export class LocationControlPlugin extends BasePlugin { export class LocationControlPlugin extends BasePlugin {

View File

@ -353,7 +353,7 @@ export class NestedSelectControlPlugin extends BasePlugin {
body: [ body: [
...inputStateTpl( ...inputStateTpl(
'themeCss.nestedSelectControlClassName', 'themeCss.nestedSelectControlClassName',
'--nested-select' '--select-base'
) )
] ]
}, },
@ -362,9 +362,13 @@ export class NestedSelectControlPlugin extends BasePlugin {
body: [ body: [
...inputStateTpl( ...inputStateTpl(
'themeCss.nestedSelectPopoverClassName', 'themeCss.nestedSelectPopoverClassName',
'--nested-select', '--select-base-${state}-option',
{ {
state: ['default', 'hover', 'focused'] state: [
{label: '常规', value: 'default'},
{label: '悬浮', value: 'hover'},
{label: '选中', value: 'focused'}
]
} }
) )
] ]

View File

@ -309,7 +309,10 @@ export class SelectControlPlugin extends BasePlugin {
{ {
title: '选择框样式', title: '选择框样式',
body: [ body: [
...inputStateTpl('themeCss.selectControlClassName', '--select') ...inputStateTpl(
'themeCss.selectControlClassName',
'--select-base'
)
] ]
}, },
{ {
@ -317,9 +320,13 @@ export class SelectControlPlugin extends BasePlugin {
body: [ body: [
...inputStateTpl( ...inputStateTpl(
'themeCss.selectPopoverClassName', 'themeCss.selectPopoverClassName',
'--select', '--select-base-${state}-option',
{ {
state: ['default', 'hover', 'focused'] state: [
{label: '常规', value: 'default'},
{label: '悬浮', value: 'hover'},
{label: '选中', value: 'focused'}
]
} }
) )
] ]

View File

@ -3,110 +3,120 @@ import {getSchemaTpl} from 'amis-editor-core';
export const inputStateTpl = ( export const inputStateTpl = (
className: string, className: string,
token: string = '', token: string = '',
options: { options?: {
state: string[]; state?: {
} = { label: string;
state: ['default', 'hover', 'focused', 'disabled'] value: string;
token?: string;
}[];
hideFont?: boolean;
hidePadding?: boolean;
hideMargin?: boolean;
hideRadius?: boolean;
hideBackground?: boolean;
hideBorder?: boolean;
} }
) => { ) => {
return [ const stateOptions = options?.state || [
{
label: '常规',
value: 'default'
},
{
label: '悬浮',
value: 'hover'
},
{
label: '选中',
value: 'focused'
},
{
label: '禁用',
value: 'disabled'
}
];
const res: any = [
{ {
type: 'select', type: 'select',
name: `__editorState${className}`, name: `__editorState${className}`,
label: '状态', label: '状态',
selectFirst: true, selectFirst: true,
options: [ options: stateOptions
{
label: '常规',
value: 'default'
},
{
label: '悬浮',
value: 'hover'
},
{
label: '选中',
value: 'focused'
},
{
label: '禁用',
value: 'disabled'
}
].filter(item => options.state.includes(item.value))
}, },
...inputStateFunc( ...stateOptions.map((item: any) => {
`\${__editorState${className} == 'default' || !__editorState${className}}`, return {
'default', type: 'container',
className, visibleOn:
token `\${__editorState${className} == '${item.value}'` +
), (item.value === 'default' ? ` || !__editorState${className}` : '') +
...inputStateFunc( `}`,
`\${__editorState${className} == 'hover'}`, body: inputStateFunc(
'hover', item.value,
className, className,
token item.token || token,
), options
...inputStateFunc( )
`\${__editorState${className} == 'focused'}`, };
'focused', })
className,
token
),
...inputStateFunc(
`\${__editorState${className} == 'disabled'}`,
'disabled',
className,
token
)
]; ];
return res;
}; };
export const inputStateFunc = ( export const inputStateFunc = (
visibleOn: string,
state: string, state: string,
className: string, className: string,
token: string, token: string,
options: any = [] options: any
) => { ) => {
const cssToken = state === 'focused' ? 'active' : state; const cssTokenState = state === 'focused' ? 'active' : state;
if (token.includes('${state}')) {
token = token.replace(/\${state}/g, cssTokenState);
} else {
token = `${token}-${cssTokenState}`;
}
return [ return [
getSchemaTpl('theme:font', { !options?.hideFont &&
label: '文字', getSchemaTpl('theme:font', {
name: `${className}.font:${state}`, label: '文字',
visibleOn: visibleOn, name: `${className}.font:${state}`,
editorValueToken: `${token}-${cssToken}`, editorValueToken: token,
state state
}), }),
getSchemaTpl('theme:colorPicker', { !options?.hideBackground &&
label: '背景', getSchemaTpl('theme:colorPicker', {
name: `${className}.background:${state}`, label: '背景',
labelMode: 'input', name: `${className}.background:${state}`,
needGradient: true, labelMode: 'input',
needImage: true, needGradient: true,
visibleOn: visibleOn, needImage: true,
editorValueToken: `${token}-${cssToken}-bg-color`, editorValueToken: `${token}-bg-color`,
state state
}), }),
getSchemaTpl('theme:border', { !options?.hideBorder &&
name: `${className}.border:${state}`, getSchemaTpl('theme:border', {
visibleOn: visibleOn, name: `${className}.border:${state}`,
editorValueToken: `${token}-${cssToken}`, editorValueToken: token,
state state
}), }),
getSchemaTpl('theme:paddingAndMargin', { !options?.hidePadding &&
name: `${className}.padding-and-margin:${state}`, !options?.hideMargin &&
visibleOn: visibleOn, getSchemaTpl('theme:paddingAndMargin', {
editorValueToken: `${token}-${cssToken}`, name: `${className}.padding-and-margin:${state}`,
state editorValueToken: token,
}), state,
getSchemaTpl('theme:radius', { hidePadding: options?.hidePadding,
name: `${className}.radius:${state}`, hideMargin: options?.hideMargin
visibleOn: visibleOn, }),
editorValueToken: `${token}-${cssToken}`, !options?.hideRadius &&
state getSchemaTpl('theme:radius', {
}), name: `${className}.radius:${state}`,
...options editorValueToken: token,
]; state
}),
...(options?.schema || [])
].filter(Boolean);
}; };
export const buttonStateFunc = (visibleOn: string, state: string) => { export const buttonStateFunc = (visibleOn: string, state: string) => {

View File

@ -16,18 +16,20 @@ setSchemaTpl('style:formItem', ({renderer, schema}: any) => {
}; };
}); });
setSchemaTpl('theme:formItem', ({schema}: any = {}) => { setSchemaTpl('theme:formItem', ({schema, hidSize}: any = {hidSize: false}) => {
return { return {
title: '表单项', title: '表单项',
key: 'formItem', key: 'formItem',
body: [ body: [
getSchemaTpl('theme:labelHide'), getSchemaTpl('theme:labelHide'),
{ !hidSize && {
type: 'col-size', type: 'col-size',
name: '__size', name: '__size',
label: '宽度' label: '宽度'
} }
].concat(schema) ]
.filter(Boolean)
.concat(schema)
}; };
}); });

View File

@ -131,7 +131,6 @@
&:before { &:before {
width: var(--Checkbox-inner-size); width: var(--Checkbox-inner-size);
height: var(--Checkbox-inner-size); height: var(--Checkbox-inner-size);
background: var(--Checkbox-onHover-color);
} }
} }
@ -140,7 +139,6 @@
cursor: not-allowed; cursor: not-allowed;
background-color: var(--checkbox-checkbox-disabled-bg-color); background-color: var(--checkbox-checkbox-disabled-bg-color);
&:before { &:before {
background-color: var(--Checkbox-onDisabled-color);
border-width: 0; border-width: 0;
} }
} }
@ -243,10 +241,6 @@
input:checked + i { input:checked + i {
background: var(--button-primary-hover-bg-color); background: var(--button-primary-hover-bg-color);
border-color: transparent; border-color: transparent;
&:before {
background: var(--checkbox-checked-hover-bg-color);
}
} }
& > i:before { & > i:before {
@ -264,9 +258,6 @@
&:checked + i { &:checked + i {
border-color: var(--Checkbox-onHover-color); border-color: var(--Checkbox-onHover-color);
background: var(--Checkbox-onHover-color); background: var(--Checkbox-onHover-color);
&:hover {
background: var(--checkbox-checked-hover-bg-color);
}
&:before { &:before {
width: var(--Checkbox--full-inner-size); width: var(--Checkbox--full-inner-size);
@ -283,14 +274,12 @@
&[disabled]:checked + i { &[disabled]:checked + i {
&:before { &:before {
border-color: var(--Checkbox-onDisabled-color); border-color: var(--Checkbox-onDisabled-color);
background: var(--Checkbox-onDisabled-bg);
border-width: 0 0 px2rem(1px) px2rem(1px); border-width: 0 0 px2rem(1px) px2rem(1px);
} }
} }
&:checked[disabled] + i { &:checked[disabled] + i {
border-color: var(--Checkbox-color); border-color: var(--Checkbox-color);
background: var(--Checkbox-onDisabled-bg);
} }
} }
@ -325,7 +314,6 @@
&:before { &:before {
width: var(--Checkbox-inner-size); width: var(--Checkbox-inner-size);
height: var(--Checkbox-inner-size); height: var(--Checkbox-inner-size);
background: var(--Checkbox-onHover-color);
} }
} }

View File

@ -7,7 +7,9 @@ import {
hasAbility, hasAbility,
columnsSplit, columnsSplit,
flattenTreeWithLeafNodes, flattenTreeWithLeafNodes,
getVariable getVariable,
CustomStyle,
setThemeClassName
} from 'amis-core'; } from 'amis-core';
import type {ActionObject, Api, OptionsControlProps, Option} from 'amis-core'; import type {ActionObject, Api, OptionsControlProps, Option} from 'amis-core';
import {Checkbox, Icon, Spinner} from 'amis-ui'; import {Checkbox, Icon, Spinner} from 'amis-ui';
@ -337,6 +339,29 @@ export default class CheckboxesControl extends React.Component<
return result; return result;
} }
formateThemeCss(themeCss: any) {
if (!themeCss) {
return {};
}
const {checkboxesClassName} = themeCss;
const defaultThemeCss: any = {};
const checkedThemeCss: any = {};
Object.keys(checkboxesClassName).forEach(key => {
if (key.includes('checked-')) {
const newKey = key.replace('checked-', '');
checkedThemeCss[newKey] = checkboxesClassName[key];
} else if (key.includes('checkbox-')) {
const newKey = key.replace('checkbox-', '');
defaultThemeCss[newKey] = checkboxesClassName[key];
}
});
return {
...themeCss,
checkboxesClassName: defaultThemeCss,
checkboxesCheckedClassName: checkedThemeCss
};
}
@supportStatic() @supportStatic()
render() { render() {
const { const {
@ -361,7 +386,11 @@ export default class CheckboxesControl extends React.Component<
translate: __, translate: __,
optionType, optionType,
loading, loading,
loadingConfig loadingConfig,
themeCss,
id,
env,
classPrefix: ns
} = this.props; } = this.props;
let body: Array<React.ReactNode> = []; let body: Array<React.ReactNode> = [];
@ -393,8 +422,34 @@ export default class CheckboxesControl extends React.Component<
body = this.columnsSplit(body); body = this.columnsSplit(body);
const css = this.formateThemeCss(themeCss);
return ( return (
<div className={cx(`CheckboxesControl`, className)} ref="checkboxRef"> <div
className={cx(
`CheckboxesControl`,
className,
setThemeClassName({
...this.props,
name: 'checkboxesClassName',
id,
themeCss: css
}),
setThemeClassName({
...this.props,
name: 'checkboxesCheckedClassName',
id,
themeCss: css
}),
setThemeClassName({
...this.props,
name: 'checkboxesLabelClassName',
id,
themeCss: css
})
)}
ref="checkboxRef"
>
{body && body.length ? ( {body && body.length ? (
body body
) : loading ? null : ( ) : loading ? null : (
@ -417,6 +472,63 @@ export default class CheckboxesControl extends React.Component<
{__(createBtnLabel)} {__(createBtnLabel)}
</a> </a>
) : null} ) : null}
<CustomStyle
{...this.props}
config={{
themeCss: this.formateThemeCss(themeCss),
classNames: [
{
key: 'checkboxesClassName',
weights: {
default: {
suf: ' label',
inner: 'i'
},
hover: {
suf: ' label',
inner: 'i'
},
disabled: {
inner: `.${ns}Checkbox--checkbox input[disabled] + i`
}
}
},
{
key: 'checkboxesCheckedClassName',
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: 'checkboxesLabelClassName',
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> </div>
); );
} }