diff --git a/packages/amis-core/src/utils/style-helper.ts b/packages/amis-core/src/utils/style-helper.ts index 47f583308..3bea1b685 100644 --- a/packages/amis-core/src/utils/style-helper.ts +++ b/packages/amis-core/src/utils/style-helper.ts @@ -417,7 +417,7 @@ export function insertEditCustomStyle(params: { } else if (key === 'root') { const res = map( styles[key], - (value, key) => + (value: any, key) => `${key}: ${ resolveVariableAndFilter( value.replace(/['|"]/g, ''), @@ -430,7 +430,7 @@ export function insertEditCustomStyle(params: { } else if (/^root:/.test(key)) { const res = map( styles[key], - (value, key) => + (value: any, key) => `${key}: ${ resolveVariableAndFilter( value.replace(/['|"]/g, ''), @@ -444,7 +444,7 @@ export function insertEditCustomStyle(params: { } else { const res = map( styles[key], - (value, key) => + (value: any, key) => `${key}: ${ resolveVariableAndFilter( value.replace(/['|"]/g, ''), diff --git a/packages/amis-editor/src/plugin/Form/ChainedSelect.tsx b/packages/amis-editor/src/plugin/Form/ChainedSelect.tsx index 167420944..2494df72b 100644 --- a/packages/amis-editor/src/plugin/Form/ChainedSelect.tsx +++ b/packages/amis-editor/src/plugin/Form/ChainedSelect.tsx @@ -219,7 +219,7 @@ export class ChainedSelectControlPlugin extends BasePlugin { body: [ ...inputStateTpl( 'themeCss.chainedSelectControlClassName', - '--chained-select' + '--select-base' ) ] }, @@ -228,9 +228,13 @@ export class ChainedSelectControlPlugin extends BasePlugin { body: [ ...inputStateTpl( 'themeCss.chainedSelectPopoverClassName', - '--chained-select', + '--select-base-${state}-option', { - state: ['default', 'hover', 'focused'] + state: [ + {label: '常规', value: 'default'}, + {label: '悬浮', value: 'hover'}, + {label: '选中', value: 'focused'} + ] } ) ] diff --git a/packages/amis-editor/src/plugin/Form/Checkboxes.tsx b/packages/amis-editor/src/plugin/Form/Checkboxes.tsx index cdfa1067e..bff70b03e 100644 --- a/packages/amis-editor/src/plugin/Form/Checkboxes.tsx +++ b/packages/amis-editor/src/plugin/Form/Checkboxes.tsx @@ -25,6 +25,7 @@ import { resolveOptionEventDataSchame, resolveOptionType } from '../../util'; +import {inputStateTpl} from '../../renderer/style-control/helper'; export class CheckboxesControlPlugin extends BasePlugin { static id = 'CheckboxesControlPlugin'; @@ -230,7 +231,70 @@ export class CheckboxesControlPlugin extends BasePlugin { title: '外观', body: [ 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') ]) ] diff --git a/packages/amis-editor/src/plugin/Form/LocationPicker.tsx b/packages/amis-editor/src/plugin/Form/LocationPicker.tsx index edcc9a093..cf336f51b 100644 --- a/packages/amis-editor/src/plugin/Form/LocationPicker.tsx +++ b/packages/amis-editor/src/plugin/Form/LocationPicker.tsx @@ -3,7 +3,6 @@ import {registerEditorPlugin} from 'amis-editor-core'; import {BasePlugin, BaseEventContext} from 'amis-editor-core'; import {RendererPluginAction, RendererPluginEvent} from 'amis-editor-core'; import {getEventControlConfig} from '../../renderer/event-control/helper'; -import {inputStateTpl} from '../../renderer/style-control/helper'; import {ValidatorTag} from '../../validator'; export class LocationControlPlugin extends BasePlugin { diff --git a/packages/amis-editor/src/plugin/Form/NestedSelect.tsx b/packages/amis-editor/src/plugin/Form/NestedSelect.tsx index 424a0254a..4d376185b 100644 --- a/packages/amis-editor/src/plugin/Form/NestedSelect.tsx +++ b/packages/amis-editor/src/plugin/Form/NestedSelect.tsx @@ -353,7 +353,7 @@ export class NestedSelectControlPlugin extends BasePlugin { body: [ ...inputStateTpl( 'themeCss.nestedSelectControlClassName', - '--nested-select' + '--select-base' ) ] }, @@ -362,9 +362,13 @@ export class NestedSelectControlPlugin extends BasePlugin { body: [ ...inputStateTpl( 'themeCss.nestedSelectPopoverClassName', - '--nested-select', + '--select-base-${state}-option', { - state: ['default', 'hover', 'focused'] + state: [ + {label: '常规', value: 'default'}, + {label: '悬浮', value: 'hover'}, + {label: '选中', value: 'focused'} + ] } ) ] diff --git a/packages/amis-editor/src/plugin/Form/Select.tsx b/packages/amis-editor/src/plugin/Form/Select.tsx index 4504f5b9f..4ac88f40d 100644 --- a/packages/amis-editor/src/plugin/Form/Select.tsx +++ b/packages/amis-editor/src/plugin/Form/Select.tsx @@ -309,7 +309,10 @@ export class SelectControlPlugin extends BasePlugin { { title: '选择框样式', body: [ - ...inputStateTpl('themeCss.selectControlClassName', '--select') + ...inputStateTpl( + 'themeCss.selectControlClassName', + '--select-base' + ) ] }, { @@ -317,9 +320,13 @@ export class SelectControlPlugin extends BasePlugin { body: [ ...inputStateTpl( 'themeCss.selectPopoverClassName', - '--select', + '--select-base-${state}-option', { - state: ['default', 'hover', 'focused'] + state: [ + {label: '常规', value: 'default'}, + {label: '悬浮', value: 'hover'}, + {label: '选中', value: 'focused'} + ] } ) ] diff --git a/packages/amis-editor/src/renderer/style-control/helper.tsx b/packages/amis-editor/src/renderer/style-control/helper.tsx index 40e0ed8cb..49e7170fe 100644 --- a/packages/amis-editor/src/renderer/style-control/helper.tsx +++ b/packages/amis-editor/src/renderer/style-control/helper.tsx @@ -3,110 +3,120 @@ import {getSchemaTpl} from 'amis-editor-core'; export const inputStateTpl = ( className: string, token: string = '', - options: { - state: string[]; - } = { - state: ['default', 'hover', 'focused', 'disabled'] + options?: { + state?: { + label: string; + 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', name: `__editorState${className}`, label: '状态', selectFirst: true, - options: [ - { - label: '常规', - value: 'default' - }, - { - label: '悬浮', - value: 'hover' - }, - { - label: '选中', - value: 'focused' - }, - { - label: '禁用', - value: 'disabled' - } - ].filter(item => options.state.includes(item.value)) + options: stateOptions }, - ...inputStateFunc( - `\${__editorState${className} == 'default' || !__editorState${className}}`, - 'default', - className, - token - ), - ...inputStateFunc( - `\${__editorState${className} == 'hover'}`, - 'hover', - className, - token - ), - ...inputStateFunc( - `\${__editorState${className} == 'focused'}`, - 'focused', - className, - token - ), - ...inputStateFunc( - `\${__editorState${className} == 'disabled'}`, - 'disabled', - className, - token - ) + ...stateOptions.map((item: any) => { + return { + type: 'container', + visibleOn: + `\${__editorState${className} == '${item.value}'` + + (item.value === 'default' ? ` || !__editorState${className}` : '') + + `}`, + body: inputStateFunc( + item.value, + className, + item.token || token, + options + ) + }; + }) ]; + return res; }; export const inputStateFunc = ( - visibleOn: string, state: string, className: 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 [ - getSchemaTpl('theme:font', { - label: '文字', - name: `${className}.font:${state}`, - visibleOn: visibleOn, - editorValueToken: `${token}-${cssToken}`, - state - }), - getSchemaTpl('theme:colorPicker', { - label: '背景', - name: `${className}.background:${state}`, - labelMode: 'input', - needGradient: true, - needImage: true, - visibleOn: visibleOn, - editorValueToken: `${token}-${cssToken}-bg-color`, - state - }), - getSchemaTpl('theme:border', { - name: `${className}.border:${state}`, - visibleOn: visibleOn, - editorValueToken: `${token}-${cssToken}`, - state - }), - getSchemaTpl('theme:paddingAndMargin', { - name: `${className}.padding-and-margin:${state}`, - visibleOn: visibleOn, - editorValueToken: `${token}-${cssToken}`, - state - }), - getSchemaTpl('theme:radius', { - name: `${className}.radius:${state}`, - visibleOn: visibleOn, - editorValueToken: `${token}-${cssToken}`, - state - }), - ...options - ]; + !options?.hideFont && + getSchemaTpl('theme:font', { + label: '文字', + name: `${className}.font:${state}`, + editorValueToken: token, + state + }), + !options?.hideBackground && + getSchemaTpl('theme:colorPicker', { + label: '背景', + name: `${className}.background:${state}`, + labelMode: 'input', + needGradient: true, + needImage: true, + editorValueToken: `${token}-bg-color`, + state + }), + !options?.hideBorder && + getSchemaTpl('theme:border', { + name: `${className}.border:${state}`, + editorValueToken: token, + state + }), + !options?.hidePadding && + !options?.hideMargin && + getSchemaTpl('theme:paddingAndMargin', { + name: `${className}.padding-and-margin:${state}`, + editorValueToken: token, + state, + hidePadding: options?.hidePadding, + hideMargin: options?.hideMargin + }), + !options?.hideRadius && + getSchemaTpl('theme:radius', { + name: `${className}.radius:${state}`, + editorValueToken: token, + state + }), + ...(options?.schema || []) + ].filter(Boolean); }; export const buttonStateFunc = (visibleOn: string, state: string) => { diff --git a/packages/amis-editor/src/tpl/style.tsx b/packages/amis-editor/src/tpl/style.tsx index 39246567a..50fe607ea 100644 --- a/packages/amis-editor/src/tpl/style.tsx +++ b/packages/amis-editor/src/tpl/style.tsx @@ -16,18 +16,20 @@ setSchemaTpl('style:formItem', ({renderer, schema}: any) => { }; }); -setSchemaTpl('theme:formItem', ({schema}: any = {}) => { +setSchemaTpl('theme:formItem', ({schema, hidSize}: any = {hidSize: false}) => { return { title: '表单项', key: 'formItem', body: [ getSchemaTpl('theme:labelHide'), - { + !hidSize && { type: 'col-size', name: '__size', label: '宽度' } - ].concat(schema) + ] + .filter(Boolean) + .concat(schema) }; }); diff --git a/packages/amis-ui/scss/components/form/_checks.scss b/packages/amis-ui/scss/components/form/_checks.scss index 48df9d3b0..0e7738a0b 100644 --- a/packages/amis-ui/scss/components/form/_checks.scss +++ b/packages/amis-ui/scss/components/form/_checks.scss @@ -131,7 +131,6 @@ &:before { width: var(--Checkbox-inner-size); height: var(--Checkbox-inner-size); - background: var(--Checkbox-onHover-color); } } @@ -140,7 +139,6 @@ cursor: not-allowed; background-color: var(--checkbox-checkbox-disabled-bg-color); &:before { - background-color: var(--Checkbox-onDisabled-color); border-width: 0; } } @@ -243,10 +241,6 @@ input:checked + i { background: var(--button-primary-hover-bg-color); border-color: transparent; - - &:before { - background: var(--checkbox-checked-hover-bg-color); - } } & > i:before { @@ -264,9 +258,6 @@ &:checked + i { border-color: var(--Checkbox-onHover-color); background: var(--Checkbox-onHover-color); - &:hover { - background: var(--checkbox-checked-hover-bg-color); - } &:before { width: var(--Checkbox--full-inner-size); @@ -283,14 +274,12 @@ &[disabled]:checked + i { &:before { border-color: var(--Checkbox-onDisabled-color); - background: var(--Checkbox-onDisabled-bg); border-width: 0 0 px2rem(1px) px2rem(1px); } } &:checked[disabled] + i { border-color: var(--Checkbox-color); - background: var(--Checkbox-onDisabled-bg); } } @@ -325,7 +314,6 @@ &:before { width: var(--Checkbox-inner-size); height: var(--Checkbox-inner-size); - background: var(--Checkbox-onHover-color); } } diff --git a/packages/amis/src/renderers/Form/Checkboxes.tsx b/packages/amis/src/renderers/Form/Checkboxes.tsx index 9b36677be..0b91c9252 100644 --- a/packages/amis/src/renderers/Form/Checkboxes.tsx +++ b/packages/amis/src/renderers/Form/Checkboxes.tsx @@ -7,7 +7,9 @@ import { hasAbility, columnsSplit, flattenTreeWithLeafNodes, - getVariable + getVariable, + CustomStyle, + setThemeClassName } from 'amis-core'; import type {ActionObject, Api, OptionsControlProps, Option} from 'amis-core'; import {Checkbox, Icon, Spinner} from 'amis-ui'; @@ -337,6 +339,29 @@ export default class CheckboxesControl extends React.Component< 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() render() { const { @@ -361,7 +386,11 @@ export default class CheckboxesControl extends React.Component< translate: __, optionType, loading, - loadingConfig + loadingConfig, + themeCss, + id, + env, + classPrefix: ns } = this.props; let body: Array = []; @@ -393,8 +422,34 @@ export default class CheckboxesControl extends React.Component< body = this.columnsSplit(body); + const css = this.formateThemeCss(themeCss); + return ( -
+
{body && body.length ? ( body ) : loading ? null : ( @@ -417,6 +472,63 @@ export default class CheckboxesControl extends React.Component< {__(createBtnLabel)} ) : null} +
); }